/ 00
article

Stop paying your best model to type.

Two weeks ago I claimed that putting a cheaper model on execution and a strong one on verification cost about a third of frontier-everything, and I dropped the number without showing my work. Here it is — a headless-Unity prototype drained as four milestones under three model policies, priced task by task against my own telemetry. The cheap-worker run shipped seven-for-seven first-pass at $1.66 a task, Fable cost the most for a reason that has nothing to do with how good it is, and the whole thing turned into a new release of wood-fired-tasks that routes models by role and by task size.

Most people point their best model at every coding-agent task. It’s an expensive habit, and on the wrong kind of work it doesn’t even buy better code. Put a cheaper, capable model (Sonnet 4.6) on the workers that do the typing and keep a strong one (Opus 4.8) for verification and planning. On one real run that worked out to $1.66 a task — about a third of the all-Opus bill, for the same verified result.

Two weeks ago I dropped a number in a post about validation and walked right past it. I’d just shipped per-role model selection in wood-fired-tasks, where execution, validation, and planning can each run a different model. The first backlog I drained that way put a cheap model on the work and a strong one on the checks. It came in around a third of the price of running my best model on everything, and it passed every check on the first try. I wrote all that in one sentence and moved on. No table, no breakdown. If I read that line from someone else, I’d ask to see the spreadsheet.

So here’s the spreadsheet. It’s a better story than I expected, and that’s mostly luck, because the run it came from was never meant to be an experiment. It was a prototype I built for a completely different reason. I only went back and priced it out after the fact.

An experiment I didn’t mean to run

I wasn’t trying to ship a game. I was testing a workflow: how far can a coding agent get toward a playable Unity build with nobody in the editor? No hands on the keyboard. The loop writes the C#, kicks off a headless Unity build, runs the validators, reads the exit code, and decides for itself whether the task is done. I broke the prototype into a hundred tasks and let it drain the backlog wave by wave while I did other things. The game at the end of it was disposable. What I cared about was the pipeline.

Two things happened mid-run that turned it into an accidental experiment. Fable 5 came out, and I’d just wired the per-role model controls into the loop. So one prototype ended up drained three different ways in a single week, on the same harness, without my planning any of it. The first two milestones ran Opus on everything, because that was the session default and I never touched it. The third ran Fable on everything, because Fable launched that morning and the session picked it up. The last one I set by hand: Sonnet doing the bulk of the typing, Opus held back for the checks and the planning.

So it’s one project, drained under three setups, with the same verification harness sitting underneath all of it. It’s not a clean A/B test, and I’ll get to why later. But it’s real work — every task closed, gated, and already on a bill, not a benchmark I cooked up to prove a point. When I finally sat down to reconcile it, I gave the research agent the instruction I always give: find out whether mixed-model routing is worth it, don’t sell me on it. Two of the four things I expected going in didn’t hold up.

What does mixed-model execution cost, milestone by milestone?

Cost per verified task ran from $1.66 to $11.15 across the four milestones. That’s a 6.7× spread, and the verification gate stayed green the entire time — every milestone shipped at 100% on the first pass. So the spread is about price and nothing else. The cheap end was Sonnet on the workers with Opus checking. The expensive end was Fable doing everything, and Fable wasn’t expensive because it worked harder.

Here’s the whole run, milestone by milestone — the model mix, the tasks it closed, the cost per task at current list rates, and the first-pass result, so the cost never shows up without the quality sitting right next to it:

milestone     model mix              tasks    $/task   first-pass
M1            Opus 4.8 (all)           38       4.24    38/38
M2            Opus 4.8 (all)           17       4.61    16/17 (1 re-verify)
M3            Fable 5 (all)            13      11.15    15/15 attempts
M4 (mixed)    Sonnet + Opus / Fable    17       3.48    17/17
  └ run 1     Sonnet work, Opus check   7       1.66    7/7
  └ runs 2-3  Fable 5 (all)            10       4.75    10/10
