toolcall() ← all concepts

// concept · tool descriptions

Your agent skipped the tool you gave it.

You wrote the function, wired it up, and the model answered from memory instead. It isn't ignoring you — it never saw the part you spent your time on.

// the assumption

You register a tool and quietly assume the model has some sense of what it does — that it can tell a well-written function from a broken one, or infer behaviour from the code, the types, the docstring buried in the body.

# what you think you handed over def weather(city: str) -> dict: """Hits the forecast API, 15-min cache, falls back to the last good reading.""" ... # 200 careful lines

The model sees three things

A tool definition is exactly a name, a description, and an input schema. That's the whole surface. Your implementation is never sent — not the body, not the comments, not the type hints, not the file it lives in. The model picks which tool to call by reading those three fields and nothing else.

# what actually crosses the wire { "name": "weather", "description": "Gets the weather", "input_schema": { "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] } }

So "the model ignored my tool" is almost always "the model read one vague line and decided it probably wasn't relevant." The description is the interface. It isn't documentation for your teammates — it's the only pitch the tool gets to make.

Say when, not just what

This is the single highest-leverage change. Most descriptions state what the tool is. The model's actual problem is deciding whether to reach for it right now, and that's a different question. Be prescriptive about the trigger condition.

"Gets the weather" "Weather utility" "Get current weather for a location. Call this when the user asks about current conditions, today's forecast, or whether to bring an umbrella. Do not use it for historical weather."

The official guidance is explicit about this: write detailed descriptions and be prescriptive about when to call, not just what it does. On recent Opus models — which reach for tools more conservatively by default — stating the trigger conditions in the description gives a measurable lift in how often the tool actually gets called when it should.

No number here on purpose. The source says "measurable lift" and "meaningful lift" and gives no percentage — so neither do we. Also: that behavioural finding is documented on recent Opus models. The mechanism (selection from name + description + schema) is general to tool and function calling everywhere; the size of the effect is model-specific.

The rest of the surface

Three more levers, all on the same three fields:

Name it specifically. get_current_weather beats weather. The name is read as part of the pitch, not as an identifier.

Describe every property. The description field isn't the only prose the model gets — each schema property carries its own. Use enum where the values are fixed, mark only the genuinely required parameters as required, and give the rest defaults.

Keep the set focused. Too many tools can confuse the selection. If you genuinely have a large library, that's what dynamic tool discovery is for — load the relevant few rather than every definition into the context window.

"input_schema": { "type": "object", "properties": { "city": { "type": "string", "description": "City name, e.g. 'Singapore'" }, "units": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Defaults to celsius" } }, "required": ["city"] # units is optional — don't over-require }
No tool-count threshold exists. "Too many tools can confuse the model" is the claim; there is no published "more than N and it degrades" figure. You may see a hard cap of 128 tools per agent on one product surface — that's a limit, not the point where quality falls off. Don't treat it as a target.

The fix

Before you debug the agent, read your tool definitions the way the model does: name, description, schema, nothing else. If you can't tell when to call it from those three fields alone, neither can the model.

1 specific name # get_current_weather, not weather 2 description says WHEN # "call this when the user asks…" 3 every property described# + enum for fixed values 4 only truly required # everything else optional + default 5 keep the set focused # discovery beats a wall of definitions
A bad description doesn't error. The model can still call a poorly-described tool — the failure mode is silent: it picks the wrong tool, or doesn't call one at all and answers from memory. Nothing in your logs says "description too vague," which is exactly why this one survives so long.

Related: tools vs. resources vs. prompts covers which primitive to reach for; this page is about making the one you chose actually get picked. And idempotent tools covers what happens after it does.

Source: the authoritative Claude API tool-use reference (tool-use concepts and agent-design guidance) — tool definitions carry only name, description and input schema; descriptions should be prescriptive about when to call; names should be specific; property descriptions and enum matter; and tool count should stay focused. Verification notes: content/research/tool-description-ignored.md.

One concept a week. Free.

The deeper, copy-paste version of each ToolCall short — in your inbox.

// total: 0.00 · spam: void · unsubscribe: one click