Foundations, lesson 14
Scoped tools
Each agent gets only the tools its job needs
A review agent must only read records, but it holds every one of the tools in the catalogue. Most of them change data. The answer comes out right, yet a wrong pick would have paid a refund or sent an email. This is the agent at Lumen Supply, an online electronics shop. You will watch an agent hold every tool. Then you fix it so each role holds only the few its job needs.
A tool you never give cannot be called
An agent picks from the tools it can see. Every extra tool is another wrong option, and a tool that changes data turns a wrong pick into a real mistake.
The code decides the list and the model picks inside it.
Three things go wrong as the list grows. The pick gets less accurate. A read-only role holds a tool that writes. Nothing fixes the order of steps, so a required lookup can be skipped.
A scoped agent has few tools and picks right
The reviewer holds four read tools. It calls three of them, lookup_order, list_refunds and get_policy, finds the refund and the limit, and answers.
Open the agent card to see the tools it held. None of them can change data.
- ColleagueRefund 5501 on order 1042 was $80. Is that within the refund limit? Answer from the…
Show the result
Refund 5501 on order 1042 was $80. Is that within the refund limit? Answer from the records and change nothing.
- Agentholds 4 tools, 0 that change data unasked
Show the result
lookup_order list_refunds get_policy get_customer
- Toolscalled: lookup_order, list_refunds, get_policy
Show the result
lookup_order list_refunds get_policy
- AgentYes, refund 5501 for $80 on order 1042 is within the limit. The refund policy sets a $500 limit, and the records show…
Show the result
Yes, refund 5501 for $80 on order 1042 is within the limit. The refund policy sets a $500 limit, and the records show only this one $80 refund against an $80 order. I made no changes.
4 tools held: only what the job needs.
The roles as written
tools_for returns the tools an agent in a role may call. The starting version returns the whole catalogue for every role, so a reviewer can pay a refund.
Each tool also costs context. A schema of about 150 tokens goes out with every request. The whole catalogue is thousands of tokens on each call, and four tools is a few hundred.
Does a reviewer need the refund tool?
Take the review job. The agent must check a refund against the limit and change nothing. The starting tools_for gives it every tool.
Predict: What does the agent hold?
- AOnly the read tools, because the job says to change nothing.
- BEvery tool, including the ones that pay and send, because the code gave it all.
Show the answer
B. The job text is a request. The tool list is what the agent can do. A sentence that says "change nothing" does not remove a tool.
The agent holds every tool
This is the same job with the starting code. The agent answers correctly, but it held tools that change data and needed none of them. The result card is red.
This is a real Claude Haiku 5.5 run through the Agent SDK, recorded once and replayed here.
- ColleagueRefund 5501 on order 1042 was $80. Is that within the refund limit? Answer from the…
Show the result
Refund 5501 on order 1042 was $80. Is that within the refund limit? Answer from the records and change nothing.
- Agentholds 18 tools, 10 that change data unasked
Show the result
lookup_order get_customer list_refunds get_policy process_refund cancel_order update_address issue_coupon send_email create_label track_parcel check_stock reorder_stock price_history fraud_score block_customer add_note escalate_ticket
- Toolscalled: lookup_order, list_refunds, get_policy
Show the result
lookup_order list_refunds get_policy
- AgentYes. Refund 5501 for $80 on order 1042 is within the $500 refund limit, and I made no changes.
Show the result
Yes. Refund 5501 for $80 on order 1042 is within the $500 refund limit, and I made no changes.
18 tools held: more than the job needs.
Give each role only the few tools it needs
The fix maps each role to its own short list of no more than five tools. The reviewer gets four read tools, the refunder gets the refund tool with its lookups, and an unknown role gets none. A tool several roles need, such as the policy lookup, sits in each list.
A broad tool is the same problem in one piece. Swap a general run_query for a narrow tool that reads one named table, and a wrong pick stays small.
Tools can also come from an MCP server, a program that offers tools over a standard protocol. A server can also offer a resource, a catalogue the agent can list. A team shares servers in a .mcp.json file at the repository root, and a user-level file lives on one machine.
auto, any or one named tool
A short tool list says what the agent may call. tool_choice says whether a step must call one. With auto the model may answer in words and call nothing. With any it must call some tool, and which one is still its pick. With one named tool the step is fixed.
A fourth value, none, stops every tool call. Claude Haiku 5.5, the model in these runs, accepts a forced choice. Some larger current models reject any and a named tool with a 400 error. There, keep auto and mark the tool strict, so its input still follows the schema.
choice_for(role, step) returns the choice for a step, and the tests assert it. Force a lookup first, then let the model choose for the rest. A line in the system prompt cannot set the choice, because it is a request field.
- Colleaguea review question
Show the result
review
- Agenttool_choice: any
Show the result
any
- Toolscalled: lookup_order, list_refunds, get_policy
Show the result
lookup_order list_refunds get_policy
- Agent(no words)
Show the result
tool_choice any: lookup_order, list_refunds, get_policy.
- Colleaguea review question
Show the result
review
- Agenttool_choice: auto
Show the result
auto
- Toolscalled: no tools
Show the result
- AgentTo check a refund on order 1042, I need the customer's ID so I can pull up their account and confirm the order belongs…
Show the result
To check a refund on order 1042, I need the customer's ID so I can pull up their account and confirm the order belongs to them.
tool_choice auto: no tools.
- Colleaguea review question
Show the result
review
- Agenttool_choice: tool get_policy
Show the result
tool get_policy
- Toolscalled: get_policy, lookup_order
Show the result
get_policy lookup_order
- Agent(no words)
Show the result
tool_choice tool get_policy: get_policy, lookup_order.
The same job, with a different tool list
Use the switch to run the job with every tool, then with the role's tools. The card marked "This is where the runs split" shows how many tools the agent held.
Try the refund and parcel jobs too. A refund job needs the refund tool, so scoping is not removing everything.
This part is interactive in the lab: run ./workshop watch scoped-tools.
Try it: tools and jobs
Change one setting at a time. Pick a job, then switch between every tool and the role's tools.
Every combination is a recorded run, so this works with no internet.
This part is interactive in the lab: run ./workshop watch scoped-tools.
Scoped tools in the Agent SDK
The harness serves only the tools tools_for returns from an in-process MCP server. It lists the same names as the allowed tools. role_agents writes the same table as one subagent per role.
The Agent SDK does not expose tool_choice, so the three choice rows above call the Messages API directly. This is a real Claude Haiku 5.5 run.
Every connected server's tools are available to the agent, though Claude Code may defer loading their definitions behind tool search when there are many.
- ColleagueCustomer c-77 is verified. Refund order 1042 in full and give the refund id.
Show the result
Customer c-77 is verified. Refund order 1042 in full and give the refund id.
- Agentholds 4 tools, 0 that change data unasked
Show the result
lookup_order get_customer get_policy process_refund
- Toolscalled: lookup_order, get_customer, process_refund
Show the result
lookup_order get_customer process_refund
- AgentRefund r-901 has been processed for the full $80 on order 1042. The order record doesn't show which customer it belongs…
Show the result
Refund r-901 has been processed for the full $80 on order 1042. The order record doesn't show which customer it belongs to, so I didn't confirm that it's c-77's order before refunding.
4 tools held: only what the job needs.
You do: scope each role
Copy the starting code and open work/scoped-tools/roles.py. tools_for() gives every role all 18 tools, and choice_for() always returns auto.
./workshop start scoped-tools
./workshop check scoped-tools
./workshop watch scoped-tools
The checks want five tools or fewer per role, no tool that changes data for a reviewer, and a refund tool for the refunder. An unknown role gets nothing, the read step must call a tool, and the policy step must call get_policy.
Check your understanding
Answer each question, then read why every option is right or wrong. The wrong options are the mistakes engineers make on the job.
1. A support agent holds 18 tools and picks the wrong one in 3 of every 10 calls. What is the most direct fix?
- ARewrite each of the 18 descriptions to be twice as long.
- BRaise the turn limit so a wrong pick can be tried again.
- CGive each role the 4 or 5 tools its job needs.
- DKeep all 18 so the agent can handle any request.
Show the answer
Answer: C
- A Longer text adds to the crowd the model sorts through. The list is the problem.
- B Extra turns give more chances to pick wrong, and a wrong write is not undone.
- C Correct. A short list leaves few wrong picks, and the tools a job needs stay in reach.
- D Every extra tool is another wrong option, and some of the 18 change data.
2. A read-only reviewer called the refund tool even though its prompt said never to refund. What fixes it for good?
- ARemove the refund tool from the reviewer's tool list.
- BRepeat the rule three times in the system prompt.
- CAsk the reviewer to confirm before each call.
- DRename the refund tool so it is harder to spot.
Show the answer
Answer: A
- A Correct. A tool the role does not hold cannot be called, whatever the prompt says.
- B A prompt is a request. The tool stays in the list and can still be picked.
- C A confirmation still lets the call through once the model says yes.
- D The model reads the description too. The tool is still held and callable.
3. Every review must start with the policy lookup, but in 2 of 10 runs the agent answers first. What makes the first step fixed?
- AAdd a line to the system prompt that says to look up the policy first.
- BGive the agent only the policy tool for every step.
- CSet tool_choice to auto so the model decides each step.
- DSet tool_choice to the policy tool on the first request.
Show the answer
Answer: D
- A A prompt line is followed most of the time. The 2 misses show it does not fix the order.
- B That removes the other tools the later steps need.
- C With auto the model may answer in text and skip the lookup.
- D Correct. A named tool makes the first call that tool, and the model picks freely after.
4. Which two statements about the values of tool_choice are true? Select two.
- AWith auto, the model may answer in text and call nothing.
- BWith any, the model picks the best tool for the question.
- CWith a named tool, the model calls that tool first.
- DA system prompt line can set the value for a step.
Show the answer
Answer: A, C
- A Correct. Auto leaves the decision to the model, and text is a valid answer.
- B Any only requires some call. Which tool comes back is still the model's pick.
- C Correct. The named tool is forced, so the step cannot be skipped.
- D The value is a request field. Prompt text cannot set it.
5. An agent with one broad run_query tool can read or delete any of 12 tables, and it once deleted rows. What is the better design?
- AKeep
run_queryand add a prompt line that forbids deletes. - BSwap it for a few narrow tools, such as one that reads a named table.
- CAdd 12 more tools so the agent has a choice for each table.
- DForce
run_querywith tool_choice so it is always used the same way.
Show the answer
Answer: B
- A The tool can still run a delete. A prompt line does not narrow it.
- B Correct. A narrow tool can only do its one job, so a wrong pick stays small.
- C Twelve more tools add twelve more wrong picks and keep
run_queryin reach. - D Forcing the broad tool makes the risk certain. It does not narrow it.
6. One developer wants a private notes server on their own machine, and the other 5 on the team must not get it. Where does its configuration go?
- AThe
.mcp.jsonfile at the root of the repository. - BThe system prompt of the reviewer role, as an instruction.
- CA note in the README telling each person to opt in.
- DA user-level file on that developer's machine.
Show the answer
Answer: D
- A That file is checked in, so all 6 people would get the server.
- B A prompt cannot connect a server. Servers come from configuration.
- C A README only describes a setup. It connects nothing, for anyone.
- D Correct. A user-level file lives on one machine, so only that developer gets the server.
7. A team of 6 wants the same MCP servers for everyone who opens the repository. Where does the configuration go?
- AEach person's own user-level file.
- BThe system prompt of each role.
- CA
.mcp.jsonat the repository root. - DThe README, with steps for each person to follow.
Show the answer
Answer: C
- A A user-level file lives on one machine. The other 5 never get it.
- B A prompt cannot connect a server. Servers come from configuration.
- C Correct. It is checked in, so everyone who opens the repository gets the same servers.
- D A README is read once. Nothing connects until each person does it by hand.
8. Two MCP servers are connected, one with 5 tools and one with 7. Which two statements are true? Select two.
- AOnly the first server's tools load until it is disconnected.
- BAll 12 tools are available to the agent at once.
- CConnecting more servers makes the agent safer, since it has more options.
- DA resource can list what a server offers, so the agent sees a catalogue.
Show the answer
Answer: B, D
- A Connected servers are available together, so all 12 tools are in reach at once.
- B Correct. Each connected server's tools join the same list, even if their definitions load on demand.
- C More tools are more wrong picks. Connect only what the job needs.
- D Correct. A resource gives the agent a summary of what it can reach.
9. A connected server offers 9 tools, 3 of which change data, and the reviewer role must only read. What keeps the 3 out of its reach?
- AConnect the server and list only the read tools the role may call.
- BConnect the server and tell the reviewer in its prompt to skip 3 of them.
- CConnect a second server so the reviewer has a safer choice.
- DLeave the server unconnected and give the reviewer no tools.
Show the answer
Answer: A
- A Correct. The role's list names the tools it may call, so the other 3 are never offered to it.
- B A prompt is a request, and the 3 tools stay callable.
- C A second server adds tools and leaves the 3 in reach.
- D That also removes the read tools the review needs.
Play: spot the bug
This lookup falls back to the full list when a role is not found.
def tools_for(role: str) -> list[str]:
return ROLES.get(role, ALL_TOOLS)
Predict: A config typo asks for the role "reviwer". Which tools does that agent get?
- ANone, since the role does not exist.
- BAll 18, process_refund included.
Show the answer
B. A fallback to everything turns a typo into full access. Fail closed: an unknown role gets no tools, so the mistake shows up as an agent that cannot act.
References
- Agent SDK subagents: how to give each subagent its own short tools list.
- Define tools: tool_choice auto, any, tool and none, and when each one fits.
- MCP in Claude Code: how servers add tools, and why every extra tool costs context.
- Agent SDK permissions: allowed and disallowed tools for an SDK agent.
Conclusions
- An agent can only call what it holds, so give each role the few tools its job needs, never more than five.
- A prompt that says "do not use it" is weaker than removing the tool.
- Use
tool_choiceto make a step call a tool, and name the tool when the order is fixed.
You can now write a role map and a choice for each step, so an agent's tools and its mistakes stay small.
Role
The job an agent does, which decides its tools
Scoped tools
A short list held by one agent, not the full set
Write tool
A tool that changes data or sends something
Default deny
A role that is not listed holds no tools
tool_choice
A request field set to auto, any or one named tool