Function tools let an agent call your application code. You define the function and its arguments. The agent requests a call, your code returns a result, and the harness continues the turn.
Your handler can run in an application server, a worker, or an environment you control. Attaching an environment to a session does not automatically run function tools there.
If you use function calling in the Responses API, you can reuse your function implementation with the session flow described here.
Define a function
Add a function definition to agent.tools when you configure the agent. Give it a name, a description, and a JSON Schema for its arguments:
{
"type": "function",
"name": "get_customer",
"description": "Look up a customer by ID.",
"parameters": {
"type": "object",
"properties": { "customer_id": { "type": "string" } },
"required": ["customer_id"],
"additionalProperties": false
}
}
Handle required actions
When the agent needs a function result, the session emits agent.session.requires_action. Read the pending calls from event.session.required_actions. You can also retrieve the session and read session.required_actions without streaming.
A function entry in required_actions looks like this:
{
"type": "function_call",
"turn_id": "turn_123",
"call_id": "call_123",
"name": "get_customer",
"arguments": { "customer_id": "123" }
}
Run the named function with the supplied arguments. Use required_actions to decide which calls need results; a function_call item in session history alone does not establish that a result is pending.
Return the result
Send agent.session.input.tool_result to the session events endpoint. Copy turn_id and call_id from the pending action:
- For success, set
success: trueand supplyoutputas a string or a supported content array. Serialize JSON objects to strings. - For an error, set
success: falseand supply anerrormessage that the agent can use.
For each pending get_customer call, run your lookup and return its result. Here, action is the entry from required_actions:
const result = {
turn_id: action.turn_id,
call_id: action.call_id,
};
let outcome;
outcome = {
success: true,
output: JSON.stringify(getCustomer(action.arguments)),
};
await client.beta.agents.sessions.events.create(sessionId, {
events: [
{ type: "agent.session.input.tool_result", ...result, ...outcome },
],
});The harness continues the turn after it receives the required results. Follow session events and items to check the turn’s outcome and retrieve its output.
Recover after a disconnect
Retrieve the session to find pending actions. If you already ran a function, submit its saved result with the same turn_id and call_id.
For functions with side effects, store results durably by session, turn, and call ID. If execution might have succeeded but no result was saved, check the outcome before running the function again.
Load functions on demand
Functions load eagerly by default. To defer a function, set defer_loading: true on its definition and include { "type": "tool_search" } in agent.tools. See Tool search for a complete example.