Claude Certification Program · v1.0 · Effective July 2026 · All four tracks open

Home › Study guides › CCAR-F › Domain 2 › Lesson 2.3

CCAR-F · Domain 2 · 18% of the exam · Lesson 2.3 · 20 min read

Distributing tools across agents and configuring tool_choice

Why a long tool list hurts selection, how to scope each subagent to its role, when a cross-role tool fits, and what tool_choice auto, any and forced guarantee.

Written against task statement 2.3 of the official CCAR-F exam guide (Version 1.0, effective July 2026). An independent resource, not affiliated with Anthropic; the practice questions are written from scratch.

2.3.1 Why the synthesis agent started searching the web

Picture a small newsroom. A researcher digs up sources, a fact-checker reads them closely, a writer pulls the findings into a story, and a sub-editor lays out the page. Now imagine the editor hands every one of them the full building keyring. Nothing stops the writer from wandering into the wire room and spending the afternoon reading news instead of writing. Nobody told the writer to. The keys were in their pocket, so the option was always there.

That is the situation our multi-agent research system got into. A coordinator agent receives the research question and hands pieces of it to four specialised helper agents, called subagents. The search agent finds sources on the web, the analysis agent reads documents, the synthesis agent combines the findings, and the report agent produces the cited report. For convenience, every subagent was given the same list of all 18 of the system's tools.

Within a week the synthesis agent, whose whole job is to combine findings already collected, was running its own web searches mid-draft and pulling in sources nobody had vetted. Tool selection also became unreliable everywhere. The analysis agent occasionally called send_report, and the search agent sometimes ran a document parser on a page of search results.

A model never sees the code behind a tool. It chooses by reading each tool's name, description and input format, and matching them against what it is trying to do. So the tool list you hand an agent IS the set of choices it can make, and a long, generic list makes every turn a hard, unfocused decision. Two mechanisms put this right. Tool distribution decides which agent sees which tools. tool_choice, a setting on each request to the model, decides whether the model may answer in text, must call some tool, or must call one particular tool.

2.3.2 Why 18 tools make every choice worse

Here is the principle that trips people up, because it sounds backwards: giving an agent MORE tools makes it LESS reliable. With 18 tools in front of it, every turn is an 18-way decision. The model has to weigh 18 descriptions, set aside the ones that do not apply, and still pick correctly among the rest. Several sound alike (web_search, search_academic, fetch_url, load_document), so it must weigh fine distinctions that may not matter for its task at all. Decision complexity goes up; selection reliability goes down.

Anthropic's own advice on writing tools warns that too many tools, or overlapping ones, can distract an agent from an efficient strategy. The exam guide makes the point concrete with a reference point: an agent with 4 or 5 tools rather than 18. Those numbers illustrate the principle. They are not an API limit or a documented maximum. Treat them as a design signal: when an agent's list grows past a handful, ask which of those tools this role actually needs.

Think of a pastry chef with five implements at their station. They work fast and rarely reach for the wrong one. Give the same chef the whole kitchen's forty implements and they spend effort choosing, and now and then pick up the fish knife. Put precisely: selection reliability falls as the number of candidate tools rises, because each choice is made among all of them, relevant or not.

Eighteen tools for everyone versus a scoped set per role

18 tools for everyone

Every subagentthe same 18 tools
18-way choiceon every turn
Overlapping namesfine distinctions to weigh
Cross-role misusesynthesis searches the web

4 to 5 per role

Search agent4 search tools
Analysis agent4 document tools
Synthesis agent2 tools plus verify_fact
Report agent3 output tools
A shared list of 18 tools makes every turn an 18-way choice; a role-scoped set of 4 or 5 keeps each choice small.

That explains the analysis agent calling send_report. Nothing was broken. It was making an 18-way choice on every turn, and now and then it chose wrong.

2.3.3 Scoping tools to each role

If the number of tools is half the problem, the other half is WHICH tools. An agent with a tool outside its specialisation tends to misuse it, and the reason is unglamorous. The synthesis agent's instructions (its system prompt) say "combine the findings", but its tool list says "you may also search". When the findings feel thin, one more search looks like the helpful next step, and nothing in the agent's world says searching is someone else's job. The prompt discourages; the tool list permits; permission wins often enough to matter.

The fix is scoped tool access: each subagent gets only the tools its role needs. It is tempting to leave the extra tools in place and add a firm line to the prompt: "Do not perform web searches." Resist it. A prompt is advice, and advice is followed most of the time. A tool that is not in the list cannot be called at all, on any turn, however tempting it looks. Remove the option and that misuse cannot happen.

Here is the research system after scoping. The tool highlighted on the synthesis agent, verify_fact, is a deliberate exception we come to in the next section.

The coordinator and its four scoped subagents

