How a function call flows
While Orca waits for your result, the turn’s status iswaiting and the session’s status is requires_action. Nothing happens until you answer.
Step 1: describe the tool on the agent
Examples on this page assumeclient is an OpenAI client configured as in the quickstart.
A tool definition has a name, a description the model reads to decide when to use it, and parameters as a JSON Schema. Write the description for the model: say what the tool does and when to use it.
Step 2: answer calls
There are two ways to answer. Pick based on whether the code that sends messages can also run the functions.Option A: the stream helper (simplest)
Passtool_handlers to sessions.stream. Each handler receives the parsed arguments and returns a JSON-serializable result. The helper sends results back for you while the stream is open, all within the same turn.
Option B: answer from any process
If calls should be handled somewhere else, such as a worker queue, poll the session for pending calls and post each result as an input event. Heresession_id is the session to watch and run_tool is your own dispatcher.
- Keep polling until the turn ends. The model can request several calls at once, and they may appear in
required_actionsone at a time. One snapshot can miss some. - Remember which
call_ids you answered. If you answer the same call twice, or rerun a function that has side effects, you may do the work twice. - Send
"success": Falsewith an"error"message when the tool could not do its job. The model sees the error and can react, such as by asking the user for a different ID. - Answering the same call again with a different result is rejected (HTTP 409). Resending the identical result is harmless.
argumentsmay be a JSON string. Parse it before use.
Keep it safe
The model chooses the arguments, and the model can be influenced by anything it reads, including user input and tool output. Treat arguments like any untrusted request:- Validate every argument against the schema and your business rules.
- Check that the end user is allowed to do what the call asks. The model does not know your permissions.
- Give each tool the narrowest job possible.
lookup_order(order_id)is safer thanrun_sql(query). - Require confirmation in your application for anything destructive or expensive. Instructions such as “never delete” are not a security control.
Function tools or MCP?
See also: turns and statuses, runnable examples (both answer styles in Python and TypeScript), and the sessions reference.