Course · Codex · Models & effort
Match the dial to the task's value without ever reading a price
You’ve now run the same two tasks through five effort levels, both models, and two profiles, and every stop landed on one of four words: matched, overkill, underpowered, coin flip. That’s not incidental vocabulary - it’s the whole chapter’s finding, stated four ways instead of derived four times. This lesson puts every stop on one board, without a single price tag, and closes on the table that tells you which word to expect before you run anything.
The cost rule you can apply without a price tag
Section titled “The cost rule you can apply without a price tag”You don’t need a number to make the right call, because the relationship is fixed regardless of what the number is:
More reasoning effort means more tokens generated and more latency before the answer. Always. A bigger model compounds it.
That’s true at every price point, so the discipline doesn’t depend on knowing the price - it depends on knowing the ratio. The question is never “what does high cost?” in absolute terms. It’s “does this task’s value justify the extra tokens and wait that high spends?” On the rules engine - where a wrong call means a rewrite and miscategorised money - yes, easily. On the accounts endpoint, no: the extra reasoning produces the same four routes, more slowly, for more tokens. Same dial, opposite verdict, and you reached it every time without a dollar figure.
The two corners the grid still owes you
Section titled “The two corners the grid still owes you”Every trace so far has moved one dial at a time and landed on the setting each task actually earned. Two corners are still missing, and nobody reaches them on purpose - they’re what you get from carrying yesterday’s setting into today’s task. A light model turned up to high on the endpoint. A capable model turned down to low on the engine.
> add a CRUD accounts endpoint following the pattern in transactions.py (model: light, model_reasoning_effort = high)
Thinking… Should accounts support soft-delete? transactions.py doesn't, but financial resources sometimes want the trail. Weighing consistency against audit safety before committing… read transactions.py ✎ accounts.py - list / create / read / delete, same shape Done. (Kept hard-delete for consistency with transactions.py.)Overkill. Same four routes, same file read, and a paragraph of deliberation over a question the codebase had already closed. The light model can narrate hesitation just as long as the capable one did two lessons back - hesitation isn’t insight, and the pattern didn’t need either.
> design the categorisation rules engine for budgetcli - how rules match transactions, how conflicts resolve, how a user orders them (model: capable, model_reasoning_effort = low)
✎ rules.py - substring match against merchant description, first rule in the list wins Done.Coin flip. No “Thinking…” block, no surfaced conflict question - the same design light/low would have shipped, from a model that had the reach to find the merchant-code, deterministic-tiebreak design a capable model reached at high and was simply never asked to spend it. The design might still be right. Nothing in this trace tells you that, and nothing would have told you it was wrong either - that’s what makes the cell a coin flip and not just another underpowered.
The board, replotted
Section titled “The board, replotted”This is the same grid your traces just walked by hand - “pattern-following endpoints” is the accounts-endpoint shape, “the design fork” is the rules-engine conflict question two lessons back, and the overkill and coin-flip corners are the two you just watched fail - now covering every corner at once. Move the dials and watch the redo tax appear the moment a hard task lands on an underpowered corner, and the wasted spend appear the moment an easy task lands on an overpowered one. The reading beneath the grid updates with you; read it after every move, not just the first one.
The decision matrix
Section titled “The decision matrix”Strip the widget away and the whole chapter collapses into one table: task shape down the side, dial setting across, the verdict word your traces actually produced in each cell.
| Task shape | light + low | light + high | capable + low | capable + high |
|---|---|---|---|---|
| One right answer (accounts endpoint) | matched | overkill | overkill | overkill |
| Genuine fork (rules engine) | underpowered | underpowered | coin flip | matched |
The two rows ask two different questions. The top row asks “does extra spend buy anything,” and the answer is no in three of four cells - the pattern already decided the code, so every corner past the cheapest one is pure overhead. The bottom row asks “does the level bother to look for the fork,” and only the corner with both dials turned up does. Nothing in between is free: capable/low on a fork isn’t matched, it’s a confident guess from a brain that could have found the real answer if the effort dial had let it try - that’s the coin flip, and it’s the cell most people land on by accident, because a capable model sounds like enough.
What this doesn’t solve
Section titled “What this doesn’t solve”A matched verdict is not a correctness guarantee. It means the level spent roughly the right amount of effort finding an answer - you still read the diff and the design the same way the first chapter taught you to. And the dial can’t diagnose the task’s shape for you: that judgment call is still yours, every time, and misjudging it - treating the rules engine as boilerplate, or the accounts endpoint as a design problem - lands you in the wrong row of the table above no matter how carefully you’d have read it otherwise. Nor does spending correctly here fix an agent that still doesn’t know your repo’s conventions: a matched run on the accounts endpoint still writes float(row["amount"]) if nothing has told it budgetcli stores money as integer cents - fixing that is the rules chapter’s job, not this one’s, and neither chapter substitutes for the other. And xhigh’s availability depends on the model, so this dial’s ceiling is set by your auth tier as much as by the task - worth checking before you plan around a level you might not have.
The row this chapter adds
Section titled “The row this chapter adds”| Move | Tokens | Turns | Blast radius | Recurs? |
|---|---|---|---|---|
| Read-only question (ch 1) | ~3,900 est. | 1 | None | No |
| Fix the CSV date bug (ch 1) | ~2,100 est. (code) | 4 | Money-adjacent | Partly |
| Manage a week of context (ch 2) | kept under budget via compaction | +1 per boundary check | None | No |
Write AGENTS.md (ch 4) | ~284 est., paid every session | 0 - reads automatically | None | Yes |
| Route effort + model to the task’s shape (ch 5, this chapter) | ~5,120 est. (rules.py at 512 lines - the design turn; the endpoint is a fraction of that and barely moves the total) | 1, at the matched corner - the redo tax above is what an off-diagonal corner would have cost instead | None new - the dial doesn’t decide what the agent can touch; the approvals chapter owns that row | Partly - the judgment is reapplied per task unless it’s bundled into a profile, in which case the right default recurs for free |
That last cell works the same way the AGENTS.md row did two chapters back: the judgment itself doesn’t hold on its own, but naming it - a profile, a habit of checking the shape before the first prompt - is what makes it hold without you re-deriving it every morning.
Where this goes next
Section titled “Where this goes next”Everything so far has been one agent, on one model, at one effort, working a task in front of you - the base case, and it has a ceiling. When the job is genuinely big - recategorising three years of budgetcli history, or refactoring money-handling across dozens of files - the next move isn’t a bigger gear on a single agent. One agent doing all of that serially floods the very context window you learned to guard two chapters back, and you wait on it the whole time. The answer is more agents: pushing the heavy, parallelisable work off the main thread into isolated contexts that each carry their own window and report back.
That’s the whole idea of Subagents - and it’s where the course goes next.