Tool Use — tools for agents
A good agent is only as good as the tools you gave it. How to design tools the model understands, calls correctly, and doesn't break. The practical guide.
In the Structured Outputs & Tool Use guide we saw the basic mechanics of function calling. Here we go deeper into design — how to build tools an AI agent can actually use successfully, which is the art that separates an agent that works from one that gets stuck.
The agent loop — a reminder
An agent runs in a loop: the model gets a goal + a list of tools, decides which to call, the code runs them and returns results, and repeats until the task is done.
while not done:
response = model.generate(messages, tools=TOOLS)
if response.tool_calls:
for call in response.tool_calls:
result = run_tool(call.name, call.input) # your code runs it
messages.append(tool_result(call.id, result))
else:
done = True # the model finished and returned a final answer
The tools are the model's "hands." If they're poorly designed — the agent will choose wrong, send wrong parameters, or get into loops.
Designing a good tool — 6 principles
- Clear name and description. The description is the tool's "prompt."
get_order_statuswith the description "returns an order's status by order number" is far better thanlookupwith no explanation. Write when to use it and when not to. - Few, well-defined parameters. Each parameter with a description, a type and an enum where possible. Fewer parameters = fewer errors.
- One tool = one task. Don't build a mega-tool that does ten things by a flag. Split into focused tools.
- Concise results. Return only what the model needs. Don't return 5,000 lines of JSON — filter/summarize (see Context Engineering).
- Limit the number of tools. Too many tools confuse it. If there are many, group by context or use dynamic retrieval.
- Consistent naming. The same convention for all tools — it's easy for the model to learn the pattern.
Most "agent failures" are actually tool-design failures — a vague description or a bloated result. Improve the tools before you blame the model.
Error handling — don't let a tool crash the agent
A tool that fails should return a clear error message to the model, not crash. The model can read the error and try differently:
def run_tool(name, args):
try:
return TOOLS[name](**args)
except Exception as e:
# return the error to the model as a result, don't raise
return {"error": str(e), "hint": "check the parameters and try again"}
- Validation errors: if a parameter is invalid, tell the model exactly what's wrong.
- Limit attempts. If the agent fails the same tool 3 times — stop and escalate, don't enter an infinite loop.
- Timeouts: a slow tool (an external API) needs a timeout so it doesn't hang the agent.
Human-in-the-loop — for dangerous tools
Not every action should run automatically. Tools that perform an irreversible action (sending an email to a customer, making a payment, deleting data) need human approval before running. Design the flow so the agent proposes the action, and a human approves.
- Mark "sensitive" tools that require approval.
- Show the user exactly what's about to happen (which tool, which parameters).
- Only after approval — run it.
Orchestrating multiple tools
When a task requires a sequence of tools (search → filter → act), the model manages the order. For this to work:
- Descriptions that hint at a sequence ("use search_products before add_to_cart").
- Return identifiers the model can pass to the next tool (e.g.
order_id). - Sub-agents for complex tasks — a sub-agent with its own set of tools and a clean context.
- For connecting external tools in a standard way — MCP.
Security — tools are an attack surface
A tool gives the model the ability to act in the real world — and that's dangerous if the model is "influenced" by prompt injection:
- Least privilege. Each tool gets only the access it truly needs.
- Validation on the tool side. Don't trust the parameters the model sent — validate them (e.g. that the user is allowed to access this order_id).
- Sandboxing for tools that run code.
- Human approval for risky actions, as above.
- See AI agent security for a deeper dive.
Next step
Build a full agent, connect tools in a standard way with MCP, and secure it.