The Four Ways an Agent Gets Stuck

Across long-running agents, the failures that cost the most are not reasoning failures. They are termination failures. Four patterns show up repeatedly.

Budget exhaustion. The agent runs until the token budget hits zero, then stops mid-task. The work that was done survives in long-term memory. The work that was in flight does not.

False-positive self-termination. The agent decides it is done before the work is actually done. The artifact exists but is incomplete. The operator does not find out until a customer or a cron job notices.

Late termination. The agent passes the point where a human would have stopped and keeps going. It runs past completion because the loop has no continuation condition — only a hard cap that eventually triggers.

Indefinite oscillation. The agent's stop condition is symmetric: it evaluates to true, the agent continues, the continuation makes it false, the agent stops, the stop makes it true again. The loop hangs.

These four patterns are the same failure at different layers of the same mistake: the operator treated termination as a feature the model would handle.

Why the Model Cannot Be the Termination Oracle

The tempting assumption: "the model will know when it is done." That sentence is the bug.

The model has no privileged access to "done." It has access to the conversation so far, the context it was assembled with, and the available actions it can take. None of those is a definition of "done" for this task. The model will guess. Sometimes the guess is right. Often it is not.

This is not a model capability problem. It is an architecture problem. The termination stage of the agent loop asks a question the model cannot answer correctly by design: "have we met the success criterion?" The model's answer depends on what it can see. What it can see is the conversation. The conversation does not contain the success criterion — it contains the history of attempts.

The fix is to treat termination as a first-class engineering concern. Define a predicate. Write it down as a specification the runtime can evaluate. The runtime, not the model, checks the predicate at the end of each iteration.

The Termination Stage in the Agent Loop

The Agent Loop runs in six stages: intake, context, inference, tool execution, persistence, and termination. The termination stage asks one question: should we run another iteration?

The runtime evaluates the stop condition and either returns the final artifact or loops back to intake. Simple in theory. Broken in practice when the stop condition is the model's own impression of completion.

The most common broken pattern: the runtime asks the model "are you done?" and the model says "yes." The runtime terminates. The operator inspects the output and finds it incomplete. The model's answer was based on what it could see in the conversation — not on whether the artifact met the success criterion.

The fix: move the termination predicate out of the model and into the runtime. The model produces output. A separate check — a verifier, a file-existence test, a schema validator — decides whether the loop continues.

Narrative: The Daily-Report Agent

Consider an agent that runs a database query, formats the results into a daily report, and writes the report to a shared file location. The termination condition seems obvious: the report file exists and contains today's date in the header.

The operator did not specify this. The operator assumed the model would figure it out.

The agent ran the query, formatted the output, wrote the file, and then called the report tool seventeen more times. Each call produced a valid report. The operator arrived in the morning to find eighteen reports, the last seventeen duplicates of the first. The agent had not received a stop signal, so it continued.

The cost: seventeen wasted tool calls, seventeen report files overwriting each other in the logs, and a session that consumed tokens past the point of useful work. The agent had correctly produced the artifact. It continued because nothing told it to stop.

The fix: add an explicit stop condition — "stop when the report file at /reports/daily.md exists and its header contains today's date" — and route that condition through the runtime's termination check, not through the model's self-assessment.

Narrative: The Migration-Watcher Agent

A second agent monitored a multi-step system migration. Its job: check the status of each migration step, alert if any step failed, and stop when all steps reported success.

The operator defined a termination condition: stop when no step has failed in the last check. The agent ran. The first status check showed all steps passing. The agent terminated — correctly, by its condition.

The problem: the first check ran before several steps had begun. The agent stopped at the first clean check, not at the actual completion of the migration. Three steps that had not yet started reported as passing because they had not yet reported anything.

The failure was not a model failure. The condition was symmetric: "all steps passing" evaluated to true before the steps had run, stayed true while they were running (because the agent was not re-checking), and the loop had no mechanism to re-evaluate. The agent evaluated once, terminated, and the migration continued without observation.

