> ## Documentation Index
> Fetch the complete documentation index at: https://docs.maximem.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# instance.record_thinking

> Stream a reasoning step from your agent so Synap can see what it is deliberating between the user's turn and the reply.

<Note>
  Requires `maximem-synap` 0.5.1 or newer (Python) and
  `@maximem/synap-js-sdk` 0.5.1 or newer (JS). Earlier versions do not
  have this method, and 0.5.0 loses events sent immediately after
  `listen()`.
</Note>

<CodeGroup>
  ```python Python theme={null}
  await sdk.instance.record_thinking(
      content,
      conversation_id=None,
      user_id=None,
      customer_id=None,
      session_id=None,
      step_index=None,
      thought_type=None,
      metadata=None,
  )
  ```

  ```typescript TypeScript theme={null}
  await sdk.instance.record_thinking(options: RecordThinkingOptions)
  ```
</CodeGroup>

<Note>
  Advanced: for real-time integrations. Requires an active [`instance.listen`](/sdk-reference/instance/listen) stream.
</Note>

`record_thinking()` reports one reasoning step from your agent: a plan, a self-correction, a decision about which tool to reach for. Without it, Synap sees the observable edges of a turn — the user's message, the tools you called, the reply you sent — and nothing of the deliberation in between, which is usually where the next question is decided.

It is the same stream `send_message()` uses. There is no separate channel and no extra connection.

## What happens to a reasoning step

<Warning>
  **Reasoning is a short-lived hint, not a memory.** It is never written to conversation history, never compacted, and never extracted into long-term memory. The anticipation agent reads it to decide what to prefetch, and it is held for at most 30 minutes of conversation inactivity. Do not use it as a way to store something you want back later; use [`memories.create`](/sdk-reference/memories/create) for that.
</Warning>

A reasoning step arrives mid-turn, while your agent is still working. The anticipation agent treats it as something to observe rather than act on: pushing a bundle at that moment would arrive after your agent had already fetched, so it waits for the turn to end.

## Parameters

<ParamField path="content" type="string" required>
  The reasoning text. One step, not the whole chain.
</ParamField>

<ParamField path="conversation_id" type="string">
  The conversation this thought belongs to.
</ParamField>

<ParamField path="user_id" type="string">
  External user identifier.
</ParamField>

<ParamField path="customer_id" type="string">
  External customer identifier. Required on B2B. **Not accepted on B2C.**
</ParamField>

<ParamField path="session_id" type="string">
  External session identifier. Usually unnecessary: the SDK opens and tracks a session for you.
</ParamField>

<ParamField path="step_index" type="integer">
  Where this thought sits in the current turn, if your agent numbers them. Travels in the event's metadata under this exact key.
</ParamField>

<ParamField path="thought_type" type="string">
  A label for the kind of reasoning: `"plan"`, `"reflect"`, `"tool_decision"`, `"self_correction"`. Travels in metadata under this exact key.
</ParamField>

<ParamField path="metadata" type="dict[str, str]">
  Extra string key-value pairs. **Your own entry wins:** a `step_index` or `thought_type` you put here is not overwritten by the arguments above.
</ParamField>

## Returns

Returns `None`. The coroutine resolves once the event is on the stream, or buffered for the next reconnect.

## Example

<CodeGroup>
  ```python Python theme={null}
  await sdk.instance.record_thinking(
      content="The user asked about a refund, so check the order status before quoting the policy.",
      conversation_id=conversation_id,
      user_id="user_789",
      customer_id="cust_456",
      step_index=1,
      thought_type="plan",
  )
  ```

  ```typescript TypeScript theme={null}
  await sdk.instance.record_thinking({
    content: 'The user asked about a refund, so check the order status before quoting the policy.',
    conversation_id: conversationId,
    user_id: 'user_789',
    customer_id: 'cust_456',
    step_index: 1,
    thought_type: 'plan',
  });
  ```
</CodeGroup>

## What your provider actually returns

Most models do not hand back their raw reasoning. Depending on the provider and on what you asked for, you may get a summary, an encrypted blob you cannot read, or nothing at all. Send what you have; a turn with no reasoning to report is an ordinary turn, not a gap to fill with something invented.

## Raises

<ResponseField name="ListeningNotActiveError" type="error">
  No stream has been started, or it has been stopped. A stream that is mid-reconnect does **not** raise: the event is buffered and replayed.
</ResponseField>

## See also

* [instance.record\_tool\_call](/sdk-reference/instance/record-tool-call): report a tool your agent is about to call.
* [instance.record\_tool\_result](/sdk-reference/instance/record-tool-result): report what it returned.
* [instance.send\_message](/sdk-reference/instance/send-message): the full event table.