Coordinatorspawns subagents, routes complex cases
Search agentweb_search, search_academic, search_news, save_source
Analysis agentload_document, extract_metadata, extract_claims, summarize_section
Synthesis agentcompare_findings, draft_section, verify_fact
Report agentformat_citations, render_report, send_report
Each subagent sees only the tools its role needs, so a cross-role action such as the synthesis agent searching the web is impossible rather than merely discouraged.

In the Claude Agent SDK (software development kit), this is a configuration decision, not a prompt-writing one. Each subagent definition has a tools list, and a tool you leave off the list is not in that subagent's session at all. Leave the list out entirely and the subagent inherits every tool available to subagents, which is exactly how our system ended up with 18 tools everywhere. Look at the two tools lines below; they are the whole mechanism.

agents={
    "synthesis": AgentDefinition(
        description="Combines collected findings into a coherent argument.",
        prompt="You synthesise findings already gathered. You do not search.",
        tools=["compare_findings", "draft_section", "verify_fact"],   # ONLY these
    ),
    "search": AgentDefinition(
        description="Finds and saves candidate sources on the web.",
        prompt="You find sources. You do not analyse or write.",
        tools=["web_search", "search_academic", "search_news", "save_source"],  # no writing tools
    ),
}

In a real system these custom tools would be served by an MCP (Model Context Protocol) server, and their full names would carry that server's prefix. The principle is the same.

2.3.4 Constrained tools and the scoped cross-role exception

Scoping decides which tools an agent gets. Two refinements decide what those tools are allowed to do.

The first is to replace generic tools with constrained alternatives. The analysis agent needs to open the documents the search agent saved. Originally it had fetch_url, a tool that could fetch any address on the internet. That is far more power than "open a saved document" needs, and the extra power is where the trouble lives. The agent can wander to any page, load something nobody vetted, and treat it as a source. The replacement is load_document, which takes a document URL (web address), checks it against the sources the search agent saved, and refuses anything else. The agent's job did not change; the tool's boundary now matches the job exactly.

A generic tool is a master key: it opens everything, including doors you never meant to open. A constrained tool is a key cut for one door. It is also easier to describe, which makes it easier to select correctly.

The second refinement answers the opposite pressure: strict scoping can create a bottleneck. The synthesis agent often needs to check a claim while it writes ("did this survey really run in 2023?"). With no search tools, every check goes back to the coordinator, which asks the search agent and then hands the answer back. That round trip is slow, and it repeats many times per report. Yet when you log the checks, the large majority are simple: one claim, compared against a source that has already been collected. Only a small share need judgement, several sources or a fresh search.

The answer is a scoped cross-role tool: a narrow slice of another role's capability, handed over because the need comes up so often. Here that is verify_fact, given to the synthesis agent. It takes one claim and checks it against the sources already saved, with no open web access. The common simple check now happens inside the synthesis agent's own turn, so the round trip disappears. The hard cases still go through the coordinator, which decides whether the search agent should run a new search. Handing the synthesis agent the full web_search tool instead would bring back exactly the misuse that scoping removed.

The need The tool Who gets it Why this shape
Open a saved document load_document, validates the URL against saved sources Analysis agent Replaces the generic fetch_url, which could open anything
Check one simple claim verify_fact, checks against saved sources only Synthesis agent A scoped cross-role tool for a high-frequency need
Resolve a complex claim Route to the coordinator Coordinator, then the search agent Rare, needs judgement and possibly a fresh search

Memorise the pattern, not the tool names: the names change from question to question, the shape does not.

2.3.5 tool_choice: auto, any and a forced tool

Distribution decides what an agent CAN call. The exam also asks about a second question: for one particular request, MUST the model call a tool, and if so, which one? That is what the tool_choice parameter controls. It is a field of a single request to the Messages API (the interface your code uses to send each turn to Claude), sent alongside the tools list, so it applies to that request only. The docs list four options: the exam tests three, and the fourth is worth recognising.

tool_choice What the model must do When to use it
{"type": "auto"} Decide for itself: call a tool, or answer in text. The default whenever tools are provided. Ordinary agent turns, where a text answer is a legitimate outcome
{"type": "any"} Call one of the provided tools; it chooses which. It cannot reply with text alone. When a tool call is mandatory but the right tool depends on the input
{"type": "tool", "name": "extract_metadata"} Call that specific tool. When one named tool must run first
{"type": "none"} Call no tools at all. The default when no tools are provided. Recognise it; the exam centres on the other three

Memorise the three: auto may answer in text, any must call some tool, forced ("type": "tool" with a name) must call that tool. Recognise none.

any answers a specific failure: the model sometimes replies conversationally when your code was waiting for a tool call to process. "I'd be happy to extract that for you" is useless to a program expecting structured input. any guarantees a tool call comes back instead of prose, while leaving the choice of tool to the model. That fits a request where several tools could apply and the input decides which, such as a document that must go through whichever extraction tool suits it.

