Each post in this series will dissect one specific Claude Code tool. But first, we need a shared foundation: What is a tool, and how does Claude use one? Every later deep dive builds on this mechanism.
Why Tools Exist
An LLM, by itself, can only generate text. That creates two fundamental limitations:
- It cannot act on the outside world. Generating the sentence “I deleted the file” does not actually delete anything.
- Its output is not inherently reliable. A model may return malformed structures, omit fields, or hallucinate content, making the result unsafe for downstream programs to consume.
Tools fill both gaps:
- Actions — a tool declares an executable function. When the model calls it, the harness performs the real operation: reading a file, sending a request, switching modes, and so on.
- Structure — a JSON Schema defines the input. The model must produce arguments that conform to that schema; invalid input can be rejected before execution.
From this perspective, a tool does not simply “make the LLM more powerful.” It creates a trusted channel between the LLM and the outside world.
What a Tool Definition Looks Like
In the Anthropic API, a tool definition is a JSON object. Here is a simplified version of AskUserQuestion:
{
"name": "AskUserQuestion",
"description": "Use this tool only when you are blocked on a decision that is genuinely the user's to make: one you cannot resolve from the request, the code, or sensible defaults. ...",
"input_schema": {
"type": "object",
"properties": {
"questions": {
"type": "array",
"description": "Questions to ask the user (1-4 questions)",
"minItems": 1,
"maxItems": 4,
"items": {
"type": "object",
"properties": {
"question": {
"type": "string",
"description": "The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: \"Which library should we use for date formatting?\""
},
"header": {
"type": "string",
"maxLength": 12,
"description": "Very short label displayed as a chip/tag (max 12 chars). Examples: \"Auth method\", \"Library\", \"Approach\"."
},
"multiSelect": {
"type": "boolean",
"default": false,
"description": "Set to true to allow the user to select multiple options ..."
},
"options": {
"type": "array",
"minItems": 2,
"maxItems": 4,
"items": { "...": "..." }
}
},
"required": ["question", "header", "options"]
}
}
},
"required": ["questions"]
}
}
There are three top-level fields:
-
name— the tool's unique identifier and a naming signal the model can interpret -
description— natural-language guidance explaining what the tool does, when to use it, and when not to use it -
input_schema— a JSON Schema defining the argument structure, field-level descriptions, and validation rules
That is the entire tool definition. There is no hidden configuration inside the definition itself. Every design intention must be encoded in these three fields.
The Four Layers of a Tool Definition
Later posts will analyze each tool through four layers. These layers are simply an expanded view of the three top-level fields:
| Layer | Location | Purpose |
|---|---|---|
| 1. Naming |
name and field names inside the schema |
Communicates meaning through names |
| 2. Tool-level description | description |
Helps the model decide, “Is this the tool I should use?” |
| 3. Field-level descriptions | Each field's description inside input_schema
|
Tells the model what belongs in each field |
| 4. Schema validation |
type, minItems, maxLength, enum, and so on |
Hard-blocks invalid input |
The signal density decreases while coverage increases:
- Naming — understood from a single word and reinforced every time the model encounters the field
- Tool description — available whenever the model considers using the tool; defines the broad behavioral boundary
- Field description — becomes most relevant while the model is filling that field; provides a precise hint
- Schema validation — becomes visible when the model gets something wrong; acts as a hard guardrail
Together, these four layers form the complete prompting surface of a tool definition.
How Claude “Reads” Tool Definitions
The important point is that the available tool definitions are sent with the model request, rather than appearing only after a tool has been selected.
The flow looks roughly like this:
- The harness collects all available tool definitions.
- On each request to Claude, it includes the tool list in the API's
toolsparameter. - Claude receives the system instructions, the available tool definitions, and the conversation history as part of the request context.
This has two direct consequences:
- Every word in a description costs tokens. If your tool definitions total 20 KB, that payload must be processed across requests, and the cost compounds over a long conversation.
-
A tool description can reference neighboring tools. Because the model sees the available definitions together,
AskUserQuestioncan say, for example, “Do not use this to ask whether the plan is OK; that isExitPlanMode's responsibility.”
That is why a good tool description must be both short and precise. Short saves tokens; precise ensures that every sentence defines a responsibility, boundary, or collaboration contract.
How Claude Calls a Tool
A tool call is a message round trip.
Step 1: The Model Emits a tool_use Block
When Claude decides to use a tool, it does not execute the tool directly. Instead, it emits a special block in its response:
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "AskUserQuestion",
"input": {
"questions": [
{
"question": "Which authentication method should we use?",
"header": "Auth method",
"options": [
{
"label": "JWT (Recommended)",
"description": "Stateless and easy to scale horizontally"
},
{
"label": "Session cookie",
"description": "Uses a server-side session store"
},
{
"label": "OAuth",
"description": "Connects to a third-party identity provider"
}
]
}
]
}
}
Step 2: The Harness Intercepts and Executes It
The harness intercepts the model's output, finds the implementation associated with name, and passes it the input. That implementation might be a local function, an external service, or a UI interaction.
Step 3: The Harness Returns a tool_result
After execution, the harness sends the result back to the model:
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "The user selected: JWT (Recommended)"
}
This block is included in the next message sent to Claude. Claude then continues: it may call another tool based on the result, or it may respond to the user in plain text.
Throughout the process, the model is the decision-maker. It decides when to call a tool, which tool to call, what arguments to pass, and how to use the result. The harness is responsible for execution and for carrying messages between the model and the tool implementation.
Two Tool-Result Modes
Success
A successful tool_result carries content:
{
"type": "tool_result",
"tool_use_id": "...",
"content": "..."
}
The content may be plain text or structured content blocks, such as multiple text segments and images.
Failure
A failed result adds is_error: true:
{
"type": "tool_result",
"tool_use_id": "...",
"content": "Error: file not found",
"is_error": true
}
This is a loud failure: the error is not silently swallowed. The model can see the failure and decide what to do next—retry, choose a different approach, or ask the user.
This is also why strict schema validation matters. A harness can reject invalid input explicitly instead of allowing the model to continue with an empty or semantically ambiguous result.
Tool Results Consume Context Too
Every tool_result returned to the model becomes part of the conversation context. That means result size must be controlled:
- A
grepresult containing 100,000 lines can exhaust the context window almost instantly. - Good tools summarize, truncate, or paginate their output before returning it.
- A read tool might default to a fixed number of lines; a search tool might expose a result limit.
This explains why many of Claude Code's read-oriented tools return deliberately compact results. It is not a lack of capability; it is intentional context-budget management.
Tools Are Structured Prompt Engineering
Compare two approaches.
Free-form prompt version:
You can call a function named AskUserQuestion to ask the user a question. After the user chooses, you will receive the answer.
Tool version:
-
name=AskUserQuestion -
description= detailed behavioral constraints -
input_schema= exact field types, validation rules, and examples
The difference is not whether the function can be implemented. The difference is whether it can behave reliably:
| Dimension | Free-form prompt | Tool |
|---|---|---|
| Structure | The model improvises | JSON Schema provides hard constraints |
| Failure | Malformed output may fail silently or produce a bad value | Schema validation rejects it explicitly |
| Boundaries | The model decides based on intuition | The description states when to use and not use it |
| Composition | The model must remember how several functions relate | Tool descriptions can reference neighboring tools directly |
| Main-loop visibility | Results are mixed into conversational text | Structured tool_use and tool_result blocks can be intercepted by the harness |
A tool is, fundamentally, structured prompt engineering. It turns the soft requirement “make the model do this reliably” into a specification that is validatable, composable, and maintainable.
What Comes Next
With the mechanism established, every later post in this series will use the same outline to dissect one concrete tool:
- Purpose
- A concrete example, including a counterexample
- Trigger conditions
- Technical implementation across four layers
- Naming
- Tool-level description
- Field-level descriptions
- Schema validation rules
- Division of responsibility with neighboring tools
- Takeaway
This prelude explains the mechanism: what tools are and how Claude uses them. The rest of the series focuses on design: how a specific tool uses all four layers to turn a capability from merely “possible” into something stable, predictable, and composable.
Next: AskUserQuestion—how Claude Code turns “AI asking a question” into a structured interaction primitive.
Top comments (0)