AI Agent Stack everyone must use with GPT 5.6 + Fable 5 (Builder's Guide)

Fable 5 + GPT-5.6: The A - Z Build of an Agent Stack That Ships While You Sleep
This is the complete build, in order, with a checkpoint after every piece.
Bookmark these 12 builds before you forget.
Introduction
You have the two most capable models ever made generally available, and you are still using one of them at a time, by hand.
Three things changed in the last month.
Run casually, these models are an expensive way to generate impressive wrong things.
Run inside a system, they are the closest thing to an employee you can rent. Anthropic's enterprise numbers put Claude Code at about $13 per developer per active day. OpenAI puts Codex at $100 to $200 a month.
This guide builds that system in twelve builds: the actual files, in order, each tested before publishing, with a checkpoint after each so you know a piece works before you stack the next one on it.
It is for anyone with a repo, a terminal, and access to either CLI. The examples are code-flavored because loops grew up around code, but the router, the advisor, and the gate work on invoices and reports the same way.
Read it in order, doing the checks. Each build takes 10 to 20 minutes, about two hours in total. The 30 days at the end are the schedule during which the system earns the right to run without you.
Three principles predict every design decision below:
The map, and why the usual one is wrong
Loop engineering is agentic workflow with an explicit stopping condition and retry logic. The harness decides when work is finished, instead of leaving "am I done" to the model.
The standard picture is swyx's Loopcraft stack: five loops nested inside each other, execution inside task inside product inside system inside oversight, each with its own exit. It is the best one anybody has drawn.
I used it for weeks. Then I tried to build against it, and it broke in four places.
1)Problem one: the loops do not nest.
Nesting means one turn of the outer loop equals one complete run of the inner loop. That is not what happens. The system loop does not wait for the product loop to finish. It runs on Sunday whether or not anything shipped.
You can interrupt a token stream by hand without unwinding four layers. It is a picture of containment drawn over a system that does handoffs.
2) Problem two: a loop drawn as endless is a bill.
The original draws the product loop that way. In practice it ends on a budget, on a checkpoint, or on somebody losing patience.
Calling that "none by design" hides the exact place where money leaks out of an agent system: a loop that nobody told how to quit.
3) Problem three: there is no abort.
Every layer has a happy ending and no unhappy one. Real loops need both: how it closes when it works, and how it stops when it cannot.
Every runaway bill I have seen was a loop with a defined exit and an undefined abort.
4) Problem four: verification is missing, and it is the whole game.
Verification is the contract between layers. When a lower loop hands an upper loop a report instead of a fact, the upper loop closes on a lie.
That single gap is why a loop can hit its stopping condition and still be wrong.
This is the version I build against.
The Evidence Ladder
Six rungs, two exits each, and one rule: control flows down as goals, evidence flows up as facts, and no rung may close on a report from the rung below it.
Five laws fall out of the shape.
Every rung has an abort, or it is a bill. If you cannot name how a loop ends badly, you have built a subscription. This is why ralph.sh carries two caps and the swarm carries a cycle cap.
Evidence flows up and control flows down. A rung closes on a fact produced below it, never on a summary written below it.
The factory gate is this law in SQL. Two reviewers said green. The gate still refused, because nobody had produced a passing test row.
A verdict is an opinion. A row is evidence.
Cost per turn climbs about tenfold per rung.
A bug that escapes rung 2 costs ten times more to catch at rung 3, and a hundred times more at rung 4.
That is the entire argument for putting your best verification as low on the ladder as it will go, which is why the gate is a bash script and not a meeting.
Timescale belongs to the model, not to the rung.
Rung 2 took minutes in 2024, takes hours in 2026, and will take days soon. Design against the exit condition, never against the clock. This is where the old picture ages fastest.
Only rung 5 has no exit condition, and that is what human means.
You live there. The ladder exists to earn one sentence: a loop can hit its stopping condition and still be wrong.
Tests pass, the gate goes green, both reviewers sign, and the last commit is still a mistake. Every rung below you exists to make that check smaller. None of them can take it from you.
Prerequisites
claude CLI (Claude Code) with Fable 5 access
codex CLI with GPT-5.6 access # or the official plugin inside Claude Code
python3, jq, git, gh, make, cron
a repo with a test command that works today
# optional, for mixed fleets (BUILD 7):
openai/codex-plugin-cc # official: run Codex inside Claude Code
claude-model-switch # local proxy: any provider behind Claude Code
CLIProxyAPI # wrap CLI subscriptions as API endpointsWhat you are building
your-repo/
CLAUDE.md # BUILD 1: Claude-side constitution
AGENTS.md # BUILD 1: Codex-side constitution
.claude/
skills/model-bench/SKILL.md # BUILD 0: prices, API ids, fallbacks. the only file with numbers
skills/model-router/SKILL.md # BUILD 4
skills/stuck-protocol/SKILL.md # BUILD 5
skills/ship-gate/SKILL.md # BUILD 2
agents/fable-expert.md # BUILD 5
agents/fresh-eyes-reviewer.md # BUILD 6
agents/sol-reviewer.md # BUILD 6
agents/scout.md # BUILD 7
loop/
ralph.sh # BUILD 3: the heartbeat
two_lane.sh # BUILD 6: cross-vendor review loop
PROMPT.md TASKS.md # BUILD 3: the work protocol
gate/
verify.sh # BUILD 2: deterministic final vote
eval_gate.py eval/cases.jsonl # BUILD 2: routing-change gate
router/
router.py # BUILD 4
advisor_loop.py # BUILD 5
~/.codex/
config.toml # BUILD 0: luna/terra/sol profiles
prompts/effort.md # /effort score the task, name the seat
prompts/plan-stop.md # /plan-stop plan, price it, then stop
prompts/fable-advice.md # /fable-advice cross-vendor expert consult
prompts/review-hostile.md # /review-hostile clean-context verdict
prompts/compost.md # /compost failures become laws, weekly
factory/
factory_gate.py # BUILD 8: blackboard + completion gate
factory.sh # BUILD 8: brief -> implement -> review -> gate
factory.db # BUILD 8: the rows that decide
swarm/
swarm.sh # BUILD 9: plan -> dispatch -> score -> replan
goals.jsonl # BUILD 9: one goal per line, each with its check
system/
verify_goals.py # BUILD 10: daily re-verification, forever
goals/ # BUILD 10: one file per finished thing
ROUTING.md # BUILD 12: the full routing policy, both harnesses
progress.log # every build appends here
# optional (BUILD 7): claude-model-switch proxy on localhost:4000,
# CLIProxyAPI for wrapping CLI subscriptions as API endpointsBUILD 0: Configure the Engines
Set these before writing any file of your own. Every number below was verified against the official pricing pages the week of publication.
The bench: every seat, July 2026
The roster the system hires from.
Prices live in one skill file, .claude/skills/model-bench/SKILL.md, loaded on demand before any routing or cost question. No other file hardcodes a number.
Prices moved three times in the six weeks before this was written. A price in an article is wrong by publication. A price in a skill file is one edit.
The split that decides everything downstream:
That split is why this system is bi-vendor. Fable judges and plans, Sol reviews and drives terminals, and neither one does the bulk typing.
Two seats people misread.
Opus 4.8 is not the old flagship gathering dust. It is the automatic fallback under Fable and the recommended default for complex agentic coding. Your system inherits it whether you plan for it or not.
Sonnet 5 at introductory pricing is the best value on the board. Close to Opus 4.8 in capability at a fraction of Fable's input price, which is why it is the default executor everywhere in this build. That rate expires August 31, and the skill file already knows it.
That skill file is the only file in the system that contains a number:
---
name: model-bench
description: The current price sheet, API model IDs, and fallback chain for every
model this system can hire. Load before any routing decision, cost estimate,
budget question, model comparison, or when the user asks what something costs.
---
# Model bench
Single source of truth for prices and API identifiers. Nothing else in this repo
hardcodes a price, so when the labs move their rates you edit this file and
nothing else. Verified 2026-07-13. Prices move. Re-verify before you budget.
## Anthropic (Messages API, /v1/messages)
Effort: output_config {"effort": "low|medium|high|xhigh|max"}. Adaptive thinking
is always on for Fable 5 and cannot be disabled. max_tokens caps thinking PLUS
response text, so set it large (start near 64k) on high and above, or the model
runs out of room mid-thought.
| Model | In/out per Mtok | Cache read | Seat |
|---|---|---|---|
| claude-fable-5 | $10/$50 | $1.00 | conductor, planner, advisor, judge. Falls back to opus-4-8 automatically |
| claude-opus-4-8 | $5/$25 | $0.50 | conductor under retention rules |
| claude-sonnet-5 | $2/$10 (to Aug 31, then $3/$15) | n/a | default coding executor |
| claude-haiku-4-5 | $1/$5 | $0.10 | scouts, subagents, mechanical work |
1M context on Fable, Opus 4.8, Sonnet 5, priced FLAT at long context, which is
why long reads route here. Max output 128K.
## OpenAI (Responses API, /v1/responses)
| Model | In/out per Mtok | Cached | Seat |
|---|---|---|---|
| gpt-5.6-sol | $5/$30 | $0.50 | cross-vendor reviewer, terminal work |
| gpt-5.6-terra | $2.50/$15 | $0.25 | Codex daily driver (test vs Luna first) |
| gpt-5.6-luna | $1/$6 | $0.10 | mechanical work, quiet ticks |
Long context above the threshold roughly DOUBLES input price, unlike Anthropic's
flat 1M tiers. First family with explicit cache breakpoints; writes cost 1.25x.
## Open weights (bulk workers)
| Model | In/out per Mtok | Cache hit |
|---|---|---|
| deepseek-v4-flash | $0.14/$0.28 | $0.0028 (roughly 98 percent off) |
| deepseek-v4-pro | $0.435/$0.87 | n/a |
| kimi-k2.7-code | $0.95/$4.00 | $0.19 |
## Discounts that stack
- cache reads cost a tenth of fresh input at both labs (about 90 percent off)
- cache writes pay for themselves after one read (5m) or two (1h)
- batch APIs are 50 percent off both directions
- batch + cache read on a repeated prefix lands near 95 percent off
- Anthropic's newest tokenizer makes about 30 percent more tokens for the same
text, so effective cost sits above sticker. Budget on effective.
## How to answer a cost question
1. Estimate input and output separately. Agents read about 100 tokens for every
1 they write, so input dominates and cache hit rate decides the bill.
2. Apply the cache read rate to the repeated prefix, not the base rate.
3. Multiply Anthropic figures by about 1.3 for the tokenizer.
4. Quote a range, name the assumptions, say which line of this file you used.
5. If the number exceeds the repo's daily cap, say so BEFORE running anything.
Never present a price you did not read from this file. A model not listed here is
not on the bench, and adding one is a routing change that goes through the gate.Seven facts that change how you build:
The second meter: a seat is not an API key
Every number above is priced in dollars per million tokens. That is the right currency if you pay per call.
It is the wrong one if you run this on a $200 Codex Pro seat or a Claude Max seat.
On a seat the meter is a five-hour window and a weekly window, evaluated together, and one request counts against both.
You can be flush on the week and still locked out for four hours, because a single message ate the short one.
Same doctrine. Different currency. Three settings decide how much of a window one message can take:
Fast mode is the expensive one, because it multiplies a number that just got bigger.
GPT-5.6 runs far longer per message than 5.5 did. Mostly a gift. It also makes burn unpredictable.
Speed is not free. What it charges you for is the tokens you were going to burn anyway. Re-read the multiplier on the speed docs before you trust it: it is published per model, and it moves.
Ultra is the subtler trap, because the interface files it where the effort levels live and it is not one of them.
Pointed at a task that does not truly split, ultra buys four agents duplicating one investigation.
It is worth roughly 3.1 points on Terminal-Bench 2.1, 88.8 to 91.9, for a fleet's worth of burn. Off until the boundaries between the sub-problems are real.
Why Sol and Terra are both correct defaults
A field report runs Sol for nearly everything. The bench above makes Terra the Codex daily driver. Both are right, and the meter is the reason.
Rate is not cost. Cost is rate times turns-to-green, and the second term is the one that moves.
Which is BUILD 4's law arriving from the other direction: upgrade the seat before you touch the dial. On a seat that reads as Sol at high on the $200 tier, Sol at low below it. Measure before you believe either.
Set the Codex tiers now:
# ~/.codex/config.toml
model = "gpt-5.6-terra" # daily driver
model_reasoning_effort = "medium"
# service_tier = "fast" # LEAVE COMMENTED OUT. fast mode bills 2.5x
# credits. run /fast status to confirm you
# are not already in it.
[profiles.fast] # mechanical work. NOT "fast mode": this
model = "gpt-5.6-luna" # profile is a cheaper model, not a 2.5x
model_reasoning_effort = "low" # meter. two different things, one word.
[profiles.deep] # planning, evil bugs, reviews
model = "gpt-5.6-sol"
model_reasoning_effort = "high"CHECK 0: both CLIs authenticate, and your test command exits 0 on the current repo.
BUILD 1: The Constitutions
These models follow laws and optimize around tips, so every line needs a number, a never, or a command that checks it.
Create CLAUDE.md:
# CLAUDE.md
## NEVER (exceptions require asking first)
- Never switch models mid-session. Routing happens at session and
subagent boundaries only. Mid-task swaps burn the cache.
- Never review your own diff. Review comes from a fresh context or a
different lineage. Devin's reviewer catches 2 bugs per agent PR
precisely because it shares nothing with the writer.
- Never edit, weaken, or delete a test to make it pass. Automatic FAIL.
- Never report done from self-assessment. Done = gate/verify.sh passed.
- Never take a fourth advisor consult. Three misses = BLOCKED, human's turn.
- Never merge a routing or prompt change that eval_gate.py BLOCKED.
- Never run any loop without both caps set: MAX_ITERS and BUDGET_USD.
- Never assume a frontier model is up. Fallbacks: fable-5 -> opus,
sol -> terra. Log every fallback to progress.log.
- Never spawn a subagent you were not asked for. Children inherit the
parent's model AND effort, so an eager fleet inherits the expensive seat.
## DISPATCH (first match wins)
| # | Task | Seat |
|---|---|---|
| 1 | plan / architect / migrate | fable-5 plans, sonnet executes |
| 2 | extract / format / tests / docs | haiku or luna |
| 3 | context over 60k tokens | Anthropic 1M flat-priced tier |
| 4 | review of agent-written code | sol via codex, native harness |
| 5 | ambiguous | difficulty score: 0-1 cheap, 2 sonnet, 3+ frontier |
| 6 | still unsure | run cheap once, verify, escalate once on fail |
## DONE
- Every task carries a machine-checkable done_when before work starts.
- A fresh-context reviewer judges spec against diff, nothing else.
- gate/verify.sh holds the final vote. Two maker/checker
disagreements on one item -> stop, queue for a human.Create AGENTS.md at the repo root, the same laws in Codex's dialect. Keep it near 100 lines, a table of contents, not an encyclopedia:
# AGENTS.md
## Commands
| Purpose | Command |
|---|---|
| Test | make test (this command is the definition of done) |
| Lint | make lint |
## Session protocol
1. Read progress.log and TASKS.md first. 2. ONE unchecked task.
3. Implement, run the FULL suite, commit only green, descriptive message.
4. Tick the task, append one line to progress.log, stop.
Tests define done. Never weaken, skip, or delete one. Wrong test =
mark the task BLOCKED and say why.
## Model policy
Default: terra, medium effort. Mechanical: profile fast (luna, low).
Planning and evil bugs: profile deep (sol, high).
Effort before model. Profile picked at session start, never mid-task.
Fast mode OFF (2.5x credits). Ultra OFF. Neither one is an effort level.
Only spawn a subagent when I ask for one. Children inherit this session's
model AND reasoning level, so an eager spawn at high effort is a whole
fleet at high effort.
## Stuck
Signals: same error twice; two no-progress steps; a test surviving two
distinct fixes. Then /fable-advice. Max 3 consults, then BLOCKED.
## Review
/review-hostile in a FRESH session before any merge, or the cross-vendor
lane from the Claude side. Never merge your own unreviewed work.One doctrine must live on both sides, or whichever harness has the laxer habits wins every time you switch tools.
CHECK 1: for every line, ask whether the model could comply 80 percent and claim success. If yes, rewrite it with a number or a never. wc -l CLAUDE.md under 60.
BUILD 2: The Gate
A bash script must hold the final vote before anything else exists, because every later build assumes it.
Create gate/verify.sh for your stack:
#!/usr/bin/env bash
set -e
npm run typecheck --if-present
npm test --if-present
npm run lint --if-presentCreate gate/eval_gate.py, the seatbelt for every future routing or prompt change. It runs 50 to 500 held-out cases through the current config and the proposed one, with deterministic checks only:
for case in cases: # {prompt, must_include, must_not_include, max_words}
hits += passes(case, run_config(case.prompt))
verdict = "SHIP" if new_score >= old_score - 0.02 else "BLOCKED"Then make the gate unskippable as a skill, .claude/skills/ship-gate/SKILL.md:
---
name: ship-gate
description: Run the eval gate before any routing, model, or prompt change ships.
Use when the user asks to change routing rules, swap a model tier, edit a system
prompt, adjust effort levels, or merge anything touching router, prompts, or
model config.
---
# Ship gate
Any change to routing or prompts is a quality gamble until the gate says
otherwise. This skill exists so the gamble never ships silently.
1. Locate eval/cases.jsonl. If it does not exist, STOP and tell the user to
build 50 to 500 representative cases first, from real traffic. Do not
improvise cases yourself.
2. Run: python3 eval_gate.py eval/cases.jsonl, current config vs proposed.
3. BLOCKED: report both scores, list which cases regressed, do not apply the
change, suggest the smallest revert that clears the gate.
4. SHIP: apply, and append one line to progress.log with both scores.
Hard rules:
- Never override a BLOCKED verdict, even if asked nicely. Escalate to the human
with the failing cases attached.
- Never edit the cases file in the same session as a routing change. The gate
and the change must not share an author.
- Cost numbers are not a defense against a quality drop. The gate wins.The gate uses deterministic checks only, because it must never inherit the who-verifies-the-verifier problem. A routing change without an eval gate is a cost experiment you are running on your customers.
CHECK 2: ./gate/verify.sh exits 0 today, and eval_gate.py prints SHIP on its demo. If verify.sh fails now, fix it before anything else. The system stands on this script.
BUILD 3: The Heartbeat
The model brings intelligence. The loop brings discipline.
This is the exact shape behind Anthropic's 16-loop run that built a 100,000-line C compiler for about $20,000, with no orchestrator model anywhere.
Create loop/PROMPT.md:
Read progress.log and TASKS.md. Pick exactly ONE unchecked task.
Implement it. Run the tests. If green: commit with a descriptive
message, tick the task, append one line to progress.log, stop.
If the same task fails twice, mark it BLOCKED with the error and stop.
Create a file named DONE only when every task is ticked AND the full
suite passes. Never edit a test to make it pass.Create loop/ralph.sh:
#!/usr/bin/env bash
set -u
MAX_ITERS="${MAX_ITERS:-25}" # cap one: iterations
BUDGET_USD="${BUDGET_USD:-10}" # cap two: dollars
MAX_FAILS=3; fails=0; spent=0; i=0
while [ ! -f DONE ] && [ "$i" -lt "$MAX_ITERS" ]; do
i=$((i + 1))
# fresh session every iteration: no memory except the repo itself
claude -p "$(cat PROMPT.md)" --max-turns 30 \
--output-format json > out.json 2> err.log \
&& fails=0 || fails=$((fails + 1))
[ "$fails" -ge "$MAX_FAILS" ] && exit 2 # circuit breaker
cost=$(jq -r '.total_cost_usd // 0' out.json)
spent=$(awk -v a="$spent" -v b="$cost" 'BEGIN{printf "%.4f", a+b}')
awk -v s="$spent" -v c="$BUDGET_USD" 'BEGIN{exit !(s>c)}' && exit 3 # cap
sleep 2
done
[ -f DONE ] && echo "done in $i ticks, \$$spent" || echo "cap hit, \$$spent"Swap the claude line for codex exec and the identical loop drives GPT-5.6.
The exit map is deliberate: 0 done or quiet, 2 circuit breaker, 3 budget. Every alarm in BUILD 12 keys off these.
The cost line reads the session's own JSON cost report, so the cap is enforced by the harness against real spend, not an estimate.
Count the stops in that prompt. Every branch ends in one, and that is the design, not a tic.
This generation runs much longer per message than the last one did. Mostly a gift. Occasionally a bill, because a model that no longer needs encouragement to continue will carry a task four steps past the point where you wanted to look at it.
The loop solves that structurally: one task per tick, hard stop at the end.
Interactively you have to say it out loud. Two prompts do the work:
A model that runs long is only dangerous when nobody told it where the edge was.
Long tasks fail the way context fails, so iterations stay short and the environment does the remembering. Fable 5 and the Codex models now compact their own context mid-run, so resist adding clever memory plumbing; the right amount shrinks every quarter.
CHECK 3: two tiny real tasks in TASKS.md, one hand-run tick at BUDGET_USD=2. Confirm one commit, one ticked task, one log line, and that the loop exits instead of starting a second task.
BUILD 4: The Router That Earns Its Job (model, then effort)
The most rigorous routing benchmark of 2026, LLMRouterBench, found many routers, including commercial ones, fail to reliably beat picking the best single model. So the router is guilty until proven innocent on your own traffic.
The decision rule, before any code. Add a router only when both of these are true:
If one well-chosen model beats your router on those evals, delete the router and bank the simplicity.
Once it clears the bar, router/router.py runs three layers, cheapest decision first. Note that the tiers name seats, never prices: the rates come from the bench skill at runtime, so a price change never touches your router.
TIERS = { # seats, not numbers
"cheap": "gpt-5.6-luna", # or claude-haiku-4-5
"mid": "claude-sonnet-5",
"frontier": "claude-fable-5", # or gpt-5.6-sol
}
PRICES = load_bench(".claude/skills/model-bench/SKILL.md") # one source of truth
RULES = [
(kind in {"extract", "format", "summarize"}, "cheap"),
(kind in {"plan", "architect", "migrate"}, "frontier"),
(context_length > 60_000, "mid"),
]
tier = layer1_rules(task) or layer2_classifier(task)
if tier: return call(TIERS[tier], task)
return cascade(task) # cheap first, verify, escalate ONCE on failThe middle layer scores difficulty on markers you can read: why, debug, race, deadlock, refactor, security, plus code in the prompt, a prior failed attempt, and more than one subsystem touched.
Zero or one point goes cheap. Two goes mid. Three or more goes frontier. The cascade's verifier is deterministic and escalates exactly once.
Wire the same decisions into the harness so they fire without being invoked, .claude/skills/model-router/SKILL.md. Note that the skill does not restate the rules, it reads them, the same single-source-of-truth trick the bench uses for prices:
---
name: model-router
description: Route each task to the right seat and effort before starting work.
Use at session start, before spawning subagents, when the user asks which model
to use, or when a task mixes planning and execution.
---
# Model router
Read ROUTING.md and apply it. Do not improvise a policy, and do not restate one
here: this file would rot, and the policy file is the one under the eval gate.
Three things this skill enforces on top of that file:
1. Route at boundaries only. Session start and subagent spawn. A mid-task swap
invalidates the cache and re-bills the context at ten times the cached rate.
2. At session end, append the cheap-tier share to progress.log. Savings compound
only once most traffic goes cheap, so that number is the one to watch.
3. Any change to ROUTING.md ships through the ship-gate skill. No exceptions.The decision order mirrors cost: a free check first, a scored guess second, a paid experiment last.
The money is the traffic split, not the cleverness.
Which is why the cheap share in progress.log is the one number this system makes you watch.
Effort is the second dial
Effort is routing one level down: the same skill, applied to how long the model thinks instead of which model runs.
Every tool buries the dial on a different default. High in Claude Code. Medium in Codex. Hidden in most apps. So people leave one setting on for everything, and either overpay or underthink.
Default to high and treat max as a last resort, not a flex.
The model matters at least as much as the dial. Fable 5 on lower effort often beats older models running at xhigh, so reach for the better model before the higher setting.
Two settings get mistaken for higher rungs of this ladder. Neither is on it.
Different axes. Ultra is not "more than max," and pointing it at a task that does not truly split buys four agents duplicating one investigation.
The ladder does not port across versions. The same word buys a different amount of thinking on a new model than it did on the old one.
Moving a familiar task to a new seat, start one rung below the setting you trust. Climb only if the output asks.
One trap belongs to swarms specifically.
Subagents inherit the parent's model and the parent's effort. A fleet spawned from a max-effort conductor is a max-effort fleet, and it drains a window in a single message.
Pin them down in their own frontmatter, and know which harness you are in when you do, because the pin is only as good as the spawner that reads it.
On the Codex side the only real controls are the setting you opened the session with, and a line in AGENTS.md that says do not spawn unless asked. Verify which one you have before trusting either:
name: scout
model: haiku
effort: low # subagents inherit the parent. a max-effort swarm
# empties a window in one message. pin them down.Set it per tool: /effort in Claude Code and the Codex TUI, a flag like codex -e high, a line in config, or the effort field on the API.
Model routing decides who thinks. Effort routing decides how long, and the second dial is cheaper to turn because nothing else in the setup changes and the cache stays warm. Spend effort where the loop branches. Everywhere else it is a tax.
Track the one number weekly:
grep '^route' progress.log | awk -F'\t' \
'{r++; if($3!="frontier")c++} END{printf "cheap share: %.0f%%\n", c/r*100}'ROUTING.md, the policy both harnesses read
Everything above condenses into one file at the repo root.
# ROUTING.md
Routing is four decisions, and the order is the point:
1. WHERE: which harness runs the work
2. WHEN: at which boundary the decision is made
3. WHO: which model takes the seat
4. HOW HARD: which effort level that model runs at
Most teams only argue about 3. The money is in 2 and 4.
## 1. WHERE: harness before model
A model post-trained inside a harness runs out of distribution anywhere else.
Measured spread: 20.2 percent native vs 7.7 percent foreign, same weights.
| Work | Harness | Why |
|---|---|---|
| writing code | the model's native harness | writers degrade out of distribution |
| reviewing code | the reviewer's native harness | a weak review is worse than none |
| reading, scouting | anywhere | reads are cheap and verifiable |
| mechanical transforms | anywhere | if the check is deterministic, harness barely matters |
LAW: remap reader and reviewer lanes freely. The writer lane stays harness-native
until your own eval set says otherwise. That override must be a measurement, not
a preference.
## 2. WHEN: route at boundaries, never inside them
A mid-session swap throws away the prompt cache. Cached input costs a tenth of
fresh input, so a needless swap re-bills the whole context at ten times the price
and buys nothing.
Legal boundaries, the ONLY places a routing decision may happen:
- session start
- subagent spawn
- a new goal in the swarm
- a review handoff to the other lineage
- a fallback fired by an outage or a safeguard
Illegal everywhere else. No per-turn routing. No adaptive swapping mid-task.
The cascade gets exactly ONE escalation, and it opens a fresh boundary.
LAW: pick the seat when the boundary opens, then stay put until the next one.
## 3. WHO: the decision procedure (first match wins, log the result)
Layer 1, rules. Free. Always check first.
| Signal | Seat |
|---|---|
| extract / format / summarize / classify / tests | Haiku or Luna, effort low |
| plan / architect / migrate / root-cause | Fable plans, Sonnet executes |
| context over 60k tokens | Anthropic 1M tier (flat-priced) |
| reviewing agent-written code | the other lineage, native harness |
| goal splits into independent pieces | swarm: Fable writes and scores |
Layer 2, the score. One point each:
- contains why / debug / race / deadlock / refactor / security / optimize
- touches more than one subsystem
- a prior attempt already failed
- the change is irreversible or user-facing
0-1 -> cheap tier, low effort. 2 -> Sonnet, medium. 3+ -> frontier, high.
Layer 3, the cascade. Run cheap, verify deterministically, escalate exactly ONCE.
Never twice. A second failure is a spec problem, and a bigger model will not fix
your spec.
Seats and fallbacks live in .claude/skills/model-bench/SKILL.md. No prices here.
## 4. HOW HARD: effort routing
Effort is routing one level down. Cheapest dial in this file: nothing else
changes and the cache stays warm.
| Effort | Use it for |
|---|---|
| low | typos, renames, sorting, extraction, EVERY subagent by default |
| medium | routine code from a clear spec, summaries, standard writing |
| high | teardowns, migrations, nasty bugs, all conductor work (DEFAULT) |
| max | only the problem high already failed to crack |
| ultra | NOT ON THIS LADDER. width, not depth: 4 agents in parallel. off by default |
1. Default to high. The sweet spot sits there; max tips into overthinking.
2. Better model beats higher dial. Upgrade the seat before the setting.
3. Subagents INHERIT the parent's model AND effort. A fleet spawned from a
max-effort conductor runs at max and empties a window in one message. Pin
every subagent in its own frontmatter: effort: low. Where the spawner
ignores the pin, the parent's dial IS the fleet's dial. Check which you have.
4. Max is depth. Ultra is width. Ultra only when the sub-problems are genuinely
independent, never as a default, and not at all while the harness over-spawns.
5. The ladder does not port across versions. On a new model, start one rung
below the setting you trusted on the old one.
6. Fast mode is not an effort level either. It buys latency at 2.5x credits on
tokens you were burning anyway. Off.
The dial lives in four places: /effort in Claude Code and the Codex TUI, codex -e high,
model_reasoning_effort in config, the effort field on the API. Claude Code
defaults high, Codex defaults medium, most apps hide it entirely, which is why
teams accidentally run one level for everything.
## 5. Fallbacks: assume the frontier is down
Frontier availability is not guaranteed, and a safeguard can reroute a call to
Opus 4.8 mid-run, in under 5 percent of sessions, without erroring.
- Every seat has a named fallback. No exceptions.
- Every fallback is logged. A silent reroute is a bug, because you may be
reading output from a model you did not pick.
- NEVER iterate on output from a model you did not choose.
## 6. The number that decides whether any of this worked
Blended cost is your traffic split, nothing else. 70 percent cheap cuts the bill
by roughly two thirds. 10 percent saves pocket change. Router accuracy is worth
far more than router cleverness.
Track it with the one-liner in BUILD 4. Below 50 percent, savings have not
started compounding. Fix the split before touching anything else here.
## 7. The gate on this file
LAW: no change to this file ships without eval_gate.py passing on 50 to 500
held-out cases. A BLOCKED verdict is final and cannot be overridden in-session.
The gate and the change must not share an author.
## 8. When to delete this file
If a single well-chosen model beats this whole stack on your evals, delete the
router and keep the simplicity. The most rigorous 2026 routing benchmark found
many routers, commercial ones included, fail to reliably beat picking the best
single model.
Measure first. Route second. Delete gladly.CHECK 4: router.py runs offline and prints a decision, a reason, and the split. Your notes hold the 5x gap measurement, or a dated note saying the router is not yet justified.
BUILD 5: The Advisor Inversion
The classic pattern puts the smart model in charge and burns frontier tokens on bulk execution. Invert it.
Anthropic's advisor results: Haiku with an Opus-class advisor more than doubled its score on a hard browsing benchmark, 41.2 against 19.7 alone, at 85 percent lower cost per task than the mid tier.
Execution is bulk. Advice is grams.
The harness decides when the driver is stuck, never the driver, .claude/skills/stuck-protocol/SKILL.md:
---
name: stuck-protocol
description: Escalate to the fable-expert advisor when progress stalls. Use when
the same error appears twice, when two consecutive steps change no files while
errors persist, when a test fails after two distinct fix attempts, or when the
user says the agent is going in circles.
---
# Stuck protocol (the advisor inversion)
You are the cheap driver and that is a feature: execution is bulk, advice is
grams. But small models are overconfident, so you do not get to decide you are
fine. Check the deterministic signals instead.
Stuck signals (any one fires the protocol):
1. The same error string on two consecutive steps.
2. Two consecutive steps with zero files changed while errors persist.
3. The same test failing after two genuinely different fix attempts.
Procedure:
1. Count consults this session. At 3, STOP: mark the task BLOCKED with the
error attached, summarize for the human, move on. Never a fourth consult.
2. Build the brief, nothing else goes in it:
GOAL: one line
ATTEMPT x2: the last two attempts, 200 characters each
ERROR: the exact error, 300 characters
3. Spawn fable-expert with the brief. It returns guidance, not code.
4. Apply the guidance in the very next step, before anything of your own.
5. Append one line to progress.log: consult #N, what it said, whether it worked.
Hard rules:
- Never ask the expert to do the work. If the reply contains a full
implementation, take the idea and discard the code.
- Never pad the brief with your reasoning history. The expert's value is clean
context; a long brief poisons it.
- If the guidance fails, that counts as one of your two attempts toward the next
consult. Three failed consults means the task is above this session's pay
grade, and saying so is the correct output.The expert seat, .claude/agents/fable-expert.md:
---
name: fable-expert
description: Frontier advisor for stuck moments. Receives a compact brief from
stuck-protocol, returns guidance under 600 tokens, never does the work itself.
model: claude-fable-5 # swap to opus if retention rules bite
effort: high
tools: Read, Grep, Glob # may read, may never edit
---
You are the expert consultant, not the contractor. A cheaper model is driving and
has hit a wall. Your value is judgment in grams, and clean context: you know
nothing about how the driver got here, which is exactly why your read is sharper.
You receive a brief: GOAL, the last two ATTEMPTs, and the ERROR. If the brief
names specific files, you may read them. You may not edit anything.
1. If the brief is missing something you need, reply with ONE line naming what
is missing. Do not guess around a hole.
2. Diagnose before prescribing: one or two sentences on what is actually wrong.
3. Then reply in this format and nothing after it:
GUIDANCE:
1. (most likely fix: what to try, and why it should work)
2. (fallback if 1 fails)
3. (only if there is a genuinely distinct third path)
CONFIDENCE: high | medium | low
4. Under 600 tokens. No code blocks over 10 lines. Give the idea, not the
implementation. If your reply contains a full solution, you failed the role.
5. If the task itself is misconceived, say so in item 1 and recommend what to
tell the human.
Operator note: if your org cannot accept Mythos-class retention, change the model
line to opus. The role works the same; the advisor result was first proven with
Opus-class advisors.And the same lane in reverse for Codex sessions, ~/.codex/prompts/fable-advice.md:
claude --model claude-fable-5 -p "You are an expert advisor.
A cheaper model is driving and is stuck. BRIEF: <goal, two
attempts, error>. Reply GUIDANCE: up to 3 numbered items,
under 600 tokens. Do not do the work."Small models are overconfident, so the harness watches behavior instead of asking.
The brief stays tiny, because the expert's value is clean context and a long brief poisons it.
Each consultation runs a few hundred tokens of guidance. That is why the economics collapse: execution millions ride the $1 tier, and judgment arrives by the gram at $50 per million.
Cognition published the failure first. The ceiling is set by the driver, not the advisor, and the pattern only paid off after their driver improved a generation.
The open problem is a driver noticing it is stuck. Which is why the signals above are behavioral, and why they live in the harness.
CHECK 5: advisor_loop.py passes its assertions: the driver fails twice the same way, one consult fires, the task completes, consults stay under the cap.
BUILD 6: The Two-Lane Bench
Nothing grades its own homework is a law, and this build enforces it across vendors.
Same weights in a foreign harness drop hard. One 2026 measurement showed 20.2 percent native versus 7.7 percent third-party.
So each reviewer runs in its own home. Claude reviews in Claude Code. Sol reviews through the Codex CLI.
The in-house judge, .claude/agents/fresh-eyes-reviewer.md:
---
name: fresh-eyes-reviewer
description: Clean-context code reviewer. Invoke after any agent-written change.
Shares zero history with the writer, reads the diff itself, may not edit.
model: haiku # swap to opus when the diff is load-bearing
effort: medium
tools: Read, Grep, Glob, Bash
---
You have no memory of how this change was written, and that is the point. Do not
ask for the author's reasoning. Do not trust any summary. Evidence only.
1. git diff HEAD~1 (or the range given) and read every hunk.
2. Read the FULL contents of each touched file, not just the hunks. Bugs hide in
the unchanged lines around a change.
3. Run the test suite named in the README or CLAUDE.md.
4. Hunt the three classic agent failures:
laziness: partial implementations, TODOs, handled-for-one-case-only
self-grading: tests weakened, assertions deleted, suites skipped
drift: changes outside the stated task's scope
5. Verdict, in exactly this format:
VERDICT: PASS or FAIL
BUGS: numbered, each with file:line and a one-sentence reason
RISK: one sentence on the riskiest thing this change touches
Hard rules: you may not edit files, you may not re-run the writer's task, and an
empty BUGS list with VERDICT: FAIL is invalid. If tests cannot run, that is an
automatic FAIL with the reason.The cross-vendor judge, .claude/agents/sol-reviewer.md, is plumbing that runs one command and relays the verdict verbatim. Sol is the reviewer; this file gets it into its own harness:
---
name: sol-reviewer
description: Cross-vendor reviewer. Sends the latest commit to GPT-5.6 Sol through
the Codex CLI, in Sol's native harness, and relays the verdict untouched.
model: haiku # plumbing only. Sol is the reviewer.
effort: low
tools: Bash, Read
---
You are plumbing, not the reviewer. Models from one family share blind spots; this
lane exists because Sol does not share Claude's.
1. Check the CLI: codex --version. If missing, output VERDICT: FAIL with reason
"codex CLI not installed" plus the setup path (or the official plugin:
/plugin marketplace add openai/codex-plugin-cc, /plugin install, /codex:review).
2. Run the review at high effort, in Sol's own harness:
codex --profile deep exec "Review the latest commit (git show HEAD) as a
hostile senior engineer who has never met the author. Read every touched
file IN FULL, not just the hunks. Hunt: partial implementations, weakened
or deleted tests, changes outside the stated task scope. End with exactly
'VERDICT: PASS' or 'VERDICT: FAIL' followed by numbered findings, each with
file:line and a one-sentence reason."
3. Save the full output to .review_sol_<short-hash>.md.
4. Relay upward: the VERDICT line first, then the findings VERBATIM. Do not
summarize away findings, do not add reassurance, do not argue with Sol.
If the verdict is FAIL, the parent decides what to fix. You decide nothing.
Hard rules: never edit files, never re-run the writer's task, never substitute
your own review. If codex errors mid-run, report it as FAIL with stderr attached
rather than quietly retrying more than once.For CI, loop/two_lane.sh drives the whole exchange, three rounds max:
claude -p "Implement: $TASK. Run the tests. Commit when green."
review=$(codex exec "Review HEAD ... VERDICT: PASS or FAIL plus findings.")
grep -q "VERDICT: PASS" <<< "$review" && exit 0
claude -p "A reviewer from another model family found these issues.
Fix every one, rerun tests, commit: $review"Inside Claude Code you can skip the script entirely.
OpenAI ships an official Codex plugin for Claude Code, live since March 2026 and at roughly twenty thousand GitHub stars within nine weeks. That is the market telling you cross-vendor review went mainstream. Install once:
/plugin marketplace add openai/codex-plugin-cc
/plugin install codex@openai-codex
/codex:setupThree moves inside any Claude session:
Use adversarial on anything load-bearing. Use handoff when the work is terminal-heavy, where Sol is strongest.
A growing number of builders now run GPT-5.6 Sol inside Claude Code, through the proxy from BUILD 7, and prefer it to Codex for daily work.
It demonstrates the thesis: rent the weights, own the harness.
The catch is the native-harness law, since Sol in Claude Code runs outside its home. Confirm it on your own eval set. If your evals say the foreign harness wins, your evals outrank the benchmark.
Three properties make the reviewer worth having:
A softened verdict is a broken verifier, so the relay is verbatim. A third FAIL pages a human instead of taking a fourth swing.
CHECK 6: run two_lane.sh, or /codex:review on your last commit. A VERDICT lands in a .review file, and a FAIL routes back to the writer lane.
BUILD 7: Optional Fan-Outs (install when the condition appears)
Scout swarm. Install when research or codebase archaeology eats more than 30 minutes of your day. Spawn three in parallel on separate slices:
---
name: scout
description: Cheap parallel reader for research fan-outs. Spawn several at once
for codebase surveys, dependency audits, log archaeology, doc research.
Read-only by doctrine; reads fan out, writes stay single-threaded.
model: haiku
effort: low # inheritance guard (BUILD 4): a swarm that inherits
# max effort empties a window in one message
tools: Read, Grep, Glob, Bash
---
You are one of possibly many readers running in parallel. Survey your slice and
report back small and sharp. Only your final message returns to the parent, so
keep it under 400 words and make every word earn its place.
1. Narrow your assignment to one slice yourself (one directory, one subsystem,
one question), and say what you narrowed to.
2. Reads only: Read, Grep, Glob, and read-only shell (ls, git log, git show, rg).
Never edit, install, or delete. If the task needs a write, report it, do not
do it.
3. Breadth first, then depth on the two or three hottest spots.
Report format, nothing else:
FINDINGS: up to 10 bullets, each one fact with its evidence (file:line, commit
hash, or URL)
GAPS: what you could not determine and why, so the parent knows what is still dark
HOTSPOT: the single file or function that most deserves a deeper look, one line
on why
Do not editorialize, do not propose implementations, do not pad. A scout who
returns 300 useful words beats one who returns 3,000 mixed ones, because
everything you emit lands in the parent's context window and the parent is paying
for it.Reads fan out because parallel readers compound. The word cap exists because every report lands in a context window the parent pays for.
Writes never fan out. A 2026 equal-budget study found single agents match multi-agent setups on reasoning when tokens are held constant. This lane is for reading only.
Overnight burner. Install when TASKS.md holds ten or more small verifiable items. The overnight-burner skill sets up the files, confirms both caps, verifies the test command runs, then launches ralph.sh. Morning interface: git log, progress.log, tick marks.
Plan split. Install when planning tokens dominate a session's bill. One setting in Claude Code runs an Opus-class model for the plan and Sonnet for execution. Plan on the frontier by the gram, execute in bulk.
Trio bench. Install when a gnarly change deserves three perspectives. Two roles read and one writes, and the fourth pane is a trap. The plumbing sits below.
The plumbing for mixed fleets
Two open-source pieces turn a two-vendor setup into an any-vendor one. Install them only when a condition calls for a third provider.
claude-model-switch (open source, Rust, runs on localhost:4000). A local proxy between Claude Code and any Anthropic- or OpenAI-compatible endpoint.
claude-model-switch init # points Claude Code at the proxy
claude-model-switch add openrouter sk-or-xxx
claude-model-switch add glm \
--haiku glm-4.5-air --sonnet glm-4.7 --opus glm-5
claude-model-switch use glm # per session, never mid-task
claude-model-switch orchestrate start --preset trio # planner/coder/reviewerThe trio preset is BUILD 7's bench made physical: three tmux panes, each role on a different provider, each addressable (orchestrate send coder "implement milestone 1"), with mid-session role reassignment if a provider degrades.
CLIProxyAPI (open source). The same trick, pointed the other direction.
It wraps the OAuth logins of ChatGPT Codex, Claude Code, Gemini, and Grok as OpenAI-, Claude-, and Gemini-compatible API endpoints.
Translation: subscription seats you already pay for become routable API targets for scripts like ralph.sh and two_lane.sh, with no separate API keys. Community forks extend it to Factory and Amp, and wrappers like ccs add multi-account switching.
The law that governs both, from BUILD 6's data: a remapped model runs in a foreign harness.
Remap the reader and reviewer lanes freely. They are cheap and verifiable.
Keep the lane that writes code on a model native to its harness, until your own eval set proves otherwise.
CHECK 7: every installed fan-out has its trigger condition written next to it. Installing any of this speculatively is how stacks bloat.
BUILD 8: The Factory (completion becomes a database fact)
Everything so far proves work in the moment. The gate, the verdict, and the eval set all fire during the run.
Once more than one agent touches a project across more than one session, you need proof that survives the run: who worked what, in what order, and whether the last review cycle cleared.
The pattern comes from the pi-factory demo (github.com/xpriment626/pi-factory). The load-bearing idea is one sentence
A thread is a trace. A row is evidence. The gate reads rows.
progress.log is a diary. The blackboard is a ledger. SQLite is the ledger because it is queryable after everyone stops talking.
Create factory/factory_gate.py. It holds four tables (tickets, briefs, evidence, verdicts), a record command each agent calls as it works, and the completion gate. The gate's failure conditions map to the work itself:
checks = [
(tickets == 0, "No tickets were recorded."),
(done != tickets, "Not all tickets are done."),
(first_brief is None, "No architecture brief was recorded."),
(first_brief > first_code, "Implementation evidence predates the brief."),
(code_ev == 0, "No implementer code evidence was recorded."),
(build_ok == 0, "No passing build command evidence."),
(test_ok == 0, "No passing test command evidence."),
(latest("architect") != "green", "Latest architect verdict is not green."),
(latest("reviewer") != "green", "Latest reviewer verdict is not green."),
]That list encodes the whole doctrine.
Create factory/factory.sh, which wires the seats you already built into the run order and records rows between every step:
G ticket "kanban board" "columns render, drag persists" # planner rows
G brief "$BRIEF" # BEFORE any code
../loop/ralph.sh && G evidence code pass "loop completed" # BUILD 3 works
npm test && G evidence test pass "npm test green"
G verdict 1 architect green "layout matches brief" # Claude seat
G verdict 1 reviewer green "tests pass, scope clean" # Sol seat, via codex
python3 factory_gate.py gate factory.db # rows decideNothing new gets hired.
Fable cuts tickets and writes the brief, read-only. The BUILD 3 loop implements. Claude and Sol each return a verdict from their own harness. The cycle repeats up to three times until both go green.
The factory is the org chart for employees you already have.
A real run, not a mockup. The second gate call is the entire argument for this build:
$ factory_gate.py record demo.db ticket "kanban-board" "columns render, drag persists"
$ factory_gate.py gate demo.db
GATE: REFUSED
- Not all tickets are done.
- No architecture brief was recorded.
- No implementer code evidence was recorded.
- No passing build command evidence.
- No passing test command evidence.
- No review cycle was recorded.
exit: 1
... the agents work. every step writes a row ...
$ factory_gate.py record demo.db brief "Stack: node+sqlite. /tasks CRUD."
$ factory_gate.py record demo.db evidence code pass "src/board.js written"
$ factory_gate.py record demo.db evidence build pass "npm run build exit 0"
$ factory_gate.py record demo.db done "kanban-board"
$ factory_gate.py record demo.db verdict 1 architect green "layout matches brief"
$ factory_gate.py record demo.db verdict 1 reviewer green "scope clean"
$ factory_gate.py gate demo.db
GATE: REFUSED
- No passing test command evidence.
exit: 1
$ factory_gate.py record demo.db evidence test pass "npm test 33/33"
$ factory_gate.py gate demo.db
GATE: COMPLETE (1/1 tickets, cycle 1 green x2)
exit: 0Both reviewers said green. The architect confirmed the layout matched the brief. The reviewer confirmed the scope was clean.
And the gate still refused, with one line: no passing test command evidence. Nobody had run the tests.
A verdict is an opinion. Two opinions are still not a fact. One evidence test pass row later, the same gate returns COMPLETE and exits 0.
Models argue for their work convincingly, and a transcript captures the argument rather than the truth. Rows cannot be argued with.
When the gate refuses, it names the exact missing artifact. That turns "the run failed" into "produce a passing test row." A task, not a mystery.
Install condition: more than one writer session per day, review cycles that span days, or a need to prove after the fact what happened. For a solo repo with one nightly loop, BUILD 3 is enough and this is bloat.
CHECK 8: reproduce the screenshot. Record everything except a test row, and the gate must refuse with exactly one reason. Add the row and it returns COMPLETE. A gate that passes without it is a transcript reader.
BUILD 9: The Swarm (Fable plans, the fleet executes, Fable scores)
One driver with an advisor covers a task. A goal that splits into four independent pieces wants four workers.
But a fleet only holds its direction if one model plans every goal and scores every result. That is the whole reason this build exists, and the reason swarms usually fail without it.
Rung 3 made literal. Fable writes the goals, the fleet executes them, Fable scores each result against its own check, and the next cycle re-plans only the misses.
Its abort is the cycle cap. When the cap trips with misses outstanding, that is a spec problem going to a human, not a reason to run a fourth cycle.
Create swarm/swarm.sh. Three settings carry the doctrine:
FLEET=4 # writes never collide: one worktree each
WORKER_MODEL=claude-sonnet-5 # or haiku / luna / kimi for pure execution
WORKER_EFFORT=low # NEVER inherit the conductor's effort
CONDUCTOR=claude-fable-5 # or opus-4-8 if retention rules biteThose three lines are explicit because the default is not.
A fleet that inherits picks up the conductor's model and the conductor's effort both. A Fable-at-high conductor spawning four Fable-at-high workers to do mechanical work is the most expensive possible way to do the cheapest possible thing.
Set them. Never let them default.
Cross-harness fan-out is legal, and it is not the exception to ROUTING.md's first law that it looks like.
The harness travels with the worker, not with the conductor.
The conductor writes goals, never code, and each goal carries its own check command, so done stays a fact:
{"id":"strip-legacy-auth","spec":"remove the v1 auth path from routes/","check":"npm test -- tests/auth"}
{"id":"migrate-sessions","spec":"move session store to the new adapter","check":"npm test -- tests/session"}Then dispatch, score, and replan:
# dispatch: one git worktree per goal, capped at FLEET in parallel
claude --model "$WORKER_MODEL" --effort "$WORKER_EFFORT" -p "Execute this spec
exactly. Do not expand scope. Run the tests. Commit only when green."
# score: the conductor grades each goal against its OWN check command.
# the worker's confidence is not evidence. the exit code is.
bash -c "$chk" && echo "$id" >> passed.txt || misses=$((misses+1))
# replan: next cycle sees passed.txt and re-plans only what missedSeat by seat:
Reserve Fable for the two jobs no cheap model can do: writing the goals, and grading them.
A fleet is a cost strategy, never an intelligence strategy.
Multi-agent runs burn 3 to 10 times the tokens for equivalent work, and a 2026 equal-budget study found single agents match them on reasoning when tokens are held constant.
A swarm earns its keep only when the goals are independent and mostly mechanical. Writes stay single-threaded per worktree, merges happen serially, and a human takes the last commit.
CHECK 9: run the swarm on a goal that splits three ways. A broken goal must come back FAIL in results.tsv and get replanned in cycle 2, never declared done.
BUILD 10: Rung 4 (nothing that passed once goes unwatched)
Everything so far verifies work while it is being made. Nothing so far notices when finished work stops being true six weeks later. A goal you verify once is an assumption with a timestamp.
Rung 4 has two halves, and its abort matters as much as its exit: if no proposal clears the gate this week, the system does not change, and that is a success.
Half one, standing goals. Every finished thing graduates into an invariant with a predicate, re-verified daily, forever. Create one file per finished thing in goals/:
predicate: npm test -- tests/auth 2>&1 | tail -1 | grep -q passing
born: 2026-07-13
status: satisfied
last-pass: 2026-07-13
on-violation: wake me. do not auto-fix.Then system/verify_goals.py runs the lot and exits 1 if any invariant broke, naming the goal, the date it last held, and the policy you set:
held = subprocess.run(["bash","-c",predicate], timeout=60).returncode == 0
g["status"] = "satisfied" if held else "VIOLATED"
# a timeout is a violation, not a pass: an expensive predicate is a broken onePredicate rules are strict on purpose: a shell command, exit 0 means the invariant holds, cheap and read-only.
Adjectives are banned. If a shell cannot check it, a model cannot either.
Non-code goals work the same way. test -s reports/$(date +%Y-%m)-review.md is a fine standing goal for a monthly report.
Half two, compost. Once a week, read the exhaust the system already produced: BLOCKED tasks, failed gate runs, refused factory gates, reverted PRs, violated goals.
Then propose at most three changes. A new law for the constitution. A fix to a skill that keeps failing the same way. Or a standing goal you were missing.
Propose only. You sign.
claude --model claude-fable-5 --effort high --allowedTools "Read,Grep,Glob" \
-p "Read this week's exhaust: BLOCKED lines in progress.log, GATE REFUSED
entries, VIOLATED goals, PRs closed unmerged. Extract AT MOST 3 proposals:
a new law (quote the incidents), a skill fix (same failure repeating), or a
standing goal we lacked. Propose only, do not edit anything. Clean week is a
valid answer, say so and stop."This rung closes only when the evals and the judges say the system got better. Which means the system needs a memory of its own failures to improve against.
The compost run is what turns a script into an institution.
The standing goals are what make finishing safe. The sentinel detects, the normal pipeline fixes, and nothing rots in silence.
CHECK 10: verify_goals.py demo names the broken invariant with its last-pass date and leaves the healthy one alone. Then write one real standing goal for the last thing you finished.
BUILD 11: Rung 5 (your seat, and why it never empties)
Rung 5 has your name on it for a mechanical reason, not a sentimental one.
A loop can hit its stopping condition and still be wrong. Tests pass, the gate goes green, both reviewers sign, and the last commit is still a mistake.
Every build below this one exists to shrink that risk. None of them erases it.
Your standing duties, all cheap:
Three plays run on a cadence rather than on demand, because they cost real money and pay in direction rather than diffs:
Play one, the project feedback loop, monthly.
Point Fable at what you already shipped, read-only, and have it write a detailed improvement plan. Then hand execution of that plan to Opus 4.8 or Sol.
The expensive model does the part that compounds, judgment about what to change, and never the part that does not, typing.
claude --model claude-fable-5 --effort high --allowedTools "Read,Grep,Glob" \
-p "Review this project end to end. Write an improvement plan ranked by
leverage: what is fragile, what is over-built, what is missing, what should
be deleted. Do not write code. Output tasks with acceptance criteria." \
> plans/$(date +%F)-improvement.mdPlay two, the behavior analysis, monthly.
Feed it your own session and project history across both harnesses, and ask it to map how you build and where you stall.
This is the only report in the system whose subject is you. It is usually the one that changes the most.
Play three, the second-brain audit, quarterly. Point it at your notes, docs, and backlog, and ask what your own thinking says is worth building next and what is worth deleting. Treat the output as a proposal, exactly like compost.
The rungs below optimize execution, and execution is the cheap part now. Direction is the scarce input, and direction is what a frontier model is worth paying for. Buy judgment by the gram, execution by the ton, and keep the last signature.
CHECK 11: run play one on your own repo. If the plan names nothing you already knew was fragile, your context files are too thin, which is a BUILD 1 problem.
BUILD 12: Ops
Agents burn 10 to 100 times the tokens of a chat call, and input dominates at roughly 100 to 1.
Stack the four levers from BUILD 0 (split, cache, batch, compaction) and teams report landing 70 to 90 percent below their unoptimized baseline.
For sanity: $13 per developer per active day is the Claude Code enterprise average, and 90 percent of users stay under $30.
One line of discipline instead of a new subsystem: a task class may auto-merge only after 20 logged runs at a 95 percent pass rate, and a single drop below 90 percent revokes it loudly.
awk -F'\t' '$2=="fix-lint"{r++; if($3=="pass")p++}
END{printf "%d runs, %.0f%%\n", r, (r?p/r*100:0)}' progress.logWeekly spend, from the per-tick costs ralph.sh already logs:
grep '^cost' progress.log | awk -F'\t' \
-v d="$(date -d '7 days ago' +%F)" \
'$2>=d{s+=$3} END{printf "week: $%.2f\n", s}'Compute the metabolism before you cron. Daily cost is ticks times average tick cost.
The seat that handles the quiet no-work tick decides the bill. Cents on the cheap tier, dollars on a frontier model at high effort, for the identical "nothing to do" answer.
Running inside your limits
These models burn tokens fast, and how you run them decides how much of a day's work lands before you hit a wall.
First, know which wall.
Watch the meter you are actually on: the usage panel in Codex settings, /usage on the Claude side, or a monitor like ccusage or codexbar parked in the corner of the screen.
A limit you never read is a limit you discover by hitting it, with four hours left on the clock and nothing to run.
Six levers, cheapest first. Most act at rungs 0 through 2, where the tokens burn:
Together these levers set how long you can run the best models before the limit stops you.
Cron, when Week 2 starts:
# task loop: the daily tick, both caps set
0 7 * * 1-5 cd /path/to/repo/loop && BUDGET_USD=5 ./ralph.sh >> ../progress.log 2>&1
# system loop: nothing that passed once goes unwatched
30 7 * * * cd /path/to/repo && python3 system/verify_goals.py goals/ >> progress.log 2>&1
# system loop: failures become laws, once a week, proposals only
0 9 * * 1 cd /path/to/repo && codex --profile deep exec \
"$(cat ~/.codex/prompts/compost.md)" >> proposals/$(date +\%F).md 2>&1The runbook. Each alarm, and what to do about it:
The 30-day schedule. Do not skip graduations; each unlocks the next.
The Command Deck
Every loop here is reachable from a keystroke. Slash commands live in ~/.codex/prompts/ on the Codex side, where the filename becomes the command, and in .claude/skills/ on the Claude side. The CLI clips are the headless versions that cron and CI run.
Codex slash commands
/plan-stop and /effort pay for themselves fastest. Both spend a few hundred tokens to stop you spending a few hundred thousand.
These models run long, so the checkpoint you want comes before the spend. /plan-stop returns the plan, the done-when commands, the blast radius, the cost, and the one question it would ask a human. Then it stops.
Drop both files in ~/.codex/prompts/, where the filename becomes the command.
effort.md becomes /effort, the routing dial made explicit:
# /effort - pick the effort level before you spend it
Do not answer the task yet. Route it first.
Score it. One point each:
- contains a why, a debug, a race, a deadlock, a refactor, a security concern,
or an optimize
- touches more than one subsystem
- a previous attempt already failed
- the change is irreversible or lands in front of users
Then map:
| Score | Effort | Seat |
|---|---|---|
| 0-1 | low | codex -e low, or profile fast (Luna). Never put a frontier seat on it. |
| 2 | medium | Terra at medium is the seat. |
| 3+ | high | the default for real work, and where the sweet spot sits. |
Only if high has ALREADY been tried and failed: recommend max, and say plainly
what the extra thinking is expected to buy. The base rate you are arguing
against is roughly double the cost for a gain that usually does not repay.
Two reminders before recommending an upgrade:
1. A better model at lower effort usually beats a weaker model at max. Change
the seat before the dial.
2. If this task spawns subagents, state their effort explicitly (low unless
proven otherwise). Subagents inherit the parent, and a fleet at max empties a
context window in one message.
Output exactly:
EFFORT: low | medium | high | max
SEAT: <model>
WHY: <one line, naming the points that scored>
SUBAGENTS: <effort to pin, or none>
Then stop. The human runs the task at the level you named.A live answer looks like this, and it costs a few hundred tokens to avoid a few hundred thousand:
EFFORT: high
SEAT: gpt-5.6-sol
WHY: contains "why", touches auth and sessions, prior attempt failed
SUBAGENTS: lowplan-stop.md becomes /plan-stop, the checkpoint before the spend:
# /plan-stop - plan the work, then stop
These models run long. That is a feature when the plan is right and an expensive
way to be wrong when it is not. This command buys the checkpoint before the spend.
Plan the task. Do not edit a single file. Do not run a build. Do not start.
Produce:
GOAL: <one line>
ASSUMPTIONS: <what you take for granted; if these are wrong, so is the plan>
STEPS: <numbered, each one commit's worth of work>
DONE_WHEN: <the exact shell command that proves each step landed>
BLAST RADIUS: <files and systems touched; name auth, payments, migrations, prod
config explicitly>
COST: <rough tokens or dollars, and which seat runs each step>
UNKNOWNS: <what you would ask a human if you could ask exactly one question>
Then stop and wait.
Rules while planning:
- Ambiguity goes in UNKNOWNS. Do not resolve it by guessing and proceeding. A
guess that survives into execution costs a hundred times more than a question.
- If the plan needs a credential, endpoint, or convention that is not written
down in this repo, stop and say so. Never invent one.
- If any DONE_WHEN is not a shell command, rewrite that step until it is. If a
shell cannot check it, neither can a reviewer.
- If the blast radius touches the never-list in AGENTS.md, say so at the top and
recommend queueing for a human.
You are paid for the plan here, not the diff. A short honest plan with real
unknowns beats a confident plan that quietly assumed the wrong thing.fable-advice.md and review-hostile.md become /fable-advice and /review-hostile. Both are the Codex-side mirrors of files you already wrote: the advisor brief from BUILD 5, and the hostile-reviewer contract from BUILD 6. Same rules, same caps, pointed the other way across the vendor line.
compost.md becomes /compost, rung 4's weekly institution-builder:
# /compost - turn this week's failures into next week's laws
Read this week's exhaust, all of it, and nothing else:
- BLOCKED lines in progress.log (tasks that beat three advisor consults)
- GATE: REFUSED entries (a run that could not prove it was done)
- VIOLATED standing goals (something finished stopped being true)
- circuit-breaker and budget exits (codes 2 and 3)
- PRs opened by the loop and closed unmerged (the human silently disagreed)
- any task class whose pass rate dropped below 90 percent
Extract AT MOST three proposals. Three is a hard cap, not a target. A clean week is
a valid finding, and saying so is more useful than manufacturing work.
Each proposal is exactly one of:
1. A NEW LAW for CLAUDE.md or AGENTS.md. Quote the incidents it would have
prevented. A law with one incident behind it is a coincidence; wait for the
second.
2. A SKILL FIX, when the same failure repeats in the same place. Name the skill,
the pattern, and the smallest edit that breaks it.
3. A STANDING GOAL you were missing, when something rotted silently. Write the
predicate as a shell command, or do not propose it.
Output:
WEEK: <dates>
EXHAUST: <counts: blocked, refused, violated, reverted>
PROPOSAL n: <law | skill fix | standing goal>
EVIDENCE: <the incidents, quoted>
CHANGE: <the exact text or predicate to add>
COST OF NOT DOING IT: <one line>
VERDICT: <what you would do first if you could only do one>
Hard rules:
- Propose ONLY. Do not edit CLAUDE.md, AGENTS.md, any skill, or any goal file.
The human signs, or it does not happen.
- Do not propose a law that softens a gate, raises a budget, or relaxes a never.
Those are the system asking to be allowed to fail more comfortably.
- Empty exhaust: say "clean week" and stop. Do not go looking for work to justify
the run.CLI clips
Keep these in a scratch file. They are the entire system reachable from a terminal:
# the daily tick, capped in both dimensions
BUDGET_USD=5 MAX_ITERS=20 ./loop/ralph.sh
# plan first, spend later (the single highest-leverage habit here)
codex -e high exec "$(cat ~/.codex/prompts/plan-stop.md)
TASK: migrate the session store off the legacy adapter"
# cross-vendor review of the last commit, in Sol's native harness
codex --profile deep exec "$(cat ~/.codex/prompts/review-hostile.md)"
# the mirrored lane: Codex stuck, Claude advises
claude --model claude-fable-5 --effort high -p "$(cat ~/.codex/prompts/fable-advice.md)"
# the goal loop: Fable plans, the fleet runs, Fable scores
CYCLES=3 FLEET=4 WORKER_EFFORT=low ./swarm/swarm.sh "split the auth migration"
# the system loop: nothing that passed once goes unwatched
python3 system/verify_goals.py goals/ # exit 1 names what rotted
python3 gate/eval_gate.py eval/cases.jsonl # exit 1 blocks the routing change
# rung 3, the factory: rows decide, not transcripts
./factory/factory.sh "build the kanban and notes app per PRD.md"
python3 factory/factory_gate.py gate factory.db
# the weekly institution-building run
codex --profile deep exec "$(cat ~/.codex/prompts/compost.md)"
# the one number that says whether any of this worked
grep '^route' progress.log | awk -F'\t' \
'{n++; if($3!="frontier") c++} END{printf "cheap share: %.0f%%\n", c/n*100}'The full policy lives in ROUTING.md from BUILD 4, which both harnesses read.
The Rules (print this)
Closing
Thirty days from now, if you did the checks:
The models were never the hard part. A system that stays honest when you stop watching is the hard part, and it is why rung 5 still has your name on it.
Start tonight with the twenty minutes that proves it. BUILD 2's verify.sh. One hand-run tick of BUILD 3. One review from the other lineage on your last commit.
The first time a reviewer that shares no context with the writer finds a real bug in work you were sure was done, you will not need convincing about the rest.
Build the gate tonight. Reply with what it caught on the first run.
Disclaimer
Written from the author's research notes and verified sources, with drafting and fact-checking assistance from Claude. All prices and model behaviors were checked against official pricing and documentation pages in the week of publication; they change, so verify before budgeting.
This article was written by the author's notes as mentioned in the aforementioned paragraph and edited with Claude Opus 4.7.
If you want to add any other corrections, please add it in the comments.









