Skip to main content

With the SDKs

Pass your functions via tools. They add to the core tools the environment supplies, like click and type. Python derives the schema from the signature and docstring. TypeScript declares it with tool(). The SDK runs the whole loop.
  • Functions may be sync or async. Exceptions reach the agent as tool errors and don’t crash the session.
  • Tools run only while your program waits on the session.
  • Execution is at-least-once: if posting a result fails and the wait retries, the tool may run again. Make side-effecting tools idempotent.

Over the raw API

1

Declare the tools at session create

Declare the tools when creating the session, inline on the agent or via the agent.tools override for a registered agent:
cURL
2

Detect the pending call

Long-poll changes for an ActiveStateChangeEvent whose data.state is "awaiting_tool_results". Its data.pending_tool_calls lists each pending call as a { tool_name, args, id } object:
Pending tool call event
The same list is on the session itself: pending_tool_calls on status and changes holds the calls from the agent’s latest report, so you don’t need to scan events for it. A call you just answered can stay listed until the agent reports again.
3

Post the result

Execute the call and post the result, echoing the pending call back as tool_req:
Send several at once with {"type": "batch", "results": [...]}. Report a failure as an error_event instead of a tool_result. It carries error, origin (both required), and the echoed tool_req:
Tool error report
The agent resumes once every pending call has a result. Calls still unresolved when the turn ends (for example on max_time_s) fail with a model-visible error.