Skip to content

Operating

Infinite Loops — the Eight Ways a Loop Runs Forever

A loop has no natural end. The model's only built-in stop is its own opinion of itself, and an opinion is not a bound. Every infinite loop in…

A loop has no natural end. The model's only built-in stop is its own opinion of itself, and an opinion is not a bound. Every infinite loop in production traces back to the same root — a feedback path someone forgot to cap — and it always wears one of eight faces. Learn the faces and you can spot the missing bound at the whiteboard, before it spends a night of tokens.

Why loops trend toward forever

The inner loop (Step 2) is literally while True: with a model deciding when to break. Static analysis of real-world agent projects keeps finding the same thing: every class of infinite agentic loop — retry cycles, unbounded tool calls, agent-to-agent chatter, workflow cycles — shares a single root cause, a missing strong bound on a path that feeds back into execution. Nothing exotic. Just an arrow that points backward with no counter on it.

So the operating question for this page is never "will my loop misbehave?" It is: which arrows in my loop point backward, and what bound covers each one?

The eight scenarios

1 · The doom loop — retry without a bound

The classic, and by measurement the most common. A beat fails — a flaky test, an unparseable error, a malformed tool result — and the loop's answer is try again. Same item, same approach, same failure, every beat. The log shows relentless effort; the spine shows a flat line. Bound: a per-item retry cap plus the no-progress stop — three unchanged beats means stop and escalate, not try harder (Step 5).

2 · The unprovable stop — "make it better"

Give a loop a stopping condition no machine can verify — improve the docs, clean up the code — and it will manufacture plausible progress for as long as you fund it. There is always another sentence to rephrase. This one is fully self-inflicted: the loop is behaving perfectly against a spec that never ends. Bound: a stopping condition written as a checkable spec (the A–F method, move B). If you can't write the sentence, you don't have a loop task yet.

3 · The self-triggering heartbeat

An event loop whose output re-fires its own trigger: the on-push loop that commits a fix, which is a push, which fires the loop, which commits… CI systems learned to guard this years ago (actor filters, [skip ci]); event loops must relearn it. The tell is a beat cadence that exactly matches the loop's own write cadence. Bound: filter out the loop's own events (by actor, branch, or path) and make writes idempotent — "ensure X" never re-fires on X (Step 7).

4 · The ping-pong pair

Two loops — or two agents in one conversation — where each one's output is the other's input. A delegates to B, B hands back to A; formatter-loop reformats what linter-loop just changed, and the reverse, forever. Multi-agent frameworks meet this as the group chat with no turn limit. Bound: a turn/handoff cap on any agent-to-agent path, and the fleet contract's ownership map — two loops writing the same path is a design error, not a race to referee (multi-loop.md).

5 · The oscillator

Nastier than the doom loop because every beat looks productive. Fixing A breaks B; fixing B breaks A. Files change every beat, so a naive "did anything change?" progress check passes forever while the system orbits between two states. Bound: measure progress against the goal, not the diff — a shrinking work-list in the spine, a rising pass count — and compare each proposed action against the beat history; a loop about to repeat an action it already took is oscillating, not working.

6 · The runaway heartbeat

Here the loop body is innocent; the trigger is infinite. A webhook that retries on timeout, two overlapping schedulers, a queue that redelivers — beats arrive faster than they finish, and each one is "legitimate." The tell: beat frequency far above design, with no code change. Bound: dedupe beats on an event id, keep exactly one scheduler per loop, and cap concurrent beats at one (failure-modes.md).

7 · The swelling context

The slow-motion infinite loop. Each beat appends its transcript to the next beat's context; the context grows, beats get slower and vaguer, the model loses the goal in its own history, and the loop asymptotically approaches never-finishing — while burning more per beat than the beat before. Bound: fresh context every beat, with continuity carried by the spine instead (Step 12), plus a hard context/size guard.

8 · The maker–checker standoff

The separation that keeps quality honest can also lock: the checker rejects for a reason the maker cannot fix (a rubric row the task can never satisfy, an environment-broken test), the maker resubmits its best attempt, the checker rejects again. Both sides are doing their jobs; the pair is doing nothing. Bound: a rejection cap — N straight FAILs on the same item stops the pair and escalates the disagreement to the human gate (Step 11).

Quick reference

#ScenarioThe tellThe bound
1Doom loopeffort in the log, flat spineretry cap + no-progress stop
2Unprovable stop"progress" forever, goal never nearerstop written as a checkable spec
3Self-triggerbeat cadence = loop's own write cadencefilter own events; idempotent writes
4Ping-pong pairtwo loops alternating on one surfaceturn cap + one owner per path
5Oscillatordiffs every beat, states repeatgoal-based progress; action-history check
6Runaway heartbeatbeats above design frequencydedupe on event id; one scheduler
7Swelling contextbeats slower and vaguer each roundfresh context per beat; spine carries state
8Maker–checker standoffsame item, N straight FAILsrejection cap → human escalation
Diagram

The universal rule

All eight collapse into one sentence: every path that feeds back into execution carries an explicit bound. The course's three stops — success condition met, run limit hit, no progress for 3 beats (Step 5) — are exactly that rule applied to the loop as a whole; scenarios 3–8 are the reminder to apply it to every internal arrow too: retries, handoffs, event paths, context growth. At the whiteboard, walk each backward arrow of a new loop.md down the table above; an arrow with no bound is homework before beat 1. And if one of these is already running away, stop reading — the recovery playbook step 1 is stop the loop first.

Sources: the doom loop, the three stops, and no-progress discipline come from Panaversity's Loop Engineering: A Crash Course (S1) and its scheduled-tasks companion (S4); stopping-condition-as-spec from Spec-Driven Development (S3); the verification and multi-agent feedback paths from Sydney Runkle's The Art of Loop Engineering (S6) and the cobusgreyling/loop-engineering reference repo (S7, MIT). The missing-strong-bound root cause and the measured prevalence of retry, tool-call, and agent-chat loops are from the study When Agents Do Not Stop: Uncovering Infinite Agentic Loops in LLM Agents (arXiv:2607.01641). Full attribution: resources/sources.md.