Home / The Claude API for builders
Tools: Claude proposes, the code decides
A tool is declared with a schema named input_schema; Claude never executes it itself, it returns a usage request that the code executes before returning the result so the conversation can continue.
Claude never executes a tool itself. It returns a usage request, the developer's code actually executes it, then returns the result so the conversation can continue. This cycle rests on a single contract: the schema declared by the input_schema field.
Declaring a tool
A tool is declared with three top-level fields: name, description and input_schema, the latter describing the expected shape of the arguments. A fourth field, strict, sits alongside the first three and not on tool choice: set to true, it guarantees that the call Claude produces matches the declared schema exactly, provided that schema also carries additionalProperties set to false alongside required, the form the official documentation uses in all its examples.
// Declaring a tool, with strict schema validation
{
"name": "verifier_stock",
"description": "Renvoie la quantité disponible pour une référence produit.",
"input_schema": {
"type": "object",
"properties": {
"reference": { "type": "string" }
},
"required": ["reference"],
"additionalProperties": false
},
"strict": true
}
The full cycle, from request to result
When Claude chooses to use a tool, it returns a stop_reason of value tool_use, accompanied by one or more tool_use blocks carrying the chosen arguments. The code then executes the actual call described by that block, then returns the result in a tool_result block, placed inside a message with user role. When several tools are requested in the same turn, which happens by default since parallel calls are active, all their tool_result blocks come back together in that one message.
// Usage request returned by Claude
{
"stop_reason": "tool_use",
"content": [
{ "type": "tool_use", "id": "toolu_01", "name": "verifier_stock",
"input": { "reference": "REF-042" } }
]
}
// Result returned by the code in the next turn
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 unités disponibles" }
]
}
The tool_choice field controls which tool Claude can pick: auto by default leaves Claude to decide, any forces the use of a tool without imposing its name, tool imposes one specific tool, and none stops it from using any. Choosing none with no tool declared adds no extra system tokens to the request. The tool_result block returned here follows the same message structure as the basic request, with a messages array that keeps alternating roles.
The cycle of a tool, from declaration to result
A developer declares a tool named verifier_stock whose input_schema requires the reference field to be a string. Claude returns a tool_use block whose reference field is 42, an integer.
Write, in one sentence, what this situation establishes, and in one sentence what it does not establish.
What this establishes: This establishes that Claude produced a call whose argument does not match the type declared in the schema, a string expected against a number received.
What this does not establish: This does not establish whether adding the strict field set to true to this same declaration would have prevented this call from coming out in this form, since this field was not activated in this situation.
The three most common miscalibrations
- Too broad This situation proves that Claude always produces arguments that do not match the type declared in a schema.
- Too narrow This situation proves nothing since only one call was observed on a single tool.
- Off target This situation shows that the name verifier_stock describes a read-only lookup rather than a stock change.
- A tool is declared with a schema named input_schema, alongside name and description, never by a function executed server side.
- Claude returns a stop_reason of value tool_use accompanied by one or more tool_use blocks: it is a request, never an actual execution.
- The tool_choice field accepts four values, auto by default, any, tool and none, and choosing none with no tool declared adds no extra system tokens.
- The strict field set to true sits on the tool's definition, not on tool_choice, to guarantee that the call matches the declared schema exactly.
- Parallel tool calls are active by default: all the tool_result blocks from a single turn come back in one user message.
Open an empty file and write the JSON declaration of a tool for a real action in your own project, with its name, its description and its complete input_schema. Add the strict field set to true, then re-read the schema alone, outside the context of your project, and check that it is enough to guess which call Claude should produce.
Every datable claim in this lesson links here to the public text behind it. A source that does not open proves nothing.
- Anthropic, tool use, overview consultée le 2026-09-02
- Anthropic, strict tool use consultée le 2026-09-02