Declaring a tool
parameters is ordinary JSON Schema. Check the catalog first: sending tools to a model whose
capabilities.toolUse is false is refused with 422 before any provider is called.
"tools": [
{
"name": "getWeather",
"description": "Current conditions for a city.",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string", "description": "City name" } },
"required": ["city"]
}
}
]The full loop
Four steps. The turn you get back is appended to messages verbatim, the tool result goes after it paired on the
call's id, and you send the whole thing again. Nothing is rewritten by hand.
1. Ask
{
"model": "claude-sonnet-5",
"systemPrompt": "Use tools when they help.",
"messages": [{ "type": "user", "value": "What is the weather in Lagos?" }],
"tools": [ … ],
"parameters": { "maxTokens": 1024 }
}2. The model calls
{
"type": "monolith",
"model": { "name": "claude-sonnet-5", "tier": "high", "publisher": "Anthropic", "provider": "Anthropic" },
"messages": [
{ "type": "content", "value": "Let me check.", "data": {} },
{ "type": "toolCall", "call": { "id": "toolu_01A", "name": "getWeather", "arguments": "{\"city\":\"Lagos\"}" } }
],
"usage": { "finishReason": "tool_use" }
}3. Run it and answer
{
"model": "claude-sonnet-5",
"systemPrompt": "Use tools when they help.",
"messages": [
{ "type": "user", "value": "What is the weather in Lagos?" },
{ "type": "content", "value": "Let me check." },
{ "type": "toolCall", "call": { "id": "toolu_01A", "name": "getWeather", "arguments": "{\"city\":\"Lagos\"}" } },
{ "type": "toolResult", "result": { "id": "toolu_01A", "name": "getWeather", "content": "31C, humid, scattered thunderstorms" } }
],
"tools": [ … ]
}4. The answer
{
"type": "monolith",
"messages": [
{ "type": "content", "value": "It is 31C and humid in Lagos, with scattered thunderstorms.", "data": {} }
],
"usage": { "finishReason": "end_turn" }
}
argumentsis a string Not an object. That is what every provider sends and what they expect back.nametravels besideidbecause some providers pair a result by name while others pair by id.
When a tool fails
Report it as a result rather than inventing prose. The pairing is unchanged; failure is what tells the model the
call did not succeed, and content stays whatever the tool produced.
{
"type": "toolResult",
"result": {
"id": "toolu_01A",
"name": "getWeather",
"content": "upstream timed out",
"failure": { "success": false, "code": 504, "message": "The weather service did not answer." }
}
}Forcing or forbidding a call
parameters.toolUse decides whether the model may call, must call, or must not.
| Value | Meaning |
|---|---|
{ "type": "auto" } |
The model decides. The default. |
{ "type": "none" } |
The model may not call a tool, even though tools are declared. |
{ "type": "any" } |
The model must call one of the declared tools. |
{ "type": "use", "toolCall": { … } } |
The model must call the named tool and no other. toolCall is a full tool declaration, not just a name. |
Structured output
To hold the answer to a JSON Schema instead, send responseSchema. See
structured output.
Files returned by tools
A tool result can carry files in result.documents; the same file-source and processing rules apply as to files on
a user message. See files and file processing for the public source shape, native model
capabilities, none, auto, directed, and the named processor catalog.