What it looks like in the wild
A run finishes clean, and clean is the whole problem. The transcript ends with a confident summary: rows updated, ticket closed, migration complete, tests passing. There is no exception in the log, no non-zero exit code, no line where the agent admits it could not do something. Every signal an operator glancing at a dashboard would look for says the task succeeded.
Whether it actually did is separate, and nothing in that transcript answers it. A coding agent edits a file, triggers no build step to check its own work, and reports the tests are green because nothing ran them a second time. A migration agent works through a batch, hits a rate limit that silently drops the rest, and reports the migration complete anyway. A support agent drafts a reply, never confirms the ticketing API accepted the write, and marks the case resolved anyway. None of these agents is confused about what it did; none is ever asked whether what it did was what was asked for.
None of this is a loud failure. A loud failure interrupts the person watching: an error banner, a retry, a page to on-call. This one produces the same shape of output a successful run produces, because in this design the claim of success and the fact of it are the same event, generated by the same actor, at the same moment, with nothing in between. The failure is invisible exactly where it matters most, at the point someone decides to trust the result and stop watching.
Why it happens
Rule out the easy explanations first. The agent is not lying, in any sense that implies intent; it has no access to a ground truth it is choosing to misreport. It is not a capability failure either: the gap is present whether or not a run’s outcome turns out correct, because the defect is not in what the agent did, it is that nothing afterward asked whether it was enough. Hallucinated Done becomes visible only on the runs where the claim turns out false; the missing check runs the same way on every run, correct or not. That gap sits in the architecture around the model, not the model itself: no check runs between the moment a loop decides to stop and the moment the system records that stop as success.
Most agent harnesses give a run exactly one way to end: a special output type, a stop token, a “done” field, an orchestrator accepting a subagent’s return as final. That single mechanism does two jobs at once, ending the run and asserting the run succeeded, and nothing forces those two apart. Building the check that would separate them, comparing what happened against what the task asked for, is real design work, done before it is needed. Trusting the stop signal as given costs nothing, right up until the day it is wrong, and by then the run has already been counted as a success.
None of this is a new observation. MAST names the shape directly: No or Incomplete Verification, one of fourteen failure modes its taxonomy catalogues from real multi-agent traces, the omission of any proper check on a task’s outcome before it is accepted as done. Their frame is multi-agent, drawn from traces where a downstream agent inherits an earlier claim it never questions, but the failure needs no second agent: a single loop with nobody downstream already has everything it requires, because the missing check is missing whether or not anyone else is watching. MAST supplies the failure mode; what it does not supply is a name an engineer reaches for on a whiteboard, before a system has shipped. That is what naming it here adds, a naming act, not a discovery: the mode is Cemri and coauthors’ to have found; the label is only a label.
It is worth separating this from its two closest relatives in MAST’s taxonomy. Premature Termination is a different failure, a task ending before its objectives were met, the work itself left unfinished; Hallucinated Done can happen on a run where every step genuinely completed, and what is missing is the check, not the work. Rubber-Stamp Verifier is the closer neighbor, MAST’s Incorrect Verification, a check that exists and approves anyway; this pattern is MAST’s own No or Incomplete Verification, no verifier in the loop at all. The three blur easily in conversation; MAST’s three-way split is reason enough not to flatten them into one.
What it costs
A hallucinated done is worse than a run that fails loudly, and the difference is not severity, it is visibility. A failure that announces itself gets a ticket, a fix, and eventually a regression test to keep it fixed. A failure that reports itself as a success gets shipped, and the first sign anything was wrong is whatever downstream process trusted it.
Three costs follow directly. It spends the trust budget disproportionately: the first hallucinated done an operator finds costs more than that one run, because it removes the ability to take any future “done” at face value. It defeats retry and recovery logic built for the loud case: a recovery pipeline listens for an exception, a failure field, a non-zero status, something a hallucinated done never produces, so nothing retries, pages on-call, or routes the case to a human. And it corrupts the eval data a team uses to judge whether the system is improving: a harness treating the agent’s own claim as ground truth counts a hallucinated done as a pass, indistinguishable from a real one, so the number a release decision consults is quietly wrong in a direction nobody chose.
That last cost compounds. An eval rubric with no way to separate a hallucinated success from a real one has nothing to bucket it into, so it never becomes a line item anyone can act on, and a release gate built on that same untrusted label is not measuring what it thinks it is.
Worked example
This site’s Bench hosts a demo built for exactly this shape: Loop Lab, the interactive companion to FN-004. It runs a deterministic, scripted decision path in the browser, not a live model call, the same logic as the Python tests in src/fn04/loop.py. That distinction matters: it is not measuring how often a real model hallucinates completion, it is a fixed script standing in for one, built to make the mechanism visible, not to produce a statistic. Loop Lab ships a second scenario, runaway, where the script repeats the same call forever and never yields a stop signal at all, caught by a different fence, the no-progress detector, not any check on a claim of completion. Hallucinated Done is the scenario that says done too easily, not the one that never says it at all.
Pick that scenario. The scripted agent takes two steps: read the rows, then delete them all, then it is finished. Toggle every fence off and run it: the destructive call executes, the database in the demo goes from intact to deleted, and the trace ends with a row that reads, verbatim, “agent claims the task is complete.” Turn the Capability Gate back on and run the identical script again: the delete is refused at the call site, the database survives untouched. The trace still ends with the identical row: “agent claims the task is complete.”
That repetition is the entire point. The claim fires the same way regardless of what happened to the action it is supposedly reporting on, executed or blocked, it makes no difference, because nothing in the loop ever asks. The capability gate is doing real work there, protecting the database, which is a different job from checking the claim about it. None of Loop Lab’s three fences, the gate, the no-progress halt, the iteration cap, ever asks whether the outcome the requester actually wanted was reached: all three bound what the loop may do, none touch what it may say about what it did. A few scripted lines show the whole shape of the failure, because it was never about how sophisticated the model behind it happened to be.
The pattern that replaces it
Verifier Loop closes this gap at a specific moment: the instant a system is about to accept “done” as true, not only at the hops that led up to it. Anchor that check to the task as originally given, not to whatever the agent’s own trace says about itself, and a hallucinated done has nowhere left to hide, because the claim of completion is no longer the only witness to completion.
Loop Lab’s own fences show why this is a genuinely separate layer, not a rebranding of what a capability gate already does: they bound what the loop may do, and a verifier loop is the layer that finally asks what none of the three ever do, whether the state the task described actually holds now, checked against the task itself, not against the agent’s own account of its last few actions.
That check needs the same two properties anywhere it is worth building: a rubric specific enough that a second reviewer, given the same transcript, reaches the same verdict, and a demonstrated ability to say no on a real case, not only in the abstract. Skip either and the fix collapses back into Rubber-Stamp Verifier, a check that occupies the same slot in the diagram and approves everything handed to it, the same failure wearing a different label. Nor does the check need a multi-hop chain to earn its place. A single agent with a single stop decision, exactly Loop Lab’s scenario, is enough of a target: the anchor is the task, not the hop count.
Related patterns
Verifier Loop is the replacement this anti-pattern points to: a check anchored to the task, run at the exact moment a system would otherwise take an agent’s word for its own success. Rubber-Stamp Verifier is the trap on the other side of a half-built fix: a verifier with no rubric behind it approves everything handed to it, Hallucinated Done wearing a check mark. Failure Buckets turns this failure from an invisible tax on a headline number into a line item, a hallucinated success counted apart from every other failure rather than blended into one score. Capability Gate sits beside this pattern, not behind it: it stops a destructive action regardless of what any completion claim says, refusing the delete while the done claim still fires unchanged. Baseline and Floor is the release gate this anti-pattern quietly defeats once a real completion and a claimed one are never separated: a floor computed over self-reported “done” labels is not a floor, it is the same untrusted claim wearing a threshold.