2.1

Design effective tool interfaces with clear descriptions and boundaries

In production logs, an agent keeps calling get_customer when users ask about orders — both tools carry minimal descriptions ("Retrieves customer information" / "Retrieves order details") and accept similar identifiers, so Claude can't tell them apart. The tool description is the primary mechanism Claude uses to pick a tool; thin or overlapping ones make selection unreliable among similar tools.

The fix is to expand each description with the input formats it accepts, example queries, edge cases, and explicit boundaries — when to use it versus a similar alternative. When two tools still overlap, rename one to its specific job (analyze_contentextract_web_results with a web-specific description) or split a generic tool into purpose-specific ones with defined input/output contracts (analyze_documentextract_data_points, summarize_content, verify_claim_against_source). Then review the system prompt: keyword-sensitive instructions can create unintended tool associations that override even a well-written description.

  • Differentiate every description: state purpose, expected inputs, outputs, and when to use it versus a similar alternative
  • Include input formats, example queries, edge cases, and boundary explanations — not just a one-line summary
  • Eliminate overlap by renaming (analyze_contentextract_web_results) so each tool's name and description map to one job
  • Split a generic tool into purpose-specific tools with defined input/output contracts (extract_data_points, summarize_content, verify_claim_against_source)
  • Audit the system prompt for keyword-sensitive wording that builds unintended tool associations and overrides the descriptions
Domain2 T2 1 Tool Descriptions diagram
  • "Add few-shot examples" to the system prompt as the first-step fix — adds token overhead without fixing the minimal descriptions
  • "Implement a routing layer" that parses input and pre-selects a tool by keywords — over-engineered, bypasses Claude's language understanding
  • "Consolidate both tools into a single tool" (e.g. lookup_entity) that internally branches — more effort than a first step warrants
  • Leaving "ambiguous or overlapping tool descriptions" or "minimal descriptions" in place
Claude Docs (official): Define tools · best practices for detailed, differentiated tool descriptions
Anthropic Academy on Skilljar (optional): Building with the Claude API — Module 5 (Tool Use) · Introducing tool use · Tool functions · Tool schemas
2.2

Implement structured error responses for MCP tools

When an MCP tool fails, a generic "Operation failed" tells the agent nothing — it can't decide whether to retry, fix its input, or escalate, so uniform error responses block appropriate recovery. MCP signals a failure with the isError flag on the tool result; what makes that flag useful is the structured metadata you attach to it.

Return an errorCategorytransient (timeouts, service unavailability), validation (invalid input), business (policy violations), or permission — plus an isRetryable boolean and a human-readable description. A transient timeout is retryable; a business-rule violation gets retriable: false and a customer-friendly explanation so the agent communicates appropriately instead of looping. Inside a subagent, recover from transient failures locally and propagate to the coordinator only what you couldn't resolve — along with partial results and what was attempted.

  • isError is the MCP flag that marks a tool result as a failure — the agent reads it to choose a recovery path
  • Categorize every error: transient · validation · business · permission — each implies a different recovery decision
  • isRetryable (or retriable: false) tells the agent whether retrying is worthwhile — structured metadata prevents wasted retry attempts
  • Business-rule violations carry retriable: false plus a customer-friendly explanation, not a raw error
  • Recover transient failures locally in the subagent; propagate to the coordinator only unresolved errors, with partial results and what was attempted
  • Distinguish an access failure (needs a retry decision) from a valid empty result (a successful query with no matches) — empty is not an error
Domain2 T2 2 Structured Error Responses diagram
  • Returning a uniform generic "Operation failed" — prevents the agent from making appropriate recovery decisions
  • "Generic search unavailable status" returned only after retries are exhausted — hides the failure type and any partial results
  • "Return an empty result set marked as successful" when the query actually failed — suppresses the error and risks incomplete output
  • "Terminate the entire workflow on a single failure" instead of recovering locally and propagating selectively
