> ## 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_tool_call

> Report a tool your agent is about to call, so Synap can anticipate what it will need once the result comes back.

<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_tool_call(
      tool_name,
      tool_args=None,
      tool_call_id=None,
      conversation_id=None,
      user_id=None,
      customer_id=None,
      session_id=None,
      metadata=None,
  )
  ```

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

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

`record_tool_call()` tells Synap which tool your agent is invoking and with what arguments.

<Tip>
  Prefer this over `send_message(event_type="tool_call", ...)`. Each event carries both an `event_type` and a `role`, and the two have to agree; this method sets both. A tool call reported with the wrong role is read as an ordinary assistant reply, which is silent and changes what the anticipation agent believes happened.
</Tip>

## Parameters

<ParamField path="tool_name" type="string" required>
  The tool being invoked.
</ParamField>

<ParamField path="tool_args" type="dict">
  JSON-encodable arguments.
</ParamField>

<ParamField path="tool_call_id" type="string">
  Your framework's id for this call. Pass the same id to [`record_tool_result`](/sdk-reference/instance/record-tool-result) and the two are read as one exchange. Without it, a turn with three tools in flight is three calls and three results with nothing saying which belongs to which.
</ParamField>

<ParamField path="conversation_id" type="string">
  The conversation this call 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.
</ParamField>

<ParamField path="metadata" type="dict[str, str]">
  Extra string key-value pairs.
</ParamField>

## Returns

Returns `None`.

## Example

<CodeGroup>
  ```python Python theme={null}
  await sdk.instance.record_tool_call(
      "lookup_order",
      {"order_id": "A-1042"},
      tool_call_id="call_1",
      conversation_id=conversation_id,
      user_id="user_789",
      customer_id="cust_456",
  )
  ```

  ```typescript TypeScript theme={null}
  await sdk.instance.record_tool_call({
    tool_name: 'lookup_order',
    tool_args: { order_id: 'A-1042' },
    tool_call_id: 'call_1',
    conversation_id: conversationId,
    user_id: 'user_789',
    customer_id: 'cust_456',
  });
  ```
</CodeGroup>

## What happens to it

A tool call is a short-lived hint for the anticipation agent, like reasoning. It is not written to conversation history, not compacted, and not extracted into long-term memory. It is also mid-turn, so the agent observes it rather than pushing a bundle your agent would have already raced past.

## 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.
</ResponseField>

## See also

* [instance.record\_tool\_result](/sdk-reference/instance/record-tool-result)
* [instance.record\_thinking](/sdk-reference/instance/record-thinking)
