I Read 31 Agent Loops — Most Stop When They're Tired, Not When They're Right
The problem, stated plainly: most agent loops don't know when to stop. They stop when they run out of turns, when they hit a wall they can't get past, or when a human finally looks — and then they call whatever state they're in "done." Repeating is the easy part. Knowing the latest pass is actually right — and not just the pass you happened to be on when the budget ran out — is the whole game.
This week the loop became a named, shareable artifact — a library you can browse, copy, and submit to. But the names aren't the interesting part. The exits are. Here's what changed my mind, the four ways a loop can stop ranked by how much trust each one earns, and why — now that generation is nearly free — the exit is the only part left worth engineering.
I read 31 loops to feel smug. It backfired.
Forward Future just published the Loop Library — 31 named agent loops (a docs sweep, a production-error sweep, a builder–reviewer "autonomy" loop, a versioned-experiment loop) with a clean thesis: a good loop answers four questions — what's the goal, how does it check the last attempt, what does it do with what it learned, and when does it stop.
I started this post as a tour of all 31. I deleted that draft — a catalog isn't an argument. I went back in looking for "vibes with a while loop" so I could feel clever about my own setup. Mostly I found the opposite, and it indicted my loops, not theirs.
Because my throwaway loops look like this: "keep fixing the flaky tests until they pass." It runs, something goes green on pass nine, max_turns is close, it stops, and I get a cheerful ✅ all tests passing. The suite is still flaky. The loop didn't decide it was right. It decided it was tired. Call it stop-on-exhaustion — and once you have the phrase, you start seeing it everywhere.
The good library loops don't do that. They decide what would make them stop before the first pass. That's the tell of a real one.
Why this matters now: generation got cheap
A year ago, an iteration was expensive enough that you babied each one. That's over. Charity Majors put it bluntly this month — "AI demands more engineering discipline. Not less." — because the economics of code production flipped: lines went from treasured and carefully curated to disposable and regenerable, practically overnight. The same week, GLM-5.2 shipped as open weights with a million-token context. On models like that, a short coding pass is now near-zero marginal cost.
Here's the consequence nobody likes saying out loud: when generation is a commodity, the code the loop emits is the cheap part. The scarce resource is the judgment about which pass to keep. The asset isn't the output — it's the evaluator that judges it. A frontier model wired to a "did it crash?" check is a Ferrari behind a turnstile. (I called that rigor cosplay in the stack post; cheap iteration just made it more expensive to fake.)
So the question stops being "can the agent generate a fix?" — of course it can, ten times before lunch — and becomes "can the loop tell a good pass from a lucky one, and stop on the right one?"
Hope loops vs prune loops
Watch two loops chase the same goal and the difference jumps out.
A hope loop regenerates the same doomed approach until the budget dies, then ships whatever was on screen. A prune loop spends the now-cheap generations on variety, kills the regressions fast, and iterates only the survivor.
Which means the metric I actually care about isn't a loop's success rate — it's its discard ratio: how quickly it throws away a path that isn't working. A loop that takes ten passes to abandon a dead end is worse than one that abandons it in two, even if both eventually pass. Cheap generation didn't make iteration the skill. It made discarding the skill.
The four ways a loop can stop
Strip any loop down and its exit falls into one of four buckets. They are not equal.
Trust climbs as you go down the list. Exhaustion is the bottom — it's not a stop condition at all, it's a loop fainting and you reading meaning into where it fell. Surrender is honest and often correct: the loop did its mechanical work and routes the judgment to a person. Consensus (a second model signs off) is stronger, but agreement and correctness are different things — two models can be confidently wrong together. Provable Truth — a test, an audit, a compile, a check a reviewer can re-run and watch turn red — is the only exit that proves the property you were actually after.
The honest finding from the ones I read closely: the loops worth naming anchor on Provable Truth or a deliberate human gate. None of those stop because they got tired.
The teardown
Three specimens, read for their exits rather than their actions:
| Loop (from the library) | The check it runs | How it stops | What that earns |
|---|---|---|---|
| Revolve versioned-experiment | frozen tests + scoring against a recorded baseline; keep only a regression-free win | Provable Truth — plus no-progress / budget as backstops | a kept change is provably better than the last checkpoint, with a rollback |
| The docs sweep | verifies commands, links, and examples against the repo, then opens a PR | mechanical proof + Surrender to human review | docs match the code — if someone actually reviews the PR |
| The production data cleanup | audits records against explicit rules — sampled and queried — with reversible ops; holds uncertain rows back | Provable Truth + a human gate on the irreversible step | it deletes bad prod data without being how you delete prod data |
That last row is the one that humbled me. A loop that mutates production is exactly where a lazy while would be catastrophic — and the published version refuses to be lazy: explicit inclusion/exclusion rules written before any data changes, an audit that must pass against those rules, reversible operations, and uncertain records parked for a human instead of deleted. That isn't a loop that stops when it's tired. It's a loop engineered to stop only when it's right, with a person on the one action that has no undo.
Notice what's missing from all three: nobody stops on exhaustion. That's not a coincidence — it's the difference between a loop somebody published under their name and the "keep improving X" one-liners I write for myself and never inspect.
The exit is a spec
The stack post put loop engineering on my map as a layer. Here's the part I underplayed: the stop condition deserves the same up-front design as the goal — because it is the definition of done. A practical test, learned the hard way this week: if you can't name the exit contract before the first pass, you don't have a loop. You have motion that happens to halt.
That also sharpens green doesn't mean done: green is only a verdict if the loop stopped because the check passed — not because the check happened to be green when the turns ran out.
The field map
- A loop's value is its exit, not its iteration. Anyone can write
while not done. The engineering isdone. - Exhaustion is a failure mode, not a stop condition. If the honest answer to "why did you stop?" is "I ran out of turns," the loop didn't finish — it fainted.
- Optimize the discard, not the generator. Measure how fast a loop kills dead ends. Now that passes are cheap, the discard is the scarce skill.
- The evaluator is the asset. Code is regenerable; the rubric that judges it is what's worth keeping. A frontier model behind a "did it crash?" check is horsepower wired to nothing.
- Irreversible steps get a human gate, by design. The good prod loops pair a provable audit with a person on the delete. Copy the stop, not just the action.
- Naming a loop forces the exit into the open. That — not the catalog — is why a library of loops is worth anything.
So before you write another while not done, write done first. The iterations are free now — the only scarce thing left is a loop that can prove why it stopped, instead of reporting ✅ done because it got tired.
