The support bot gives fluent, specific answers about live facts — "your order ships
Tuesday", "14 units in stock", "refund processed yesterday" — and some of them are
wrong. A user checks the real system and finds no such order. When you grep the
logs, the tool_calls field is empty for every one of these answers: the model
never requested the tool it was given. The answers came from nowhere.
A fresher's first tool-use build, usually right after wiring a lookup tool into the chat loop. The tool works when tested by hand. The failure appears in normal conversation, and it is worst with small local models, chatty question phrasing ("any idea when my order might come?"), and vague tool descriptions. Hosted models do it too, less often. Nobody notices for days because the invented answers sound exactly like the real ones. Linked module: 3.8 (Tool use / function calling).
Offering a tool does not force the model to use it. Tool use is a choice the model makes per turn, and its other option — writing likely-sounding words — is the thing it was trained to do. When the description does not clearly claim the question, or the question is phrased conversationally, the model takes the cheaper path and answers from prediction. It sounds most confident precisely when it is inventing, because nothing constrains the text. Confirm the diagnosis in two steps. First, count answers containing live facts against answers containing a logged tool call — any gap is this failure. Second, run a trap question whose true answer only the tool can know, such as an order id you created one minute ago: if the bot answers without a call, it is guessing by design, not by accident.
Three layers, in order of strength. First, detection in the harness: if a reply contains a final answer about live data but the turn contains no tool call, reject it and re-ask with an instruction to use the tool — code catches what prompts miss. Second, force the call where the API allows it: most providers accept a tool-choice setting that requires the model to call a named tool for that turn; use it on routes where a lookup is always needed. Third, rewrite the description so it claims the territory: "Use this tool for ANY question about order status, dates, or delivery — never answer these from memory", and add the same rule to the system prompt. Re-run the trap questions; every live-fact answer must now carry a call.
Log tool_calls per turn from day one, and alert when a live-fact answer ships
without one — the metric is cheap and the failure is invisible without it. Keep
three to five trap questions (ids and facts that exist only in your system) in the
regression run after every prompt, description, or model change. Treat an uncited
live fact as a failure even when it happens to be right; the habit you are
protecting is that every number traces to a tool result.
Q: "Your bot has a working order-lookup tool but sometimes states shipping dates without calling it. What is happening and what do you do?" Strong answer: state that tool use is optional to the model and prediction is its default, name the trap-question probe with a fact only the tool can know, and give the layered exit — detect answers with no call in the harness, force tool choice on lookup routes, and sharpen the description to claim the question. Bonus for noting the bot sounds most confident exactly when it never looked.