Designing tools an agent can call correctly
Most agent failures are not reasoning failures. They are interface failures — a tool whose name is ambiguous, whose arguments are guessable, or whose errors say nothing about what to do next.

Short answer
An agent chooses a tool from its name and description alone, so those are the interface. Give each tool one unambiguous job, make arguments impossible to guess wrongly by using enums and required fields, return errors that state what to do differently, and make retries safe — most bad calls are a naming problem, not a model problem.
On this page
- The description is the interface
- Make wrong arguments impossible rather than unlikely
- Errors are instructions
- Assume every call may happen twice
- Return what is needed, not what exists
- Confirmation belongs in the system, not the prompt
- Instrument the calls
- What are agent tools?
- Which failures come from the tool rather than the model?
- How many tools is too many?
- Where the schema does the work
When an agent calls the wrong tool or passes the wrong arguments, the instinct is to improve the prompt. Usually the prompt is not the problem. The tool definitions are, and they are code you control completely.
The description is the interface
A model picks a tool by reading its name and description. It cannot read your implementation, your tests, or the ticket that explains why the field is called that.
One job per tool. manage_user that creates, updates, suspends and deletes depending on a mode argument will be called with the wrong mode. Four tools with four names are chosen correctly far more often, because the choice happens where the model is strongest — matching intent to a name.
Name the job, not the resource. search_orders_by_customer beats orders. The verb and the qualifier are what disambiguate it from the other eleven tools.
*Say when not to use it. The most valuable sentence in most descriptions is the exclusion: Use for orders placed in the last 90 days. For older orders use search_order_archive.* Boundaries prevent more bad calls than capabilities do.
Describe the argument, not its type. The schema already says string. The description should say the format, the source and the constraint: the customer's account id, as returned by `find_customer` — not their email address.
Make wrong arguments impossible rather than unlikely
Every free-form string is a guess waiting to happen.
- Enums over strings. A
statusthat accepts four named values cannot receive"completed "or"COMPLETE". - Required over optional. An optional field with a hidden default is a field the model will omit and be surprised by. If the call needs it, require it.
- Reject ambiguity loudly. A tool that silently coerces a bad date into today's date produces a wrong answer that nobody can trace. Fail instead.
- Avoid arguments derivable from context. A
timezonethe caller must supply is atimezonethat will sometimes be wrong; take it from the session.
Errors are instructions
An error message is read by the model and acted on, which makes it part of the interface rather than a diagnostic.
Useless: 400 Bad Request.
Useful: `start_date` must be ISO 8601 (YYYY-MM-DD). Received "last Tuesday". Resolve relative dates before calling.
The second one gets a correct retry. The first gets the same call again, then a different tool, then an apology to the user. State what was wrong, what was expected, and what to do instead.
Assume every call may happen twice
Agents retry — on timeouts, on ambiguous results, on their own re-reading of the situation. Any tool with a side effect needs to survive that:
- Accept an idempotency key, and return the original result for a repeat.
- Prefer `set` to `increment` where you can express the operation either way.
- Make deletes idempotent — deleting something already gone is success, not an error.
- Return the resulting state, not just an acknowledgement, so a retry can be recognised as a duplicate rather than a change.
A tool that is dangerous to call twice is a tool that will eventually be called twice.
Return what is needed, not what exists
Two failures are equally common:
Too much. A tool returning the full record burns context and buries the field that mattered. Return the fields the task needs, and offer a second tool for detail.
Too little. A tool returning an id and nothing else forces another call, and the second call is another chance to go wrong. If the id is always followed by a lookup, return both.
For long results, paginate explicitly and say so in the response — showing 20 of 340; pass `cursor` for more — so the model knows the answer is partial rather than assuming it is complete.
Confirmation belongs in the system, not the prompt
Anything irreversible — sending, charging, deleting, publishing — should not be preventable only by an instruction. Instructions are advisory; the model is not obliged.
Put the constraint where it is enforced: a tool that returns a preview and a confirmation token, with the destructive action requiring that token. Then the guarantee is structural, and it holds regardless of how the conversation went.
Instrument the calls
Log the tool name, the arguments, the result, the latency, and whether the call succeeded — then look at the aggregate. Two patterns show up immediately and are worth acting on:
- A tool that is called and then immediately called again with different arguments. Its description is ambiguous.
- A tool that is never called. Either it is redundant or its name does not match how anyone describes the task.
Both are fixed by editing text, which is the cheapest fix available in this stack and the one people reach for last.
What are agent tools?
Agent tools are functions a model may call, described to it by a name, a short description and a typed argument schema. The model never sees the implementation — the description is the entire interface, which makes it a piece of product design rather than documentation.
That reframing is what the rest of this follows from. A tool a model calls wrongly is usually a tool that was named or described wrongly.
Which failures come from the tool rather than the model?
| Symptom | Usual cause | The fix |
|---|---|---|
| Wrong tool chosen | 2 tools with overlapping names | Name the job, add an exclusion sentence |
| Wrong arguments | Free-form string where a set of values exists | An enum, and a required field |
| Same call repeated | An error message with no instruction | State what was expected and what to do |
| Duplicate side effect | No idempotency key | Accept one, return the original result |
| Answer cut short | Silent pagination | Say "showing 20 of 340" in the response |
| Tool never used | Name does not match how anyone describes the task | Rename to the task, not the resource |
Every row in the right-hand column is an edit to text or a schema. None requires a better model, and none requires a longer prompt.
How many tools is too many?
The number matters less than the overlap. 30 tools with distinct jobs are chosen correctly more often than 8 that each do 4 things depending on a mode argument, because the choice happens where a model is strongest — matching an intent to a name.
The 3 habits that keep a tool set legible as it grows:
- One job per tool, with a verb in the name.
- An exclusion sentence in every description, saying when to use something else.
- A log of calls and outcomes, reviewed for the 2 patterns that indicate a naming problem — a tool called twice in a row with different arguments, and a tool never called at all.
More on the surrounding engineering in our AI development writing, the architecture trade-offs behind it, and the case studies where it went wrong first.
Where the schema does the work
Agent tools are described to a model as JSON Schema, and that schema is the cheapest place to prevent a bad call. An enum cannot receive a typo. A required field cannot be silently omitted. A documented format — the JSON Schema reference covers the ones worth using — turns a guess into a constraint.
The pattern across every agent tools problem is the same: move the correction earlier. A prompt asks the model to behave; a schema makes the misbehaviour unrepresentable; a confirmation token makes the dangerous action structurally impossible without a second step.
That ordering is the whole of the practice. Better agent tools beat better instructions, because instructions are advisory and interfaces are not.
Frequently asked questions
- Why split one tool into several?
- Because the model chooses by name, and matching intent to a name is what it does best. A single tool with a mode argument moves the decision into a parameter, where it is guessed rather than chosen.
- What makes a good error message for an agent?
- One that states what was wrong, what was expected, and what to do instead. The model reads it and retries, so a bare 400 produces the same call again while a specific message produces a correct one.
- How do I stop an agent doing something destructive?
- Structurally, not by instruction. Have the tool return a preview and a confirmation token, and require that token for the destructive call — then the guarantee holds regardless of the conversation.
- What should I log?
- Tool name, arguments, result, latency and success. Two aggregate patterns matter: a tool called twice in a row with different arguments has an ambiguous description, and a tool never called is redundant or misnamed.
Sources
- Model Context Protocol — Anthropic
- JSON Schema — JSON Schema
- Idempotent requests — IETF RFC 9110
Published by
Tecno Blocks
Engineering insights from Tecno Blocks covering web, mobile, AI, Web3, software architecture, product development, DevOps, and real-world case studies.
About the publication