Tool Calling: How to Design Tools an Agent Uses Correctly

Building agents 9 min read

A hand connecting a labelled plug into a socket on a patch panel
A tool is a socket with a shape. Make the shape wrong-proof and the agent stops guessing.

When an agent behaves badly, the instinct is to rewrite the prompt. In our experience the prompt is the cause perhaps a third of the time; the rest of the time the tools were designed for a program, not for a reader who has to infer from names and descriptions what a function does.

Tools are the agent\u2019s entire ability to affect the world, and their definitions are literally part of the model\u2019s context. Designing them well is cheaper and far more durable than prompt tuning, because a good tool constrains behaviour instead of requesting it.

Seven rules that prevent most bad calls#

  1. One tool, one job. `search_orders` and `refund_order` beat a single `manage_order` with a mode argument.
  2. Types over prose. Enums, integer ranges and formats do work a description never will.
  3. Names that say what happens. `send_email_to_customer` is unambiguous in a way `notify` is not.
  4. Errors as instructions: state what was wrong and what to do next, in one short sentence.
  5. Empty results are results. Returning an explicit no-match beats an exception the model treats as retryable.
  6. Idempotency keys on anything with a side effect, so a retry cannot duplicate it.
  7. Small returns. Trim payloads to the fields the agent needs; a 40 KB JSON blob buys confusion, not context.

Before and after#

Tool Calling: How to Design Tools an Agent Uses Correctly — Before and after
Weak designWhy it failsBetter
`query(sql)`Unbounded power, unauditable`get_orders_by_customer(customer_id, limit)`
`date: string`Model invents formats`date: string, format YYYY-MM-DD`
`HTTP 500`No action implied, retried forever`Order service unavailable. Tell the user to try later.`
Returns full recordFills context, dilutes attentionReturns six named fields
`update_status(id, status)`Any status, any record`cancel_order(id)` with permission check

Descriptions are prompt, so write them like prompt#

The description field is not documentation for your colleagues; it is text the model reads while deciding. Say when to use the tool and when not to, name the one precondition that matters, and give one example argument. Three sentences beats three paragraphs — long descriptions crowd out the rest of the context and rarely change behaviour. And review them together, in one file: tools that make sense individually often overlap in ways that only become visible when they are read as a set.

If two tools could plausibly answer the same request, the agent will sometimes pick the wrong one. Either merge them or make the boundary explicit in both descriptions.

Validate before you execute, always#

Never pass model output to a system call unchecked. Validate the arguments against the schema, resolve identifiers against records the current end user is allowed to see, and reject anything that does not match rather than coercing it into something plausible. A rejection with a clear message is a good outcome: the agent learns the constraint and tries something else within the same run. A silent coercion is how an agent updates the wrong record and nobody finds out until the report looks strange.

Test tools separately from the agent#

Give each tool its own tests: valid call, invalid arguments, permission denied, empty result, upstream timeout. Then test the agent against a stub tool layer so you can force those conditions deliberately. Almost every production incident we have reviewed reproduces trivially at this level once someone thinks to try — the empty-result case in particular, which is rare in development and routine on a real Tuesday afternoon.

Frequently asked questions

How many tools is too many?

Beyond roughly ten in one loop, selection accuracy starts to fall and descriptions crowd the context. If you need more, group them behind a narrow router or split into specialised agents with small tool sets each.

Should tools return raw API responses?

No. Return a small, stable shape with the fields the agent actually needs. Raw responses waste context, expose fields the agent may misuse, and couple your prompt behaviour to somebody else’s API version.

How do I stop the agent inventing arguments?

Constrain them: enums instead of free strings, explicit formats, and identifiers that must resolve against real records. Then validate and return a clear rejection. Invented arguments are usually a sign the tool asked for something the agent had no way to know.

tool callingfunction calling agentsagent tool designjson schema toolsllm tool errors

All guides

Last updated 2026-08-04 by aiagentdevelopment.info · About us

Written by builders

Every guide is written by engineers who run agents in production, not spun from other sites.

Reviewed on a schedule

This field moves fast. Each guide carries the date of its last review, and we publish the date even when nothing changed.

No paid placements

No model provider, framework or agent platform can buy a mention, a ranking or a link here.

Twelve languages

Every guide is translated, not machine-popped — each language has its own URL and its own review date.

Limits named

We say plainly when a task does not need an agent and a plain script would be cheaper and more reliable.