When an AI agent misbehaves, the instinct is to blame the model or rewrite the system prompt. In practice, a large share of agent failures trace back to something more mundane: the tools were designed for humans reading documentation, not for a model choosing under uncertainty from a list of descriptions.
Tool design is the most underrated lever in agent reliability. Clear names, non-overlapping scopes, honest schemas and instructive errors will do more for your success rate than another round of prompt tweaking. This guide sets out how to design tools for AI agents that get called correctly, in the right order, with valid arguments.
An agent does not inspect your implementation. At decision time it sees a list of tool names, natural-language descriptions, and parameter schemas. From that text alone it must decide whether to act, which tool to use, and what arguments to supply.
This reframes the problem. Your tool definition is a prompt. Every omission in a description is a gap the model fills by guessing, and every overlap between two tools is a coin flip. Treating these definitions as throwaway metadata is the root cause of most flaky agents.
Wrapping an existing REST API endpoint by endpoint feels efficient and usually is not. If booking an appointment requires the agent to call four endpoints in sequence, each step is an opportunity to fail, and the failure modes compound.
A better unit is the task. A single schedule_appointment tool that internally checks availability, reserves the slot, creates the record and sends a confirmation gives the model one decision to make instead of four. The orchestration logic lives in your code, where it is testable and deterministic.
Use low-level tools when the agent genuinely needs flexible composition, and task-level tools when the workflow is known. Most business automations fall in the second category, so getting the granularity right usually matters more than the overall agent architecture.
A description should answer three questions: what the tool does, when to use it, and when not to. The third is the one teams skip, and it is frequently the most valuable.
Compare a description that reads "searches orders" with one that reads "Search historical orders by customer email or order number. Use this for questions about past purchases. Do not use this to check the status of an in-flight delivery, which requires the delivery tracking tool." The second eliminates an entire class of wrong calls.
Practical rules for naming and describing:
Loose schemas invite invalid arguments. Every parameter should carry the strongest constraint that is true.
Structured outputs help on the way back as well. Returning predictable shapes rather than prose makes downstream steps far easier to chain, which is covered in our guide to reliable structured outputs from LLMs.
Tool output is context, and context is finite. Dumping a thousand-row result into the conversation wastes budget and buries the useful detail.
Return the fields the agent needs for the next decision, in a compact readable form. If a result set is large, return a summary plus a count and a way to narrow the query. Include the identifiers needed for follow-up calls so the agent is not forced to re-search.
Errors deserve particular attention. An instructive error is a recovery instruction: say that the appointment time is outside business hours and list the available windows, rather than returning a validation failure with no guidance. Models follow that kind of correction reliably.
Consider an illustrative scenario. A clinic deploys an agent to handle appointment requests over chat. The first version wraps six existing API endpoints: list doctors, get doctor availability, get patient record, create booking, send confirmation and cancel booking.
In testing, the agent regularly asks patients for an internal doctor identifier it has no way to know, occasionally creates a booking without sending confirmation because it stops one step early, and returns raw validation errors when a requested slot has just been taken.
The team redesigns around three task-shaped tools. find_available_slots accepts a speciality in plain language, a date range and an optional doctor name, and returns a short list of human-readable options with opaque slot tokens. book_slot takes a slot token and patient details, and performs reservation, record creation and confirmation as one atomic operation. cancel_booking takes a booking reference and enforces the cancellation policy in code.
Three things improve at once. The model has fewer decisions to get right, it never handles internal identifiers, and partial completion becomes impossible because the multi-step work is atomic inside the tool. Where a request falls outside policy, the tool refuses and explains why, and anything involving money routes through an approval step of the kind described in our article on human-in-the-loop approval workflows.
Agent quality is usually discussed in terms of final answers, but the useful diagnostic signal sits one level down. Build a small evaluation set of realistic requests, each labelled with the tool you expect to be called and the arguments you expect to see. Then measure four things separately.
Separating these matters because the fixes are completely different. A single "accuracy" number tells you something is wrong without telling you where, and teams then default to prompt changes because that is the easiest lever to pull, even when the real defect is a parameter with no stated format.
Every tool definition occupies context and adds a candidate to every selection decision. Beyond roughly a dozen tools, selection accuracy tends to degrade, and the cost of each call rises because the definitions are resent with every turn.
Two techniques keep the list manageable. First, scope by role: a support agent gets support tools, a finance agent gets finance tools, and a router decides which one handles the request. Second, scope by state: expose tools conditionally based on where the conversation is, so a cancellation tool only appears once there is a booking to cancel. Both reduce the number of ways the model can go wrong without reducing what the overall system can do.
Any agent that reads external content, such as emails, documents or web pages, can be exposed to instructions planted in that content. The defence cannot live in the prompt, because the prompt is exactly what an injection attacks. It has to live in the tools.
That means scoping each tool to the minimum permission required, enforcing per-user authorisation inside the tool, capping values for financial actions, requiring explicit confirmation for destructive operations, and logging every call with its arguments and outcome. Our guide to prompt injection defence for AI agents covers the threat model in depth.
If an agent keeps choosing the wrong tool, the model is usually reading your descriptions correctly. The descriptions are the problem.
Tool design is where agent reliability is won or lost. Shape tools around complete tasks rather than endpoints, write descriptions that make selection unambiguous, constrain parameters so invalid calls are impossible, return compact and useful results, and make errors instructive. Then enforce every safety rule in code, because the prompt cannot be trusted to hold a boundary.
If you are building an agent that needs to act on real business systems safely, explore our AI development services or tell us about the workflow you want automated through our contact page.