ArticlesMethod
The prompt brief is a node contract
Everyone is teaching the fan-out. Nobody is teaching the contract that makes it safe.
There's a lot of writing right now about running many agents at once. Fan out, split the work, merge the results. The demos are genuinely impressive.
Almost none of it covers the part that decides whether the run was worth doing.
Spread a vague instruction across 12 agents and you don't get 12 times the output. You get 12 confident, mutually incompatible answers, each internally reasonable, and a merge step that can't reconcile them because there was never a shared definition of done. The fan-out worked perfectly. The results are unusable.
The missing piece is a contract on each job. And if you're running C², you've been writing them for two years under a different name.
Twelve agents, twelve unusable answers
The failure is specific, and it isn't a model problem.
Give 12 agents "review this module and report issues" and each one silently invents its own scope. One reports style. One reports security. One rewrites half the file and reports that as an improvement. One reports nothing because it decided the module was fine. Their outputs aren't comparable, so the merge produces a pile rather than an answer, and you end up reading all 12 in full — which is exactly the work you were trying to avoid.
Nothing was wrong with any individual agent. What was missing was a specification tight enough that 12 independent runs produce 12 commensurable results.
That specification is the contract, and it does three things: it bounds the input, it fixes the job to exactly one, and it makes the output checkable.
Bounded input: the pre-flight table
The first thing a contract does is say what the agent may read.
This sounds like a restriction and behaves like a gift. An agent given a whole repository spends its window deciding what's relevant and gets it partly wrong. An agent given 4 files and a reason for each starts from the same place you would.
In C² that's the pre-flight table — part of an autonomous prompt brief, which is a brief written for a session where you won't be present:
| File | Lines | Why |
|-----------------------------------|---------|----------------------------------------------|
| src/auth/middleware.ts | 1–80 | session pattern on L45 — don't break it |
| src/auth/tokens.ts | 120–200 | refresh flow this brief extends |
| docs/03-knowledge/gotchas/jwt.md | all | the clock-skew trap that bit us in April |
Exact paths, exact line ranges, and a reason for each. Writing that table forces you to work out the approach before the agent touches anything, which is most of its value — it's a design step disguised as a reading list.
It has a second use I didn't anticipate. The pre-flight table is a declaration of the brief's surface — what it will touch. Put two briefs' tables side by side and you can see immediately whether they can run at the same time. The contract that makes one node safe is also what tells you the shape of the whole set.
One job, and the things it must not do
The second thing a contract does is fix the scope to exactly one job — and the sharp end of that is what the brief forbids.
Every C² brief carries scope exclusions and non-goals. They read like bureaucracy until you've watched an agent helpfully refactor an adjacent module while fixing your bug, and then they read like the most valuable lines in the document.
What's being built:
- Refresh-token rotation on the existing /auth/refresh route
What's explicitly NOT being built:
- Any change to the session table schema — separate brief, PB-4
- Migration of the legacy /login path
- "While we're here" cleanup of the auth tests
An agent handed an open-ended job will expand into whatever adjacent work looks sensible, and every expansion widens the surface — which is what turns a brief that could have run alongside 3 others into one that collides with all of them. Non-goals aren't tidiness. They're what keeps the node's boundary where you drew it.
Validated output: the anchor
The third thing is the one most fan-outs skip. What does this job return, and how do you know it's true?
The wider engineering answer is a schema — JSON Schema and its relatives exist so a machine result is validated rather than parsed and hoped over. That's the right instinct, and C²'s version is older and blunter: testable acceptance criteria, plus the one signal that decides done.
That signal has a name now. It's the anchor — something no agent in the run can produce by asserting it. A test that actually ran. A query that returned rows. A deploy that resolved. Not "the agent says it's done", which is a report, not a result.
Stuart Leo
A node that grades its own homework isn't a node. It's an opinion with a filename.
Naming the anchor costs one line in the brief. It's folded into the acceptance-criteria item rather than added as a new one, so the gate stays 6 items:
- [ ] Testable acceptance criteria — and name the anchor: the one signal
that decides done, which the agent cannot produce by asserting it.
→ Anchor: `npm test -- auth/refresh` passes, and a real refresh
against staging returns a new token pair.
That's the difference between 12 results you can merge and 12 you have to re-read.
Why this is the hard part nobody sells
Fan-out is easy to demonstrate and easy to sell. It looks like leverage, it makes a good screenshot, and you can build one in an afternoon.
The contract is unglamorous. It's writing, done before anything runs, by the person who least wants to be writing at that moment. There's no demo. The payoff is invisible — it shows up as the merge that just worked, and the 3 hours you didn't spend reconciling incompatible outputs.
That's the honest cost of this method, and it's the real one: C² moves the work earlier. The brief takes 20 minutes you'd rather spend building. What you get back is a run whose output you can actually use, and the ability to run several at once without the results turning to mush.
It's also why I don't think the fan-out is the interesting part. Spawning agents is a solved problem — the tooling is good and getting better every month. Specifying a job tightly enough that 12 independent runs come back commensurable is not solved, and it isn't a tooling problem. It's a writing problem, and it sits with you.
The contract is the whole game
A graph of agents is a set of nodes and the arrows between them. The arrows are architecture. The nodes are where the work actually happens, and a node is only as good as the contract on it.
Bounded input, exactly one job, an output something other than the agent can confirm. Get those three right and the fan-out is the easy part. Get them wrong and running wide just means being wrong in parallel.
The fan-out is the easy half. The contract on each node is what makes the results worth having.
Start here: see how the Cascade gets you to a brief, how to write acceptance criteria an agent can check, or read the method.
Related
Big goals don't fit in one prompt. The C² Cascade breaks work from Platform PRD down to the Prompt Brief an agent can actually build. How the tiers fit.
Write acceptance criteria your agent can check itselfThe difference between an agent that drifts and one that self-verifies is acceptance criteria you can run. How to write briefs with criteria the agent checks itself.
What is a PRD, and why agents need oneA PRD — product requirements document — says what to build and why. Why AI agents need one even more than human teams, and what goes in it.