How to Design Tools Your AI Agent Can Actually Use
When an agent misbehaves, the tools are usually the problem, not the model. Six rules for tool names, descriptions, schemas, results, and permissions that make a capable model a reliable system.
Here's a truth that surprises people building their first agent: the model is rarely the problem. When an agent misbehaves — calls the wrong function, passes garbage arguments, ignores a capability it clearly has — the cause is almost always the tools, not the intelligence driving them. As the saying goes in agent engineering: capability and reliability are not the same thing. The model can be brilliant and your system can still be fragile.
Tools are the interface between a smart model and the real world, and designing them well is a distinct skill. Here's what separates tools an agent uses flawlessly from tools that make even a capable model look incompetent.
A tool is a contract the model reads
Every tool you give an agent has two audiences. Your code executes it — but the model decides when to call it and what to pass, and it makes that decision by reading the tool's name, description, and parameter schema. That metadata isn't documentation for humans; it's part of the prompt. Treat it that way and most tool problems disappear.
1. Name tools so their purpose is obvious
The single fastest way to confuse an agent is to give it several tools whose names don't clearly divide the territory. Picture an agent holding get_customer, lookup_user, find_account, and search_profile. What's the difference? You might know the architectural history behind each; the model doesn't. It's forced to guess which one you meant, and it will guess wrong often enough to matter.
Name tools for what they do, from the model's point of view, with no overlap. If two tools could plausibly handle the same request, either the names are unclear or you have one tool too many.
2. Write descriptions that say when, what, and when-not
A good tool description answers three questions:
- When to use this tool — the situation it's for.
- What it returns — so the model knows what it'll get back and can plan the next step.
- What it should not be used for — the boundary that prevents misfires.
That last one is the most overlooked and the most valuable. Explicitly telling the model use this for X, not for Y
prevents the tool from being reached for in the wrong situation far better than hoping the model infers the boundary.
3. Don't expose every backend function
The tempting shortcut is to auto-generate a tool for every function in your API. Resist it. A common failure mode is dumping dozens of overlapping tools on the model, which creates exactly the guess-which-one confusion above and burns context on definitions the agent rarely needs. Curate. Expose a tight set of well-named tools that map to things the agent actually needs to do — not your entire internal surface area. Fewer, clearer tools beat comprehensive coverage.
4. Keep schemas tight and typed
The arguments the model passes are structured data, and loose schemas invite malformed calls. Every constraint you encode is a mistake the model can't make:
- Prefer enums over free-form strings, so the model picks from valid options instead of inventing one.
- Mark required fields required; use clear, descriptive parameter names.
- Enforce the shape with strict validation so the model's arguments are guaranteed to match your schema before your code ever runs. This removes a whole category of silent failures — see Getting Reliable Structured Output, which covers the same strict-schema mechanism applied to tool arguments.
5. Return results the model can actually use
Tool output flows straight back into the model's context and becomes the basis for its next decision. Two failure modes here:
- Returning too much. A tool that dumps 5,000 lines of raw data drowns the model's reasoning and blows your context budget. Return the relevant slice, summarized if needed. (This is a core context engineering concern.)
- Returning too little, or cryptically. An opaque error code or a bare
nullgives the model nothing to act on. Return results — and especially errors — in a form the model can understand and recover from.No customer found with that ID; try searching by email
is a result an agent can work with;Error 404is not.
6. Build in permissions and approvals
Tools are where an agent touches the real world, so they're also where safety lives. Two practices are non-negotiable for anything beyond a toy:
- Least privilege per tool. A common, dangerous misconfiguration is giving the agent the same broad permissions as the account that launched it, when it only needs a sliver. Scope each tool to exactly what it requires; separate read access from write access.
- Explicit confirmation for high-risk actions. Anything irreversible or consequential — sending, deleting, paying, publishing — should route through a human approval step rather than firing autonomously. A well-placed
save as draft for review
gets you the agent's leverage without handing over the irreversible decisions.
The takeaway
Designing tools for an agent is prompt engineering wearing a different hat. The name, description, and schema are instructions the model reads to decide how to act — so make them clear, bounded, and tightly typed. Curate a small set of well-named tools instead of exposing everything. Return results the model can reason about, including graceful errors. And put permissions and approvals where the agent meets the real world. Do this, and a capable model becomes a reliable system; skip it, and you'll blame the model for failures your tools created.
This is a core part of building agents that work. Once your tools are solid, the way you know they're solid is by measuring — see How to Write Evals for Your AI Agent. And if you'd rather connect to standardized, ready-made tools than hand-build each one, that's what MCP is for. Prompts to build with are in the prompt library.