Most writing about agent failure collapses into a single word: hallucination. It’s not a useful category. It describes a cause, badly, and tells you nothing about what to look for or what to build.
What follows is a taxonomy — the ways agent systems actually break in production, grouped by where the failure originates. That grouping matters, because it maps to who fixes it. Boundary failures are engineering problems. Planning failures are design problems. Input failures are security problems. Scale failures are operations problems. Accountability failures are the ones that make all the others unfixable.
Use it as a checklist during design review, or as a starting point when something has gone wrong and you’re trying to name it.
Family 1 — Failures at the boundary
The agent talks to a tool and the interaction goes wrong. These are the most common failures and the most fixable, because they’re ordinary distributed-systems problems that happen to have a model at one end.
Silent side effects
A tool does more than its description implies. “Update record” also fires a webhook that emails the customer. The agent had no way to know, and neither did whoever approved the tool.
You detect this by auditing what each tool actually does rather than what it says — usually after a customer asks why they got three emails. Prevention is declaring side effects in the schema the model reads, and treating an undeclared side effect as a bug in the tool, not a mistake by the agent.
Retry amplification
The agent retries a non-idempotent write. Two invoices, two refunds, two bid adjustments. Every individual call succeeded, so nothing errored, and the logs look clean.
Detect it by reconciling counts — actions taken versus actions intended — rather than by watching for errors, because there are none. Prevention is idempotency keys honoured all the way down to the datastore. Note that “our API is idempotent” is a claim worth testing rather than believing; this is the single most common false assumption I encounter.
Partial completion
A multi-step operation fails halfway. The order was created; the inventory was never decremented. The agent, seeing a failure at step three, may retry the whole sequence and re-run step one.
This is the classic distributed transaction problem, and agents make it worse by improvising recovery. Prevention is explicit compensation paths, and a contract that distinguishes “failed cleanly” from “failed after partial application.”
Success ambiguity
The tool returns something like {"status": "ok"} for a write that was actually queued, or partially applied, or accepted-pending-validation. The agent proceeds believing the world changed. It hasn’t yet, or it changed differently.
Vague success is worse than clear failure: failure gets handled, ambiguous success gets built upon. Every subsequent step in the plan now rests on a false premise.
Stale reads
The agent reads state, reasons about it, and acts — but time passed, and something else changed the state in between. The longer the reasoning step, the wider the window, and reasoning steps are slow.
Conventional systems hit this too, but an agent’s think-time turns a millisecond race into a multi-second one. Prevention is conditional writes: assert the state you read is the state you’re acting on, and fail loudly if not.
Family 2 — Failures in the plan
The agent’s reasoning goes wrong in structured, recognisable ways. These are harder to test for, because the output is often locally reasonable.
Tool misselection
The agent picks a plausible wrong tool — the one with the similar name, the one that worked last time, the destructive one when a read-only equivalent existed.
This gets much worse as the tool count grows, and it’s a strong argument for giving any single agent a small toolset. Detect it by logging tool choice against task type and looking for the surprising pairings.
Plan drift
Over a long run, the agent gradually loses the original objective. Each step follows sensibly from the last, and step forty has little to do with what was asked. Nothing went obviously wrong; the goal simply eroded.
Detect it by comparing final outcome to original request — not by inspecting individual steps, which all look fine. Prevention is bounded runs, explicit stop conditions, and re-grounding the objective rather than relying on it surviving in context.
Premature completion
The agent declares success while the work is incomplete. It wrote the file but didn’t save, ran the tests but ignored two failures, answered the easy half of a two-part question.
This one is insidious because the agent’s own report is confident and the summary reads well. Prevention is verification that doesn’t come from the agent — a separate check that the claimed end state actually exists.
Loop failure
The agent gets stuck: same action repeatedly, or a cycle of two actions undoing each other. It doesn’t recognise the loop because each step is locally justified.
Retry budgets and wall-clock timeouts catch this. Without them it runs until something else stops it, and the something else is usually a bill.
Irreversibility preference
Offered a safe path and a destructive one that both satisfy the request, the agent picks the destructive one — delete and recreate rather than update, overwrite rather than merge. It’s often the simpler plan, and simplicity is what the model is optimising toward.
Prevention is structural: don’t expose the destructive tool when a safe equivalent exists, and gate the ones you must expose.
Family 3 — Failures from input
Something the agent read changed what it did. Covered in depth in Threat Modeling an AI Agent; summarised here for completeness.
Instruction injection
Untrusted content instructs the agent. The ticket body, the web page, the code comment, the filename. Privilege escalation through an input channel, not a prompting problem.
Context poisoning
Corrupted content is planted where it will be read later — the retrieval corpus, persistent memory, a tool description. The failure is delayed and detached from its cause, which makes attribution hard.
Context dilution
The relevant instruction is present but buried. In a long context, material in the middle is weighted less reliably, so a constraint stated once at position 40,000 may simply not govern behaviour.
This one masquerades as disobedience. The agent didn’t ignore your rule; it barely saw it. Detect by testing the same constraint at different context positions.
Self-reference loops
The agent reads its own prior output as though it were ground truth — a summary it wrote, a note it filed, a record it created. Errors compound across runs, and each iteration gains confidence because the claim now appears in the record.
This is the mechanism by which a small early mistake becomes an established fact. Prevention is marking agent-generated content as such wherever it’s stored, so a later run can weight it appropriately.
Family 4 — Failures at scale
Everything works in one run and breaks across thousands.
Cost runaway
No attacker required. A retry loop, a large context, a task that turns out to be unbounded. The first signal is the invoice, because nothing was down and no alert fired.
Per-run and aggregate ceilings. Per-run alone won’t catch ten thousand individually reasonable runs.
Concurrency collision
Two runs act on the same resource simultaneously. Each is correct in isolation; together they double-apply a change or interleave into an invalid state.
Almost nobody tests for this, because development and evaluation are single-run activities. Prevention is locking or partitioning by resource, exactly as you would for any concurrent writer.
Cascading escalation
One agent’s output becomes another’s input, and a small error amplifies down the chain. Each agent behaves reasonably given what it received; the aggregate is wrong, and no single component is at fault.
This is the failure mode multi-agent architectures introduce and rarely account for. The more hops, the less any individual trace explains.
Threshold miscalibration
The confidence threshold governing what runs automatically doesn’t reflect reality — the model’s 90% is really 75%, so a routing rule you believed was conservative is not.
Covered in What Horse Racing Taught Me About Model Confidence. Worth listing here because it presents as a sudden rise in bad automated decisions with no code change to blame, which sends people hunting in the wrong place.
Family 5 — Failures of accountability
The system may be working. You can’t demonstrate it, which in a regulated or high-stakes context is the same as it not working.
Unattributable action
Something changed and nobody can say which run did it, or why. Not primarily a security problem — an inability to know whether you have one.
Unreproducible decision
You can see what the agent did but can’t reconstruct why. Without the inputs, the plan, and the policy evaluations, a postmortem becomes speculation, and the fix becomes a guess.
Undetected drift
Behaviour changes gradually — a model update, a schema change, a shifting data distribution — and nobody notices because nothing failed loudly. The system is quietly worse than it was last quarter.
The only defence is a fixed evaluation set run on a schedule. Without one, you’ll find out when a customer tells you.
Using this
Two ways.
At design review, walk the families against your system and ask which apply. Most teams find three or four they hadn’t considered, and the boundary family usually produces the largest number of quick wins.
At incident review, name the failure before proposing a fix. “The agent hallucinated” produces no action. “Retry amplification, because the downstream API accepted our idempotency key and ignored it” produces a specific, testable fix — and tells you to go looking for every other write path with the same assumption.
That’s the real value of a taxonomy. Not completeness — this list isn’t complete and can’t be — but precision. A named failure mode is one you can search your system for, and one that a fix can actually close.
The prevention mechanisms behind most of these are collected in The Agent Reliability Handbook. This is the list of what you’re preventing.