Mitigation
Agent Stopping Criteria: When a Long-Running Agent Should Declare It's Done
Agent stopping criteria are the rules that decide whether a tool-using agent should keep working or return a final answer. Most production frameworks only cap how long an agent may run; almost none check whether the answer it stops on is actually supported by what it did. The taxonomy, the frameworks' real defaults, and a verification-based fix.

Agent stopping criteria are the rules a tool-using agent (or its harness) uses to decide, at each step, whether to keep working or return a final answer. Get this wrong in one direction and the agent burns budget looping past the point where it had everything it needed; get it wrong in the other direction and the agent hands back an answer that was never actually verified against what it did. Most production agent frameworks only solve the first problem: a hard ceiling on turns, steps, or tokens. Almost none check the second, whether the stopping point itself is supported by evidence, which means the default failure mode in production agents is not "runs forever," it is "stops confidently on an unsupported answer."
This is a mitigation question specific to behavioral state decay, not just an engineering detail, because stopping criteria are the one control point where the decay in an agent's other components gets converted into a final, external result. An agent whose plan has gone stale per plan decay, or whose context has degraded per context rot, does not fail loudly at the moment of decay. It fails at the moment it stops, when a degraded internal state gets packaged as a finished answer and handed to whatever is downstream. Getting the stop decision right does not fix the decay; it decides whether the decay becomes visible before or after it does damage.
Two failure modes, not one
Premature termination locks in an unsupported intermediate state as if it were final. The agent has partial evidence, produces a plausible-sounding answer anyway, and returns it as complete. Nothing downstream knows the difference between a verified result and a guess, because both look identical in the output.
Over-continuation is the mirror failure: the agent keeps going past the point where stopping would have been correct, compounding cost and risk with each additional step. This is where redundant re-exploration shows up concretely: an agent unsure whether it is actually done tends to re-verify, re-fetch, and re-derive facts it already has, and the completion-recognition gap measured there, correct stop signals firing in well under half of comparable runs under one common compaction strategy, is direct evidence that "am I done" is a harder judgment for an agent to make reliably than "am I making progress."
Both failures come from the same root cause: the stop decision is usually made by asking the model to judge its own completion, and a model's self-report of confidence is exactly the kind of signal that degrades under calibration drift, often without any external indication that it has done so.
What today's frameworks actually check
It is worth being precise about what popular agent frameworks enforce, because the honest answer is: almost entirely resource limits, not correctness limits.
- **LangGraph** caps total graph steps with a `recursion_limit`, defaulting to 25, and raises `GraphRecursionError` when a run exceeds it without reaching an explicit stop condition; callers raise the ceiling by passing a higher `recursion_limit` in the run config (LangGraph docs).
- **CrewAI** caps an agent's reasoning loop with `max_iter`, also defaulting to 25, and its documented behavior on approaching that ceiling is not to fail but to have the agent "try its best to give a good answer" (CrewAI docs), which is a resource cap quietly converted into a forced answer, not a verified one.
- **AutoGen** composes termination conditions explicitly, `MaxMessageTermination`, `TextMentionTermination`, `TokenUsageTermination`, combinable with a pipe operator, so a run stops on whichever fires first (AutoGen docs). This is the most composable of the four, but every built-in condition is still a resource or surface-text trigger, none of them checks whether the content produced at that point is actually grounded in the run's own trace.
- **OpenAI's Agents SDK** raises a `MaxTurnsExceeded` exception once a run passes the turn budget the caller supplied, and exposes error handlers that can substitute a controlled final output for the raw exception (OpenAI Agents SDK docs).
The pattern across all four: every mainstream framework answers "when must the agent stop" with a number, and none of them, out of the box, answers "is the agent's proposed stopping point actually supported by what it did." That second question is left to whatever custom logic, or lack of it, the application team bolts on.
A taxonomy for organizing stop conditions
This site groups the conditions that actually matter into four categories, mapped to the mechanisms above:
- **Goal-based**: the agent has reached a state that satisfies the declared objective. The frameworks above mostly leave this to the model's own judgment (a `TextMentionTermination` on a phrase like "TERMINATE" is a thin proxy for this), which is precisely the weak point evidence-carrying termination targets, described below.
- **Resource-based**: a hard ceiling on iterations, tool calls, tokens, wall-clock time, or spend. This is what `recursion_limit`, `max_iter`, `MaxMessageTermination`, and `MaxTurnsExceeded` all implement. Necessary as a backstop, but a resource cap firing is not evidence that the task is done; it is evidence that the budget ran out.
- **Pathology-based**: the run itself shows a signature of trouble independent of any budget, repeated near-identical tool calls, no measurable progress across several steps, or a collapse in the model's own stated confidence. This is the category drift regression tests and calibration drift telemetry should feed directly into a stop decision, rather than only into a dashboard someone checks later.
- **External**: a user cancels, an upstream timeout fires, or a supervising process forces a halt for reasons the agent has no visibility into. These should always override the other three.
Treating these as one undifferentiated "stopping logic" module is what produces the failure mode above: a resource-based stop gets silently presented to the user with the same confidence as a goal-based one, because the harness never recorded which category actually fired.
Evidence-carrying termination
A 2026 paper on tool-using agents proposes a concrete fix aimed directly at the premature-termination half of this problem: evidence-carrying termination (ECT), where an agent may declare itself complete only when a typed certificate binds every claim in its answer to trace evidence recorded during the run, and a deterministic replay can independently reconstruct the claimed value from that evidence (Liu, arXiv:2608.23623). In plain terms: instead of asking the model whether it is done, the harness checks whether the model's own recorded actions actually support the answer it wants to give, and refuses the stop if they do not.
The measured effect is large. Across 48 synthetic tasks spanning six tool-use families, with both clean runs and eight injected fault scenarios, baseline agents produced 252 unsafe completions out of 288 trials; ECT produced zero. On a separate, held-out evaluation of 22 task clusters, comparison agents terminated prematurely, on an unsupported state, in 40 of 66 trials; ECT produced zero premature terminations there as well, while landing a comparable rate of fully supported completions (97 of 132 versus the baseline's 92 of 132). Notably, ECT's refusal to stop was not just a strictness cost: 18 of the 66 trajectories where a supported answer was not yet reachable went on to recover, with 17 of those 18 eventually reaching a properly supported completion. Blocking a bad stop did not just avoid the bad answer, it usually bought the run enough extra steps to get a good one.
The caveat that matters here: ECT is a research design evaluated on synthetic benchmarks, not a drop-in library the frameworks above ship today. What is transferable immediately is the design principle, not the exact mechanism: a stop condition should be checked against the run's own recorded trace, not asserted by the same model that is also trying to finish the task.
Building this into a real harness
- Assign every stop event one of the four category labels above (goal / resource / pathology / external), and log it. If your logs cannot answer "which kind of stop was this" after the fact, you cannot tell a verified result from a budget timeout later, and neither can whatever consumes the agent's output.
- Never let a resource-based stop masquerade as a goal-based one. If `max_iter` or `recursion_limit` fires, the returned output should be flagged as budget-truncated, not presented with the same confidence as a task the agent judged complete on its own.
- Add at least one pathology check that does not depend on the model's self-report: a repeated-tool-call-signature counter, or a no-new-information check across the last N steps, wired to fire independently of the turn budget. This catches the redundant re-exploration pattern before it consumes the whole budget rather than after.
- Before accepting a goal-based stop, check the claim against the trace, at minimum a cheap version of ECT's principle: does the specific fact the agent is citing actually appear in a tool result it retrieved this session, or is it asserting something it never confirmed. This does not require the full certificate-and-replay machinery to be worth doing.
- On any forced or uncertain stop, checkpoint the run's state per state externalization rather than discarding it. ECT's recovery data shows that an unsupported stopping point is frequently one or two verification steps away from a supported one; a state-externalized run can resume from there instead of restarting.
Pitfalls
- Treating a resource ceiling as evidence of task completion, the single most common source of a confidently wrong answer, since the cap tells you the budget ran out, not that the work is done.
- Trusting a model's stated confidence as a stop signal without an external check, which degrades silently under calibration drift and gives no warning before it does.
- Adding pathology detection only after an incident, rather than as a standing check, which means the first case it catches is always the expensive one.
- Discarding state on a forced stop instead of checkpointing it, throwing away exactly the partial progress that a follow-up verification step could have completed.
Related terms
- Behavioral state decay: the umbrella phenomenon; a stop decision is the point where component decay becomes an external result.
- Redundant re-exploration: the cost pattern produced when an agent cannot reliably judge its own completion.
- Plan decay: a stale plan that reaches its final step is not the same as a plan that reached a correct one; stopping criteria should check the latter.
- Calibration drift: the reason a model's self-reported confidence is a weak stop signal on its own.
- State externalization: where a forced or uncertain stop's partial progress should be checkpointed rather than discarded.
- Drift regression tests: the place pathology-based stop signals should be validated before they are trusted in production.
FAQ
Isn't a maximum turn count enough? It prevents runaway cost, which matters, but it answers a different question than "is this answer correct." A run can exhaust its turn budget on a wrong path or stop well inside its budget on an unsupported one; resource caps and correctness checks need to be tracked and reported separately.
Does evidence-carrying termination replace a resource cap? No. ECT addresses premature and unsupported stops; a resource-based ceiling is still needed as the backstop against a run that never reaches any stop condition at all. The two are complementary categories, not substitutes.
Is this only relevant to single-agent systems? No, it is arguably more acute in multi-agent pipelines, where one agent's premature, unsupported stop becomes the next agent's input and is one of the concrete mechanisms behind hallucination cascades: a downstream agent has no way to tell that the upstream "final answer" it received was never actually verified.
What is the cheapest version of this to implement today? Logging which category (goal / resource / pathology / external) triggered every stop, and never letting a resource-based stop be displayed with the same confidence framing as a goal-verified one. That alone surfaces the premature-termination problem in your own logs before you need any certificate-and-replay infrastructure.