With the SDKs
Pass your functions viatools; the schema is derived from the signature and docstring in Python, or declared with tool() in TypeScript.
run_session / runSession (or a handle’s wait_for_completion / waitForCompletion with the same tools). Execution is at-least-once: if posting a result fails and the wait is retried, the tool may run again, so prefer idempotent tool functions for side-effecting operations.
Over the raw API
Without an SDK to run the loop, you declare the tools, watch for the agent to call one, and post the result yourself.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:Session create body
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
Post the result
Execute the call and post the result, echoing the pending call back as Send several at once with The agent resumes once every pending call has a result; calls still unresolved when the run ends (for example on
tool_req:{"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
max_time_s) fail with a model-visible error. Posting to a finished session returns 409.