One side effect is worth knowing. With any or a forced tool, the model goes straight to the tool call, with no explanatory sentence before it, even if your prompt asks for one. If you need both, stay on auto and ask for the tool in your message.

Forced selection is for ordering. In the analysis agent, every document should start with extract_metadata (title, authors, date) before any enrichment tool such as extract_claims or summarize_section touches it, because the claims need to be attributed and dated. Under auto the agent usually did this and occasionally did not. So the first request for each document sends tool_choice: {"type": "tool", "name": "extract_metadata"}, and the model must call it. Your code runs the extraction, appends the result, and sends the follow-up requests with tool_choice back to auto. The enrichment steps then run as normal turns, with the metadata in context.

A forced extract_metadata call, then enrichment on follow-up turns

Turn 1tool_choice forces extract_metadata
Result appendedtitle, authors, date in context
Turn 2, automodel picks extract_claims
Turn 3, automodel picks summarize_section
Doneend_turn with the analysis
Forcing applies to one request. The first turn guarantees the metadata tool runs; the later turns return to auto so the model can choose the enrichment steps.

A forced tool_choice is not a standing rule for the whole conversation. Leave it forced on every request and the agent can only ever call extract_metadata, over and over, never reaching the enrichment steps or finishing. Force once, get the guarantee, then release.

One related switch sits inside the same object. By default the model may request several tools in one response. If the forced first turn must contain exactly one call, add disable_parallel_tool_use: true inside tool_choice. With any or a forced tool, the model then calls exactly one tool; with auto, it calls at most one and may still answer in text. It is a field of the tool_choice object, not a separate request parameter.

2.3.6 The exam traps

Every trap in this task statement is one of two mistakes: handing out power the role does not need, or reaching for tool_choice to solve a problem that lives somewhere else.

  • ✗ Giving every subagent every tool "so it can handle anything". ✓ Scope each subagent to the handful of tools its role needs. A long list makes every selection harder and invites cross-role misuse.
  • ✗ Fixing misuse with a stronger prompt ("never search the web"). ✓ Remove the tool from that agent's list. A prompt discourages; an absent tool prevents.
  • ✗ Keeping a generic tool such as fetch_url because it covers everything. ✓ Replace it with a constrained tool like load_document that validates document URLs, so the tool can do only the job the role needs.
  • ✗ Giving the synthesis agent full web_search, or queuing all its checks until the draft is done. ✓ Give it a scoped verify_fact for the frequent simple checks and route the complex ones through the coordinator. Full search brings the misuse back, and a queue at the end holds up every passage that depends on an earlier fact.
  • ✗ Using tool_choice: any to stop the model picking the wrong tool. ✓ any guarantees a tool call, not the right one. Choosing well between tools is fixed by distribution and descriptions.
  • ✗ Leaving a forced tool_choice on every request. ✓ Force the tool on the first request, then send the follow-up turns with auto.

2.3.7 Put it together: scope the research system and force one call

You now have both halves of the task statement. Distribution means a few tools per agent, scoped to the role, with generic tools narrowed and a scoped cross-role tool where a frequent need crosses a boundary. Configuration means tool_choice as a per-request guarantee. The quickest way to make both stick is to build a toy version and break it.

Distribution is one kind of fix among several in this domain, and the symptom tells you which one a question wants. When the model picks the wrong tool from an already well-scoped set, the fix is usually the tool's description. The tools you scope here are often served by MCP servers, and wiring those servers into Claude Code and agent workflows is the next task (2.4). When the agent is Claude Code exploring a codebase, the tools being chosen between are the built-in Read, Write, Edit, Bash, Grep and Glob (2.5).

Key takeaways

  • ✓ An agent picks from the tools it is shown, so a long list degrades selection; the exam guide's example is 4 or 5 tools per agent rather than 18.
  • ✓ A tool outside an agent's role invites misuse because the tool list permits what the prompt discourages, so scope each subagent's tools to its role.
  • ✓ Replace generic tools with constrained ones, such as a load_document that validates document URLs instead of fetch_url.
  • ✓ For a frequent cross-role need, add a scoped tool (verify_fact for simple checks) and route the complex cases through the coordinator.
  • ✓ tool_choice is set per request: auto (the default) may answer in text, any must call some tool, and {"type": "tool", "name": "..."} must call that tool.
  • ✓ Force a tool to guarantee it runs first, then return to auto for the follow-up turns; any guarantees a call, not the right choice.

Check your understanding

4 questions written for this lesson, then one from the CCAR-F question bank on the same topic. Every answer option is explained, including the ones you did not pick. Nothing is stored.

66 CCAR-F questions on Domain 2, free

Every question in the bank is tagged to a domain, so you can drill 66 questions on Tool Design & MCP Integration alone, or sit the full 60-question timed simulator.

Open the CCAR-F question bank → Back to Domain 2 →

The question bank is free. It asks for an account only because the quiz engine has to store answers to score them and show which domains are weak. The questions on this page need nothing.

Sources