Rubric
Contents — domains, guide and mocks

Tool distribution and tool choice

CCAR-F 2.312 min read · checked 21 September 2026

Task statementDistribute tools appropriately across agents and configure tool choice

Scoped tools in a research system

Coordinatorspawns subagents; no data tools
  • Search agentweb_search, load_document
  • Analysis agentRead, Grep, extraction tools
  • Synthesis agentno search; one scoped verify_fact
  • Report agentWrite to the reports folder only
Each subagent sees only its role’s tools. The synthesis agent gets one narrow lookup for quick fact checks; anything bigger goes back through the coordinator.

Why fewer tools per agent

Every tool definition an agent can see is another option it must rule out on every turn. Anthropic’s docs say Claude’s ability to pick the right tool degrades once it has more than 30–50 available, and the engineering team notes that too many or overlapping tools distract agents from efficient strategies. Long before that limit, a second effect appears: an agent handed tools outside its specialism tends to use them. A synthesis agent that can search the web will start searching instead of synthesising what it was given, and the coordinator loses control of scope and cost.

The fix is the principle of least privilege applied to attention as well as safety: give each agent the tools its role needs and nothing more. That also gives each subagent a clear identity, which keeps the coordinator’s delegation decisions simple.

Scoping tools in the Agent SDK

In the Agent SDK a subagent is an AgentDefinition, and its tools field is the whitelist. Omit it and the subagent inherits every tool available to subagents. List tools and it gets only those — a tool you leave out is not in its session at all, so there is no permission prompt or error to deal with. disallowedTools works the other way, removing named tools; it also accepts server patterns such as mcp__crm__* to drop every tool from one MCP server.

Role-scoped subagentspython
options = ClaudeAgentOptions(
    allowed_tools=["Agent"],                         # coordinator only delegates
    mcp_servers={"research": research_server},
    agents={
        "searcher": AgentDefinition(
            description="Finds and loads sources for a research question.",
            prompt="Search, then load the most relevant documents.",
            tools=["mcp__research__web_search", "mcp__research__load_document"],
        ),
        "synthesiser": AgentDefinition(
            description="Writes a cited summary from findings it is given.",
            prompt="Use only the findings in your prompt. Verify single facts only.",
            tools=["mcp__research__verify_fact"],    # no search at all
        ),
        "reviewer": AgentDefinition(
            description="Checks a draft report against its sources.",
            prompt="Report problems; never edit files.",
            disallowedTools=["Write", "Edit", "Bash"],
        ),
    },
)

Two different lists are easy to confuse. The SDK separates availability — whether a tool is in Claude’s context at all — from permission — whether a call runs without a prompt. tools on an agent definition and bare names in disallowedTools change availability. allowedTools on the query only pre-approves calls; unlisted tools are still available and go through the permission flow. To stop an agent using a tool, remove it; do not merely leave it unapproved.

RoleTypical tool setDeliberately missing
Read-only analysisRead, Grep, GlobEdit, Write, Bash
Test executionBash, Read, GrepEdit, Write
Code modificationRead, Edit, Write, Grep, GlobBash
Synthesis in a research systemOne scoped fact-check toolGeneral web search

Exceptions, and constrained tools

Strict separation has a cost. If the synthesis agent needs to confirm a date or a figure several times per report, sending every check back through the coordinator adds round trips. The usual answer is a limited cross-role tool: a narrow verify_fact that checks one claim against the sources already gathered, rather than full search. Anything that needs real research still goes back to the coordinator, which can dispatch the search agent.

The same thinking applies to generic tools. A fetch_url tool lets an agent fetch anything; a load_document tool that accepts only URLs from approved document stores does the job the role needs and nothing else. Constraining the tool is more reliable than asking the agent, in its prompt, to be careful with it.

Replace a generic tool with a constrained one

Generic

fetch_url
  "Fetches any URL and returns
  the response body."

  input: { url: string }

Constrained to the role

load_document
  "Loads a document from the
  firm's document store or the
  regulator's filings site.
  Other domains are rejected
  with a validation error.
  Returns text and page count."

  input: { document_url: string }
Same underlying HTTP call. The constrained version rejects anything outside its job, and its description tells Claude so.

Configuring tool choice

On the Messages API, tool_choice controls whether and how Claude must use tools on a given request. It has four types, verified against the current docs:

tool_choiceBehaviourUse it when
{"type": "auto"}Claude decides whether to call a tool. Default when tools are providedNormal agent turns
{"type": "any"}Claude must call one of the tools, but picks whichA tool call is required; the right tool depends on the input
{"type": "tool", "name": "…"}Claude must call this specific toolA step must happen first, or one schema must be filled
{"type": "none"}Claude cannot call tools. Default when no tools are providedA turn that must be text only

Which tool_choice does this step need?

What must happen on this turn?
  • Model decides freely
    autothe default
  • Some tool, never plain text
    anyClaude picks which tool
  • This exact tool first
    tool + namethen auto next turn
  • No tool calls at all
    nonetext-only turn
Choose the weakest setting that guarantees what you need. Forcing a tool when Claude should choose is as much an error as hoping for a call you could have required.

Three details matter. With any or tool, the API prefills the assistant turn to force a tool call, so Claude emits no explanatory text before the tool_use block — if you need a preamble, use auto and ask for the tool in the user message. Setting disable_parallel_tool_use: true inside tool_choice limits Claude to at most one call with auto, and exactly one with any or tool. And changing tool_choice between requests invalidates cached message blocks, though cached tool definitions and system prompts survive.

