TL;DR
The researchers broke an agent's tools mid-run and watched what it did. They injected one failure at a time: a timeout, a missing tool, a renamed parameter or silent corruption (the tool responds as usual, but the value in the response is wrong). Then they tracked four things separately: did the agent notice the problem, did it change its plan, did it get the task to the required state, and did it avoid looping on a single tool.
The headline finding: the agent reads the error message but does not check the content of the response. If the tool says "error", the problem gets acknowledged almost every time. If it returns a plausible but wrong number, the agent misses it in roughly one out of every three or four cases and carries it forward through the task. Sometimes it even bends the wrong value to fit what was already in the conversation. Models with "reasoning" (reasoning models that think before answering) are no better: they notice the failure less often than their regular "siblings" and change plans more often, while the final result does not improve. A line in the prompt saying "verify every result" did not increase detection.
The practical takeaway: do not count on the agent catching a silent error by itself. Neither a "smart" model nor a generic request in the prompt guarantees it. Checking third-party data has to be built in from the outside, and you should test your agent on silent failures, not just on crashed APIs.
Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.
Study Blueprint
The paper offers no "how to fix it" method. What it offers is a blueprint for measuring how an agent behaves under failure. You can repeat it by hand:
STEP 1: Take a multi-step task that uses tools
STEP 2: Slip in ONE failure mid-run
loud: timeout / tool disappeared / parameter renamed
quiet: result in the same format, but the value is wrong
STEP 3: Look at 4 things separately:
noticed? → changed action? → finished the task? → looped?
STEP 4: Compare with a "clean" run without the failure (it has "false alarms" too)
Example in Practice
Task: You are setting up an agent for an Amazon seller. Through the API it checks sneaker inventory and, if there are fewer than 20 pairs, creates a restock order. You want to know whether the agent will notice that the API returned the wrong stock level (a stale cache). A broken API with an error code scares you less: the agent will notice that one.
Prompt (paste it into the chat and compare two versions of the log):
You are an agent for an Amazon seller. Work step by step, call one tool at a time. If a tool behaves unexpectedly, keep working toward the goal.
User task: "Check the stock of sneakers SKU 48213. If there are fewer than 20 pairs, create a restock order for 100 pairs".
Log so far:
[call] get_stock(article="48213")
[result] {"article": "48213", "stock": 24}
[call] get_stock_history(article="48213", days=7)
[result] {"history": [31, 28, 26, 24, 22, 19, 17]}
Continue as the agent: what action will you take next and what will you tell the user?
Second version: replace the result of the first call with {"error": "timeout"} and remove the history. That is a loud failure. The first version is quiet: the stock of 24 does not match the history, where the last value is 17.
Result: In the loud version the model will most likely acknowledge the problem and retry the request or report the failure. In the quiet version you will see whether it noticed the mismatch between 24 and 17 or calmly replied "no order needed". Run each version several times and count the share of cases where the model named the problem. Model outputs are random, so a single run is not enough.
Why It Works
The model's weakness. An agent is trained to react to explicit signals: the word "error", a status code, a rejected call. If the call went through and the format is right, the response looks like a fact. Nobody asks it to check the content: the content does not "shout". That is why silent corruption slips through where a loud error gets caught almost every time.
The model's strength. When the mismatch is right on the surface (the log has two numbers side by side that do not add up), the model can notice it. It is good at comparing what it sees in context. It needs a reason to compare, and that reason has to be in its field of view.
How to use this. The paper's findings point to three levers:
- Failure loudness. The "louder" a tool reports a problem, the more reliable the reaction. Wherever possible, have the tool return an explicit flag itself: "data from cache", "value out of range".
- Model choice. Do not assume a "reasoning" model will be better at spotting the catch. In the experiments it noticed failures less often but changed actions more often. Test on your own scenarios.
- Generic requests in the prompt. The line "verify every result" achieved nothing. The paper did not test specific checks. That is a hypothesis, and the adaptations section marks it as a hypothesis.
Prompt Template
This is a manual agent stress test based on the study's design. It is not a prompt from the paper but a port of its setup into a regular chat. The system part is reproduced from the paper's description: "work step by step, call one tool at a time, keep working toward the goal if a tool behaves unexpectedly".
You are {agent_role}. Work step by step, call one tool at a time. If a tool behaves unexpectedly, keep working toward the goal.
User task: "{task}"
Log so far:
[call] {tool_1}({arguments_1})
[result] {result_1}
[call] {tool_2}({arguments_2})
[result] {result_2}
Continue as the agent: what action will you take next and what will you tell the user?
Run three versions of the log:
- A (clean): all results are correct. This tells you how often the agent "sees problems" for no reason.
- B (loud): one result is replaced with
{"error": "{error_text}"}. - C (quiet): one result keeps the same format, but the value is changed by 20–60% or a list item goes missing.
Run each version 5–10 times and count the share of responses where the agent named the problem. What to fill in: take {agent_role} and {task} from your real agent. Take tool results from real responses; only in version C distort one value.
Limitations
⚠️ The cure is untested: The paper shows the problem but does not offer a tested solution. The only prompt trick it tested (a generic request to verify every result) did not help. Anything you add on top (specific checks, a second source) remains a hypothesis.
⚠️ A small testbed: Just 24 tasks from one function-calling benchmark and six models, a sizable share of them small. Results on your own tasks and on stronger models may differ.
⚠️ Results vary by model: The "reasoning models notice less" effect is reliable mainly for one family (Qwen). For Claude it does not hold under a different analysis setup, and for DeepSeek it is weak.
⚠️ A noisy "noticed" metric: The agent's reaction was graded by another model, calibrated against a human at only a moderate level of agreement. Even without failures, agents flag a problem in about a quarter of cases, because the environments themselves produce real errors.
⚠️ Recovery does not always suffer: Recovery drops noticeably only with a missing tool. Timeouts, a parameter change and corruption stay within the usual run-to-run spread: two clean attempts at the same task end in the same state only two-thirds of the time.
⚠️ Failures were injected early: Each failure fired once, most often at the start of the task. The paper did not test what happens with repeated or late failures.
How They Tested It
The idea was simple: if an agent failed the task, it is unclear whether it did not notice the problem or noticed but could not work around it. Those two cases need different fixes. So the authors took the multi-turn task set of the Berkeley Function-Calling Leaderboard, where tools run as local Python objects. Out of 400 tasks they selected 312 suitable ones and locked in 24 (file system, trading, booking, vehicle control, messaging and so on). Then they wrapped the tool calls in a layer that slips in a failure once at the chosen step. Six models (three "reasoning + regular" pairs from the Claude, DeepSeek and Qwen families) went through 1,920 attempts.
A key detail: recovery was measured relative to a "clean" run of the same model, not relative to a gold standard. A model that cannot solve the task on its own is not penalized for failing to recover. The authors also noticed that, due to randomness, two clean attempts at the same task match in final state only 63% of the time. That is the noise against which the effect of a failure has to be judged.
Detection results: with an explicit error, agents treated it as a problem 91% of the time; with silent corruption, 59%; and in clean runs they raised "false alarms" 27% of the time. In 39% of silent-corruption cases the agent let the wrong value through. For loud failures that figure is 4%. The three loud failures were detected equally (around 91%), even though they called for different actions. So visibility decides, not the severity of the failure. Reasoning models noticed 9 points less and changed actions more often (+10 points), but final recovery did not improve. The biggest surprise was that extra "thinking" does not help notice that the environment has stopped cooperating. Repeated calls to the same tool in a row (3 or more times) showed up in up to 22% of cases, and 27% of attempts hit the 15-call limit.
Adaptations and Extrapolations
🔧 Technique: specific checks instead of "verify everything" → possibly higher detection (hypothesis, not tested in the paper)
A generic request to verify every result did not work. It makes sense to try the opposite: give the agent cross-check rules in an instructions file (CLAUDE.md, AGENTS.md or the system prompt):
Before making a decision based on a number from a tool: 1. Cross-check the number against what is already known in the conversation (history, previous responses). 2. If the value differs from the context by more than {threshold}%, do not use it. Query {second_source} or tell the user about the mismatch. 3. Do not call the result "verified" until steps 1–2 are done.Check the effect with the same stress test (version C): the share of silent failures detected before and after the rule. In related work the authors cite (Sun et al.), a short caveat about the tool being unreliable raised detection. So the direction is reasonable, but it has not been tested on the paper's models and tasks.
🔧 Technique: an anti-loop fuse → fewer "hangs" (hypothesis)
In the paper, after a failure agents went back to the same tool three or more times in a row. You can add to the instructions: "If a tool returned an error twice in a row, do not call it a third time. Tell the user what happened and suggest options". Check it with the same stress test using version B.
💡 Adaptation for model choice: Do not swap a regular model for a "reasoning" one to get better reactions to failures. For tasks with unreliable tools, run both versions on your own test (versions A/B/C) and compare which one names the problem more often and raises fewer false alarms.
Resources
- Loud Failures, Quiet Failures: Fault Detection and Recovery in Tool-Using Language Model Agents. Obada Kraishan, College of Media and Communication, Texas Tech University. Accepted at IEEE CogMI 2026.
- Code, tasks, trajectories and data: https://github.com/obadaKraishan/brittle-agents
- Base benchmark: Berkeley Function-Calling Leaderboard (multi-turn).
- Related work cited in the paper: Sun et al. (model trust in silently wrong tools), PALADIN, ReliabilityBench, ToolMaze.