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
Declare the tools when creating the session, inline on the agent or via theagent.tools override for a registered agent:
changes for an ActiveStateChangeEvent with state: "awaiting_tool_results"; its pending_tool_calls lists each call as a tool_req (tool_name, args, id). Execute and post the result, echoing the tool_req back:
{"type": "batch", "results": [...]}, and report a failure as an error_event instead of a tool_result. The agent resumes once every pending call has a result; calls still unresolved when the run ends (for example on max_time_s) fail with a model-visible error. Posting to a finished session returns 409.