An agent that crashes is a bug report. Somebody sees a stack trace,
files it, and it gets fixed. The failures that cost real money are the
other kind: the run finishes, the summary is well written, the
confidence is high, and the work is wrong. Nothing in your monitoring
moves, because from the outside a wrong answer and a right answer are
both a completed run.
Most teams learn this in the same order. They ship an agent, watch
the success rate, and it looks fine. Then somebody downstream finds a
reconciliation that was never actually reconciled, or a report built
on a number no tool ever returned, and the question becomes: how long
has this been happening, and how would we know?
The answer to the second half is that you would not, unless you
built for it. What follows is the taxonomy that matters in production:
eight failure modes worth naming, the specific signal that catches
each one, and what to do when it fires. The names are less important
than the fact that they are distinct. Each one has a different
detector, a different recovery, and a different owner, and a team that
treats agent failure as one undifferentiated category ends up with one
undifferentiated response to it, which is usually a retry.
The short version
Failure enters at a specific stage of the loop.
The agent can misread the world, act wrongly on it, or misdescribe
what it did. Three families, and the third one is the expensive
family.
Loudness and cost are inversely related. A
malformed tool call is caught in the same turn it happens. A silent
partial completion is caught by someone downstream, weeks later, if at
all. The modes that are easiest to detect are the ones that matter
least.
The report is not evidence. The summary is the
part of the output the agent controls most and grounds least. Every
check worth running compares the report against the trace, or skips
the report entirely and checks the end state.
Detection is three layers, and most teams have two.
Turn-level invariants run inside the loop and are blind to the
expensive modes. End-state verification is the truth and cannot run on
live traffic. The layer in between is the one that is usually
missing.
Some of this is not a model problem. Two of the
eight modes are fixed by permissions and protocol, not by training.
Knowing which is which is most of the value of naming them.
Where failure enters the loop
An agent run is one small cycle repeated: look at the state,
decide on an action, call a tool, interpret what came back, and
eventually report. That structure is what makes agents useful and it
is also what makes them fail differently from a single model call. A
chat completion is wrong or right in one shot. An agent has twenty
chances to go wrong, each one conditioned on the output of the last,
and errors compound rather than average out.
It also means failure is not a single event with a single cause.
It enters at a stage, and the stage tells you which detector could
possibly have caught it.
Family 3 is the one that finishes the run, reports success, and is wrong.
The eight, named
1. Goal drift. The task the agent is working on at
turn twenty is not the task it was given at turn one. Nothing
dramatic happens; each turn is conditioned on the agent's own
restatement of the work, restatements lose qualifiers, and after
enough of them the qualifier that made the request specific is gone.
Ask for the cash break on one book and get a careful, correct,
well-presented answer about the whole desk. The tell is that the
output is good. It is a competent answer to a question nobody
asked.
2. Context decay. The goal survives but a
constraint does not. "Read-only", "staging only", "exclude the
internal counterparties" holds for six turns and then quietly stops
holding. This is worth separating from drift because the symptom is
different: the run starts compliant and ends non-compliant, so a spot
check on the first few turns finds nothing wrong. Constraints stated
once in prose, in the middle of a long instruction, are the ones that
go first.
3. Empty-result fiction. A tool returns zero rows,
a null, or the worst case, HTTP 200 with an error in the body. The
agent treats absence as a gap to fill and supplies a plausible value.
This is the most damaging mode in any numerical domain, because the
fabricated output is formatted exactly like a real one and there is
no downstream signal that distinguishes them. It is also the mode
most obviously worsened by good prose: a model that writes well makes
a fabricated reconciliation read like a finished one.
4. Malformed tool call. Wrong argument name, a
string where the schema wants an epoch, an enum value that does not
exist, a required field invented from a similar public API. This is
the loud one, it is caught by schema validation in the same turn it
happens, and it traces back to a model that has read every public API
reference and none of yours. It is also the mode most people mean
when they say their agent is unreliable, which is unfortunate,
because it is the cheapest of the eight to fix. See
tool-use fine-tuning for
the specific remedy.
5. Doom loop. The agent repeats an action that
cannot succeed. Sometimes literally the same call twelve times, more
often a short cycle: the call fails, the agent calls something
diagnostic, reads it, and makes the same failing call again. Budget
goes to zero and nothing is produced. Loops are easy to detect and
almost never detected, because the naive check looks for identical
consecutive calls and a two-step cycle is not consecutive.
6. Unauthorized side effect. A write outside the
permitted surface. The important property of this mode is that it can
coexist with a correct answer, which is why it has to be counted as a
failure on its own terms rather than folded into a correctness score.
An agent that produced the right number after updating a table it
should never have touched did not pass, and a scoring scheme that
says otherwise is training you to ignore it.
7. Silent partial completion. The job needed five
steps. Three ran. The summary says the job is done. This is the
single most expensive mode in the list, not because it is the most
common but because the detection lag is measured in weeks and the
discovery is almost always external. Somebody downstream finds the
hole, and by then the same agent has done the same thing a few
hundred more times.
8. Handoff cascade. In any setup with subagents or
a chain of specialists, an upstream agent's guess arrives downstream
as an established fact. The uncertainty is stripped at the boundary,
because what crosses the boundary is a conclusion and not the
reasoning that produced it. The receiving agent has no way to know
the difference and treats it as a premise. One soft guess early
becomes a firm and completely wrong conclusion three hops later, and
the trace of the final agent looks impeccable.
The detection lag is the actual cost
Rank those eight by how bad they are and you get roughly the
reverse of how loud they are. The mode that fires an exception is
cheap. The mode that files a well-formatted report is not.
Every bar past the second gridline is a failure your dashboards currently score as a success.
The signal that catches each one
Nothing above is detectable by watching a success rate, because in
six of the eight cases the run reports success. Each mode needs its
own signal, and the useful property of a named taxonomy is that the
signals turn out to be specific and cheap.
Failure mode
What you see
The signal that catches it
First response
Goal drift
A good answer to the wrong question
Anchor check: final result against the original request, stored verbatim
Roll back, re-plan from the original text
Context decay
Compliant early turns, non-compliant late ones
Constraint retention: re-assert every constraint against the last turn
Move constraints out of prose and into the guard
Empty-result fiction
A plausible number with no source
Claim-to-evidence: every figure in the summary must cite a tool result
Fail closed, and make empty results structurally distinct
Malformed call
Tool errors, arguments rejected
Schema validation before dispatch
Bounded retry with the error fed back
Doom loop
Budget consumed, nothing delivered
Action hash repeating with no state change in between
Halt. Never allow an identical retry
Side effect
Often nothing, until an audit
Write allowlist, enforced at dispatch rather than reviewed after
Halt and escalate. This is a permissions bug
Silent partial
A confident summary of unfinished work
Step coverage: each required step present in the trace with a status
Require structured completion, not prose
Handoff cascade
An impeccable trace built on a guess
Provenance: confidence and source carried in the handoff schema
Propagate uncertainty, or refuse the handoff
LLM agent reliability is three layers, not one
Sort those signals by when they can run and they collapse into
three layers with very different properties. This is the part worth
internalizing, because the gap is nearly always in the same
place.
Teams tend to build 1 because it is easy and 3 because it is rigorous. The gap in the middle is where the costly modes live.
TURN INVARIANTS
Cheap assertions inside the loop, checked before each tool call: schema valid, target on the write allowlist, budget not spent, action not a repeat of one already tried. Microseconds each, and the only layer that can stop a bad run while it is still bad.
TRAJECTORY CHECKS
Rules and one small model call run over the recorded trace once the run ends: does the answer match the original request, did every constraint hold to the last turn, does every claim in the summary have a source. This is the missing layer.
END-STATE VERIFICATION
The verifier from your eval set, comparing the world against a known-correct outcome. Definitive, and restricted to tasks where a gold answer exists, which means it measures your agent rather than watching it.
Layer one is where everyone starts and it is genuinely worth
having, because three of the eight modes stop being possible once it
is in place. It is also structurally incapable of catching the other
five, since all five produce runs that complete normally with every
invariant satisfied.
Layer three is the subject of
agent evaluation: a
pinned task set, a frozen environment, and a program that decides
whether an attempt succeeded. It is the only source of ground truth
you will ever have, and it cannot watch production, because
production tasks do not come with gold answers.
Which leaves layer two carrying the load, and layer two is
unglamorous. It is a handful of checks over a structured trace, and
it works only if the trace has the right fields in it.
# Layer 1: invariants, inside the loop, before the call goes out.
def guard(turn, run):
if not SCHEMA[turn.tool].validates(turn.args):
return RETRY("malformed", feedback=SCHEMA[turn.tool].error)
if turn.writes and turn.target not in ALLOWED_WRITES:
return HALT("side effect") # permissions bug, not a retry
if run.spent() > run.budget:
return HALT("over budget") # report incomplete, don't summarize# A loop is a repeated action with nothing changed in between, which is# why comparing to the *previous* call misses every two-step cycle.
sig = hash((turn.tool, normalize(turn.args)))
if sig in run.actions_since_last_state_change():
return HALT("loop")
return DISPATCH
# Layer 2: over the finished trace, the five things layer 1 cannot see.# anchored(run.original_request, run.result) -> goal drift# constraints_held(run.constraints, run.trace) -> context decay# every_claim_sourced(run.summary, run.trace) -> fiction, partial# steps_covered(TASK.required_steps, run.trace) -> partial# provenance_intact(run.inbound_handoffs) -> cascade
What to log, or none of this works
Every check in layer two reads a field off the trace, so the trace
is the real prerequisite and a transcript is not a trace. A wall of
interleaved prose and tool output makes the expensive modes
structurally invisible, because you cannot write a rule over it.
Per turn, the fields that earn their storage: the turn index, the
tool name, a hash of the normalized arguments, the result status kept
separate from the result payload, the diff the turn made to any
external state, and the running spend in turns, tokens, dollars, and
wall clock. Per run: the original request stored verbatim, and the
constraints stored as their own list rather than left embedded in the
prose that carried them.
Two of those are the ones people skip, and both are the ones the
hard modes depend on. Status separate from payload is
what makes empty-result fiction detectable, because a 200 carrying an
error body is indistinguishable from success unless something
unpacked it. The original request, verbatim is what
makes goal drift detectable, because the alternative is comparing the
result against the agent's own restatement, which drifted with
it.
Agent error recovery, matched to reversibility
Detection without a response is just a slower way to find out. The
useful sorting principle for the response is not how severe the
failure looks but how reversible the action was, because that is what
determines whether trying again is cheap or catastrophic.
Five triggers, five responses. The agent is not the one that decides which row it is in.
Retry, but never identically. A retry that sends
the same call is the mechanism of the doom loop, not a defence
against it. Feed the error text back, require a materially different
call, cap the attempts at two, and if the second attempt does not
differ from the first, stop rather than let the run spend the rest of
its budget discovering the same thing.
Roll back, then re-plan from the original text.
Checkpointing is what makes drift recoverable, and re-planning is
where teams undo their own work: re-planning from the agent's current
understanding of the task simply restarts from the drifted position.
Re-plan from the request as the user wrote it.
Gate the irreversible, do not review it. Every
workflow has a small number of actions that cannot be undone: the
payment, the deletion, the outbound message, the write to a system of
record. Gating those with an explicit approval is affordable
precisely because they are rare, and the alternative is an incident
review that begins after the thing already happened.
Fail closed. When a guard fires, emit nothing.
This is the discipline that gets abandoned first, because a partial
answer feels more useful than no answer, and it is how a detected
failure becomes a shipped one. Escalate with the whole trace
attached, since a human asked to adjudicate a run without its trace
will do the only thing available, which is to trust the
summary.
Underneath all five rows is one rule that is easier to state than
to hold: the agent must never be the component that decides
whether it succeeded. Self-assessment is the same generation
process that produced the work, running on the same context, with the
same drift and the same blind spots. It will tell you the run went
well, in good prose, for exactly the reasons it went badly.
How your monitoring will lie to you
A team that builds all of the above still gets a dashboard that
overstates its position, in five predictable ways.
Retries hide the loops. If the metric is final
success, a run that needed three attempts scores identically to one
that worked immediately. Track first-attempt success as its own
number, or the degradation that precedes a real outage stays
invisible until it crosses the retry budget.
The repair masks the defect. A validator that
silently fixes a malformed call is doing production a favour and your
training set a disservice. Log every repair as a failure that was
recovered, otherwise the model's actual schema competence looks
perfect right up until you change frameworks.
One run per task proves nothing. Agents are
nondeterministic, and an agent that succeeds 85 percent of the time
per attempt will look fine the first time you watch it and fail one
job in seven forever. Reliability is the fraction of tasks that pass
on every one of several attempts, not the average of the
attempts.
A judge that reads the summary will believe the
summary. The write-up is the most fluent and least grounded
part of the output, so scoring it grades the agent's prose. Point the
judge at the trace and the end state instead, and it stops agreeing
with confident fabrications.
Turn-level numbers flatter you. Ninety-nine
percent per-turn success across twenty turns is an eighty-two percent
task success rate. Aggregate at the task, always, because the task is
the unit the business cares about and the compounding is the whole
problem.
Which of these is a training problem
Naming the modes pays off here, because they do not share a fix
and the wrong fix is expensive. Three different owners come out of
the same eight rows.
Mechanical failures are supervised fine-tuning.
Malformed calls, wrong argument names, misread schemas: the model has
read every public API reference and none of yours, and demonstrations
of your own tools close that gap directly. This is
tool-use fine-tuning,
and it is the highest ratio of improvement to effort in the
list.
Judgment failures are reinforcement learning.
Drift, decay, and looping are properties of a whole trajectory rather
than of any single step, so there is no correct next token to
demonstrate. What you need is a program that scores the finished
attempt, which is the verifier from your eval set doing double duty
as a reward function. That trade is the subject of
SFT
versus RL for agents, and the broader shape is
agentic
fine-tuning.
Fabrication is half training and half interface.
The training half is teaching the model that reporting an absence is
a rewarded outcome rather than a failure to be papered over, which
requires having tasks in your set whose correct answer is "the data
is not there". The interface half is making an empty result
structurally impossible to confuse with a populated one, so the model
is not left inferring it from an empty list.
Two of them are not model problems at all.
Unauthorized side effects are a permissions question, and the rule is
to never train what you can revoke: an allowlist enforced at dispatch
is a guarantee, and a well-behaved model is a probability. Silent
partial completion and handoff cascade are protocol questions, fixed
by requiring structured completion reporting instead of a prose
summary, and by carrying confidence and provenance in the handoff
schema so that a guess cannot arrive downstream looking like a
fact.
Which is the practical argument for a taxonomy rather than a
general sense that agents are flaky. Four of the eight modes get
better with training, two get better with plumbing, and two get
better with a permissions change you could ship this week. A team
that has not separated them tends to reach for the most expensive
option available, which is a new model.
Where this fits at Numerata
Numerata's position is that the failure modes above are the reason
an agent programme is an infrastructure project rather than a prompt
project. P95 treats the trace as a
first-class object: runs are recorded with the fields the layer-two
checks need, verifiers are versioned alongside the task set, and a
failed trajectory is retained as training data rather than discarded
as noise, because the run that drifted is the most informative run
you have. Rollouts and eval passes draw GPUs from the pool
Lupine manages, which is what makes
running a task set several times a scheduling question rather than a
budget negotiation, and finished checkpoints go to
NinetyFive to serve.
The reason this runs inside your own environment is what the
traces are made of. A trace of a real agent run contains the request
as a person wrote it, the arguments passed to your internal
endpoints, the rows that came back, and the definition of a correct
outcome. That is a more sensitive artifact than the model weights it
is used to improve, and it is not something to ship to a third party
in order to find out why last Tuesday's run was wrong. Numerata
installs inside your own environment, private cloud, on-premises, or
fully air-gapped, so the traces never leave.
If you are earlier in this: agent
evaluation covers building the task set and verifier that layer
three depends on,
tool-use fine-tuning
covers the internal-API gap most mechanical failures trace back to,
and synthetic data
for fine-tuning covers what to do when you have failing
trajectories but no labelled corpus to correct them with.
Numerata runs inside your own environment: private cloud, on-prem, or fully air-gapped.
· Back to blog
GET STARTED
Let's talk deployment.
Thanks for your interest, look out for an email from our head of product.