Declare the tool
In the agent config, a custom tool is a name, a description, and a JSON Schema for its input. Write the description as clear instructions: explain when to use the tool, what it does, and any important limits.always_allow; set permission.mode: always_ask to put a human between the model and your system (Tools & permissions).
Find calls waiting for you
GET /tool-calls lists an agent’s tool calls, filterable by state and type. Your worker polls for ready custom calls:
ready means the permission check has passed and the call is waiting for your result. A custom call using always_ask remains in awaiting_permission until someone responds to its interaction. After you submit a result, it moves to completed.
Submit the result
Post the outcome with content blocks — text, inline media, or structured data:201 returns both the completed call and the durable tool_result event now in the agent’s timeline:
outcome: "failed" with a text block explaining why — a failed tool call is information the model can act on, not an error you should swallow.
The first result wins. Only ready custom calls accept results; a second submission for the same call, or a result for a built-in or MCP call, returns 409:
409, not a corrupted timeline.
Full schema and playground: List tool calls · Submit a result.