Certification
    June 9, 2026

    CCA · Page 3 — Domain 2: Tool Design & MCP Integration

    Exam-ready notes for CCA Foundations Domain 2 (18%): tool descriptions as routing, structured errors, MCP config, tool distribution, and batching.

    Share

    Domain 2 — Tool Design & MCP Integration

    CCA Foundations course · Page 3 of 8 · ← Back to all courses · Weight: 18%. Mark complete at the bottom to advance.


    2.1 — Tool Descriptions as the Routing Mechanism · Core

    Descriptions are the primary signal the model uses to pick a tool — two minimal, overlapping descriptions (e.g. get_customer = "Retrieves customer information" vs lookup_order = "Retrieves order details") get confused on ambiguous input like "check my order #12345."

    • Include input format with examples and explicit boundaries ("do NOT use for…").
    • Add ordering hints when tools are related (e.g. "run extract_metadata before this tool") — without them, the model has no way to know two tools are meant to be sequenced rather than chosen between.
    • Grep = search file contents; Glob = match file paths. Conflating them is one of the most common misrouting patterns the exam tests, precisely because both sound like "find X."
    • Fix misrouting by rewriting descriptions first — the lowest-effort change that addresses the root cause. Few-shot examples add token overhead without fixing the ambiguity; a keyword router over-engineers it; consolidating tools is more work than a first step warrants.
    • Rename + re-describe to remove functional overlap (a vague analyze_content → a web-specific extract_web_results), or split a generic tool into purpose-specific tools with defined I/O contracts (analyze_document → extract_data_points + summarize_content + verify_claim_against_source). Splitting is worth the extra tool count when the generic tool's single description can't honestly describe three unrelated jobs at once.
    • Check the system prompt too — keyword-sensitive wording elsewhere in the prompt can create unintended tool associations that override even well-written descriptions.

    ⚠ Often-missed — Why Rewriting Descriptions Beats the Alternatives · Gap

    When two minimal tools get confused, the exam offers several plausible-looking fixes — but only one is the first step. Few-shot examples add token overhead on every call without touching the root ambiguity. A keyword router in front of the model over-engineers a problem a better description solves for free. Consolidating the tools into one is more invasive than the situation warrants. Rewriting the descriptions — input formats, examples, edge cases, explicit "do NOT use for X" boundaries — is the lowest-effort change that fixes the actual cause.

    2.2 — Structured Error Responses · Core

    Return structured metadata so the coordinator can recover intelligently — a generic "Operation failed" hides the context needed to decide anything:

    • isError, errorCategory (transient = retry; validation = fix input, no retry; business = policy violation, explain to user; permission = not authorised, escalate), isRetryable, attemptedQuery, partialResults, and — for business-rule failures — a customerMessage the agent can relay directly.
    • isRetryable is guidance, not a directive. The tool only signals a retry is possible; the agent loop owns the retry budget — max attempt count, backoff between attempts, escalation once the budget is exhausted. Marking a permanent failure isRetryable: true causes infinite retry loops. A retry-after hint on the error, when present, should drive the backoff delay; when absent, the loop falls back to exponential backoff on its own.
    • Distinguish access failures from valid empty results. A timeout (needs a retry decision) is not the same as a successful query that legitimately found nothing (isError: false, results: []) — conflating the two hides information the agent needs, and can make a broken connection look, from the agent's perspective, exactly like a search that simply had no matches.
    • Use a verdict field, not a boolean, for verification tools. A fact-checker needs three distinct outcomes: "supported" (sources confirm it), "contradicted" (sources refute it), "not_found" (simply absent from any source) — "not_found" and "contradicted" demand different downstream handling (report "unverifiable" vs. flag as actively wrong), and a boolean collapses that distinction into an ambiguous single false.
    • Subagents recover locally from transient errors first, and only propagate what they can't resolve, along with what was attempted and any partial results.
    • A business-rule error still needs a technical errorCategory and a plain-language customerMessage — the agent uses the category to decide what to do next (don't retry, don't escalate as a bug), and relays the message so the customer isn't shown an internal string like "REFUND_LIMIT_EXCEEDED". Neither field alone is enough: the category without the message leaves the agent unable to explain anything; the message without the category leaves it unable to decide what to do next.

    2.3 — Distribute Tools & Configure tool_choice · Core

    • 4–5 tools per agent is optimal; ~18 tools degrades selection reliability and causes agents to misuse tools outside their specialisation (e.g. a synthesis agent attempting web searches).
    • Give each agent a scoped role with limited cross-role tools for high-frequency needs — e.g. a narrow verify_fact tool for the synthesis agent's simple 85%-case lookups, while complex verifications still route through the coordinator to the web-search agent. Over-provisioning with the full toolset violates least privilege.
    • Replace generic tools with constrained alternatives — swap a free-form fetch_url for a load_document that validates document URLs at the API level.
    • tool_choice values: {"type": "auto"} (model decides, default), {"type": "any"} (must call some tool — guarantees structured output, no plain text), {"type": "tool", "name": "..."} (must call this specific tool — good for forcing a required first step), {"type": "none"} (no tool calls).
    • Force a specific tool only for the turn that needs it (e.g. extract metadata before enrichment), then switch back to "any" or "auto" for subsequent steps — don't re-apply forced selection on every turn.
    • Principle of least privilege drives distribution decisions. When a synthesis agent burns 2–3 extra round-trips on simple fact-checks, the fix is a scoped verify_fact tool for that 85% case, not handing it the entire web-research toolset "to be safe" — over-provisioning re-creates the exact selection-reliability problem tool scoping exists to prevent.

    2.4 — MCP Configuration · Core

    • .mcp.json (project root, committed) → team / version-controlled tooling, discovered by everyone who clones the repo. ~/.claude.json → personal / experimental servers, not shared via version control. Both are discovered at connection time and available simultaneously.
    • Environment-variable expansion for credentials (e.g. ${GITHUB_TOKEN}) — never hardcode a token in .mcp.json; git history is permanent.
    • MCP resources vs tools: resources expose readable content catalogs (issue summaries, doc hierarchies, database schemas) at connection time, giving visibility without exploratory tool calls; tools perform actions. Confusing the two means an agent burns several exploratory list_issues/get_schema-style tool calls just to learn what's available — content a well-designed resource would have handed it up front, for free, at connection time.
    • Write detailed MCP tool descriptions — a thin description makes Claude fall back to a built-in (e.g. Grep) instead of a more capable MCP tool. The fix when this happens is always to enrich the MCP tool's description — never to remove or disable the built-in, which would just eliminate a useful fallback for cases the MCP server doesn't cover.
    • Prefer an existing community MCP server for standard integrations (GitHub, Jira); reserve custom servers for team-specific, proprietary workflows.
    • Scope is the question, not capability. A /review command every developer should get on clone goes in project-scoped .claude/commands/; a personal, still-experimental MCP integration goes in user-scoped ~/.claude.json — "shared via version control" vs. "just me" is the entire decision, independent of how polished either one is.

    2.5 — Built-in Tools: Read, Write, Edit, Bash, Grep, Glob · Core

    • Grep — search file contents for a pattern (function names, error strings, imports).
    • Glob — find files by path/name pattern (e.g. **/*.test.tsx), regardless of location.
    • Read — load a full file's contents. Write — create or fully replace a file. Edit — targeted change via a unique text anchor; the most efficient option when it applies.
    • Edit → Read+Write fallback: when the anchor text isn't unique, Edit can't safely locate the spot — fall back to Read the full file, then Write it back with the change, rather than a blind global replace that would touch every occurrence.
    • Build understanding incrementally — Grep first to find entry points, Read only what's relevant to follow imports and trace flows. Don't load every file up front.
    • Tracing a function across wrapper modules — identify all exported/re-exported names first, then Grep for each alias; a single-name search misses callers using a wrapper name.
    • Bash is the fallback — reach for it when no other built-in fits (running a script, a package-manager command), not as a default first move ahead of the more targeted tools above.

    ⚠ Often-missed — Tool Distribution / Separation of Concerns · Gap

    If an agent misuses a tool, the fix is to remove the tool and create a dedicated subagent for that job. NEVER patch it with instructions, few-shot examples, or tool_choice — the model will keep reaching for a tool that's simply outside its role.

    ⚠ Often-missed — Edit Anchor Mismatches (Whitespace) · Gap

    An Edit that reports "not found" immediately after a successful Read almost always means a whitespace mismatch — spaces vs tabs, or LF vs CRLF line endings. Copy old_string verbatim from the Read output rather than retyping it.

    ⚠ Often-missed — Tool Batching to Reduce Round Trips · Gap

    When several tools are needed together, prompt Claude to emit multiple tool_use blocks in one turn. Don't build a composite "do-everything" tool — that just trades one round-trip problem for a brittle, hard-to-route mega-tool that's harder for the model to select correctly and harder for you to give clean, structured errors from.

    ⚠ Often-missed — .mcp.json Credentials Are Never Hardcoded · Gap

    A hardcoded token in .mcp.json — even one later removed — stays recoverable in git history forever. The only correct pattern is environment-variable expansion (${GITHUB_TOKEN}) with the actual secret injected at runtime from the environment, never committed in any form.


    Exam reflexes for Domain 2

    • "Tool misrouting" → fix tool descriptions first (not few-shot, not tool_choice, not a keyword router).
    • "Agent misusing a tool" → remove it + dedicated subagent, never patch with instructions.
    • "18+ tools per agent" → split into scoped agents (4–5 each).
    • "Timeout returns empty success" → silent suppression anti-pattern → structured error with isError.
    • "Boolean verification result loses nuance" → verdict: supported / contradicted / not_found.
    • "isRetryable: true causing infinite loop" → the agent loop owns the retry budget, not the tool.
    • "Multiple tools, different formats" → PostToolUse hook to normalise (Domain 1).
    • "Team-shared MCP server" → .mcp.json · "personal/experimental" → ~/.claude.json.
    • "Edit fails right after a successful Read" → whitespace/line-ending mismatch — copy old_string verbatim.
    • "Find all callers of X" → Grep; "find all *.test.tsx" → Glob.
    • "Agent making exploratory calls just to see what's available" → expose an MCP resource (content catalog), not more tools.
    • "Synthesis agent doing 2–3 extra fact-check round-trips" → scoped verify_fact tool for the common case, not the full toolset.
    • "MCP tool ignored in favor of a built-in" → enrich the MCP description; don't remove the built-in fallback.

    TIP

    Test yourself on this domain. Take the Domain 2 practice quiz — 60 questions, instant scoring, an explanation for every answer.

    Ask about this article

    Get answers grounded in this post. AI-generated — based on this article, and may be imperfect.

    Free: CCA Foundations cheat-sheet (PDF)

    The domains, the 3 universal rules, core concepts, and exam-day shortcuts — one page. Enter your email and it's yours, plus my weekly AI-architecture notes.

    No spam. Unsubscribe any time.

    Scaled AI Weekly

    Enjoyed this? Get more like it every Monday.

    Real architecture decisions, LLMOps patterns that survive production, and engineering leadership advice — from 12+ years of building at enterprise scale. Free. No spam. Unsubscribe anytime.

    Join engineers building production AI systems

    Comments