/outer-loop — improve the process, not the output
An inner loop optimizes the work: propose → run → measure → keep or roll back.
An outer loop optimizes how the inner loop searches: read its traces, find where the
search itself is stuck, change the mechanism, run again.
The finding worth internalizing (Qu & Lu, verified): both levels used the same LLM.
The 5x came from architecture, not a smarter model. And crucially — parameter-level
adjustments without mechanism changes yielded no reliable gains. Tuning the knobs does
nothing. Changing how it searches is the whole effect.
What their outer loop actually found: the inner loop kept falling back on the model's
priors — retrying familiar moves even after those moves stopped working. The outer
loop broke the pattern by forcing exploration in directions the model's instincts avoid.
Prior-lock is the default failure of any repeated agent process. That is what you are
hunting.
PRECONDITION — refuse to run without these four
An outer loop is expensive and easy to fool. It only earns its cost when the inner loop has:
- A metric. A number that moves, in the right direction, without a human deciding.
(
val_bpb, tests passing, exit code, row-count parity, build time, cost per run.)
No metric → stop. Say so plainly and offer to build the metric first.
- Traces. Logs of what the inner loop actually tried and what happened — not just the
final artifact. You cannot diagnose a search you cannot see.
- Repetition. It has run enough times that a pattern exists to find. A handful of
runs is anecdote, not a stuck search.
- A budget that can absorb it. Two levels of loop burn far more than one.
If any fail: do not build the outer loop. Fix the missing piece, or run the inner loop
better by hand. Most work never qualifies — that is the correct outcome, not a failure.
FROZEN — what the outer loop may never touch
A loop allowed to edit its own grader will make the test easier instead of the work better.
Karpathy's whole design rests on this: the agent edits train.py, it may never touch
the evaluation harness.
Hard boundaries, no exceptions:
- The verifier / metric definition. Never. If the metric is wrong, the human changes it.
- Safety and preference rails — never-send-outward, show-draft-before-send, redlines,
confirm-before-spend, finance discipline. These are values, not parameters.
- Anything money-adjacent, outward-facing, or destructive.
- Its own precondition list (above). It may not decide it qualifies.
Everything it proposes is a draft change requiring explicit human approval before it is
written. The outer loop reports and recommends; it does not self-apply.
(This is exactly why ultra-code was archived. Do not recreate it.)
The loop
- READ THE TRACES. Not the outputs — the attempts. What did it try, in what order,
how often did it repeat a move that had already failed?
- DIAGNOSE THE SEARCH, not the work. Ask: where is this process stuck in a rut?
Symptoms of prior-lock: same fix attempted across runs · the same stage always the
bottleneck · retries that vary wording but not approach · exploration that never leaves
one region of the space.
- PROPOSE A MECHANISM CHANGE. Not a prompt tweak — a different way of searching.
Useful families (the paper drew from these): multi-armed bandits (spend attempts where
they pay), design of experiments (vary one factor at a time), combinatorial search
(systematic coverage instead of greedy), forced diversity (require N approaches that
differ structurally, not in wording).
- STATE THE EXPECTED EFFECT ON THE METRIC before running. A prediction you can be
wrong about — otherwise you cannot tell improvement from noise.
- A/B IT. Run inner-with-change vs inner-as-is on the same input. Keep only if the
metric moves. Roll back by default.
- REPORT + REQUEST APPROVAL. Show the trace evidence, the diagnosis, the mechanism
change, the measured delta. Human decides whether it gets written.
- CAP. Hard limit on outer iterations and total spend, declared before starting.
Failure modes
- Consistency without verification. Every checker reading outputs derived from the same
source produces green lights and no truth. The outer loop needs anchors — a test that
actually ran, a number pulled live from the source system. See
graph-loop.
- Optimizing the measurable instead of the valuable. The metric becomes the target and
the real goal quietly drifts. Re-state the actual goal every round and check the metric
still proxies it.
- Meta-theatre. Adding a level of loop because it's interesting, not because the inner
loop is demonstrably stuck. Honor the build bar in
manager: name the hours saved or the
output shipped.
- Budget runaway. Two nested loops multiply. Cap both.
Where this applies
Qualifies today — anything with a real metric plus traces:
- A health/uptime prober — exit codes are a deterministic metric, and it logs. Outer
question: which breakages recur, and is the probe set itself missing a class?
- A recurring discovery sweep — its log plus its output table are traces. Candidate
metrics: new items per run, share surviving to shortlist, false-positive rate. Outer
question: are the filters stuck in one region of the search space?
Qualifies once a metric exists — build the metric first:
- A site or app build — build passes · zero placeholder strings · a performance score.
The closest thing most projects have to a real objective number.
- A pipeline whose gates are agent judgments — convert them to assertions (row-count
parity, cost ceiling, null-rate threshold) and it gains a real metric.
Does not qualify — do not force it: cover letters, shot selection, clinical protocols,
in-voice replies. No automated verifier exists for taste, and a loop there pays a model to
agree with itself.
Related — do not duplicate
graph-loop — topology (what runs in parallel) + anchors. This skill is time-axis
(how the process improves across runs). Different axes; use both.
fable-review-loop — reviews the artifact/codebase across 4 lenses → plan.md.
This one reviews the process via its traces. Reach for review-loop when the code is
messy; reach for this when the code is fine but the process keeps stalling the same way.
/loop — the inner loop runner, gated by the 4-condition test in ~/CLAUDE.md
(which is the same test, one level down).
manager — routing + budget ceiling + build bar. Route the outer loop's own work
through it: trace reading is cheap-tier, diagnosis is the frontier bit.
- Source: github.com/karpathy/autoresearch (MIT) · arXiv 2603.23420.
1---2name: outer-loop3description: Bilevel loop engineering — put a loop on top of a loop. When a recurring process already runs (a sweep, a pipeline, a review cycle) but keeps getting stuck the same way, this reads its traces, finds where the SEARCH is stuck rather than where the output is wrong, and proposes a change to the mechanism itself. Based on Karpathy's AutoResearch loop plus Qu & Lu's "Bilevel Autoresearch" (arXiv 2603.23420), which got a verified 5x over a single loop using the SAME model at both levels — the gain is architectural, not intelligence. Requires an inner loop with traces and a metric; refuses to run without them. Triggers - "outer loop", "/outer-loop", "bilevel", "loop on the loop", "why does this loop keep getting stuck", "improve the process not the output", "meta-loop".4---56# /outer-loop — improve the process, not the output78An **inner loop** optimizes the work: propose → run → measure → keep or roll back.9An **outer loop** optimizes *how the inner loop searches*: read its traces, find where the10search itself is stuck, change the mechanism, run again.1112The finding worth internalizing (Qu & Lu, verified): **both levels used the same LLM.**13The 5x came from architecture, not a smarter model. And crucially — *parameter-level14adjustments without mechanism changes yielded no reliable gains.* Tuning the knobs does15nothing. Changing **how it searches** is the whole effect.1617**What their outer loop actually found:** the inner loop kept falling back on the model's18**priors** — retrying familiar moves even after those moves stopped working. The outer19loop broke the pattern by forcing exploration in directions the model's instincts avoid.20**Prior-lock is the default failure of any repeated agent process.** That is what you are21hunting.2223## PRECONDITION — refuse to run without these four2425An outer loop is expensive and easy to fool. It only earns its cost when the inner loop has:26271. **A metric.** A number that moves, in the right direction, without a human deciding.28 (`val_bpb`, tests passing, exit code, row-count parity, build time, cost per run.)29 *No metric → stop. Say so plainly and offer to build the metric first.*302. **Traces.** Logs of what the inner loop actually tried and what happened — not just the31 final artifact. You cannot diagnose a search you cannot see.323. **Repetition.** It has run enough times that a *pattern* exists to find. A handful of33 runs is anecdote, not a stuck search.344. **A budget that can absorb it.** Two levels of loop burn far more than one.3536If any fail: **do not build the outer loop.** Fix the missing piece, or run the inner loop37better by hand. Most work never qualifies — that is the correct outcome, not a failure.3839## FROZEN — what the outer loop may never touch4041A loop allowed to edit its own grader will make the test easier instead of the work better.42Karpathy's whole design rests on this: the agent edits `train.py`, it may **never** touch43the evaluation harness.4445**Hard boundaries, no exceptions:**46- **The verifier / metric definition.** Never. If the metric is wrong, the *human* changes it.47- **Safety and preference rails** — never-send-outward, show-draft-before-send, redlines,48 confirm-before-spend, finance discipline. These are values, not parameters.49- **Anything money-adjacent, outward-facing, or destructive.**50- **Its own precondition list** (above). It may not decide it qualifies.5152Everything it proposes is a **draft change requiring explicit human approval before it is53written.** The outer loop reports and recommends; it does not self-apply.54*(This is exactly why `ultra-code` was archived. Do not recreate it.)*5556## The loop57581. **READ THE TRACES.** Not the outputs — the *attempts*. What did it try, in what order,59 how often did it repeat a move that had already failed?602. **DIAGNOSE THE SEARCH, not the work.** Ask: where is this process stuck in a rut?61 Symptoms of prior-lock: same fix attempted across runs · the same stage always the62 bottleneck · retries that vary wording but not approach · exploration that never leaves63 one region of the space.643. **PROPOSE A MECHANISM CHANGE.** Not a prompt tweak — a different way of searching.65 Useful families (the paper drew from these): multi-armed bandits (spend attempts where66 they pay), design of experiments (vary one factor at a time), combinatorial search67 (systematic coverage instead of greedy), forced diversity (require N approaches that68 differ structurally, not in wording).694. **STATE THE EXPECTED EFFECT ON THE METRIC** before running. A prediction you can be70 wrong about — otherwise you cannot tell improvement from noise.715. **A/B IT.** Run inner-with-change vs inner-as-is on the same input. Keep only if the72 metric moves. **Roll back by default.**736. **REPORT + REQUEST APPROVAL.** Show the trace evidence, the diagnosis, the mechanism74 change, the measured delta. Human decides whether it gets written.757. **CAP.** Hard limit on outer iterations and total spend, declared before starting.7677## Failure modes7879- **Consistency without verification.** Every checker reading outputs derived from the same80 source produces green lights and no truth. The outer loop needs **anchors** — a test that81 actually ran, a number pulled live from the source system. See `graph-loop`.82- **Optimizing the measurable instead of the valuable.** The metric becomes the target and83 the real goal quietly drifts. Re-state the actual goal every round and check the metric84 still proxies it.85- **Meta-theatre.** Adding a level of loop because it's interesting, not because the inner86 loop is demonstrably stuck. Honor the build bar in `manager`: name the hours saved or the87 output shipped.88- **Budget runaway.** Two nested loops multiply. Cap both.8990## Where this applies9192**Qualifies today — anything with a real metric plus traces:**93- **A health/uptime prober** — exit codes are a deterministic metric, and it logs. Outer94 question: *which breakages recur, and is the probe set itself missing a class?*95- **A recurring discovery sweep** — its log plus its output table are traces. Candidate96 metrics: new items per run, share surviving to shortlist, false-positive rate. Outer97 question: *are the filters stuck in one region of the search space?*9899**Qualifies once a metric exists — build the metric first:**100- **A site or app build** — build passes · zero placeholder strings · a performance score.101 The closest thing most projects have to a real objective number.102- **A pipeline whose gates are agent judgments** — convert them to assertions (row-count103 parity, cost ceiling, null-rate threshold) and it gains a real metric.104105**Does not qualify — do not force it:** cover letters, shot selection, clinical protocols,106in-voice replies. No automated verifier exists for taste, and a loop there pays a model to107agree with itself.108109## Related — do not duplicate110111- **`graph-loop`** — topology (what runs in parallel) + anchors. This skill is time-axis112 (how the process improves across runs). Different axes; use both.113- **`fable-review-loop`** — reviews the *artifact/codebase* across 4 lenses → `plan.md`.114 This one reviews the *process* via its traces. Reach for review-loop when the code is115 messy; reach for this when the code is fine but the process keeps stalling the same way.116- **`/loop`** — the inner loop runner, gated by the 4-condition test in `~/CLAUDE.md`117 (which is the same test, one level down).118- **`manager`** — routing + budget ceiling + build bar. Route the outer loop's own work119 through it: trace reading is cheap-tier, diagnosis is the frontier bit.120- **Source:** github.com/karpathy/autoresearch (MIT) · arXiv 2603.23420.