Horizontal bar chart titled 'Same verified outcome. 6.7× the cost.' showing cost per verified task across six model policies, from most to least expensive: Fable 5 on everything (milestone M3) at $11.15 per task with 15/15 first-pass PASS; the Fable portion of the mixed milestone (M4 runs 2–3) at $4.75 with 10/10; Opus 4.8 on everything (M2) at $4.61 with 16/17; Opus 4.8 on everything (M1) at $4.24 with 38/38; the mixed milestone overall (M4) at $3.48 with 17/17; and, highlighted in ember, Sonnet on the workers with Opus on the checks (M4 run 1) at $1.66 per task with 7/7 first-pass PASS.
Cost per verified task — same project, four milestones, three model policies. Every bar passed at 100% on the first try, so the 6.7× spread comes down to price alone.

The row that backs up my claim is M4, run 1. Seven tasks written by Sonnet, validated and planned by Opus, closed at $1.66 a task. Seven for seven, no rework. The Opus-everything milestones ran $4.24 to $4.61 a task for the same verified result, so the cheap-worker run cost about a third as much. About a third — receipts attached. Fable-only came in at $9.67 a task per attempt, nearly six times the price. The cleanest comparison is inside that one mixed milestone, where the work was running the same day on the same gates: Sonnet’s tasks cost $1.66, Fable’s cost $4.75. Same harness, same bar, 2.9 times the bill.

Fable is an F1 car on a dirt road

Don’t read that as Fable being bad. Fable blew me away. It’s the most capable model I’ve put my hands on, and the fact that it came back the most expensive per task says nothing about the model. It says something about the road I ran it on.

Someone online put it better than I could, and I’m kicking myself for not saving his name: Fable is an F1 car, and most people are running it on a dirt road. Put it on tarmac and it’ll show you what it can do. A parallel task-DAG drain is a dirt road. The work gets chopped into small, independent, heavily cached pieces — about the opposite of the long, deep, reasoning-heavy problem a car like that is built to win.

My first guess was the obvious one. A pricier model must be working harder, burning more tokens, spinning up more subagents to get to the same place. The telemetry said otherwise. Per task, Fable’s output tokens and call counts and subagent spawns line up with Opus’s almost exactly. It did the same amount of work. It just got charged more for it.

Bar chart titled 'The premium wasn't effort — it was the cache-read rate' showing cache-read price in US dollars per million tokens for three models: Sonnet 4.6 at $0.30, Opus 4.8 at $0.50, and Fable 5 at $1.00, with Fable highlighted in ember and annotated as twice Opus's cache-read rate. The caption notes that re-reading already-loaded context is 55 to 62 percent of every milestone's bill.
Cache reads are 55–62% of every milestone’s bill, and Fable charges double for them. On a cache-heavy drain, the premium lands on the one line you spend the most on.

Here’s why. This kind of run is mostly cache reads — agents re-reading context they already paid to load. On every milestone that’s 55 to 62 percent of the bill, far and away the biggest line. Fable charges twice what Opus does for those reads. So you take a model that doubles the price of the one thing you do most, and the premium lands right on top of your largest cost. That’s not Fable being the wrong tool. It’s a headless parallel drain being the wrong place to judge it. A model’s sticker price tells you almost nothing until you hold it up against the shape of the work you’re about to run.

Put the cheap model where the tokens are

The routing falls out of one fact: the workers eat almost all the tokens. In the mixed run they burned about 600 thousand, against 312 thousand for the verifiers and 53 thousand for the auditors. Writing the code is where the volume is. Verification is the slot I hang the whole outcome on, and it’s a sliver — $3.11 of that run’s $11.61.

Horizontal bar chart titled 'Put the cheap model where the tokens are' showing token volume by pipeline slot in the mixed run: Workers, running on Sonnet 4.6, at 602 thousand tokens (62% of run tokens) highlighted in ember; Verifiers, on Opus 4.8, at 312 thousand (32%); and Integration auditors, on Opus 4.8, at 53 thousand (5%). The caption notes verification was just $3.11 of the run's $11.61 total.
Where the tokens live in the mixed run. Workers burn 62% of them, so the cheaper model goes there; verification — kept on Opus — was $3.11 of the $11.61 total.

So put the cheap, capable model where the tokens are, and save the expensive one for the small slot where a wrong answer actually ships. You don’t get worse code out of this. You just stop paying top rates to generate boilerplate, while still paying them where the judgment happens. Stop paying your best model to type.