The fix: the termination condition must be evaluated against an external ground truth — the actual state of the migration, not the agent's own output. A separate verification step that re-reads the system state and confirms all steps completed would have caught this.

The Four Parts of a Testable Stop Condition

A stop condition that works is:

1. Stated before the loop starts. In the system prompt, in the first user message, or in a structured plan. Visible to every iteration. 2. Testable. "Done when X is true" beats "done when I feel like it." If you cannot check it, it is not a condition. 3. Bounded. A maximum number of iterations, a maximum token cost, a maximum wall-clock time. The bound is the safety net. 4. Owned. Someone — the human, the parent agent, a watchdog process — is responsible for declaring the loop terminated. The model's self-assessment is not ownership.

Three concrete patterns that implement these four parts:

"Stop after N tool calls and emit a summary." The bound is explicit: N calls. The ownership is the runtime. The artifact is the summary, not the individual calls. This pattern is the simplest correct termination design.

"Stop when this JSON field is set to true." The agent writes the field as part of its work. A separate verification step — not the model — inspects the field. This decouples the model's self-assessment from the termination decision.

"Stop when the verifier passes." A second agent or a hard rule checks the output against the success criterion. The producer does not terminate itself.

The common thread: stop conditions must be owned by something other than the model that produced the work. A model that evaluates its own output for correctness is a symmetric stop condition — it will find a way to pass.

The Four Failure Modes in Detail

Budget exhaustion is the most visible failure. The fix is a hard bound — a maximum token count, a maximum iteration count, or a maximum wall-clock time — that the runtime enforces regardless of what the model thinks.

False-positive self-termination is the most expensive failure because it is silent. The loop exits. The artifact exists. The artifact is incomplete. Nobody checks until a downstream consumer finds the gap. The fix is decoupling the model's self-assessment from the termination decision.

Late termination — running past the point of completion — is a missing continuation condition. The loop has a termination predicate but no continuation predicate. The agent checks whether to stop, not whether to continue. The fix: define both.

Indefinite oscillation is a symmetric condition. The agent's stop condition evaluates to true, so the agent continues; the continuation changes the condition to false, so the agent stops; the stop changes it back to true. The loop hangs. The fix: evaluate the condition with a separate operator that does not itself change state when the loop runs.

What "Vibe Termination" Costs

"Vibe termination" is when the agent stops when it feels done. The signal is that some runs end at three iterations and others run to the iteration cap. The cost is unpredictability — the operator cannot audit whether termination was correct because the termination criterion was never written down.

The cost of wrong termination goes beyond the budget hit:

  • False-positive termination produces artifacts that look complete but are not. Downstream consumers trust them. The gap surfaces later, often at the worst time.
  • Late termination wastes resources and may corrupt the artifact if the agent overwrites its own output in later iterations.
  • Indefinite oscillation consumes resources with no output. The loop produces nothing and exits only when the hard cap is hit.

Wrong termination is a design failure, not a model failure. Swapping to a smarter model does not fix any of these four patterns. Engineering the stop condition does.

Designing for Reliable Termination

Before a long-running loop runs, answer these questions in writing:

1. What does "done" look like for this task? Be specific: a file at a path, a JSON field set to a value, an API call that returns 200. 2. Who evaluates whether "done" is true? The model? A separate verifier? A file-existence check? 3. What is the hard bound if the condition never fires? Maximum iterations, maximum tokens, maximum wall-clock time? 4. Who is responsible for declaring the loop terminated — not for noticing it ran too long, but for making the call?

If the answer to question 2 is "the model," the loop will fail in one of the four patterns described above. The fix is not a better model. The fix is naming a non-model actor as the termination owner.

Reading Order

The pieces that build on this one:

Takeaway

The question "how does this loop know it is done?" is the question most agent designs skip. The answer "the model will figure it out" is the reason most agent designs fail in one of four predictable patterns.

Write the stop condition down. Make it testable. Bound it. Name who owns it.

The model is not the termination oracle. The stop condition is.