Claude Docs (official): Handle tool calls · returning errors with the is_error flag and instructive messages
Anthropic Academy on Skilljar (optional): Building with the Claude API — Modules 5 + 8 · Handling message blocks · Sending tool results (M5) · Defining tools with MCP · Implementing a client (M8)
2.3

Distribute tools appropriately across agents and configure tool choice

Give one agent 18 tools instead of the 4–5 it actually needs and its tool selection gets unreliable — every extra tool adds decision complexity. Worse, an agent handed tools outside its specialization tends to misuse them (a synthesis agent that can web-search will). The principle is scoped tool access: give each subagent only the tools its role needs, plus a few constrained cross-role tools for specific high-frequency needs.

When the synthesis agent constantly needs simple fact-checks, give it a narrow verify_fact tool and keep complex investigations routed through the coordinator — rather than the full web-search toolset. You also control how tools get called with tool_choice: "auto" lets Claude decide, "any" guarantees it calls some tool rather than returning conversational text, and {"type": "tool", "name": "..."} forces one specific tool first (e.g. extract_metadata before any enrichment tool), with later steps handled in follow-up turns.

  • Keep each agent near 4–5 relevant tools; ~18 tools degrades selection reliability by increasing decision complexity
  • Restrict each subagent's tool set to its role to prevent cross-specialization misuse (a synthesis agent attempting web searches)
  • Replace a generic tool with a constrained alternative (fetch_urlload_document that validates document URLs)
  • Provide scoped cross-role tools for high-frequency needs (verify_fact for the synthesis agent); route complex cases through the coordinator
  • tool_choice: "auto" = model decides · "any" = must call a tool (no plain text) · {"type":"tool","name":"..."} = forces one named tool first
Domain2 T2 3 Tool Distribution and tool_choice diagram
  • "Give the synthesis agent access to all web search tools" so it can handle any verification directly — over-provisions and violates separation of concerns
  • "Accumulate all verification needs and return them as a batch" at the end of a pass — creates blocking dependencies between steps
  • "Proactively cache extra context" anticipating future needs — speculative caching can't reliably predict what will be verified
  • Giving an agent tools outside its specialization, where it tends to misuse them
Claude Docs (official): Forcing tool use (tool_choice) · auto · any · tool · none
Anthropic Academy on Skilljar (optional): Building with the Claude API — Module 5 · Using multiple tools · Fine-grained tool calling · Multi-turn conversations with tools
2.4

Integrate MCP servers into Claude Code and agent workflows

An MCP server is an external process that hands Claude extra tools; where you configure it decides who gets it. Put shared team tooling in a project-level .mcp.json (committed to the repo) and personal or experimental servers in your user-level ~/.claude.json. To keep secrets out of git, reference credentials with environment-variable expansion — ${GITHUB_TOKEN} in .mcp.json rather than the literal token.

At connection time Claude discovers the tools from every configured server and makes them all available at once, so write detailed MCP tool descriptions — otherwise the agent quietly prefers a built-in tool like Grep over a more capable MCP tool. Prefer an existing community server for standard integrations (e.g. Jira) and reserve custom servers for team-specific workflows. Finally, expose content catalogs (issue summaries, documentation hierarchies, database schemas) as MCP resources so the agent sees what data exists without burning exploratory tool calls.

  • Project-level .mcp.json = shared team tooling (committed); user-level ~/.claude.json = personal/experimental servers
  • Use environment-variable expansion (${GITHUB_TOKEN}) in .mcp.json so auth tokens are never committed
  • Tools from all configured servers are discovered at connection time and available to the agent simultaneously
  • Write detailed MCP tool descriptions, or the agent prefers built-in tools (like Grep) over more capable MCP tools
  • Expose content catalogs as MCP resources (issue summaries, doc hierarchies, DB schemas) to cut exploratory tool calls
