Skip to content
Mastering Claude

Home / The Claude API for builders

The Claude API for builders7 minApplication

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.

Figure 1

The cycle of a tool, from declaration to result

01
Declaration
The code declares the tool with an input_schema, its name and its description.
02
Usage request
Claude responds with stop_reason tool_use and a tool_use block carrying the chosen arguments.
03
Local execution
The code executes the actual call described by the tool_use block, outside Claude.
04
Result returned
The result goes into a tool_result block, inside the following user message.
05
Conversation resumed
Claude resumes the conversation with this result now available.
The figure shows the five steps of a tool's cycle: schema declaration, usage request returned by Claude, local execution, result returned, conversation resumed.
Calibrate it yourself

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 to remember
  • 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.
Do this now

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.

Check the source

Every datable claim in this lesson links here to the public text behind it. A source that does not open proves nothing.