Unbounded Loop
also known as No Step Cap, Open-Ended Agent, Agent Stuck, Loops Forever
Anti-pattern: run the agent loop without a step budget and let model self-termination decide.
Context
A team has implemented an agent loop as 'keep iterating while the model says it is not done', with no external counter, timer, or cost cap to interrupt the loop from outside. The implicit assumption is that the model will say 'done' when the work is complete, and that this self-termination signal is reliable enough to drive the loop's exit.
Problem
In practice the model rarely declares itself done on hard tasks: it wanders into related questions, retries failed actions, or loops on errors without recognising that it is looping. With no external bound on iterations, total cost, or wall-clock time, the loop can run for hours and burn through significant budget before anyone notices. The user is left waiting while the agent grinds. Picking an exact cap is empirical and feels arbitrary, but no cap at all is worse: the agent will eventually be put in a state where it never terminates on its own, and unbounded cost is the result.
Forces
- Caps cut off legitimate work.
- Choosing the cap is empirical.
- Model self-termination feels natural until it fails.
Example
A team ships an agent without a step budget, trusting the model to decide when to stop. On a flaky network it retries the same tool forever; on an ambiguous task it wanders for forty turns and bills accordingly. The post-mortem is brief: they add `max_steps` and a stop-hook predicate. Cost becomes bounded by construction and the same incident class disappears from the support queue.
Diagram
Solution
Therefore:
Don't. Set max_steps. Add a stop hook. See step-budget, the-stop-hook.
What this pattern forbids. By definition, this anti-pattern imposes no useful constraint; the missing constraint is the failure mode.
And the patterns that stand alongside it, or against it —
- alternative-toStep Budget★★— Cap the number of tool calls or loop iterations the agent is allowed within a single request.
- alternative-toStop Hook★★— Define an explicit programmatic predicate that decides when the agent's loop should terminate.
- conflicts-withRumination Agent★— Run a single agent through a protracted think-search-verify-revise-act loop spanning hundreds of tool calls, autonomously re-formulating hypotheses across the run.
- complementsErrors Swept Under the Rug✕— Anti-pattern: scrub failed actions, stack traces, and error observations from the agent's own context so the trace looks clean, leaving the model with no evidence of what did not work.
- complementsCascading Agent Failures✕— Anti-pattern: build a multi-agent system where one agent's failure or hallucination propagates as input to peers, until the whole system has drifted.
- complementsDemo-to-Production Cliff✕— Anti-pattern: ship a demo-validated agent straight into production without a frozen eval, cost ceiling, loop-detector, or named oncall, then act surprised when accuracy drops and cost runs away.
- complementsToken-Economy Blindness✕— Anti-pattern: operate multi-agent loops with no per-run token budget or alarm, allowing recursive loops to silently accumulate $10k+ in undetected costs.
- complementsMissing max_tokens Cap✕— Anti-pattern: call the model without an explicit max_tokens (or equivalent) so a single call can drain the run's budget on a runaway generation.
- alternative-toNaive Retry Without Backoff✕— Anti-pattern: retry failed model or tool calls immediately, amplifying load on systems that are already failing.
- alternative-toComposable Termination Conditions★— Express agent stop criteria as small single-purpose conditions composed with AND/OR into one explicit termination contract instead of ad-hoc loop guards.
Neighbourhood
Click any neighbour to follow the language. Scroll to zoom, drag to pan.