Tool Descriptions Drive Selection
The model picks tools from descriptions, not names.
Tool Descriptions Drive Selection is a free Claude Architect lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Claude Architect learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Model Reads, It Doesn't Guess
When Claude decides which tool to call, it does not pick based on the tool's name. It reads each tool's description and reasons about which one fits the task.
This is the single most important fact in tool design: the description is the primary selection mechanism. A tool named process_refund with a vague description is harder to select correctly than a clearly described tool with an awkward name.
If you want reliable behavior, you invest your effort in writing descriptions — not in clever naming.
A Name Is Not a Spec
Names are short and ambiguous. Consider two tools: search_orders and lookup_order. From names alone, which one finds an order by ID? Which one filters a list by date? You cannot tell, and neither can the model.
The description carries the real meaning:
- What the tool is for (purpose).
- What it returns.
- What inputs it expects, with examples.
- Its edge cases and applicability boundaries.
Name the tool sensibly, but never rely on the name to disambiguate behavior.
Anatomy of a Good Description
A strong tool description answers everything the model needs to choose and call it correctly. Include:
- Purpose — the one job this tool does.
- Return values — what comes back, in what shape.
- Input formats with examples — concrete sample arguments.
- Edge cases — empty results, not-found, ambiguity.
- Applicability boundaries — when NOT to use it.
The boundary clause is what stops misrouting between similar tools.
lookup_order = {
"name": "lookup_order",
"description": (
"Fetch a single order by its exact order_id. "
"Returns status, items, total, and ship date. "
"order_id format: 'ORD-' + 8 digits, e.g. 'ORD-10293847'. "
"Returns an empty result (not an error) if no order matches. "
"Use this ONLY when you already have a specific order_id; "
"to find orders by customer or date, use search_orders instead."
),
"input_schema": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
}Vague Descriptions Cause Misrouting
The most common failure is a minimal or ambiguous description. It is a top exam anti-pattern, and the usual wrong answer when a question asks why a tool was mis-selected.
Watch what happens with thin descriptions:
get_data: "Gets data."fetch_info: "Fetches info."
When the task is "find the customer's latest order," the model cannot distinguish these two. It may call the wrong one, or oscillate. Overlapping or ambiguous descriptions cause misrouting — the fix is sharper, non-overlapping wording, not a renamed tool.
Draw Clean Boundaries Between Tools
When two tools could plausibly apply, each description must explicitly point away from the other. This removes the overlap that confuses selection.
Notice how each description names its sibling and states when to defer to it. That mutual boundary is what keeps the model on the right tool.
tools = [
{
"name": "search_orders",
"description": (
"List orders matching a customer_id and/or date range. "
"Returns an array of order summaries (id, status, total). "
"Use to DISCOVER orders when you do not know the order_id. "
"For full details of one known order, use lookup_order."
),
},
{
"name": "lookup_order",
"description": (
"Fetch full details of ONE order by exact order_id. "
"Use only when the order_id is already known. "
"To find orders, use search_orders first."
),
},
]Document Edge Cases in the Description
Edge cases belong in the description because they shape the model's downstream reasoning, not just the call itself.
Two distinctions matter most:
- An access failure (the system was unreachable — maybe retry) versus a valid empty result (no matches — do not retry, just report).
- What happens on ambiguous input — for example, multiple customer matches.
If the description says "returns empty when no order matches," the model won't treat 'no results' as an error to retry. If it says "returns multiple matches when the name is not unique," the model knows to ask for more identifiers rather than guess.
Keep the Toolset Small
Even perfect descriptions degrade when there are too many of them. Selection is a reasoning task, and more options dilute it.
- 4-5 tools per agent is the optimal range for reliable selection.
- At 18+ tools, selection reliability degrades noticeably.
So good descriptions and a small toolset work together: scope each agent's tools to its role, then describe those few tools precisely. A bloated toolset cannot be rescued by wording alone.
Scope Tools to the Role
Description quality and least privilege point the same direction. A research subagent should not carry a refund tool; a read-only reviewer should not carry Write or Bash.
Scoping by role does two things at once:
- Removes overlapping candidates, so the descriptions that remain are easier to tell apart.
- Keeps each agent near the 4-5 tool sweet spot.
Fewer, role-relevant tools means crisper, non-overlapping descriptions — and that is exactly what drives accurate selection.
support_agent = AgentDefinition(
name="support",
description="Resolves customer order and refund requests.",
system_prompt="Verify identity, then resolve the request.",
allowed_tools=[
"get_customer",
"lookup_order",
"process_refund",
"escalate_to_human",
], # 4 role-scoped tools, each clearly described
)Descriptions Select; tool_choice Constrains
Descriptions decide which tool fits. The tool_choice parameter is a separate lever that constrains whether and how a tool is called:
"auto"— the model picks text or a tool (selection still driven by descriptions)."any"— the model must call SOME tool; useful to guarantee structured output.{"type":"tool","name":"X"}— force one specific tool.
Forcing a tool does not fix a bad description — it just removes the choice. With "auto" or "any", the model is still reading descriptions to choose among candidates, so the wording still has to be clean.
resp = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=tools,
tool_choice={"type": "auto"}, # model selects by reading descriptions
messages=messages,
)Where Tools End and Resources Begin
In MCP, not everything should be a tool. The server exposes three primitives, and choosing the right one keeps your tool descriptions focused:
- Tools — actions that DO something (place a refund, run a query).
- Resources — read-only data and context, like schemas or catalogs.
- Prompts — reusable templates.
Modeling a read-only schema or catalog as a Resource rather than a tool removes it from the action-selection pool entirely. That is one fewer ambiguous candidate competing in your descriptions, which directly helps tool selection.
Make Errors Selectable Too
Selection doesn't stop after the first call — the model often has to choose a recovery tool next. That choice depends on the error it gets back.
A generic error like "Operation failed" gives the model nothing to route on. A structured MCP error does:
isError: trueanderrorCategory(transient / validation / business / permission).isRetryable, amessage, theattempted_query, and anypartial_results.
With this, the model can intelligently decide: retry a transient fault, fix a validation issue, or escalate a business/permission failure — instead of stalling.
{
"isError": true,
"errorCategory": "transient",
"isRetryable": true,
"message": "Order service timed out",
"attempted_query": "lookup_order(order_id='ORD-10293847')",
"partial_results": null
}Quick Check
Apply what drives tool selection to a real misrouting bug.
Recap
Key takeaways on tool selection:
- Claude selects tools by reading their descriptions, not their names.
- A good description states purpose, return values, input formats with examples, edge cases, and applicability boundaries.
- Overlapping or ambiguous descriptions cause misrouting; draw explicit boundaries that point each tool away from its siblings.
- Document edge cases in the description — especially empty results vs access failures and ambiguous matches.
- Keep 4-5 tools per agent; selection degrades at 18+. Scope tools to the role.
tool_choice(auto / any / forced) constrains calling but does not replace a clear description.- Model read-only data as MCP Resources, and return structured errors so the model can route recovery.
Frequently asked questions
Is the “Tool Descriptions Drive Selection” lesson free?
Yes — the full text of “Tool Descriptions Drive Selection” is free to read here on the web, and the Claude Architect course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Claude Architect course, upgrade to CoddyKit PRO.
What will I learn in “Tool Descriptions Drive Selection”?
The model picks tools from descriptions, not names. You practise Claude Architect with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Claude Architect?
No prior experience is required. Claude Architect on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Tool Descriptions Drive Selection” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Claude Architect lesson?
Yes. Every Claude Architect lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Tool Descriptions Drive Selection
- Anatomy of a Great Description
- Avoiding Overlapping Tools
- Input Formats & Examples