The harness is what makes it safe

None of this is worth anything if the cheap worker ships worse code, so that’s the part I lean on hardest. Across all fifteen runs the verifiers came back clean: 100% pass, no fails, no half-passes left hanging. The harness doesn’t know or care which model produced the code. A verifier re-runs the build and the tamper checks on every task, auditors check the seams between tasks, and perf gates and self-validating binaries close out each milestone. On the mixed run, Opus rebuilt the player behind Sonnet’s seven tasks and signed off on all of them without a single fix.

It’s the same point I made when I stopped reading the code, pushed a step further. The harness isn’t only there to protect quality. It’s the thing that lets me move the work down to Sonnet at all, because it catches what a cheaper model might get wrong before any of it ships. Take that net away and you’re gambling that the cheap model didn’t slip something through. Keep it, and the lower bill comes with no asterisk.

Here’s the part I didn’t expect. The only real bugs that showed up after the fact — four of them across the whole project — all came out of the Opus milestones, not the cheap ones. I won’t pretend that means mixed-model is more accurate. The numbers are tiny, and the mixed milestone had barely any time to age before I looked. But there’s no sign of a quality tax for moving the worker down to Sonnet, and the failure everyone braces for — the cheap model quietly sneaking junk past the graders — just didn’t happen.

So I shipped the lesson

I didn’t want this to be a post I’d nod at and forget, so I built it into the tool.

On M4 I set the routing by hand, once, for a single run. The new release of wood-fired-tasks makes it part of the project instead, and it adds the one thing I couldn’t pull apart by hand: task size. You write a model policy, and for each task the loop picks the model from two things — which role is about to run, and how big the task is. A slot can name a model outright, or say auto and grab the best current match from the live catalog at dispatch (so something like Fable shows up the day it lands, no config change), or just inherit the session. The policy lives on the project, with a database-wide default underneath it.

The size part is the one I’m happiest with, because I got it almost for free. wood-fired-tasks already scores every task’s size in WSJF points to decide what to work on next. I just pointed that same number at a second question: what should run it. A one-point task drops to something cheap and fast. A thirteen-point task climbs to something stronger. Verification stays strong no matter what. Back on M4, I had to wave a hand at the fact that task weight, not just model choice, was driving part of the cost gap. Now the tool sorts that out on its own, task by task.

What I won’t let this run away with

I wouldn’t carve $1.66 into anything. The tasks weren’t the same difficulty across milestones. M3 carried the hardest part of the project, and the cheap stretch of M4 was mostly light headless C#, while the heavy terminal Unity work happened to fall in M4’s Fable stretch. So part of that gap is task weight, not the model — which is the whole reason size now lives in the policy. It’s one milestone per setup, a few dozen tasks each. That’s a strong direction, not a clean stat. And the mixed milestone’s spotless bug record is misleading on its own: zero bugs, sure, but also almost no time for any to surface, while the others had days of real use behind them.

One more, and this is the part that actually rattled me. The dollar figures here are hand-priced. When I first checked them against my own Grafana dashboards, they didn’t match — and the dashboards were the ones that were wrong. The pricing formula behind those panels still had Opus at last-generation rates, and no row for Fable at all, so Fable had been sliding through completely unpriced. The token capture was perfect. The layer that turns tokens into dollars had quietly gone stale, and I’d been glancing at those numbers for days without catching it. I’ve said before that you can’t improve what you can’t measure. Turns out you also have to keep checking that the thing doing the measuring still works.


The habit worth breaking is grabbing the biggest, newest model and pointing it at everything. On the wrong kind of work it doesn’t even buy you better results. It runs up frontier rates to generate volume, and on a cache-heavy job it charges you double for the thing you do most. So make the model a choice you make per task: by role, by size, against the real shape of your work, with checks good enough that the cheap worker can’t hand you something worse than the expensive one would have. Put the cheap, capable model where the tokens are. Save the expensive one for grading and for the hard problems. And give the F1 car some tarmac before you decide it isn’t worth it.

Companion posts: how I stopped reading the code, the harness that makes cheap execution safe, and you can’t ask an agent to log itself, the telemetry that priced this whole thing.

/ 02
next
Latest post

You’re reading the most recent one.