How to fix: model won’t call my tool / function calling not triggering
Last verified: June 2026· Tool use and agents
Where this shows up
Tool use and agents
How it shows up
The same root cause surfaces in a few different ways. If any of these match, you're in the right place.
- The model answers in prose describing what it would do, instead of emitting a tool call.
- The tool fires for some phrasings of the same request and not others.
- One tool is always chosen over another that fits better — usually the descriptions overlap.
- The model invents a plausible answer rather than calling the tool that would have retrieved the real one.
- Tool calls work in a short conversation and stop working as the context grows.
Diagnose it first
Confirm which cause you actually have before changing anything — most wasted time here comes from fixing the wrong one.
| Check | What the result tells you |
|---|---|
| Log the exact request body and confirm the tool array is present. | Tools dropped by a wrapper, a conditional, or a framework default cannot be called. Verify at the wire, not in your application code. |
| Ask the model directly why it did not use the tool. | Models are reasonably good at reporting that a description was ambiguous or seemed inapplicable, which points straight at the wording to change. |
| Test the tool in isolation with no other tools registered. | If it fires alone but not alongside others, the descriptions overlap and the model cannot tell which one applies. |
| Check whether the schema validates. | An invalid or unsupported JSON Schema construct can cause a provider to reject or ignore the tool, sometimes without a clear error. |
| Re-test the same request with a much shorter conversation. | If it fires in a short context and not a long one, tool definitions are competing with accumulated context rather than being misunderstood. |
The fix
- 1Rewrite the tool description to be prescriptive about *when* to call it, not just what it does (e.g. “Call this when the user asks about current prices or recent events”).
- 2Raise the effort/reasoning setting if your model supports it — higher effort generally increases appropriate tool use.
- 3Add explicit guidance in the system prompt for when the tool is required.
- 4Verify the tool schema is valid and the tool is actually included in the request.
- 5Avoid over-aggressive language (“CRITICAL: you MUST…”), which can cause modern models to over- or mis-trigger.
Provider-specific behaviour
The error means roughly the same thing everywhere, but each provider signals it differently.
- Tool choice parameter
- Most providers expose a tool-choice setting that can force a specific tool, require some tool, or leave it automatic. Forcing is the correct answer when a call is genuinely mandatory for a route — it is a control, not a workaround. Leaving it automatic and hoping is what produces intermittent behaviour.
- Parallel tool calls
- Several providers emit multiple tool calls in one response. Client code that reads only the first call silently drops the rest, which presents as "the tool did not run" even though the model requested it correctly.
- Strict schema modes
- Some providers offer a strict mode that guarantees arguments conform to your schema. It removes a whole class of malformed-argument failures, but it constrains which schema features you may use — unsupported constructs are rejected outright rather than ignored.
- Reasoning effort
- Where a model exposes a reasoning or effort setting, low values bias it toward answering directly rather than planning a tool call. Raising effort for tool-heavy routes often resolves under-triggering without any prompt change.
What doesn't work
Common fixes for this error that look right and aren't.
Adding "CRITICAL: you MUST ALWAYS call this tool" to the description.
Emphatic instructions tend to produce over-triggering — the tool fires when it is irrelevant — which is harder to detect than under-triggering and degrades answers across the board. If a call is truly mandatory, set tool choice explicitly instead of arguing with the model in prose.
Registering many narrowly-scoped tools to be thorough.
Every additional tool makes selection harder and increases overlap between descriptions. A smaller set of well-separated tools is chosen more reliably than a large set of near-duplicates.
Describing what the tool does and stopping there.
The model already infers roughly what a tool does from its name and schema. What it lacks is the trigger condition — when to reach for it — and that is the part most descriptions omit.
Prevent it
Treat tool descriptions as part of the prompt and validate tool-use behavior with evals across representative inputs.
Common variations and related errors
You'll usually hit this same root cause under a few different names. Same fix.
- "tool not called"
- "function calling failed"
- "agent stopped before tool"
- "no tool_use in response"
Frequently asked questions
What causes “model won’t call my tool / function calling not triggering”?
The tool description is vague, the model is being conservative, or the prompt doesn’t make clear when the tool should be used.
How do I prevent “model won’t call my tool / function calling not triggering” from recurring?
Treat tool descriptions as part of the prompt and validate tool-use behavior with evals across representative inputs.
How should I write a tool description so the model reliably calls it?
Lead with the trigger condition, not the capability. "Call this when the user asks about current prices, availability, or anything after your knowledge cutoff" outperforms "Fetches product data" because it tells the model when the tool applies. Then state explicitly what the tool does not cover, so it can be ruled out cleanly when a neighbouring tool is the better fit.
Should I force tool use with the tool-choice parameter?
Yes, when the route genuinely requires it — a lookup that must hit live data should not be left to the model's discretion. Forcing is the right control for a mandatory call. Reserve automatic selection for routes where calling the tool is genuinely optional, and fix descriptions rather than forcing when the issue is that the model cannot tell two tools apart.
Why does the tool fire in testing but not in production?
The usual difference is context length and prompt composition. Production requests carry longer histories, more retrieved content, and more system instructions, all of which compete with the tool definitions. Reproduce with a realistic production-length context rather than a clean one, and the failure normally appears immediately.