Domain2 T2 4 MCP Server Scoping diagram
  • Leaving thin MCP descriptions so the agent keeps "preferring built-in tools (like Grep) over more capable MCP tools"
  • Committing literal credentials instead of ${...} environment-variable expansion in .mcp.json
  • Building a custom MCP server for a standard integration (e.g. Jira) when a community server already exists
  • Putting shared team servers in user-level ~/.claude.json (not shared) instead of project-level .mcp.json
// Shared team tooling — committed to the repo so everyone gets it.
// File: .mcp.json   (project scope; ~/.claude.json would be user/personal scope)
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        // Reference the secret by name — never commit the literal token.
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}
Claude Docs (official): Connect Claude Code to tools via MCP · configuring MCP servers, scopes, and resources
Anthropic Academy on Skilljar (optional): Building with the Claude API — Module 8 (MCP) + Claude Code in Action — Module 3 · Introducing MCP · MCP clients · Defining tools with MCP · The server inspector · Defining resources · Defining prompts (BCA) · MCP servers with Claude Code (CC)
Peace Of Code (YouTube, optional): Ep 08 — MCP Servers, Config, Cline & More
2.5

Select and apply built-in tools (Read, Write, Edit, Bash, Grep, Glob) effectively

Each built-in tool answers one question, and picking the right one keeps the agent fast and reliable. Grep searches inside files for content — function names, error messages, import statements; Glob matches file paths by name or extension pattern (**/*.test.tsx). Read and Write do whole-file operations, while Edit makes a targeted change by matching unique anchor text.

When that anchor text isn't unique, Edit fails — the reliable fallback is to Read the full file and Write it back. The expert move is to build understanding incrementally rather than reading everything upfront: start with Grep to find entry points, then Read to follow imports and trace flows. To trace a function used across wrapper modules, first identify all the exported names, then Grep each name across the codebase.

  • Grep = search file contents (callers of a function, error messages, import statements)
  • Glob = match file paths by naming pattern (**/*.test.tsx)
  • Read/Write = full-file operations; Edit = targeted change via unique text match
  • On a non-unique Edit match, fall back to Read + Write for a reliable modification
  • Explore incrementally: Grep for entry points → Read to follow imports and trace flows; don't read all files upfront
  • Trace usage across wrapper modules by listing all exported names first, then Grep-ing each name
Domain2 T2 5 Built-in Tool Selection diagram
  • Retrying Edit on non-unique anchor text instead of falling back to Read + Write
  • Using Glob (path patterns) to search file contents, or Grep (content) to find files by name
  • Reading all files upfront instead of Grep-to-entry-point, then Read-to-trace incremental exploration
Claude Docs (official): Tools reference · built-in Read, Write, Edit, Bash, Grep, Glob behaviors
Anthropic Academy on Skilljar (optional): Claude Code in Action — Module 2 + Building with the Claude API — Module 5 · Adding context · Making changes (CC) · The text edit tool · The web search tool (BCA)
Peace Of Code (YouTube, optional): Ep 09 — Claude Built-in Tools Explained

Further Reading — Claude Docs

Official Anthropic documentation for the concepts in this domain.

Tool descriptions & tool_choice Define tools
Structured error responses Handle tool calls (is_error)
MCP server integration Connect Claude Code to tools via MCP
Built-in tools Tools reference

Further Reading — Anthropic Academy on Skilljar

Optional self-paced courses.

Anthropic Academy on Skilljar

Further Viewing — Peace Of Code (YouTube)

Watch if a topic is still unclear.

CCA Full Course — Peace Of Code

Tool descriptions & misrouting prevention Ep 06 — Tool Descriptions & Tool Misrouting Explained
Structured error handling & tool_choice Ep 07 — Agent Error Handling & tool_choice Explained
MCP servers, configuration & scoping Ep 08 — MCP Servers, Config, Cline & More
Built-in tools (Read, Write, Edit, Bash, Grep, Glob) Ep 09 — Claude Built-in Tools Explained