Force the first step, then let the model work

Your code
Claude API
Tools
Step 1: Your code to Claude API: Contract + tool = extract_metadata
Step 2: Claude API to Your code: tool_use: extract_metadata
Step 3: Your code to Tools: Run extraction
Step 4: Tools to Your code: Parties, dates, governing law
Step 5: Your code to Claude API: Result + tool_choice auto
Step 6: Claude API to Your code: Chooses enrichment tools as needed
tool_choice is set per request. Force what must happen first, then return to auto for the rest of the task.

Traps the wrong answers are built from

Tempting but wrongDo this instead
Giving every agent every tool “for flexibility”Scope each agent’s tools to its role; add narrow exceptions where needed.
Relying on a prompt to stop an agent using a tool it holdsRemove the tool from that agent with tools or disallowedTools.
Confusing allowedTools with availabilityallowedTools pre-approves calls; restrict availability with tools or bare disallowedTools.
Forcing one tool when the right one depends on the inputUse any so a call is guaranteed and Claude still chooses.
Leaving tool_choice forced for the whole conversationForce only the step that must come first, then return to auto.

You should now be able to

  • Assign each agent the minimum tool set for its role, with narrow cross-role exceptions.
  • Restrict subagent tools with AgentDefinition.tools and disallowedTools, and tell availability from permission.
  • Replace generic tools with constrained alternatives that enforce the role’s boundary.
  • Choose between auto, any, forced tool and none for a given step.
  • Force a first step with tool_choice, then continue in later turns with auto.

Practice questions

Original questions written for this lesson, in the exam’s style. Answer first, then open the reasoning — every option is explained, including why the wrong ones are tempting.

  1. Question 1

    A research system’s synthesis agent has the same 14 tools as the search agent. Reports increasingly cite sources the search agent never found, and costs are rising.

    What is the best change?

    1. ATell the synthesis agent in its prompt not to search unless necessary.
    2. BSet tool_choice to none for every synthesis request.
    3. CRemove search tools from the synthesis agent and give it one narrow fact-check tool.
    4. DMove all agents to a larger model so they follow scope better.
    Show answer and reasoning
    1. AIncorrect. The agent still holds the tools and will judge “necessary” for itself; the behaviour is only discouraged.
    2. BIncorrect. That also blocks any legitimate fact-check and does not address the mis-scoped tool set.
    3. CCorrect. Scoping the tools to the role stops the drift; the narrow tool covers the frequent, legitimate need.
    4. DIncorrect. A bigger model with the same tools can still wander; the design gives it the option.
  2. Question 2

    A document pipeline defines four extraction tools, one per document type. With the default tool_choice, some documents come back as plain-text summaries and the pipeline fails.

    Which tool_choice fixes this while keeping the right schema per document?

    1. A{"type": "any"}
    2. B{"type": "tool", "name": "extract_invoice"}
    3. C{"type": "auto"} with a stronger prompt
    4. D{"type": "none"}
    Show answer and reasoning
    1. ACorrect. It guarantees a tool call but lets Claude choose which extraction tool fits the document.
    2. BIncorrect. Forcing one tool fills the invoice schema for every document, including contracts and receipts.
    3. CIncorrect. This is the current setting; a prompt makes a tool call more likely but does not guarantee it.
    4. DIncorrect. It prevents tool calls entirely — the opposite of what the pipeline needs.
  3. Question 3

    A compliance agent in the Agent SDK must never run shell commands. The team lists Read, Grep and Glob in allowedTools and leaves Bash out, but logs show Bash calls still being attempted.

    Which two changes actually keep Bash away from the agent? (Select 2.)

    1. APass a tools list naming only Read, Grep and Glob.
    2. BAdd the bare name Bash to disallowedTools.
    3. CAdd Bash to allowedTools with a comment saying not to use it.
    4. DSet tool_choice to any so only approved tools can be chosen.
    5. ETell the agent in its system prompt that Bash is forbidden.
    Show answer and reasoning
    1. ACorrect. tools controls availability: unlisted built-ins are removed from Claude’s context.
    2. BCorrect. A bare name in disallowedTools removes the tool from context, just like omitting it from tools.
    3. CIncorrect. That pre-approves Bash calls — the opposite of the goal.
    4. DIncorrect. any forces some tool call; it does not remove tools from the set.
    5. EIncorrect. The tool stays available; a prompt only discourages its use.
  4. Question 4

    An insurance claims workflow must always run extract_claim_fields on the first turn, then let Claude decide between fraud-check, coverage and payout tools based on what it finds.

    How should tool_choice be configured?

    1. AForce extract_claim_fields on every request in the conversation.
    2. BUse any on every request so a tool is always called.
    3. CLeave auto and put “extract first” in the system prompt.
    4. DForce extract_claim_fields on the first request, then use auto.
    Show answer and reasoning
    1. AIncorrect. Later turns would keep re-extracting instead of moving on to the tools the case needs.
    2. BIncorrect. It does not guarantee extraction happens first; Claude could start with any tool.
    3. CIncorrect. It usually works, but the requirement is “always”, which a prompt cannot guarantee.
    4. DCorrect. The fixed first step is guaranteed, and later turns keep Claude’s freedom to choose tools.

Sources

Drafted with AI assistance and checked against the sources above; expert review is in progress. Spotted an error? Tell us and it gets fixed, dated and listed on how this is written.