Tools & Tool Calling
A tool is an external capability the model can invoke: a database query, an API call, a search index, a calculator, a file write. Tool calling is the mechanism by which the model decides one is needed and requests it.
This is the step that turns a model from something that generates text into something that takes action, and it is where most of the engineering effort in an AI system actually goes.
The Loop
The model never executes anything itself. It returns a structured request, your code runs it, and the result goes back into the context for the next turn.
Three consequences follow from the model not being the executor:
- Every permission check is yours. The model requests; your code decides whether that request is allowed, for this user, right now.
- Every loop is yours to bound. Nothing stops a model requesting the same tool indefinitely except an iteration cap in your code.
- Every tool result is untrusted context. A result containing text that looks like an instruction will be read as one. See Guardrails & Safety.
Defining a Tool
The model chooses tools based only on the name, description, and parameter schema you supply. A tool it uses incorrectly is nearly always a description problem, not a reasoning problem.
{
"name": "get_invoice_status",
"description": "Look up the current approval status of a single invoice by its invoice number. Use this when the user asks whether a specific invoice has been paid or approved. Does not search by supplier or date - use search_invoices for that.",
"input_schema": {
"type": "object",
"properties": {
"invoice_number": {
"type": "string",
"description": "The invoice number exactly as printed, for example INV-2026-0041"
}
},
"required": ["invoice_number"]
}
}
What makes that description work:
- It says when to use the tool, not just what it does.
- It says what the tool does not do, and names the alternative. Negative boundaries prevent the most common misfires.
- Each parameter carries a format example, so the model does not guess at a convention.
Design Rules
| Rule | Why |
|---|---|
| Few, well-named tools over many overlapping ones | Selection accuracy falls as the tool list grows and descriptions start to overlap |
| One job per tool | A tool that reads and writes cannot be granted read-only permission |
| Return structured, trimmed results | Raw API payloads waste context and bury the useful field |
| Return errors as descriptions, not exceptions | "Invoice not found" lets the model recover; a stack trace does not |
| Make writes idempotent | A retried tool call must not post the transaction twice |
| Separate read tools from write tools by permission | Read tools can run automatically; write tools go behind an approval gate |
Every registered tool also costs context on every call, since its definition sits in the prompt whether it is used or not. Twenty tools is a context and accuracy problem before it is a capability win. Route to a smaller tool subset per task instead.
Failure Modes
| Failure | Cause | Mitigation |
|---|---|---|
| Wrong tool selected | Overlapping or vague descriptions | Sharpen descriptions, state the boundaries, reduce the tool count |
| Hallucinated arguments | No format example, or no null path | Add examples to the parameter schema, allow an explicit "unknown" |
| Loop that never terminates | Tool keeps failing, model keeps retrying | Hard iteration cap, plus a token budget per request |
| Silent wrong answer after a tool error | Error returned as an empty result | Return an explicit error string the model can reason about |
| Destructive action taken unprompted | Write tool available with no gate | Human-in-the-loop approval on write tools. See Autonomous AI |
Where MCP Fits
Tool calling is the model-side mechanism. The Model Context Protocol is the integration standard around it: instead of writing bespoke glue for every system, a system exposes an MCP server and any MCP-aware client can use its tools.
The trade is standardisation against control. An MCP server built by someone else defines its own tool descriptions and return payloads, which are exactly the things that determine whether the model uses a tool correctly. Review them as you would review a dependency. See MCP for the protocol detail.
Key Takeaways
- The model requests tool calls; your code executes them. Authorisation, validation, and loop bounds are all your responsibility.
- Tool descriptions are the model's only selection signal. Say when to use it and what it does not cover.
- Prefer few sharp tools to many overlapping ones. Every definition costs context on every call.
- Return trimmed, structured results and descriptive errors, so the model can recover rather than guess.
- Split read tools from write tools and gate the writes. Make every write idempotent.
- Tool results are untrusted input, same as user text.