Skip to content

Loops

A Loop is a standing goal with a verifiable definition of done. Instead of prompting an agent and shepherding it turn by turn, you describe the outcome (“the payments test suite passes”, “the build is green with zero type errors”) and the checks that prove it — and the loop iterates until those checks hold, or until one of its guardrails says stop.

Loops are ClusterCode’s take on loop engineering: you stop being the person who prompts the agent and design the system that prompts it instead. If you want the full reasoning, read our essay Loop Engineering.

The core rule: the writer never grades its own homework

Section titled “The core rule: the writer never grades its own homework”

Every iteration splits the work between two roles that never collapse into one:

  • The maker — your chosen engine (Claude, Codex, or Copilot) takes one attempt at the goal in a DevBox: implement, commit, push the loop’s branch.
  • The checker — after the maker finishes, deterministic gates run your test/build/eval commands and read exit codes (no model involved), and then an independent verifier rules on every gate from a separate, blank-context session — a different engine from the maker whenever the DevBox has one. The verifier must cite evidence — file and line, a command it ran, output it observed. An approval without evidence is rejected and re-run.

An agent asked to grade its own work tends to praise it. The maker/checker split is structural, not a prompt suggestion — the verdict comes from a separate session, an adversarial read-only prompt, and, by default, a different engine than the one that wrote the code.

That different-engine default is resolved per iteration: a verifier CLI you pin always wins; otherwise Codex makers are checked by Claude, and Claude or Copilot makers by Codex. If the DevBox ships only one AI CLI family, the verifier falls back to that family — still a separate, blank-context session that never sees the maker’s conversation, and best paired with a distinct verifier model. What never happens is no judgment: with no AI CLI in the container the iteration fails instead of skipping the verifier, and verifier-approves can’t be removed.

  1. Brief — the loop builds a compact, cold-start brief: the goal, the definition of done, a summary of what failed last time, and a log of approaches already tried. Each iteration starts fresh — no inherited context rot, and the brief is rebuilt from persisted state, so a crashed orchestrator never loses the thread.
  2. Maker turn — one agent execution (a normal ClusterCode Run you can open and watch) implements against the loop’s branch and commits. The branch is pushed after every iteration.
  3. Deterministic gates — your pinned commands run against the committed code. A dirty tree fails the iteration; uncommitted work never gets graded.
  4. Verifier turn — if the gates are green, the verifier rules per-gate with evidence, through a structured verdict (never free text a parser has to guess at).
  5. Decision — any required gate failed: the failing output steers the next brief and the loop iterates. Everything green: the gates run once more to catch flaky suites, and then the loop opens a pull request.

Want the gears? How a Loop run works walks this cycle step by step — every guardrail, check, and stop condition.

GateWhat it checks
tests-passYour test command exits 0
build-succeedsYour build/typecheck command exits 0
lint-cleanYour lint command exits 0
eval-scriptAny command you supply — your own eval, benchmark, or acceptance script
agent-checkA plain-English assertion you write (“the migration is reversible”) — the independent verifier rules on it with evidence
verifier-approvesThe independent verifier approves every gate, with evidence (always on)

Deterministic gates carry fully-resolved pinned commands — e.g. npx vitest run --config vitest.config.ts, never npm test. A command that dispatches through package.json scripts could be redefined by the code under test; a pinned command can’t.

agent-check gates work the other way around: instead of a command, you write a checkable assertion in plain English, and the verifier — never the maker — rules on it with evidence. The rubric lives in the loop’s definition of done, not in the repository, so the maker can’t edit it; and like all judgment gates it’s only evaluated once every deterministic gate is green.

A maker with write access could try to “pass” by weakening the checks — editing a failing test, adding a lint suppression, loosening a config. Loops treat that as a first-class threat:

  • Gates run against the committed SHA, after a clean-tree check.
  • Every iteration’s diff is screened against a tamper set (test files, lint/CI config, lockfiles, package.json, thresholds). Touching them never auto-passes — the verifier is pointed at each touched file and told to rule on whether the change weakens a check.
  • Before verified, the deterministic gates are re-run once. If a gate flips between runs, the flake is called out in the PR body instead of silently passing on a lucky green.

