| name | designing-agent-tools |
| description | Designs, builds, and iteratively improves tools for AI agents — covering schema design, descriptions, response formatting, MCP servers, programmatic tool calling (PTC), progressive disclosure, evaluation, and evolving tools with model capabilities. Triggers on "build a tool," "write a tool," "MCP tool," "agent tool," "tool for Claude," "tool design," "improve my tools," "tool evaluation," "tool description," "programmatic tool calling," "PTC," "tool composition," "reduce tool call tokens," "progressive disclosure," "too many tools," "my agent keeps calling the wrong tool," "agent can't use this tool," building MCP servers, Desktop extensions (DXT), or API tool definitions. |
| metadata | {"version":"3.1.0"} |
Designing Agent Tools
Expert guidance for building tools that AI agents use effectively.
Before Building
Gather this context (ask if not provided):
- Agent context — What agent uses these tools? What tasks? What other tools exist?
- Underlying resources — What APIs/databases/services do the tools wrap? Auth required?
- User workflows — What real-world prompts will users give? What multi-step workflows?
Core Principles
Build for Agent Affordances
Agents have limited context, process tokens sequentially, and reason in natural language:
- Don't build
list_all_X. Build search_X with filters.
- Return human-readable names, not opaque UUIDs.
- Every token in a response competes with reasoning space.
Fewer, Deeper Tools
Each tool added increases wrong-tool risk. Consolidate:
| Instead of | Build |
|---|
list_users + list_events + create_event | schedule_event (finds availability and schedules) |
read_logs | search_logs (returns relevant lines with context) |
get_customer_by_id + list_transactions + list_notes | get_customer_context (compiles all relevant info) |
Test: If an agent chains 3+ tools for a common task, merge them.
Make Invalid Calls Unrepresentable
Use enums, not strings. Name user_id, not user. Mark required params required.
Schema Design
Parameters:
- Name unambiguously:
user_id not user, channel_name not channel
- Use enums for constrained values
- Set sensible defaults for optional params
Descriptions — write as if briefing a new team member:
- Make implicit context explicit (query formats, terminology, resource relationships)
- Include 1-2 examples of valid inputs
- State what the tool does NOT do if boundary is non-obvious
For detailed description guidance: See references/tool-descriptions.md
Tool Use Examples — for tools with complex or nested parameters, supply structured input_examples (full example argument objects) alongside the schema. This raises accuracy on complex parameters from ~72% to ~90% by showing the model concrete, correctly shaped inputs rather than relying on the schema alone.
Response Design
High-signal only:
- Natural language names alongside any technical IDs
- Contextual relevance over raw completeness
Control size:
- Pagination with sensible defaults (10-25 items)
response_format enum: "concise" (content only) vs "detailed" (includes IDs, metadata)
- 25,000 token ceiling on responses
- Never silently truncate — append: "Showing 10 of 47. Use
offset or narrow query for more."
Errors must be actionable:
❌ "Error: Invalid parameter"
✅ "Error: `start_date` must be ISO 8601 (e.g., '2025-03-15T00:00:00Z'). Received: 'March 15'"
Namespacing
When agents access many tools, namespace by service and resource:
- Service:
slack_search, github_search, asana_search
- Resource:
asana_projects_search, asana_tasks_search
Test prefix vs suffix naming — effect on agent performance varies by model.
Tool Search
When the tool count is large enough to crowd the context window, mark tools with defer_loading: true so their full definitions load on demand instead of upfront. The agent discovers and pulls in only the tools a task needs, cutting tool-definition token overhead by ~85%. Pair with namespacing so the agent can find the right tool by name.
When to Promote an Action to a Tool
A bash tool in a loop is already a computer-use agent. Not every action needs its own tool. Promote an action to a tool when you need:
| Reason | Example |
|---|
| UX | AskUserQuestion — needs special rendering in the UI |
| Guardrails | File edit tool with staleness check (verify file hasn't changed since last read) |
| Concurrency | Group read-only tools that can safely run in parallel |
| Observability | Isolate specific actions for latency/token logging |
| Autonomy control | Group by reversibility — auto-approve undoable actions, require confirmation for destructive ones |
If none of these apply, the action can stay in bash/code execution.
The Tool Composition Problem
Each tool call round-trips through the model's context. Three sequential tool calls means three reasoning steps, three serialized results (even if the next step only needs a fraction), and three latency hits. This composition tax grows with the number of actions.
Programmatic Tool Calling (PTC)
PTC lets the model write code that orchestrates tool calls inside a container. Tool results return to the running code, not the model's context window. Only the final output reaches the model.
Standard tool calling:
Model → tool_1 → [result in context] → Model → tool_2 → [result in context] → Model
(every intermediate result consumes context tokens)
Programmatic tool calling:
Model → writes code → code calls tool_1 → result stays in code →
code calls tool_2 → result stays in code → code returns final output → Model
(only final output consumes context tokens)
When PTC helps most:
- Multi-step search (filter 50 results down to 5 relevant ones)
- Data pipelines (fetch → parse → filter → aggregate)
- Any workflow where intermediate results are large but the final output is small
Results: On search benchmarks, PTC improved accuracy by ~11% while using ~24% fewer input tokens.
Key insight: Tool handlers still sit in the middle of every call — they can inspect, reject, log, or queue for human approval. PTC preserves the control surface of tools while getting the composability of code.
For implementation details: See references/programmatic-tool-calling.md
Code Execution with MCP
A related pattern takes PTC further: instead of loading every MCP tool definition into context, expose MCP tools as importable filesystem code APIs that the agent loads on demand and calls from generated code. The agent reads only the tool modules a task needs, and intermediate results stay in the execution environment. In Anthropic's example this cut tool-related context from ~150k to ~2k tokens (~98.7% savings).
MCP Server Quick Start
- Scaffold with the MCP SDK for your language
- Connect locally:
- Claude Code:
claude mcp add [--transport stdio|http|sse] [--scope ...] <name> -- <command> [args...]. The -- separator is required — omitting it causes argument misparsing. Remote HTTP/SSE transports are supported in addition to local stdio.
- Claude Desktop: Settings > Developer
- Add tool annotations:
readOnlyHint, destructiveHint, idempotentHint, openWorldHint
- For distribution via Claude Desktop, package as an MCP Bundle (
.mcpb). MCPB was formerly named DXT; .dxt files still load for backward compatibility (CLI dxt→mcpb, package @anthropic-ai/dxt→@anthropic-ai/mcpb).
Tool Design Workflow
Copy this checklist and track progress:
Tool Design Progress:
- [ ] Step 1: Map the workflow (identify what tasks the tools enable)
- [ ] Step 2: Choose tool boundaries (consolidate where possible)
- [ ] Step 3: Define schemas (names, types, enums, descriptions)
- [ ] Step 4: Design responses (format, pagination, error messages)
- [ ] Step 5: Implement and connect locally
- [ ] Step 6: Test manually — find rough edges
- [ ] Step 7: Write evaluation tasks
- [ ] Step 8: Run evaluation and analyze results
- [ ] Step 9: Improve based on agent feedback → re-evaluate
Step 1–2: Think about the workflow the way a human would subdivide it. Tools should match task decomposition, not API structure.
Step 3–4: For each tool, provide a complete spec:
- Name, description, parameters (types, constraints, examples)
- Response schema with success and error examples
Step 5–6: Connect to Claude Code or Claude Desktop. Try the tools yourself on real prompts.
Step 7–9: See references/tool-evaluation.md for evaluation setup.
Evaluation
Strong vs Weak Tasks
| Strong | Weak |
|---|
| "Schedule a meeting with Jane next week to discuss Acme Corp. Attach last planning notes and reserve a room." | "Schedule a meeting with jane@acme.corp." |
| "Customer 9182 reported triple charges. Find logs and check if others are affected." | "Search payment logs for customer_id=9182." |
Strong tasks require judgment and multiple tool calls. Weak tasks spell out the answer.
Key Metrics
| Metric | Signal |
|---|
| Task accuracy | Tools working correctly? |
| Tool call count | Efficient paths? |
| Tool errors | Schemas confusing? |
| Token consumption | Responses bloating context? |
Iterative Improvement
- Concatenate evaluation transcripts → feed to Claude
- Identify patterns → refine tools
- Re-evaluate with held-out test set
- Repeat until performance plateaus
For detailed evaluation setup, metrics, and analysis: See references/tool-evaluation.md
Seeing Like an Agent
Tool design is iterative. What works for one model may not work for the next. The core practice: read the model's outputs, experiment, and revise.
Shape Tools to Model Abilities
Think of giving an agent a math problem. Paper is the minimum. A calculator is better but limited. A computer is most powerful but requires coding ability. Design tools shaped to what the model can actually do — and revisit as capabilities change.
Expand the Action Space Without Adding Tools
The bar to add a new tool should be high — each tool is one more option the model must evaluate. Before adding a tool, ask: can progressive disclosure solve this instead?
Progressive disclosure alternatives:
- Give the agent a search tool to find information in skill files
- Reference docs from the system prompt that the agent reads on demand
- Delegate to a sub-agent with specialized instructions instead of a specialized tool
- Let the agent write and execute code for one-off operations
Evolve Tools as Models Improve
Tools that helped a weaker model may constrain a stronger one:
- A todo-list tool that kept early models on track became limiting when newer models could manage their own state — it was replaced with a task coordination tool for sub-agents
- RAG-injected context was replaced by giving models search tools to build their own context
- System prompt reminders every N turns became unnecessary and were removed
Revisit your tools with each model upgrade. Stick to a small set of supported models with similar capability profiles.
For case studies from Claude Code: See references/iterative-tool-design.md
Anti-Patterns
- 1:1 API wrapping — Agents need workflow-level tools, not CRUD endpoints
- Overlapping tools — If two tools handle the same prompt, agents oscillate. Merge or differentiate.
- Returning everything —
list_contacts with 10k results destroys context. Use search_contacts.
- Opaque IDs only —
"a1b2c3d4-e5f6" is meaningless. Include "Jane Smith" alongside.
- Silent failures — Empty results with no explanation. Always say what happened.
- Generic param names —
query, input, data give no clue. Be specific.
- Never revisiting tools — tools that helped a weaker model may constrain a stronger one. Re-evaluate with each model upgrade.
- Adding tools when progressive disclosure works — skill files, sub-agents, and code execution can expand the action space without adding to tool count.
Output Format
When designing tools, deliver:
- Tool specification — name, description, parameters, response schema with examples
- Implementation — working code with validation and pagination
- Evaluation tasks — 5-7 realistic prompts covering happy path, multi-step, edge cases, scope boundaries
- Integration instructions — how to connect (MCP add, API config, env vars)
Sources