Table of contents
Open Table of contents
Why
Four sessions open at once, every one of them waiting for me to press y. I switch between them, read the diff, confirm, switch back. An hour later I notice I haven’t thought about anything. I’ve just been clicking approve.
That’s not using an agent. That’s babysitting one.
So I read the six pieces I’d been saving. Cursor’s self-driving codebases, Uber’s software factory, Josh Rosen on LLM-as-judge, and three long posts from X. Very different domains, very different scale, but they’re all describing the same move: how to pull the human out of every step and leave them on the last one.
Loop: the check is the whole thing
Hanako’s definition is the cleanest. A loop is four parts: produce, check, correct, repeat until green. Three of those don’t matter much. The check is the whole thing.
Because without something that can fail the work while you’re out of the room, you don’t have a loop. You have a scheduler.
Almost everyone builds the work first and bolts a review onto the end, and that review is another model looking at the output. Two optimists agreeing.
Anthropic’s version is blunter: never let a model grade its own work. Something produced in one context, reviewed by the same context, skews positive. That isn’t a quirk of the model. It’s structural to self-assessment — a blind spot is a blind spot precisely because it looks fine from where you’re standing.
So the check gets written first, and written in a shape a program can evaluate:
GREEN the test suite exits 0
GREEN every claim carries a source line
GREEN the diff touches only files listed in the plan
NOT A CHECK the output looks good
NOT A CHECK the model says it's confident
NOT A CHECK no errors were raised
That last one is the nasty one. Absence of an error is not evidence of correctness. A loop built on it will confidently repeat the same mistake until the budget runs out, with a clean log the whole way.
Graph: the ceiling of a loop
A loop makes one unit of work good. It can’t decide which units exist, and it can’t decide their order.
So you get an excellent agent doing three wrong things, one at a time, in the wrong order. Every step is correct. The result is still slow and still the wrong shape. Tuning the loop won’t help, because the fault isn’t inside any unit.
The graph is that layer: what runs, what runs in parallel, what waits, what shouldn’t run at all.
- A node is one bounded job, one input in, one output out.
- An edge is a dependency — this node’s output feeds that node’s input.
Every unnecessary wait comes from treating “and then” as an edge. “Summarize this file, and then check the weather” — the weather doesn’t consume the summary. There’s no edge there. Those two got chained by the order I typed them. Take that question to every arrow in a pipeline you already have: does the next step actually read the previous step’s output? If you can’t name the variable that crosses, there’s no edge.
One line I liked a lot: the code node is not a model. Merging, ranking, deduplicating, comparing exports before and after — none of that is reasoning. Each has exactly one right answer, each is a few lines of code. Handing it to a model just adds cost, latency and variance to a step that had none.
The test is simple. If you can describe the transformation without using the words judge, decide, assess or summarize, it’s code.
And the relationship between the two is one sentence: the loop lives inside a node, the graph lives between them.
Two return paths
This is where I got the most out of the reading.
- The correction edge is short. A gate rejects one unit back to the step that produced it. It fixes the run you’re in.
- The learning edge is long. An accepted result goes back to the splitter as a constraint. It fixes every run after.
Almost everyone builds the first and skips the second. The symptom is a system that’s fast and never gets smarter.
polydao gives the second one a concrete home, a CONSTRAINTS.md:
2026-08-19 · press releases are not independent sources. Two releases = 1 source.
2026-08-24 · "acquired by" needs a filing or a company statement, never coverage.
Loaded at the top of every launch. Three lines in week one, thirty by month three. Each line is a mistake no agent will make again in any future run.
All my corrections used to live in chat history. Said once, gone. Then on Monday I retype what I already typed on Friday. Giving corrections a place to live is worth far more than it costs.
There’s also one expensive detail: return the unit, not the batch. Four slices, one fails. Send the whole batch back and three correct slices get rewritten. The new versions are different, not better, because nothing was wrong with them. Now you re-verify all four, and any of those three may fail this time for unrelated reasons. You converted one failure into four uncertain outcomes and paid for the privilege. Do it twice in a run and it never converges.
From the outside this looks like the model failing over and over. It’s actually a return path destroying correct work.
The judge is moving into the runtime
Josh Rosen’s piece is about a different shift: LLM judges are moving out of offline eval and into the runtime.
A judge used to tell you whether yesterday’s version got worse. Now it participates in control flow — continue, retry, route to another model, gather more evidence, or escalate to a person.
The ones I think I can use directly:
- Break the judgment apart. Don’t ask “is this output good”. One judge checks whether it answered the request, one checks whether the claims are supported by evidence, one checks whether the required work got done. One big fuzzy decision becomes several small clear ones, combined by deterministic logic on the outside.
- Compare instead of score. Models can’t reliably tell a 7 from an 8. They’re much better at telling you which of two things is better.
- Judge the work, not the answer. Judging the final reply is fine for a chatbot. For an agent that worked for twenty minutes, the result can look completely reasonable while it retrieved the wrong documents, ignored a key source, or wandered around and got lucky at the end. Judge the places where the real decisions get made — a research agent’s source selection before synthesis, a coding agent’s approach before implementation.
- Disagreement is worth more than the vote. Three judges voting 2-1 that something is good doesn’t interest me much. The fact that they disagreed is an excellent escalation signal.
The cost is stated plainly too. Once a judge is in the critical path, the judge’s mistakes are the application’s mistakes. A slightly noisy judge in an offline eval is annoying. The same judge standing in front of every important action can create loops, block good work, approve bad work, and add latency to every execution.
At scale, the bottleneck moves
The pieces above are methodology. Cursor and Uber are the bill.
Cursor: three tiers. A root planner that decomposes but doesn’t code, subplanners recursing down, workers doing isolated tasks and leaving handoff notes. One week, one large Linux VM, ten million tool calls, roughly a thousand commits an hour.
Two counterintuitive results:
- The bottleneck is disk I/O, not CPU. Hundreds of agents compiling at once means many GB/s of build artifacts read and written. Which means project structure and compilation overhead matter more to efficiency than tokens do.
- Don’t require 100% correctness. Demanding it caused major serialization. Leaving some slack lets agents trust that other issues will get fixed by their peers soon. Keep the error rate small and constant, clean up periodically, instead of blocking everything up front.
They also burned through three architectures that failed: equal-role agents managing their own locks (held locks too long, never released them, twenty agents degrading to the throughput of one to three), rigid pipeline roles (bottlenecked by the slowest worker), and a single all-purpose executor (too many roles at once, so it started sleeping randomly, refusing to spawn tasks, and claiming premature completion).
Uber is another order of magnitude. Over 70% of pull requests come from agents, 3,600 agent skills, 30K skill executions a day. Over six months users grew 7x and requests grew 9.4x, while holding the model constant, cost per thousand requests dropped almost 34% and cost per session dropped 52% from its June peak.
Their approach is to decompose a session’s cost into six terms that multiply, then optimize each one. The most directly stealable:
- Default subagents to a weaker model. The primary model handles decomposition and evaluation; subagents execute well-defined tasks that don’t need frontier reasoning.
- Auto-compact at 400k even on 1M context models.
- Reasoning effort defaulted to Medium.
- A 1-hour cache TTL for interactive sessions, because people leave them idle for more than 5 minutes. Subagents stay at 5 minutes.
- Route MCP through a CLI. A hundred-plus tools is 50-70K tokens of schema, re-sent every single turn. Let the model run a shell command that resolves the tool at call time, and that whole block disappears from context.
- Code-mode. One SQL query means submit, poll two to five times, then fetch. Every poll is a model turn and every one lands in context. Move that loop into a subprocess and return only the summary — more than 50% fewer tokens even on tiny result sets, more than 90% on bulk work.
One number I sat with for a while: they built a context graph with 24M nodes and 80M edges. Same prompt, same model. The grounded agent answered in 38 seconds. The ungrounded one spent 20 minutes, spawned 2 subagents, hit 3 errors, and concluded — incorrectly — that the dataset was unqueryable.
An ungrounded agent doesn’t fail cheaply. It fails expensively.
So where should I stand
Six pieces later, there’s really only one thing I need to change: move myself out of the loop and onto the gate.
And where the gate opens is decided by blast radius, not confidence.
Confidence is the weakest input in that decision, for a simple reason: it’s the only variable the model can influence. What matters is how hard the mistake is to undo.
- Reversible and contained — copy, tests, an isolated function with coverage. One bad merge costs a revert. This lane can open first.
- Reversible but wide — a shared utility, a schema addition. Deterministic checks plus a clean trajectory before anything passes.
- Hard to reverse — migrations, deletions, writing to production data, moving money. This lane doesn’t open.
That third row isn’t a threshold set very high. It’s a lane that doesn’t open. The difference matters because thresholds get adjusted and closed lanes don’t.
The human goes on the step with the highest consequence and the lowest reversibility. Approve the merge, choose which fixes ship. Not reviewing intermediate output, not confirming every step — a human standing in the middle of a graph becomes the slowest node in it, and the whole graph runs exactly as fast as a person can read.
Writing this I realized it’s the same problem I wrote about in the burnout post at the end of last year, one layer up.
Back then the math was: with finite energy, after spending 50% of your time getting A to 80%, you shouldn’t spend another 50% on the remaining 20%. This is the same question. With finite attention, it shouldn’t go into confirming every step. It should go into the one irreversible step, and into the check that can actually fail.
Giving up that 20% takes learning. So does standing up out of the loop.
But
There’s something I have to say, or this becomes the seventh piece of the same thing.
Three of these six are AI-written longform, posted on Twitter, ending in a course pitch or a funnel to a Telegram channel. The top reply under one of them reads: this is ai slop article.
And all of them are earnestly telling you: never let a model grade its own work.
None of them were graded by anyone.
Cursor and Uber are different, not because they’re better written, but because they have scars. Cursor threw away three architectures because those architectures actually blew up across hundreds of agents. Uber talks about disk I/O and a 400k compaction threshold because the bill actually landed on their desk. The polydao piece is the most solid of the three for the same reason — it opens by saying it: I rebuilt this four times this year and threw three of them away.
I’ve written before that every paradigm and structure exists to optimize what has already been found. They maintain stability. They don’t give you the feeling of being a person.
These six add up to a very complete paradigm. I’ll probably rebuild my harness along these lines, because it genuinely would free me from clicking approve.
But if the time that frees up only goes into building a more elegant harness, then I’ve just turned myself into a node executing someone else’s loop. A copy that’s very good at building harnesses.
Write the check first. That holds for agents, and it holds for me. Mine is probably: did I make one thing this year that didn’t grow out of somebody else’s template.
Sources
- Towards Self-Driving Codebases — Cursor
- Running a Software Factory Efficiently at Uber Scale — Uber Engineering
- LLM-as-Judge Architectures — Josh Rosen
- Loops and Graphs — Hanako
- 300 Agents, One Graph — Mr. Buzzoni
- How to Actually Build AI Agents — CyrilXBT