Guardrails — deterministic, not model judgment

Section titled “Guardrails — deterministic, not model judgment”

The loop’s controller is orchestrator-side, deterministic code. The agent can’t negotiate with it:

Stop reasonWhat happened
verifiedAll gates green, confirmed by re-run, verifier approved — PR opened
budget_exhaustedIteration cap or a dollar cap was reached
no_progressConsecutive iterations produced equivalent diffs with the same failures — the loop detected it was spinning and stopped itself
circuit_brokenRepeated infrastructure failures tripped the circuit breaker
errorAn unrecoverable dispatch/infrastructure error
user_cancelledYou cancelled it

Progress is measured by fingerprinting each iteration’s diff (normalized so whitespace and comment churn don’t count as change) together with the set of failing gates. The first equivalent attempt triggers a replanning turn — a short read-only model turn that writes a revised approach into the next iteration’s brief (it may change the approach, never the goal, gates, or budgets). A second equivalent attempt stops the loop — long before the budget would have.

Budgets are set at creation and enforced by the controller:

  • Max iterations (default 3)
  • Max cost per iteration and max cost per day (in dollars; the daily window rolls over at UTC midnight — a capped loop parks and resumes the next day rather than dying)
  • Wall-clock limit per iteration — the hard kill for a runaway attempt

Owning the outer loop means more than pause and cancel — you can steer a loop while it runs. From the loop’s detail page, Edit / steer lets you change three things on an active or paused loop:

  • the goal,
  • the completion gates (add, remove, or edit them), and
  • the budget (iteration cap and the dollar / wall-clock caps).

Everything else — the target machine, the DevBox or image, the repository and branch, and the maker and verifier engines — is fixed for the loop’s life. Those choices anchor branch continuity and DevBox reuse; to change them, create a new loop.

Changes apply at the next iteration boundary

Section titled “Changes apply at the next iteration boundary”

An edit never lands mid-iteration. When an iteration starts, it takes an immutable snapshot of the goal, gates, and budget, and it is graded against that snapshot for its whole life. So:

The current iteration finishes under the previous settings; your change takes effect from the next iteration.

The next iteration’s brief tells the maker exactly what you changed, so it can adjust its approach rather than discovering the new rules by failing them.

Changing the goal or the gates re-aims the loop, so the “no progress” detector (which watches for the same failing gates and an oscillating diff) resets — a freshly-steered loop gets clean runway instead of being stopped for repeating work it did before you changed the target. A budget-only edit changes nothing about progress detection. Infrastructure-error counting (the circuit breaker) is never affected by a steer.

Lowering max iterations (or a dollar cap) below what the loop has already spent is allowed and intentional: the next pre-iteration check stops the loop as budget exhausted. That is the supported way to wind a loop down gracefully — the timeline records the steer and the stop, so it is clear why it ended.

An edit can never remove the last checker. At least one of verifier-approves or an agent-check gate must always remain — the maker/checker split is the core of the design, so the one thing you are never allowed to do is let the maker be the only judge of its own work. Attempting it is rejected with a clear validation error.

Every steer — and every pause, resume, and cancel — is written to the loop’s timeline with who did it and when, interleaved with the iterations, so the audit trail of owner interventions is part of the glass box.

Every iteration is recorded permanently: its brief, its commit, its cost, each gate’s exit code and output tail, and the verifier’s per-gate reasoning and evidence. The loop’s detail page shows the full timeline, and each iteration links to its Run so you can open the actual transcript. When a loop says “done”, you can see exactly why it believes that — and when it says “stuck”, you can see what it tried.

Loops are available on every plan, with a per-tier cap on how many can be active at once:

Resource FreeStarterProEnterprise
Active Loops 1 3 15 60 20×

/ 20× mark limits where Pro is exactly 5× Starter and Enterprise 20×.

Viewing, pausing, resuming, cancelling, and steering an existing loop is never gated — control and transparency are free on every tier.