Skip to main content

Will your agent loop stop honestly?

Leave an agent looping on a task and one of three things happens: it finishes, it stops on a false “done”, or it runs away with your budget. Which one you get isn’t up to the agent. It’s decided by whether the oracle can be satisfied without the work, whether the measurement fails open, and whether anything enforces a stop. None of those improve with a smarter model.

This page simulates thousands of loops in your browser. Nothing you configure or replay is sent anywhere.

Predict first

With a promise-string marker and a 35% chance of real progress per iteration, what share of runs will end with a false “done”?

The four jobs

Every automated loop needs these four jobs done. /loop supplies only the trigger. /goal supplies the target and a model as the oracle. The governor is always yours.

  • Trigger

    What starts the next turn

    A script that starts a fresh agent every iteration, with the state on disk.

  • Target

    What should become true

    1 iteration of real progress, each with a 0.35 chance.

  • Oracle

    What proves it’s true

    A promise string in output, trusted alone. When the measurement throws, it fails open.

  • Governor

    What forces a stop

    Nothing: this is on you.

Configure the loop

Presets

A 15% chance of a premature claim sounds small, so most people guess low. It’s about 22%: every iteration that doesn’t finish is another chance to claim done, and a promise string believes the claim.

The task

No amount of work finishes it. The agent either cheats, takes a way out, or loops.

Only an impossible task uses it. An agent that doesn’t cheat says BLOCKED and stops.

The oracle

q is the chance per iteration that the agent claims done before it is. The values are illustrative, not measured. Edit them on the marker ladder.

The marker and a deterministic check must agree. A premature claim is logged, and the loop goes on.

When the measurement throws

A thrown measurement reads as zero remaining, so the run ends falsely done.

Cost
Context

Each iteration costs c₀ + r.

Price an iteration from a model

Loading the model prices…

Governors

Checked after every iteration. The first one that fires ends the run.

Checked after each iteration, so a run can go over by up to one iteration’s cost.

Stops when the same failure shows up twice in a row.

Checked at the start of every iteration. Only a person can touch it, so it never fires in the simulated runs. Try it on the animated run below.

With no governor that fires on its own, a run that never finishes is cut off at 2,000 iterations and counted as runaway.

Simulation

Every random draw comes from this seed, so the same seed always gives the same runs. Up to 10,000 runs.

The results are waiting on your guess

Make your prediction above first. Guessing before you see the answer is how you find out whether your intuition about loops is any good.

How strong is your marker?

A good marker is at least as hard to satisfy as the work it stands for.

Weakest at the top. Choose a rung to make it the oracle. The q values are illustrative, not measured, so change them to match what you’ve seen.

Replay a real loop

Drop the log your loop writes, one line per iteration, and see where each governor would have stopped it and what that would have saved. Progress means the work was kept and the score improved. Anything else is a stall.

Loading the replay…

Cautionary tales

These are cited figures from real loops, not simulated ones.

  • $1,818

    A cron loop quietly billed the API instead of a subscription, because ANTHROPIC_API_KEY was set: about $858 the first night and $960 the second.

    Would have stopped it: A budget in dollars, checked every iteration.

    Source: dev.to

  • About $6,000

    An overnight loop re-sent a very large conversation every 30 minutes.

    Would have stopped it: Fresh context, and a budget. A schedule is not a budget.

    Source: MakeUseOf

  • $437

    A summarizer listed the same directory 14,000 times overnight. It stopped only when it ran out of token quota.

    Would have stopped it: A repeated-failure check, or a stall detector.

    Source: dev.to

  • 1,966 attempts

    max_iterations: 0 meant “unlimited”, so the loop asked itself the same question 1,966 times.

    Would have stopped it: A maximum iteration count with a real number in it.

    Source: dev.to

The five parts of a loop

measure()
Runs the checks and returns facts: error counts, coverage, open issues.
pick()
Chooses one task from those facts.
run()
Calls the agent. This is the only part the agent controls.
accept()
Keeps the work, or rolls it back, only if nothing vetoed it, the tests and build still pass, and the score didn’t drop.
The governor
Enforces caps, detects stalls, and checks for the kill switch.

What to build first

  1. The oracle, plus the known-bad changes that prove it can fail.
  2. A queue that can rebuild its state from disk.
  3. Spending limits, each with an actual number.
  4. A one-line-per-iteration log that includes the session_id.
  5. Then, and only then, the loop itself.

The simulation’s rates are illustrative and its cited figures come from the sources linked above. Everything runs in your browser.