Bad tools = bad agents, no matter how strong the model. Tool design is where most agent quality is won or lost.
What makes a good tool
1. Single responsibility
One tool does one thing. get_weather(city) not get_weather_or_news_or_stocks(query, type). Models reliably select tools when each tool's purpose is clear.
2. Self-explanatory schema
{
"name": "search_documents",
"description": "Search the knowledge base for documents relevant to a query. Returns top-k results with title, snippet, and url.",
"parameters": {
"query": { "type": "string", "description": "Natural-language search query" },
"k": { "type": "integer", "default": 5, "minimum": 1, "maximum": 20 }
}
}
- Description is in second person and describes when to use it, not just what it does.
- Parameter descriptions explain semantics, not just types.
- Defaults and bounds prevent obvious errors.
3. Useful error messages
On failure, return structured errors the model can recover from:
{ "error": "INVALID_DATE", "message": "date must be YYYY-MM-DD; got 'last Tuesday'", "hint": "Use parse_date tool to resolve relative dates first" }
The model reads error messages — they're prompt input. Good errors enable self-correction.
4. Idempotent where possible
A retried tool call shouldn't double-charge. Where idempotency isn't natural, return a deterministic id the agent can check.
5. Output formatted for LLM consumption
- Markdown table > JSON array of objects for tabular data the agent needs to read.
- Truncate large results with a clear marker:
... 47 more results omitted .... - Strip noise: don't return raw HTML when you can return clean text.
6. Right-sized
- Too granular:
get_user_email,get_user_phone,get_user_address→ too many tool calls. - Too coarse:
do_anything_with_user→ ambiguous. - Right:
get_user_profile(user_id, fields=[...]).
Common bad-tool failures
- Tools that lie. Return success on logical failure. Bug compounds quickly.
- Tools with stateful gotchas. "Call
initfirst" — model forgets, fails. Make stateless or auto-init. - Tools that timeout silently. Return a clear timeout error or upstream-failure signal.
- Schema drift. Tool changes shape, agent prompts not updated, model hallucinates old args.
Eval tools, not just agents
- Tool-call accuracy: of N expected tool calls, how many did the agent make?
- Argument-shape accuracy: correct field names, types, semantics.
- Recovery rate: when a tool errors, does the agent recover?
LangSmith + your own trajectory eval makes this measurable.