Skip to main content

Graph Engineering: A Crash Course

12 Concepts · From a line of steps to a run that fans out, checks itself, and merges

Your loop works. It fires every morning at 9am, the harness fences it in, and its spine carries yesterday's learning into today. That was enough.

Now the job gets bigger. You write "review file A, then file B, then file C, then write the report." The agent does exactly that, and it runs correctly. It also takes the time of all four steps added together. If step C stalls, the report never happens, and A's finished work sits upstream with nowhere to go. You have drawn a graph. It is the saddest possible one: a straight line where every box has one arrow in and one arrow out.

Graph engineering, in the sense the field now uses the phrase, is the practice of drawing one run of agent work as a graph and cutting every arrow that carries nothing. The whole idea fits in one sentence: the model was never the bottleneck, the line you drew was. A bottleneck is the one narrow point that slows everything behind it. Cut the arrows that carry nothing, and the line collapses into something wider. Independent jobs all run at once, a checker with a clean context tries to kill what they found, and one job at the end merges the survivors. That shape is called the diamond. This course teaches it, using the article that made the phrase viral, Anatoli Kopadze's Graph Engineering explained, and the tool that made it a one-line prompt, Anthropic's Dynamic Workflows in Claude Code.

You need these first: Loop Engineering and Harness Engineering. The loop course taught the beat, the spine, the maker-checker split, and the ratchet. The harness course taught the five verbs, worktrees, and typed output. This course assumes all of it. A loop is one node. This course is what you draw between the nodes. If those words are new, do those courses first.


📚 Teaching Aid​

Open Full Slideshow

View Full Presentation for Graph Engineering: A Crash Course


New here? A 2-minute recap of what you should already know
  • A beat: one full run of a loop. Discover, implement, verify, and commit.
  • The spine: saved state, such as progress.md, that a loop reads first and writes last.
  • Maker-checker: one agent creates the work. A different agent or command checks it.
  • The ratchet: every caught failure becomes a permanent fix, so the same mistake cannot repeat.
  • Typed output: the agent returns fixed-shape JSON, and code validates it before anything trusts it.
  • Worktrees: separate working folders, so parallel agents cannot overwrite each other.
  • The human gate: risky decisions go to a person. Nothing unattended reaches main.

If any of these are new, read the Loop Engineering and Harness Engineering courses first. This course connects the machinery those courses built.

Key words in plain English​

The words you need before Concept 1, plus the ones the course defines later.

Quick glossary
TermPlain-English meaning
GraphA plan for your AI work, drawn as boxes and arrows. Which jobs must happen, and which job waits for which.
ChainA graph that is one straight line. Every box waits for the box before it.
NodeOne box. One agent doing one job, with one thing going in and one thing coming out.
EdgeOne arrow. This job needs what that job produced, so it waits. It counts only when something real passes along it.
Node contractOne bounded job, a defined input, and a defined output whose shape is enforced.
SchemaThe fixed shape an output must match. Code checks it before the next node starts.
DeterministicSame input, same output, every time. Plain code is deterministic. A model is not.
Context windowThe limited amount of text a model can hold at once. Everything it reads and writes in one run has to fit there.
TokenA small unit of text that a model reads or writes. Tokens are what you pay for.
LLMLarge language model. The model behind a chat or an agent.
Cheap modelA smaller, faster, lower-cost model. Good for bounded jobs with a schema.
Strong modelA larger, more capable, more expensive model. Saved for judgment.
RepoA repository. A project folder whose history git tracks.
JSONA plain-text format for structured data, with named fields and values.
Shared stateThe object every node reads and some nodes write. Each part of it needs one owner.
Fake edgeAn arrow that records only the order you typed the steps in. No data crosses it.
Fake-edge testAsk every arrow whether the next step needs the result of the one before. If not, cut it.
Fan-outOne node splits a job into many independent jobs that all run at once.
MergeMany results come back into one node. A dead node hides here unless the merge counts.
BreadthMany independent jobs done at the same time. The thing a graph buys.
DiamondThe one shape worth memorizing. Fan out, reduce, verify, synthesize.
SkepticAnother name for a verifier. A checker whose job is to doubt a finding.
ReduceShrinking many results before synthesis. Code where it can be code, a model only for judgment.
VerifyA checker with a clean context tries to kill each finding before it moves on.
SynthesizeOne node reads the survivors and writes the single answer.
Gold setA saved sample of outputs you have checked and trust.
OrchestratorThe program or agent that starts each node and passes results between them.
Sub-agentsHelper agents that each take one smaller job from the main run.
Verifier nodeA node on an edge whose only job is to try to kill a finding, with its own empty context.
Dynamic workflowClaude Code's feature. Ask for a workflow, or type ultracode, and Claude writes the orchestration script and runs a fleet of sub-agents from it.
Context collapseToo many raw outputs poured into one step, so the context window overflows.
Layered fan-inMerging in stages. Batch the results, summarize each batch, then combine the summaries.
False independenceTwo nodes look independent, but they write the same file or hit the same limited service.
Hidden edgeA dependency the prompts never mention, such as a shared file.
Silent node failureOne node returns nothing, and the report looks complete anyway.
DAGDirected acyclic graph. Every arrow points forward and nothing loops back.
Loop-back edgeAn arrow that sends work back to an earlier node, such as a failed review going back to the writer.
Dynamic edgesEdges whose number is decided while the run is running.
TopologyThe shape of the drawing. Which nodes connect to which.
AnchorA measurement no node can argue with. A test that ran, money that arrived.
Frozen rulesRules the graph may not change, because a node that could bend them would.
Static graphA graph drawn once and run many times.
Dynamic graphA graph drawn per run, because the split is not known until the work starts.
Complexity budgetThe limits you declare before a run, down to the minimum evidence for "done".
Execution graphThe shape of one run. The meaning this course teaches in full.
Memory graphThe older meaning. Durable typed records that outlive any run. Concept 7's deeper note.
Commit DAGGit history, read as a graph. It remembers what was tried and what was kept.
Knowledge graphA graph of facts, with the source that proves each fact attached to its edge.
SubgraphA small piece of a knowledge graph, handed to an agent instead of the whole thing.
Governance graphThe other older meaning. Loops watching loops. Concept 9's deeper note.
Counter-metricA second number watched beside the one a loop optimizes, so gaming shows up.
DogfoodingUsing your own method on your own real work.

The loop course gave loops a body metaphor: heartbeat, body, spine. This course adds one picture. Think of the graph as the plan on the whiteboard, the drawing that decides what runs side by side and what has to wait. The picture stops being exact in one place. A person draws a whiteboard plan, and Concept 10 shows that a run can also draw its own.

One phrase, three meanings, and which one this course teaches

The industry has used "graph engineering" for three different things this summer.

The first is the execution graph: the shape of one run. Nodes are jobs, edges are real data dependencies, and the design question is what may run at once and where the run must wait. This meaning went viral in late July 2026, and it is the one this course teaches in full, because you can use it tonight.

The second is the memory graph: durable typed state that outlives the run. Karpathy's autoresearch writes its history into a commit DAG, and Anthropic's Knowledge Graph Cookbook builds a graph of facts with a source on every edge. It is the deepest of the three and the most work to build. It appears as a deeper note in Concept 7.

The third is the governance graph: loops watching loops. Carlos E. Perez's essay names four ways a single loop breaks, and fixes each with an edge rather than a better loop. It matters once you run more than one loop against the same memory. It appears as a deeper note in Concept 9, and its central warning, anchors, is the execution graph's warning too.

Three nested bands: the execution graph inside the memory graph inside the governance graph, labeled with their timescales

Figure 1. Three meanings, three timescales, nested. This course teaches the inner band in full.

The three are layers of one system: a run (seconds to hours), what the run established (months), and the wiring between runs and their checkers (as long as the system lives). Read the two notes when a run has produced a result worth keeping, or a second loop worth watching.

The history of the name, the viral six-step playbook, and the frameworks and skeptics that came before the term are in the appendix, after the projects. None of it is needed to learn the fake-edge test.

One note on tools. The execution graph has exactly one tool-specific spelling. In Claude Code, asking for a workflow in your prompt, or including the keyword ultracode, makes Claude draw the graph and run it. That is Part 4. In OpenCode there is no equivalent trigger as of this writing, so you write the fan-out yourself, one opencode run per worker. Everything else is a drawing you make before either tool starts, and it is identical in both: the fake-edge test, the diamond, the verifier, the counting merge. That is the strongest evidence that the graph is a discipline rather than a feature.

True in early September 2026, and each fact here stays true for a different length of time. Dynamic Workflows is generally available, and its limits and defaults move with the product. Kopadze's article is a snapshot. The Bun port numbers differ between sources because they measure different things. Before you trust a flag, a limit, or a cost figure, check the live sources: code.claude.com/docs, opencode.ai/docs.

What this course covers​

PartTopicWhat you learn
1The line you drewWhy a chain is a graph, what nodes and edges really are, and the one test that makes a run faster for free
2The diamondFan out, reduce, verify, synthesize. The one shape that pays, and why the checker needs a clean context
3Where graphs breakThree traps and their fixes, and the anchors no shape of graph can replace
4One run, end to endAn auth audit as a dynamic workflow in Claude Code, and the same diamond as a script in OpenCode
5Staying groundedWhen not to build a graph, what it costs, and the bridge to the next two courses
LiveDogfoodingThe book's own pipeline, drawn, with its real edges and its fake ones
PracticeProjectsEight builds, easy to hard

Preview: the twelve concepts in one line each​

  1. A list of steps is already a graph, the slowest kind, because most of its arrows are fake.
  2. A node is one job with a contract. An edge is real data passing from one job to another.
  3. The fake-edge test cuts every arrow that carries no data, unless the two jobs write the same place.
  4. Fan out to buy breadth. One job per worker, a cheap model once it has earned the node, a separate room for each.
  5. Reduce with code. Spend a model only where the shrinking needs judgment.
  6. The verifier never shares a context with the worker, and it checks a real signal.
  7. The synthesizer writes from survivors only, counts before it writes, and attaches its evidence.
  8. Graphs fail silently in three ways. Each fix is a line of code, not a better model.
  9. A graph where every node reads another node's report is consistent, not verified. It needs anchors.
  10. A graph buys breadth, not judgment. If every job needs the one before it, there is no graph to build. Build a loop.
  11. A fleet costs many times what a chat costs. Declare the budget before the run.
  12. The graph cannot decide what counts as evidence or what "better" means. That stays with you.

Want to learn by doing? Read Part 4 first to see one finished run. Then come back for the parts.

Two ways to read this course

First time? Read Parts 1 to 3, which are Concepts 1 to 9, then Part 4, and build it. Skip the two notes marked "Going deeper." That is about an hour of reading, or ninety minutes with the exercises. Then do Projects 1 to 3.

Second read, after your first diamond has produced a report you wanted to keep: the two deeper notes, all of Part 5, and Projects 4 to 8.

What to remember, and what to look up

Two layers, aging differently. Remember the first. Look up the second.

  • The lasting layer. The twelve lines above, and the one-line summary at the end. Nodes do the thinking, edges carry the results, and an edge only counts if data crosses it.
  • The mechanical layer. Every concurrency cap, token multiple, dollar figure, flag, and prompt keyword below. Treat each as a pointer to the live source, not a fact to memorize. Where this course and the live docs disagree, the docs are right.

Part 1: The Line You Drew​

1. Your chain is already a graph, the saddest one​

Your morning-triage loop reads its spine, does its beat, writes its spine. Now the job gets wider: not one file to review but forty. The obvious prompt is "review file 1, then file 2, then ... then file 40, then write the report." You have just drawn a graph. A graph is a plan for the work, drawn as boxes and arrows. It shows which jobs must happen and which job waits for which. This one is a chain: a graph that is one straight line, where every box waits for the box before it. Count what that costs:

  • The total time is the sum of every step. Forty reviews of ninety seconds each take an hour, even though no review needs any other review to finish first.
  • Failure is sequential. Forty steps are forty points where a stall stops the run. If file 23 hangs, files 24 to 40 never happen, and neither does the report.
  • Work is trapped upstream. The twenty-two finished reviews sit in the context window, the limited space of text a model can hold at once, with nowhere to go, because the only step that could use them will never run.
  • The context fills. Every review's output stays in the same window to the end, whether the report needs it or not.

The same eleven jobs drawn as a chain and as a four-layer graph, with time bars: eleven units against four

Figure 2. The same eleven jobs, drawn twice. Eight of the chain's ten arrows carry no data.

The chain is correct, and it is slow and fragile for one reason only. The arrows say wait, and most of them are lying.

Kopadze puts the payoff in numbers. A linear workflow with forty steps has forty sequential points of failure, and it takes as long as all forty steps added together. The same forty jobs drawn as a graph have only as many real dependencies as actually exist, usually three to five. The run finishes at the speed of the slowest layer. His illustration is five minutes against fifteen seconds, and the ratio is the point. The model was never the bottleneck. The line you drew was.

In simple terms

A to-do list is a graph with all its arrows pointing down the page, because that is how lists are written. A project plan holds the same jobs, with the arrows drawn where the dependencies really are. Graph engineering is turning the list back into the plan. The picture stops being exact in one place: one person works a to-do list, and a graph's jobs run on many workers at once.

Remember

A list of steps is a graph whose arrows all say "wait", and most of those arrows carry no data. Cut them, and the same jobs finish at the speed of the slowest layer, not the sum.

Check yourself: Your changelog loop runs "collect merged pull requests (PRs), then summarize each, then group by area, then write the entry." Which arrows are real?

Show answer

One and a half. "Summarize each" needs the PR list, so the first arrow is real. But the forty summaries do not need each other, so that is a fan-out, not a chain. "Group by area" needs all the summaries, so that arrow is real, and it is a merge. "Write the entry" needs the grouping. So the drawing is one collect, forty summaries at once, one group, one write. Four layers, not forty-three steps.

2. Nodes, edges, and the node contract​

A node is one job: one agent doing one task, with one thing going in and one thing coming out. Researching a competitor. Reviewing a file. Checking a claim. Not "handle the launch," which is a project, and not "think about it," which has no output.

An edge is a dependency: this job needs what that job produced, so it has to wait. An edge only counts when something real actually passes along it. Order is not an edge. Habit is not an edge. Data is an edge.

Kopadze's summary is the one to keep: nodes do the thinking, edges carry the results.

Shann Holmberg added the other one-liner, two days after Peter Steinberger asked whether the field had moved from loops to graphs (the appendix tells that story). The difference between a loop and a graph is who decides the path, the agent or you. In a loop you set the goal and the bar, and the agent picks its route. In a graph you declare the valid paths and the checks along them, and the agent's freedom lives inside each node. So a loop is the smallest graph there is: one node with an edge back to itself.

One consequence people miss: not every node is an agent. Nodes sit on a scale. Fixed steps are plain code: fetch the file list, remove duplicates by key, post to Slack. Model steps are one call to the language model (the LLM), with no tools: classify this ticket. Agent steps are a whole agent run, a loop from the loop course, in its own context. A router, the step that picks which path the work takes next, is a table, not a model. Known business rules stay deterministic, which means the same input always gives the same output, with no model involved. The model is spent only where judgment is required. What is new in 2026 is the top of that scale: a node can be a full agent run.

One more thing travels the edges besides results. Shared state is the object every node reads and some nodes write. Decide, per node, who may write which part of it. Unowned state is the first way graphs rot, and Concept 8's false-independence trap is the same rot at the file level.

What makes a node usable in a graph, rather than by a person, is a node contract: one bounded job, a defined input, a defined output. A node whose output is a wall of free text is a node only a human can read. A node whose output has a fixed shape is one the next node can consume without guessing. Here is one, in the plainest form:

NODE CONTRACT
JOB: research one competitor's pricing (one job, nothing else)
IN: { competitor: "name", url: "https://..." } passed in, never assumed
OUT: { price: number, plan: string, source: url, date: "YYYY-MM-DD" }
SCHEMA: enforced. if the agent returns free text, it is rejected and retried
WHY: a defined output is what lets the next node read this one
without a human in the middle. that is what makes it wirable.

This is the harness course's typed output, promoted from one reviewer's verdict to every box on the drawing. In the harness, code validated the checker's JSON before anyone trusted it. In a graph, code validates every node's output before the next node may start, because the next node is not a person but another node with a contract of its own.

Two consequences follow, and both return in Part 2. First, a node with a contract is a candidate for a cheap model (a smaller, faster, lower-cost model) when the job is bounded, because of the schema, which means the fixed shape the output must match. The schema catches the shape failures a cheap model makes. It does not make the output correct, so the cheap model earns the node only once an eval, a scored test of output quality, shows it clears that node's quality bar. Evals are the next course's job. Second, a node with a contract can be checked by a stranger, because the checker receives a typed finding, not a chat transcript. That is what makes Concept 6 possible.

In simple terms

A node is a worker with a job description, an in-tray, and an out-tray. The contract says what goes in each tray. Without the trays, the only way to pass work along is to walk over and explain, which is a conversation, not a graph. The picture stops being exact in two places. A real worker can ask about a strange item in the tray, and a node cannot. And some workers on the drawing are plain code, not agents.

Try it now: write one contract (3 min)

Take one step from any workflow you run, and write its contract in the four-line form above: JOB, IN, OUT, SCHEMA. Then look at the OUT line and ask whether a program, not a person, could read it and start the next step. If the honest answer is "it would need to read the prose," you have found the reason your steps run in a line. The wire is missing.

Remember

Nodes do the thinking, edges carry the results. An edge counts only when data crosses it. A node counts only when its output has a shape that code can check.

Check yourself: A step's output is a paragraph that says "the pricing page lists three plans, and the middle one seems popular." Can the next node start from it?

Show answer

No. Only a person can read that output, so the node has no contract. Give it a defined output, such as price, plan, source, and date in a fixed shape, and have code reject anything else.

3. The fake-edge test​

This one test makes your run faster without a single new tool, so learn it tonight.

The fake-edge test is this. Walk the workflow you run today step by step. At each arrow, ask one thing: does this step actually need the result of the one before it?

If yes, the edge is real. Keep the order. If no, the arrow is a fake edge: it records only the order you typed the steps in, and the wait is wasted. Those two jobs can run at the same time.

The simplest example is the one to remember. "Review file A for bugs, then review file B for bugs." It reads like a sequence, but the review of B never looks at what the review of A returned. Run them side by side, and the pair finishes in the time of the slower file.

The fake-edge test: two review jobs joined by an arrow that carries no data, then the same two jobs side by side, feeding one node that counts what arrived

Figure 3. The fake-edge test. Cut the arrow when no data crosses it, then ask the second half: do A and B write the same thing?

Almost any workflow you draw has two or three fake edges, and each one is time thrown away for free. The habit comes from prose: instructions are written as lines, so the diagram inherits the shape of the prose rather than the shape of the work. Most people find three real dependencies inside a chain of twelve.

Cut the arrows that carry no data, and the line collapses into something wider. A fan-out is a set of independent jobs that all run at once. A merge is the one job that needs all of them, so it waits for them. That is the shape Part 2 names.

One warning before you start cutting. Sequence is not dependency, but resources are. Two review jobs whose prompts never mention each other, but which both write to the same findings.md, are not independent. The file is an edge that the prompt never drew. Concept 8 names this trap. For now, the test has two halves. Does B read A's result? And do A and B write the same thing? Cut the arrow only when both answers are no.

In simple terms

Ask each arrow to show its receipt. An arrow that can point to a piece of data it carries stays. An arrow that can only say "that is the order they were written in" gets cut. The picture stops being exact in one place: a receipt does not show two jobs silently sharing a file, which is the second half of the test.

Remember

Ask every arrow whether the next step needs the result of the one before. If not, cut it, unless the two steps write the same place. Cut only when both answers are no.

Check yourself: A launch workflow runs seven steps in a line. Profile the buyer, then map where buyers spend time, then collect competitor pitches, then write a positioning doc. Then write landing copy, then a week of posts, then outreach messages. Redraw it.

Show answer

Two layers of three, with a real edge between them. The three research jobs do not read each other, so fan them out. The positioning doc needs all three, so that is a real merge. The three writing jobs each need the doc but not each other, so fan them out again. Seven steps become three layers, and the run finishes in the time of the slowest research job, plus the doc, plus the slowest writing job. One arrow the list omits is a human gate on the doc, because everything downstream inherits its mistakes.


Part 2: The Diamond​

In any serious agent system the same picture appears. The work splits, several workers dig side by side, something checks what they found, and everything merges back into one answer. Kopadze calls that shape the diamond. The work fans out, the results are shrunk, and one node writes the answer. A skeptic, which means a checker whose job is to doubt each finding, sits on the edge before anything moves downstream. This course makes the checker a stage of its own, because it is the stage people skip.

So the chant here has four stages. Reduce means shrinking many results into fewer, with code where you can. Verify means a skeptic with a clean context tries to kill each finding. Synthesize means one node writes the single answer from what survived. Fan out, reduce, verify, synthesize.

The diamond: a split node fanning out to five cheap-model workers, a code reduce node, five clean-context skeptics, and one synthesizer

Figure 4. The diamond. The color code is reused in every figure that follows. Blue for cheap-model workers, gray for code, orange for strong-model skeptics with a clean context, purple for the synthesizer.

Claude Code ships this shape as a built-in command, /deep-research. It fans out searches across several angles, cross-checks the sources, votes on each claim, and returns one cited report with the failed claims filtered out. One warning, for Concept 10. The diamond is a shape, and production teams have learned not to hard-code it as a fixed pipeline for open-ended work, because the split is not known until the work starts. Whether you draw it once or per run is a separate decision. Once you can see the diamond, you stop asking "how do I make my agent do more steps" and start asking "where is the split, where is the merge."

4. Fan out: breadth, cheap models, isolation​

Fan-out buys breadth, which means many independent jobs done at the same time. One node splits the job into pieces that do not need each other, and every piece runs at once, each in a fresh context. Forty file reviews take the time of one. Three rules make a fan-out work.

One job per worker, with a contract. "Research the market" fanned out five ways is five agents wandering. "Research pricing against the top three competitors, give every claim a source URL and a date, and return this schema" fanned out five ways is five workers whose outputs code can merge.

Cheap models on the wide nodes, once they have earned them. Fan-out multiplies cost by the width, so the bounded, schema-checked jobs are where a cheap model pays. The strong model, the larger and more capable one, is saved for the judgment nodes, the verifier and the synthesizer. Run the wide nodes on the strong model first. Keep a sample of their outputs as a gold set, which means a saved set of outputs you have checked and trust. Move to the cheap model when its outputs match that set. A fan-out where every worker runs the most expensive model is the fastest way to turn a graph into an invoice.

Isolation, or it is not a fan-out. Every worker gets its own worktree, its own scratch directory, its own output slot. Any two nodes writing the same place need an edge. Parallelism, which means running them at the same time, is the wrong tool there.

The width needs a cap, and the cap belongs in the prompt. "One agent per file, twelve files on this first run" is a fan-out. "One agent per file" over an unknown repo is a bill you have not read yet. Concept 11 turns this into a budget you declare before the run.

In simple terms

Fan-out is hiring five contractors instead of one, for jobs that do not need each other, each in a separate room. It pays only when the jobs are truly separate and the contractors are cheap. The picture stops being exact in two places. Contractors can talk in the hallway, and workers in a fan-out cannot. And each worker starts with an empty memory, so nothing learned in one room reaches the next job.

Try it now: fan out by hand (5 min)

In a repo you know, run two reviews side by side instead of in a line. In one shell: claude -p 'Review src/a.ts for bugs. Return JSON: {file, findings:[{line, issue, severity}]}' > a.json &. In another, the same for src/b.ts. Then wait, and jq -s '.' a.json b.json (jq is a small command-line tool for reading JSON). (OpenCode: opencode run '<same prompt>'.) You just ran a fan-out with the shell as the orchestrator, which means the program that starts each node and passes results between them. The two JSON files were the contract. Notice that the merge was jq -s, no model. That is Concept 5.

Remember

Fan out only jobs that do not need each other, one job per worker, with a contract and a separate room. Use a cheap model once it matches the gold set, and cap the width in the prompt.

Check yourself: Twenty workers in a fan-out all append their findings to one results.md. Which rule does that break?

Show answer

Isolation. Two nodes writing the same place need an edge, not parallelism. Give each worker its own output slot, and let code combine them afterwards.

5. Reduce with code where you can, a model only where you must​

Between the workers and the checker sits the stage almost everyone skips. The rule: reduce with code wherever the operation is deterministic, and spend model tokens only where the reduction needs a judgment about meaning. Validate shapes, remove duplicates by key, filter the empties, count what came back, group by file. That is code: no model, and no tokens, the paid units of text a model reads and writes. Deciding that two differently worded findings are the same finding, or summarizing forty results into one paragraph, takes judgment. Concept 8 spends a model on that, in batches, after code has done its part.

Why code first, and not "ask an agent to combine these"? Three reasons.

Cost. Reduce runs over every worker's output, so a model call here is multiplied by the width of the graph, for work that jq or ten lines of JavaScript does exactly.

Determinism. Removing duplicates with a model is a judgment that differs from run to run. Removing duplicates by a key is the same every time. So the verify stage receives the same kind of input every time, which is what lets you trust its pass rate later.

Context. The synthesizer at the end of the diamond can only read so much. If reduce does not shrink the pile, synthesis reads the raw pile, and the raw pile from a thousand workers does not fit. Concept 8's first trap is what happens when this stage is missing.

Here is what the diamond looks like inside when the coordination is code. In Claude Code, a dynamic workflow is a run where you ask for a workflow and Claude writes a short script much like this one, then runs the coordination from it. That is why passing results between agents costs no extra context: the results live in variables, not in a chat.

// a market-scan diamond, in the shape of the script a workflow generates
// (simplified; the real calls are agent(prompt, { schema, label, model }),
// parallel() and pipeline(): see code.claude.com/docs/en/workflows)

const angles = [
"pricing vs the top 3 competitors",
"what buyers complain about in reviews",
"the feature gaps in the category",
"where the market moves in the next 12 months",
];

// FAN OUT: one researcher per angle, all at once, cheap model, typed output
const raw = await parallel(
angles.map((a) => () =>
agent(`research: ${a}. every claim needs a source url + date.`, {
schema: Finding, // validated output, never free text
model: "haiku", // bounded node -> cheap model
label: `research:${a}`,
})
)
);

// REDUCE: plain code. no model, no tokens.
const findings = dedupeBySource(raw.flat().filter(Boolean));

// VERIFY: a fresh skeptic per finding, tries to kill it (Concept 6).
// every agent() call is a new agent with an empty context: it never
// sees the researcher's chat, only the finding it is handed
const verdicts = await parallel(
findings.map((f) => () =>
agent(`try to disprove this finding: ${JSON.stringify(f)}`, {
schema: Verdict, // { verdict: "keep" | "drop", why }
model: "opus", // judgment node -> strong model
label: "skeptic",
})
)
);
const survivors = findings.filter((_, i) => verdicts[i]?.verdict === "keep");

// SYNTHESIZE: one agent writes the answer from what survived (Concept 7)
return agent(
`one report, ranked by confidence, sources attached: ${JSON.stringify(survivors)}`,
{ model: "opus", label: "report" }
);

Read the middle line, dedupeBySource(raw.flat().filter(Boolean)), as the whole concept. Four workers' outputs become one clean list, and it cost nothing.

In simple terms

After five researchers hand in their notes, someone staples each set of exact duplicates into one copy, throws away the blank pages, and counts the rest before the editor reads anything. That someone should be a stapler, not another researcher. Deciding that two differently worded notes say the same thing is a researcher's job, given to one only after the stapler has done its part. The picture stops being exact in one place. Code only removes the duplicates you told it how to recognize.

Remember

Reduce with code wherever the operation is deterministic. Spend a model only where the reduction needs judgment, and only after code has shrunk the pile.

Check yourself: A team's diamond has forty workers, then a single "combine and dedupe these" agent, then a synthesizer. The run works at forty workers and fails at four hundred. What is missing, and where?

Show answer

A reduce stage in code. The "combine" agent does reduce's job with a model, so at four hundred workers its context fills before it can remove any duplicates. Replace it with code that removes duplicates by key and counts what arrived. If the list is still too long for one context, layer the fan-in, which is Concept 8.

6. Verify: the checker with a clean context​

Every serious test of AI self-review says the same thing: models miss most of their own mistakes. So you never let the agent that did the work check the work. You put a separate node on the edge, a verifier node, whose only job is to try to kill the finding before it moves on. If the finding survives, it passes. If not, it dies right there, before it ever reaches the report.

You built this in the loop course as the maker-checker split. The loop course never had to name one catch, because it had only one context: the checker needs a clean context.

Give the verifier the same chat the worker had, and it is not checking anything. It is agreeing with itself in a different font. A graph of agents sharing one context is a single loop in a costume, and it breaks the same way, only later and at a higher price. So the rule is absolute: a worker and its verifier must never share a context. The verifier receives the finding, the typed output from Concept 2's contract, and nothing else. It has not seen the work it is judging, and that is the point.

Then make it check a real signal, not the worker's claim to be done. "Does the test actually pass" beats "did the agent say it passes." And split the checking three ways:

VERIFIER NODE
INPUT: one finding from a worker (the finding only, never the worker's chat)
CONTEXT: fresh and empty. it has not seen the work it is judging.
CHECKS: three skeptics run in parallel, each with a different question
1. is it correct? -> does the claim actually hold up
2. is it current? -> is the source recent, not something stale
3. is the source real? -> does the link resolve to the claim it is cited for
PASS: keep the finding only if a majority of skeptics let it live
FAIL: drop it before it ever reaches the final answer

Two verifiers side by side. One holds the worker&#39;s transcript in its context and agrees with itself. The other holds only the typed finding and fans out to three questions that vote

Figure 5. The same finding judged twice. The verifier on the right has never seen the work it is judging, which is the point.

The verifier is itself a small fan-out: three skeptics per finding, in parallel, merged by a vote. The three questions are Kopadze's. The majority vote is this course's default, and the next course says when a single strict question or a unanimous rule fits better. The three questions must be different questions, because the same model given the same input three times repeats its errors, and a majority of such votes is one vote with extra confidence. The fix is a different prompt, evidence set, or role per reviewer.

One honest boundary. A clean-context verifier is a much better checker than a shared-context one, and it is still a model. It can pass a wrong finding, fail a right one, and drift when the model beneath it updates. How do you know the verifier is any good? That question is the next course: Trusting the Checker.

In simple terms

You do not let a student grade their own exam, or let the grader sit next to the student during the exam. The grader gets the finished paper, a blank desk, and a rubric, which means a written scoring guide. Three graders with three different rubrics beat ten graders with the same one. The picture stops being exact in two places. The grader is not a wiser teacher, only the same kind of model with a different context. And a good grader has been graded too, which this one has not yet.

Try it now: make a checker see nothing but the finding (6 min)

Take one finding from your Concept 4 fan-out, the JSON for one issue. Run a verifier on it in a fresh shell, with nothing else in the prompt:

claude -p 'You are a skeptic. Here is one finding: <paste the JSON>.
Try to disprove it by reading the file yourself. Return only JSON:
{"verdict":"keep|drop","why":"","evidence":"file:line or command output"}'
# OpenCode: opencode run '<same prompt>'

Then set a trap: invent a likely-sounding finding for a line that does not exist, and run the same verifier. If it keeps the invented finding, you have learned the reason the next course exists.

Remember

A worker and its verifier never share a context. The verifier gets the typed finding and nothing else, checks a real signal, and asks three different questions.

Check yourself: Why is a majority vote of three verifiers with the same prompt and the same input weaker than it looks?

Show answer

Because their errors repeat. The same model reading the same input three times is one opinion counted three times. Give each verifier a different question, evidence set, or role.

7. Synthesize, and where the survivors go​

The last node of the diamond is the only one that writes prose. It reads the survivors, the findings that reduce compressed and verify let live, and writes the one answer: a ranked report, a merged list, a single draft. Three rules keep it honest.

It reads survivors, never raw output. Reduce has shrunk the pile and verify has thinned it, so the synthesizer's context holds a short list of typed, checked findings. It can be a strong model doing careful work rather than a large model drowning.

It counts before it writes. The synthesizer, or the merge just before it, compares how many results arrived against how many the fan-out launched. Twelve files were dispatched and eleven came back, so the report says so in its first line, rather than describing eleven files as twelve. Concept 8's third trap is what happens when this count is missing.

It ranks by evidence, and attaches it. Every line in the report points at the finding it came from, and every finding points at its source. "Ranked by confidence, sources attached" is the synthesizer's contract, and it lets a human, or a later run, check the report without re-running the graph.

Now the honest limit of the diamond. Its output is a report, and a report is a transcript with better formatting. Tomorrow's run starts with an empty context, and everything today's survivors established is a file someone has to find and re-read. Where do the survivors go?

Going deeper: the memory graph, where survivors go

This is the second meaning of "graph engineering," the one the phrase meant before it went viral. The agent forgets, the graph does not.

The memory graph in one page: two graphs, a schema, and four fixed rules

Survivors are worth keeping only if a later run can query them without re-reading a report. So the synthesizer writes them down as typed, connected records: nodes and edges that any later agent can query. Two different graphs do this job, and beginners often collapse them into one.

The commit DAG (a DAG is a graph whose arrows never loop back) remembers the work: what was tried, what came from what, what was kept. You already own one, Git history. Karpathy's autoresearch (March 7, 2026) is a ratchet loop whose memory is exactly that: a branch that advances only on improvement, plus a results.tsv of every attempt, including the failures, deliberately left untracked. His AgentHub sketch (since taken private) kept failed experiments as durable nodes, so a group of agents can ask children, leaves, and lineage of the search graph instead of merging to main. A commit is a fact by construction.

The knowledge graph remembers the facts: which entities exist (named things such as people, companies, and products), how they relate, and which source proves each claim. You build it, and Anthropic's Knowledge Graph Construction Cookbook (March 23, 2026) collapses the old NLP pipeline into structured-output prompts. Extract typed entities and relations on a cheap model, with a description field per entity. Resolve which names refer to the same thing on a stronger model, using those descriptions, and keep every alias, reason, and confidence, so a false merge is one reversal rather than a rebuild. Assemble a graph where every edge carries its source document. Query it by handing agents a subgraph, which means a small piece of the graph, never the whole thing. Resolve the task's entities, expand one or two steps out, include the conflicts, and write it out within budget with stable edge ids. A claim is a statement with evidence, which is why it needs the receipts a commit does not.

Four fixed rules govern every write, and they are the memory version of this course's verifier. Every claim has a source or is marked inference. Every artifact has an authoring run and a version. Every evaluation names its rubric. Every superseded object stays addressable, replaced and never erased. The smallest version that clears the bar is three JSON files in a repo, entities.json, claims.json, runs.json, with an append-only rule enforced by a jq pre-commit hook. Add a reviewer that must cite a claim id for every factual statement, or return REVISE naming the missing evidence. "Triple not found" beats "seems off," because one is a mood and the other is a work order.

That is where the diamond's synthesizer should write, once its report has been worth keeping twice. The Cookbook and autoresearch, both in the sources, teach the build in full, and Trusting the Checker teaches how to know the extraction and the reviewer are any good. Do not build it before a real query demands it. Most runs do not.

In simple terms

The synthesizer is the editor who writes the final piece from the checked notes. A good editor writes only from what survived fact-checking, says up front if a reporter never filed, and adds a footnote for everything. A good newsroom also keeps the notes after the piece runs, which is the memory note above. The picture stops being exact in one place: an editor can call the reporter, and the synthesizer cannot.

Remember

The synthesizer reads survivors only. It counts what arrived against what was sent and puts the count in the first line. Every claim carries its evidence.

Check yourself: Fourteen findings went to the verifiers. Ten came back "keep", three came back "drop", and one verifier crashed. What does the synthesizer's first line say?

Show answer

How many were dispatched and how many came back, with the one unchecked finding listed as unverified. It writes from the ten survivors only.


Part 3: Where Graphs Break​

8. Three traps, and their fixes​

A chain fails loudly: one step stops, everything stops, and you notice. A graph fails in three silent ways, and each has a fix that is a line of code, not a better model.

Three panels, each with its fix drawn beneath. Outputs piling into one overflowing step, two agents writing one file, and a report claiming six reviews when one node returned nothing

Figure 6. Three ways a graph fails silently, and the fix for each. Batch the merge, isolate the workers, count at the merge.

Trap 1. Context collapse is what happens when you fan out a thousand nodes and feed all thousand outputs into one final step. You blow past the context window before synthesis even starts. This is Concept 5's missing reduce stage, at scale. The fix is a layered fan-in: batch the results, summarize each batch, then combine the summaries.

// layered fan-in: never pour 1,000 raw outputs into one step
const batches = chunk(results, 40); // groups of 40
const summaries = await parallel(
batches.map((b) => () =>
agent(`summarize this batch: ${JSON.stringify(b)}`, { label: "batch" })
)
);
return agent(`write the answer from these summaries: ${JSON.stringify(summaries)}`, { label: "answer" });
// the final step reads ~25 summaries, not 1,000 raw outputs

Layered fan-in is a second diamond stacked inside the first. The batch summaries are a fan-out, and their combination is a merge.

Trap 2. False independence is when two nodes look independent because their prompts never mention each other. But both write to the same file, or both call the same outside service that allows only so many requests a minute. That shared resource is a hidden edge: a dependency the prompts never drew. Running the nodes in parallel across it is the fake-edge test run backwards, because you cut a dependency that was real. Kopadze's example comes from Bun, a JavaScript tool whose team later moved its whole code base to a new language with agents. Concept 11 has the numbers. Their first attempt at fanning a big job across many agents shared one workspace, and the agents overwrote each other. The fix is to give every worker its own isolated space, and to audit for shared resources, not just shared data.

// isolate the workers: no shared file, no shared workspace
await parallel(
files.map((f) => () =>
agent(`refactor ${f}. work in your own git worktree and touch no other file.`, {
label: `refactor:${f}`,
})
)
);
// each worker edits in its own worktree, so they cannot overwrite each other,
// and the results merge cleanly afterwards
// rule: any two nodes writing the same file need an edge, not parallelism

Trap 3. Silent node failure is when one dead node among two hundred slips into a report that looks complete. Eleven files get reviewed, and the report describes twelve. In a dynamic workflow, a stopped or crashed agent() resolves to null, and the generated code drops it with .filter(Boolean). That filter is correct, and it is also exactly the trap, because a filtered null is a silent gap unless something counts before and after. The fix is that every merge counts its inputs against the number it expected and flags the gap, instead of running on with half the data.

// fan-in guard: catch the node that quietly died
const results = (await parallel(jobs)).filter(Boolean); // a stopped or failed agent() is null
if (results.length < jobs.length) {
log(`WARNING: ${jobs.length - results.length} of ${jobs.length} nodes returned nothing`);
}
// never synthesize on a partial set and call the report complete

The verify stage needs one refinement. A checker that failed is not a checker that disproved the finding. If a skeptic hits a rate limit or an error, the finding it was judging goes to the report as unverified, a separate count from dropped, never silently kept and never silently discarded. The bundled /deep-research workflow does this, and Part 4's script does too.

The third fix has a rule behind it. When a budget runs out or a node dies, return the best current artifact: the work that completed, the issues left unresolved, and the reason for stopping. Do not hide partial failure behind a fluent final answer. A run that says "I stopped at 40 of 60 files because the token budget ended, and here is what the 40 showed" is worth more than a confident report that silently covered two thirds of the job. And one failed branch must not discard the ninety-nine that finished: collect what settled, record what did not, and let the next node decide whether that is enough to continue.

In simple terms

Three ways a team project goes wrong without anyone noticing. Everyone dumps their notes on one desk until nothing fits, so batch them. Two people edit the same document at once, so give each a copy and merge later. One person never hands anything in and the report pretends they did, so count the submissions. None of these needs a smarter team. Each needs one rule. The picture stops being exact in one place: a missing teammate usually gets noticed, and a dead node does not.

Cycles: the diamond flows one way, and most real graphs do not

Everything in Part 2 flows one way, and that is deliberate for a first graph. The diamond is a DAG, a directed acyclic graph, which means a drawing where every arrow points forward and nothing loops back. Production graphs are different. LangChain's first lesson from three years of running agents as graphs is that agent graphs are usually not DAGs. Real work needs cycles: retrying a failed tool call, asking a user for missing information, revising a draft after the reviewer fails it, calling a tool again until there is enough context, pausing for a human and resuming. The standard starter graph shared on social media this summer had one of these. Researcher, writer, reviewer, and a dashed loop-back edge from the reviewer's fail verdict to the writer. A loop-back edge is an arrow that sends work back to an earlier node.

Researcher, writer, and reviewer nodes in a line, a green pass edge to ship, and a dashed red fail edge curving back from the reviewer to the writer

Figure 7. The starter graph, with the cycle most production graphs have. Bound it, and keep the writer's and reviewer's contexts apart.

Two rules keep cycles from turning a graph back into a runaway loop. First, bound every loop-back. A reviewer-to-writer edge with no limit on rounds is a loop with no stop condition, the loop course's first problem, now multiplied by the width of the graph. The discovery-loop spec in Part 4 shows the shape: two clean rounds to stop, and a hard cap on total agents. Second, keep the verifier outside the cycle's context. A loop-back that hands the writer the reviewer's chat, or the reviewer the writer's, has silently merged the two contexts Concept 6 kept apart.

Production graphs have a third thing the Part 2 drawing does not: dynamic edges, which means edges whose number is decided while the run is running. You know the research should fan out and synthesize, but not how many sources there will be until the run starts. LangChain's Send primitive exists for exactly this: a node that decides at runtime how much work to create. A dynamic workflow is the same idea, with the orchestrator drawing the fan-out's width from the task, not from you. Concept 10 turns that into a decision.

Remember

Graphs fail silently. Layer the fan-in so no step reads the raw pile. Isolate every worker so no two write the same place. Count at every merge so a dead node cannot hide.

Check yourself: Two audit agents run in parallel with prompts that never mention each other. Both write their findings to findings.md, and the second one's write overwrites the first. Which trap, and which fix?

Show answer

False independence. The prompts were independent, and the resources were not. The shared file is a hidden edge. The fix is a worktree per worker, or a per-worker output slot, plus an audit for shared resources. Layered fan-in fixes a different trap, too many outputs at the merge. A counting merge would catch the symptom, one finding fewer than expected, without naming the cause, so the next run would collide the same way. Isolation first. Then, where a shared write cannot be avoided, an explicit edge that orders it.

9. Anchors: topology does not buy truth​

This is the deeper trap, and the part nobody wants to hear.

Imagine you build the full graph. Paired checkers on every worker, audit nodes on the checkers, meta-nodes tuning the other nodes. Every node watches another node, and every one of them reads a report. The audit checks the numbers against the finance numbers, which came from the same system. Everything is consistent. Nothing is verified.

This graph fails exactly like the single loop did, only later, more expensively, and with far more green lights on the way down.

A ring of green-ticked nodes, each reading another node&#39;s report. Three lines drop out of the ring to tests that ran, revenue that arrived, and rules nobody may change

Figure 8. A ring of nodes citing each other passes its own audit with every light green. Only the anchors touch anything outside the ring.

Topology means the shape of the drawing, which nodes connect to which. Topology alone does not buy truth. The graph needs an anchor: a node that cannot be argued with. Tests that actually ran, not "should pass", but did pass. Revenue that arrived in the bank. Customers who actually stayed. Documents a human wrote. Be strict about the last kind, because the failure hides there. A run log is an anchor only where the cited lines are captured output from something outside the model: a test runner, a compiler, a database, an API. An agent's own prose inside a log file is model output wearing a filename, and citing it is how a circular graph passes its own audit.

Some rules must be frozen. Frozen rules are rules the graph may not change, because a node that could bend them would bend them to win. The test file the refactor sweep may not edit. The rubric the verifier may not rewrite. The cap on agents that the discovery loop may not raise. The graph is only as honest as the things inside it that refuse to move. Judge it on numbers that cannot argue back, and it stays grounded. Let it grade its own reports, and it will be confidently wrong.

The audit is one number. Pick ten random findings from a run's report and walk each one down: finding, verifier verdict, source. Count how many end in something no model produced. That count is your run's grounding.

Going deeper: the governance graph, loops watching loops

This is the third meaning of "graph engineering," Carlos E. Perez's reading of Steinberger's question, and it starts from the same warning as this concept.

The governance graph in one page: four failures, four edges, and anchors again

Zoom out until each of your loops becomes a single node, and ask how the nodes connect. That is the governance graph, and it decides whether a system of loops stays honest or merely stays busy. The loop is the node, the graph is the wiring. Not every node is a loop: a human gate, a ground-truth check, and a frozen checker are nodes too.

Perez's essay opens with a support team whose loop optimizes the ticket-resolution rate. The number climbs for a quarter. Then renewal data arrives, and customers are leaving at twice the old rate, because the bot learned to close tickets by pushing customers away. The loop worked perfectly, and its number had stopped meaning the real outcome. He names four ways a single loop breaks, each fixed by an edge, never by a better loop:

How a single loop breaksThe graph's answer
Gaming (Goodhart's law: a measure that becomes a target stops being a good measure)Pair every optimizing loop with a watching loop on a counter-metric, a second number the first loop is not chasing, so gaming shows up in it. Resolution paired with renewal.
Blindness upwardA slower loop owns the faster loop's target, so changing targets is governed work.
ConflictAn arbitration node above the loops, a supervising loop or a human gate, that owns the trade-off.
Measurement decayIndependent audit loops that test whether the numbers still touch the world.

Three practical questions move to the center, asked once per edge. Routing: when loop A finishes, who receives the result? Trust boundaries: which loop may fire which, under whose identity? Gate placement: put the human where a wrong automatic move is costly and hard to reverse. One rule for routing: a model may classify a request, but a deterministic table, not the model, decides what the system may do next.

Perez's closing warning is the one this concept already made: a graph of loops that only read each other's reports needs anchors, frozen nodes, and a root judgment from people about what better means. The cheap starting version is two rules. Every optimizing loop gets one watching loop, and at least one signal in the system must come from reality rather than from another model's report. Nothing about your first loop changes. Everything about your second does. Perez's essay, in the sources, teaches this layer in full, and Human-Agent Teams is what it becomes on an org chart.

In simple terms

Three newspapers citing each other in a ring are not three sources. Someone has to have attended the event. Anchors are the reporters who were actually there. Frozen rules are the ethics code that reporters may not rewrite. And "what counts as news" is decided by the editor, never by the printing press. The picture stops being exact in one place. An agent that says it went and looked is still a reporter's story. An anchor is the captured output of something outside the model, such as a test runner or a bank record.

Remember

A graph where every node reads another node's report is consistent, not verified. Anchor it in things no model produced, and freeze the rules a node would bend to win.

Check yourself: A verifier cites a line from run.log as its evidence. When is that an anchor, and when is it not?

Show answer

It is an anchor only when the cited line is captured output from something outside the model. That means a test runner, a compiler, a database, or an API. If the line is an agent's own sentence about what it did, it is model output with a filename, and citing it is circular.


Part 4: One Run, End to End​

This part draws one real diamond and runs it in both tools. The job is to audit every route file under src/routes/ for missing auth checks (auth is the code that checks who a user is and what they may do). Here is the drawing, before any tool starts:

The auth-audit diamond with the run&#39;s numbers on it: 12 dispatched, one file returning nothing, 14 findings, four dropped, one unverified, and a report whose first line states the counts

Figure 9. One run, with its numbers on it. The cap is twelve, so the fan-out fits in a single wave under the sixteen-agent limit.

Three real edges. File findings feed reduce, reduce feeds the skeptics, survivors feed the report. Everything else runs at once. The cap is twelve, not twenty, for a reason. Claude Code runs at most sixteen agents at the same time, so a wider fan-out is scheduled in waves. The run then finishes in the time of the slowest wave, not the slowest file. Twelve fits in one wave.

In Claude Code: ask for a workflow​

Claude Code shipped the tooling to run this drawing directly, the dynamic workflow from Concept 5. Ask for one in your prompt, in your own words ("use a workflow to...") or with the keyword ultracode. Instead of working through a single line of steps, Claude writes a short orchestration script, the kind you saw in Concept 5. A runtime executes it in the background with a coordinated fleet of sub-agents, which means helper agents that each take one smaller job. The important part is that the coordination is code, not a conversation. With sub-agents or skills, Claude is the orchestrator and every result lands in a context window. With a workflow, the script holds the loop, the branching, and the intermediate results, so your context holds only the final answer.

Open a real repository you know, and paste a spec in this shape. The lines are the diamond's stages plus Concept 11's budget, declared up front:

ultracode: audit every route file under src/routes/ for missing auth checks

FAN OUT: one agent per file, in parallel, each in its own isolated copy
VERIFY: an independent checker on each finding, with fresh context,
that opens the file itself and cites the line; a finding the
checker could not check is reported as unverified, not dropped
CAP: 12 files on this first run
ON FAIL: name any file that does not return, never skip it silently
REPORT: one merged list of routes missing auth, ranked by severity,
first line: how many files were dispatched and how many came back
AFTER: change nothing in the repo; I will read the report and decide

Claude Code highlights the keyword and writes a workflow script for the task instead of answering turn by turn. Before anything runs, you see the planned phases, and you can read the raw script, adjust the prompt, or cancel. In the default and accept-edits permission modes this prompt appears every run, unless you choose "don't ask again" for a named workflow. Auto mode asks only on first launch. Bypass mode and claude -p never ask. The docs warn that a single run can use meaningfully more tokens than working through the same task in conversation. Then the fleet runs in the background, one agent per file, while your session stays free. /workflows opens a progress view: each phase with its agent count, token total, and elapsed time. You can drill into any agent, pause the run, or stop it. At the end you get one report, with its count on the first line, not twelve separate chats.

Three things the docs say that matter for the drawing. First, the keyword is an opt-in only in a prompt you type. It does not start a workflow from claude -p, a scheduled task, or a webhook. So a headless run, one with no person at the keyboard, starts a saved or bundled workflow by name. Its launch needs approval, typically by a Workflow(<name>) permission rule, which is Leaving the Laptop's problem. Second, there is no mid-run user input. Only permission prompts can pause a run, so every human gate goes between workflows, one run per stage. Third, an agent() call resolves to null if it is stopped or hits an unrecoverable error, and the generated script drops those with .filter(Boolean). That line is Concept 8's counting merge, and your spec's ON FAIL is what turns a silent filter into a named gap. The bundled /deep-research workflow shows the same discipline in production. It fans out searches, cross-checks sources, and votes on each claim. When a verifier cannot check a claim, the report lists it as unverified rather than counting it as disproved.

That is a graph: twelve agents from a single paragraph. When a run comes out well, save it. In /workflows, select the run and press s. It lands in .claude/workflows/ as a command you re-run by name, with args for the next question or path list. Commit that file next to the code it audits. The drawing is now a versioned artifact. Keeping it in the repo is what makes a rule like "change nothing without asking" a property of the system rather than a hope in a prompt. Two settings and three limits are worth knowing. The reference docs carry the real limits, not the announcement, so check the docs before you design against any of these numbers.

  • /effort ultracode makes Claude plan a workflow for every substantial task in the session, rather than waiting to be asked.
  • A size guideline in /config (unrestricted, small, medium, large) tells Claude how many agents to aim for, as advice rather than a cap. The default is medium, under fifteen agents.
  • Up to 16 concurrent agents, fewer on machines with limited CPU cores.
  • 1,000 agents total per run.
  • A Large workflow warning once a run schedules more than 25 agents or projects past 1.5 million tokens.

In OpenCode: the same diamond as a script​

OpenCode has no workflow trigger as of this writing, so you are the orchestrator, and the script is short enough to write by hand. It is longer than a sketch because it does what the course asks of every graph.

#!/usr/bin/env bash
# auth-audit.sh: the diamond, with the shell as orchestrator
# Works with OpenCode or Claude Code: RUN="opencode run" or RUN="claude -p"
set -uo pipefail # no -e: one failed worker must not kill the run. We count it instead.
RUN=${RUN:-"opencode run"}
CAP=${CAP:-12} # CAP: files on this first run
WIDTH=${WIDTH:-8} # at most this many workers at once (waves, not a stampede)
rm -rf out wt && git worktree prune && mkdir -p out/findings out/verdicts wt
mapfile -t FILES < <(ls src/routes/*.ts | head -"$CAP")

# NODE CONTRACTS: code checks the shape before a result counts as returned
worker_ok() { jq -e 'type=="object" and (.file|type=="string") and (.findings|type=="array")' "$1" >/dev/null 2>&1; }
verdict_ok() { jq -e 'type=="object" and (.verdict=="keep" or .verdict=="drop") and (.finding|type=="object")' "$1" >/dev/null 2>&1; }
throttle() { while [ "$(jobs -rp | wc -l)" -ge "$WIDTH" ]; do sleep 0.2; done; }

# FAN OUT: one worker per file, own worktree, own output slot, typed output
for f in "${FILES[@]}"; do
throttle
name=$(basename "$f" .ts)
(
out="$PWD/out/findings/$name"
if git worktree add -q "wt/$name" HEAD 2>/dev/null && cd "wt/$name"; then
$RUN "Audit $f for routes missing an auth check. Return ONLY JSON:
{\"file\":\"$f\",\"findings\":[{\"line\":0,\"route\":\"\",\"issue\":\"\"}]}" > "$out.tmp" 2>/dev/null
fi
if worker_ok "$out.tmp"; then
mv "$out.tmp" "$out.json" # returned: shape validated by code
else
echo "$f" >> "$(dirname "$out")/../failed.txt" # failed (no worktree, crash, or bad shape): named, never silent
fi
) &
done
wait # the parent waits for every worker

# REDUCE: code only. Count validated results, name the failures, flatten, dedupe.
DISPATCHED=${#FILES[@]}
RETURNED=$(ls out/findings/*.json 2>/dev/null | wc -l)
echo "dispatched $DISPATCHED, returned $RETURNED"
[ -s out/failed.txt ] && echo "did not return: $(paste -sd, out/failed.txt)"
if [ "$RETURNED" -gt 0 ]; then
jq -s '[.[] | .file as $f | .findings[] | . + {file: $f}] | unique_by(.file, .line)' out/findings/*.json > out/all.json
else
echo '[]' > out/all.json
fi

# VERIFY: one fresh skeptic per finding, each into its own file. The loop runs in
# the parent shell (process substitution, not a pipe), so `wait` sees every job.
i=0
while IFS= read -r finding; do
throttle
i=$((i+1))
(
$RUN "You are a skeptic. Finding: $finding
Open the file yourself and try to disprove it. Return ONLY JSON, echoing the finding back:
{\"finding\": $finding, \"verdict\":\"keep|drop\",\"why\":\"\",\"evidence\":\"file:line or command output\"}" \
> "out/verdicts/$i.tmp" 2>/dev/null
if verdict_ok "out/verdicts/$i.tmp"; then
mv "out/verdicts/$i.tmp" "out/verdicts/$i.json"
else
echo "$finding" >> out/unverified.jsonl # the checker failed: unverified, never refuted
fi
) &
done < <(jq -c '.[]' out/all.json)
wait

# SYNTHESIZE: survivors carry the finding itself, not just the verdict. Count first.
if ls out/verdicts/*.json >/dev/null 2>&1; then
jq -s '[.[] | select(.verdict=="keep") | .finding + {evidence: .evidence}]' out/verdicts/*.json > out/survivors.json
else
echo '[]' > out/survivors.json
fi
UNVERIFIED=$( [ -f out/unverified.jsonl ] && wc -l < out/unverified.jsonl || echo 0 )
$RUN "Write one report of routes missing auth, ranked by severity, from these verified findings only:
$(cat out/survivors.json)
First line, verbatim: 'dispatched $DISPATCHED, returned $RETURNED, unverified findings $UNVERIFIED'.
Change nothing in the repository." > out/report.md
echo "report: out/report.md"

The script does four things a sketch would skip, and each is a concept from earlier. worker_ok and verdict_ok are Concept 2's node contracts, enforced by jq -e before anything counts as returned. A worker that crashed, produced an empty file, or answered in prose lands in failed.txt by name. RETURNED counts validated results, not files, and the reduce line prints the gap. The verify loop reads from process substitution rather than a pipe. So the background skeptics are children of the parent shell, and the second wait really waits for them. Each skeptic writes its own file, so nothing appends to one path at once. A skeptic that fails is unverified, not drop, so the finding survives into the report's count as something no one checked. WIDTH is the concurrency cap, the shell's version of the sixteen-agent limit.

Same drawing, same four stages, same count in the first line. Claude Code wrote the equivalent script from the spec and ran it in-process. What neither tool does for you is decide which arrows were real, cap the width, or keep the verifier's context clean. Those were decisions you made on the whiteboard, and they are the entire course.

One run, before and after​

Before, the line. "Review route 1, then route 2, ..., then write the report." Twelve sequential reviews at ninety seconds each is eighteen minutes. Route 8 hangs, so routes 9 to 12 never happen, and the report is never written. The seven finished reviews sit in a context window nobody will read.

After, the diamond. Twelve reviews at once, ninety seconds. Reduce validates and counts eleven of twelve, and says so. Fourteen findings go to fourteen fresh skeptics, who open the files themselves, drop four as unsupported, and fail to check one. Nine survivors reach the synthesizer, and the report's first line reads "dispatched 12, returned 11, unverified findings 1: routes/billing.ts did not return." Three minutes, with one route and one finding flagged for a human. Same model. Same repo. Only the drawing changed.

Try it now: run one diamond (15 min)

In a repo you know, paste the Claude Code spec above with CAP: 5, or run CAP=5 ./auth-audit.sh. Watch three things. The plan Claude shows before running (or the dispatched 5 line), how many findings the skeptics drop, and whether the count in the report's first line matches. If the count matches and at least one finding was dropped, you have run a graph with a reduce, a clean-context verifier, and a counting merge. If no finding was dropped, make one up and run the verifier again. That failure is the lesson: the skeptic just showed you what it can and cannot catch.

Ready diamonds you can adapt

Every one of these is the same shape aimed at a different job. Swap the bracketed parts for your own. In Claude Code, start with ultracode: or "use a workflow to". In OpenCode, they are the stages of a script like the one above. Keep yourself as the last yes before anything ships, and put every human gate between workflows, because a run cannot pause for you in the middle.

Five specs

Decision-grade research desk. Split [your question] into five distinct angles, one researcher per angle, in parallel. Every finding needs a source link and a date. A skeptic attacks each finding and drops what fails. Merge the survivors into one report ranked by confidence, and save it to research-report.md. Human gate: change nothing after that without asking.

Content pipeline. Three parallel jobs: what the current top pages on [topic] cover, the real questions people ask, and what those pages skip. Merge into an outline, then one draft. A fact-checker flags every claim without a source. Save to drafts/, with the flagged claims listed at the top. Human gate: never publish.

Launch kit, as two workflows with a gate between them. Workflow A runs three parallel research jobs (the buyer's exact words, where those buyers spend time, how competitors pitch them). It merges them into a one-page positioning doc, saves it, and stops. Human gate: you read and edit the doc. Workflow B, run only after you approve, runs three parallel writing jobs from the doc (landing copy, a week of posts, outreach messages). A checker compares every asset against the doc. Save to launch-kit/. Dynamic workflows have no mid-run user input, and the docs recommend exactly this split when sign-off is needed between stages. That is the governance graph's gate placement rule, enforced by the runtime.

Repository refactor sweep. One agent per file in parallel, to find every function over 100 lines and propose a refactor. An independent fresh-context checker on each proposal. Remove duplicate proposals against everything already seen. Cap 50 files on the first run. Report how many files came back, so nothing fails silently.

Dynamic discovery loop. For jobs where you do not know how big the work is until you are in it. Run finders in parallel for [security issues / dead code / broken error handling]. Remove duplicates from each new find against everything seen. An independent checker on the survivors. Loop until two rounds in a row find nothing new. That is the stop rule Claude Code's own workflow examples use, and you can pick your own if your finders are noisier. A hard cap on total agents, so it cannot run away. The final list is ranked by severity. This is the diamond wrapped in the loop course's ratchet, and the cap is its frozen node.


Part 5: Staying Grounded​

10. Do you even need one?​

Here is the case against graphs. A graph buys breadth. It does not buy better judgment. It is a tool for width, for independent work done at once. When the work is not wide, the line was never the problem.

Skip the graph when:

  • the task is small or isolated, like adding one function or fixing one bug,
  • you want to approve every step,
  • you do not know yet what you are looking for, or
  • the steps really depend on each other in sequence.

The sign is the fake-edge test. If you cannot find two jobs with no edge between them, there is no graph to build. It is a loop, and a loop is fine.

Six questions, asked in order, decide how much structure a job needs. Each "no" saves a layer.

  1. Can success be verified? If not, do not begin with autonomy at all. Define a test, a rubric, or a human decision first.
  2. Are the steps stable? If yes, a chain is enough. If no, you need an orchestrator that draws the graph per task.
  3. Are the subtasks independent? If yes, fan out. If no, model the dependencies explicitly and limit how many workers may write at once.
  4. Is the work wider than one context can hold? If yes, reduce and layer the fan-in. If no, one worker and one verifier may be the whole graph.
  5. Must the results survive the run? If yes, persist them as typed records, as the Concept 7 note describes. Do not rely on the report to carry them.
  6. Can you afford the cost and the time? Set budgets before adding workers, not after the invoice.

Answered together, they produce a level rather than a preference:

Your situationStart withWhy
Simple, low-risk questionOne direct prompt (zero-shot)Fastest, no machinery to maintain
The output can be checkedA loopRepeated feedback improves the artifact
The sequence is stableA chainPredictable, testable stages
The categories are clearA routerSeparates policies and models cleanly
The units are independentA fan-outCuts total time
Findings need checkingThe diamondBreadth with a clean-context verifier
The decomposition varies per taskA dynamic workflowThe orchestrator draws the graph per run
Results must survive sessionsA memory graphPersistent, queryable, with sources

A staircase of eight levels from zero-shot to a memory graph, with the loop and chain steps marked as where most work stops

Figure 10. Climb only as far as the work forces you. Most work stops at the second or third step, correctly.

The diamond is the sixth row, not the first. Most work stops earlier, and that is a correct outcome, not a failure of ambition.

The evidence behind the table. The fake-edge test and the skip-when list match the one controlled study of the question. Researchers from Google Research, Google DeepMind, and MIT compared one single-agent architecture and four multi-agent ones across coding, finance, web-browsing, and planning benchmarks. They held tools, prompts, and compute fixed to isolate the effect of topology. The headline is the fake-edge test with numbers on it. Multi-agent coordination dramatically improved performance on tasks that split into independent, mergeable subtasks, with reported gains of up to about 80%. It degraded performance on sequential-reasoning tasks by 39 to 70%. The coordination overhead outgrows the task, and the messages between agents compress the reasoning a single context would have carried. The two task properties that predicted the right architecture were the density of sequential dependencies and the density of tool use. A predictive model built on them picked the best architecture for most unseen tasks. That is Part 1 in one finding. The graph wins where the arrows are fake and loses where they are real, and the way to know which you have is to count the real ones before you build. Treat the percentages as the paper's, from its benchmarks and its model families, and check the paper before quoting them.

Static or dynamic. The table hides one more decision, and it is where the most experienced builders of graphs have changed their minds. A static graph is drawn once and run many times: classify, search three sources, synthesize, every day. A dynamic graph is drawn per run, because the split is not known until the work starts. LangChain built its early deep research on predefined LangGraph workflows and then moved to a more agentic core loop, an agent harness in its own words. GPT Researcher made the same move. It swapped a graph-shaped multi-agent pipeline for a harness, so that planning, delegation, and context management emerge per task instead of being hard-coded. That is not a defeat for the diamond. It is the reason dynamic workflows exist: the orchestrator draws the diamond from the task, with the fan-out's width and the verify stage's shape decided at run time. The drawing you make on the whiteboard is then the constraints on that run, rather than every edge: the cap, the clean-context rule, the count, the gate. Question 2 in the list above is this decision. If the steps are stable, draw the graph once and keep it in the repo. If they are not, keep the constraints in the repo and let the run draw the rest.

Left: a fixed classify, search, synthesize graph kept in a repo. Right: a whiteboard of constraints and an orchestrator drawing an unknown number of workers at run time

Figure 11. Static or dynamic. The drawing you keep in the repo is either every edge, or the constraints the run must obey.

In simple terms

You do not hire a crew to change one lightbulb. You hire a crew when the job has ten lightbulbs in ten rooms. And before you hire, you check that the rooms are really different rooms. The picture stops being exact in one place. A crew costs about the same per person, and a fleet costs more per worker on the strong model.

Remember

A graph buys breadth, not judgment. If you cannot find two jobs with no edge between them, build a loop. Climb the ladder only as far as the work forces you.

Check yourself: A team wants a dynamic workflow for "fix the failing login test." What do the six questions give them?

Show answer

A loop. Success is verifiable (the test), the steps are stable (read, fix, run), and there is no width, because it is one test in one file. Question 3 is no and question 4 is no, so no fan-out and no diamond. There are not two jobs here with no edge between them. A workflow would spend the token multiple of Concept 11 to run one worker slowly.

11. The cost and the supervision​

A graph costs a lot more than a normal chat. The coordination is what gets cheaper, not the work itself. The agents still burn tokens, and a fleet of them burns a pile. Anthropic's own write-up of its multi-agent research system, a diamond in production, reports that it substantially outperformed a single agent on breadth-first work and consumed roughly fifteen times the tokens of an ordinary chat interaction. That is the trade: parallel breadth buys coverage and pays for it in tokens.

The clearest public example is the Bun port, and its two sources count different things. Anthropic's announcement describes Jarred Sumner moving Bun from Zig to Rust with dynamic workflows. It reports roughly 750,000 lines of Rust with 99.8% of the existing test suite passing, and eleven days from first commit to merge. At the time, the port was not yet in production. Sumner's own write-up, which Kopadze relays, counts the input instead: 535,496 lines of Zig, and about fifty dynamic workflows over those eleven days. About sixty-four agents ran at a time, four workflows side by side in separate worktrees with sixteen agents each. Two adversarial reviewers, whose job was to attack the work, checked every implementer. The cost was around $165,000 at API pricing, with Sumner watching the runs for the full eleven days. The port has since shipped inside Claude Code itself (v2.1.181 onward). There is real criticism over whether that much generated code can be reviewed safely. Treat each set of numbers as its author's, and check both before quoting either. The sixty-four is four times the per-workflow limit in the current docs, not a breach of it. The conclusion survives the disagreement: the heavy version is for teams with the budget, the caps, and the monitoring to run it. If that is not you yet, you are not missing anything. Start small, watch what a run costs, and go wider only once one run has earned it. The docs give the same advice: run the workflow on a small slice first, one directory instead of the repo. Watch per-agent token use in /workflows. A run scheduling more than 25 agents, or projecting past 1.5 million tokens, gets a Large workflow warning, which is advisory only. Choosing a /config size guideline replaces the 25-agent threshold with that guideline's count, and sessions with ultracode on skip the warning.

So declare the complexity budget before the run starts, in the prompt, the way Part 4's spec did. A complexity budget is the set of limits a run must obey, written down: maximum sub-agents, maximum concurrent workers, maximum tool calls, maximum elapsed time, maximum tokens, maximum financial cost, maximum retries, and the minimum evidence required before anything is called finished. That last item is the one people forget, and it is the one that makes the rest meaningful. When a budget runs out, the rule from Concept 8 applies: return the best current artifact, what completed, what did not, and why you stopped.

Put the model tiering beside the budget, because it is where most of the cost is won or lost. Cheap models for the wide, bounded nodes: extraction, classification, one-file reviews. Strong models for the judgment nodes: the skeptics, the synthesizer, hard verification. Short paths for simple requests, and the full diamond only for work whose value justifies the coordination. A hundred workers is the right answer when the task is truly wide, the branches truly independent, and the result worth the spend. It is the wrong answer whenever one context window could have held the whole problem.

In simple terms

A fleet is a payroll. Write down the headcount, the hours, and the budget before the first person clocks in, and decide in advance what "done" has to show. A crew that has never been told when to stop will stop when the money runs out, and describe that moment as success. The picture stops being exact in one place: a payroll is paid per hour, and a fleet is paid per token.

Remember

A fleet costs many times what a chat costs. Declare the budget in the prompt before the run, including the minimum evidence for "done". Cheap models on wide nodes, strong models on judgment nodes.

Check yourself: Which line of the complexity budget do people forget most often, and why does it matter?

Show answer

The minimum evidence required before anything is called finished. Without it, a run that stops when the money runs out can describe that moment as success.

12. What the graph cannot do, and where this goes next​

Three statements the graph cannot make for you.

"The verifier's keep is now trustworthy." No. A clean context upgraded the checker from self-review to review, and that is a large gain. But the checker is still a model. It can keep a wrong finding, drop a right one, and drift when the model beneath it updates. Measuring the verifier, with gold sets, calibration (whether its confidence matches its accuracy), pass rates, and drift, is the next course: Trusting the Checker. Its method is the ratchet, pointed at the checker itself. Read the verifier prompt and its score history. Propose one change. Run it against a gold set. Keep the change if the score improves, and revert it if not.

"The run's results are safe." Only as safe as where they went. A diamond's report is a file, and a file in a laptop repo dies with the laptop. Where survivors go for the long term is the memory note in Concept 7. Where the whole fleet goes when it must run without your machine, scheduled and headless on a runtime you do not watch, is the course after next. That is Leaving the Laptop.

"A better drawing means better judgment." This is the oldest boundary in this book, and it does not move. The graph buys width. It places checking outside the worker's context and merging outside the chat, which is why a hundred agents can work one problem in the time of one. But which arrows are real, what counts as evidence, where the human gate sits, and what "better" means come from outside every graph, from you. Intent and accountability, Concept 1 of the first course, remain the two things no arrangement of nodes and edges can contain.

Remember

The graph lets a fleet do in minutes what a line would do in hours, and lets a stranger check every finding. It cannot decide what the fleet is for, which findings are worth keeping, or what counts as proof. That is you.

Check yourself: Name the two things no graph can contain, and the course that measures whether the verifier is any good.

Show answer

Intent and accountability. Trusting the Checker, the next course, measures the verifier with gold sets, calibration, pass rates, and drift.

Where this book continues: describe a fleet with a verifier, a counting merge, and a human gate in plain words, and it becomes a team. Workers with separate desks, a fact-checker who has not seen the draft, an editor who counts the submissions, and an owner who signs off. That is the Human-Agent Teams crash course, what a well-drawn graph becomes on an org chart.


Using a graph on this book (dogfooding)​

Does this book practice what this course preaches? Dogfooding means using your own method on your own real work, so draw the book's pipeline and see.

The feedback loop from the loop course is a chain, and its edges are real. A reader note must exist before an issue is opened, and an issue before a pull request. A PR must exist before a human approves it, and approval before a lesson changes. All four arrows carry data, so that part of the book stays a line, correctly, and a person wants to approve the last step.

The width is elsewhere. When a change touches many lessons, the check that each lesson still reads correctly is one job per lesson with no edge between them: a fan-out. The verifier is a reviewer that receives one lesson and the change, with a fresh context and none of the author's chat. The merge counts: a review pass over forty lessons that reports thirty-nine has a lesson to name. And the anchor is the build. A lesson that does not compile is not "flagged as fine," whatever any reviewer said.

What the book does not run is the memory graph over its own content, which is Concept 10 applied to ourselves. The cross-session questions are still answered by the issue links and Git history, and a knowledge graph would add error surface without a query that demands it. The day a question arrives that the links cannot answer, the Concept 7 note is the plan on file.


🚀 Projects​

Here are eight builds, easy to hard. Do them in either tool. The drawing is the same, and only the trigger differs (ultracode: or "use a workflow" in Claude Code, a script around opencode run or claude -p otherwise).

Two rules before you start, every time:

  • Use a throwaway repo, and a real job. A fan-out over files you know is the only kind whose findings you can judge.
  • Draw the graph before you run it. Boxes, arrows, and the fake-edge test on paper, before a tool starts. A drawing that took five minutes beats one you reconstruct from a bill.
Project 110-15 minCut the fake edgesDraw the workflow you already run, and find the arrows that carry nothing.

Difficulty: easy. Uses Concepts 1 to 3.

Do. On paper or in Mermaid, draw one workflow you run today as boxes and arrows, in the order you run it. Then run both halves of the fake-edge test on every arrow. Does the next step read this result, and do the two steps write the same thing? Cross out every arrow that fails.

Done when you can name the real dependencies (usually three to five). State how many layers the redrawn graph has, against how many steps the line had. Almost nobody draws this and finds nothing.

Project 220-30 minWrite the contractsGive every box an in-tray and an out-tray, and find the one that only a human can read.

Difficulty: easy. Uses Concept 2.

Do. For every node in Project 1's drawing, write the four-line contract: JOB, IN, OUT, SCHEMA. Then validate one real output against its schema with jq -e.

Done when every node has a contract and at least one output was rejected by jq for not matching. The rejected one is the node that was forcing your steps into a line, because only a person could read its output.

Project 345-60 minYour first diamondFan out, reduce with jq, verify with a stranger, merge with a count.

Difficulty: medium. Uses Concepts 4 to 7 and Part 4.

Do. Run Part 4's auth audit, or the equivalent for your repo, over five files. Reduce with jq, not a model. Verify with a skeptic per finding that sees only the finding. Count at the merge.

Done when the report's first line says how many were dispatched and how many returned, and at least one finding was dropped by a verifier. Read the dropped findings afterwards. What the skeptic caught, and what it would not have, is the real output.

Project 430-45 minThe clean-context drillProve that a verifier which saw the work agrees with it, and one that did not does not.

Difficulty: medium. Uses Concept 6.

Do. Take five findings from Project 3, including one you invent. Run each through two verifiers: one given the worker's full transcript plus the finding, one given only the finding. Compare verdicts.

Done when you have a table of ten verdicts and can point at the invented finding's row. Most people find that the shared-context verifier kept it and the clean one dropped it. If both kept it, the next course measures what you found.

Project 530-45 minThe counting mergeKill a worker on purpose and make the report confess.

Difficulty: medium. Uses Concept 8.

Do. Re-run Project 3, but make one worker fail. Point it at a file that does not exist, or kill its process. Then read the report.

Done when the report names the missing file in its first line rather than describing N-1 files as N. If it did not, add the count to the merge and run again. That one if is the difference between a report you can trust and one you must re-check by hand.

Project 61-2 hrsLayered fan-inRun something wider than one context, and merge it without drowning.

Difficulty: hard. Uses Concepts 5 and 8.

Do. Pick a job with at least a hundred units: every function in a repo, every heading in a long document, every row of a CSV. Fan out, then merge in two layers: batch summaries of forty, then a synthesis over the summaries.

Done when the synthesizer's input is under a page, the batch count is reported, and the final answer cites which batch each finding came from. Then try the single-layer merge once, watch it fail, and keep the failure as the reason this project exists.

Project 71-2 hrsFollow the leavesWalk ten findings down to something no model wrote, and count.

Difficulty: hard. Uses Concept 9.

Do. Take a real report from Project 3 or 6. Pick ten findings at random and walk each one down: finding, verifier evidence, source. For each, write down whether the bottom is captured tool output, a human-written document, or a model's own prose.

Done when you have a number out of ten, and can name one finding whose only evidence was an agent's sentence about itself. Then fix that one. Make the verifier cite a command, an exit code, or a line, and run it again.

Project 8Capstone: a weekendThe research desk, savedA reusable diamond with a human gate, a budget, and a report you would sign.

Difficulty: capstone. Uses everything.

Do. Build the decision-grade research desk from Part 4's specs, on a question you actually need answered. Five angles fanned out on a cheap model, reduce in code, three-question skeptics on a strong model, a counting merge, a ranked report with sources, a human gate before anything is saved, and every budget line declared in the spec. Save it as a command you can re-run by name.

Done when you have re-run it on a second question without editing the spec, and the two reports each state their dispatched and returned counts. You can walk any line of either report to a source no model wrote. When that walk succeeds, this course has nothing further to teach you.


Appendix: where this came from​

None of this is required reading. It is for the reader who arrived from social media and wants to know how much of what they saw was real.

The timeline

The short version: the pattern is decades old, the name is two months old, and the viral versions of it are mostly right.

The timeline, and what the memes got right and wrong

On March 7, 2026, Andrej Karpathy released autoresearch. It is one agent locked in a small training repo, running one five-minute experiment at a time and keeping only what improves the metric. Fortune ran with "the Karpathy Loop" in a March 17 headline, crediting the phrase to analyst Janakiram MSV in The New Stack, and for a season the field talked about loops. On May 28, 2026, Anthropic announced Dynamic Workflows for Claude Code, since made generally available. Claude writes an orchestration script for the task and runs tens to hundreds of parallel sub-agents from it. The advertised demo was Jarred Sumner porting Bun from Zig to Rust in eleven days.

On July 18, 2026, Peter Steinberger posted twelve words after midnight: "Are we still talking loops or did we shift to graphs yet?" Within hours it was a slogan. Hamel Husain published "Loop Engineering Is Dead. Enter Graph Engineering," and Santiago Valdarrama posted "Loop engineering is dead. Long live graph engineering!" Both read as jokes about the industry's habit of renaming things, and engineers pushed back within hours that this was a decades-old idea, critical-path scheduling and dataflow, wearing a new name. On July 19, Perez's essay From Loop Engineering to Graph Engineering? gave the governance reading. Dale Everett's Loops are just shitty graphs gave the opposite one: the graph was always the real structure, and the single loop was the simplest special case. On July 20, Shann Holmberg supplied the one-line test this course adopts in Concept 2. Harrison Chase, who built LangGraph, replied in the same thread that he still did not know what graph engineering was, but that it was basically just LangGraph. On July 22, LangChain published 3 Years of Graph Engineering with LangGraph, the most useful of the framework responses, whose lessons are in Concepts 2, 8, and 10. On July 24, Anatoli Kopadze published the article this course is built on, Graph Engineering explained: what it is, when to use it and when not to. It became the guide most of the summer's viral posts link back to, including his own posts of talks by the head of Claude Code, Andrew Ng, and Jensen Huang.

August and September brought the second wave. Practitioner guides came from Adnan Masood (typed handoff contracts, hardcoded policy routers, human checkpoints, and an invoice-dispute system as the worked example) and from Aishwarya Srinivasan (the disambiguation, and a rule for when the graph earns its complexity). AI Builder Club kept a running guide with its catalog of the skeptics, and a stream of "company as a graph" products appeared. Underneath all of it sits one piece of actual evidence that predates the name: the Google Research, DeepMind, and MIT study Towards a Science of Scaling Agent Systems (December 2025), which Concept 10 uses.

Three corrections to carry. The "11-page PDF by two Anthropic seniors" that also circulated is an independent study note. Its own first page says it is not affiliated with or endorsed by Karpathy or Anthropic, and "1000x" is a slogan, not a measurement. Kopadze's cost and concurrency figures for the Bun port differ from Anthropic's announcement, so Concept 11 attributes them carefully. And the "free Google graph engineering course" being shared around is not a Google course. The course behind the chatter is DeepLearning.AI's Agentic Knowledge Graph Construction, made with Neo4j, whose agents are built on Google's ADK. One real convergence the memes missed: on May 19, 2026, Karpathy joined Anthropic's pretraining team. The loop tradition and the workflow tradition did meet. Just not in a PDF.

The pushback is the good news, and Kopadze says so himself: a pattern that has run critical systems for thirty years is exactly the one you want to trust with your work. (All sources listed in Sources & further reading.)

The six-step playbook, and where each step already lives​

Most readers arrive here through a viral six-step playbook. Three of its steps are behind you, this course is the middle two, and the last one is the deeper note.

The six steps, mapped onto this series
The step, as the post puts itWhat it actually isWhere you learned it
1. Build one loop: generate, critique, reviseThe maker-checker beat and the ratchetLoop Engineering
2. Add tools: search, code, databaseConnectors, and the tool schemas that fence themLoop and Harness Engineering
3. Go parallel: agents in separate worktreesFan out with isolationHarness Engineering, and Concept 4 of this course
4. Add a graph: typed nodes and edges, not transcriptsThe node contract, and the memory graphConcept 2, and the deeper note in Concept 7
5. Ground the evaluatorThe clean-context verifierConcept 6 of this course
6. The graph survives every sessionDurable memory with sourcesThe deeper note in Concept 7, and the Cookbook in the sources

So the honest version of "1000x" is not a benchmark. Steps 1 to 3 give you a capable worker, and steps 4 to 6 let a fleet of them finish in the time of the slowest one. Same model, different drawing.

The naming treadmill
One caution, in this book's own spirit

The industry renames the frontier about once a season. Prompt engineering, then context engineering, then harness engineering, then loop engineering, and now graph engineering, in three flavors at once. Each name is partly real and partly noise. The execution graph is critical-path scheduling and dataflow, decades old. Kopadze's reply to that pushback, quoted in the timeline note above, is the right one. What became newly visible in 2026 is that capable agents can run these graphs unattended, from a single line in a prompt, so the design question reached a much larger group of builders. The names change fast. The shape underneath grows slowly. Learn the shape, and the next rename costs you an afternoon, not a course.

Prior art, frameworks, and the skeptics
What already existed, who said so, and why this course still does not teach a framework

The strongest objection came from the people best placed to make it. Harrison Chase's LangGraph has built agents as graphs of nodes, edges, and shared state for three years, and it is downloaded tens of millions of times a month. He said he still did not know what graph engineering was, but that it was basically just LangGraph. David Khourshid, who builds state-machine tooling, pointed out that a loop is a directed cyclic graph, and that directed graphs of states and transitions are decades-old computer science. Rhys Sullivan predicted the ten-thousand-word slop article (slop means low-quality filler text) before it was written. Nathan Flurry noted that none of the posts mentioned A2A, the agent-to-agent protocol whose enterprise history predates the term. Paweł Huryn called the whole history confusing, and argued that the naming keeps mistaking the mechanism, loops and graphs, for the substance, objectives and verification. Concede all of it. It is true.

The prior art, at the level the official docs support. LangGraph is a StateGraph of nodes and edges over shared state, with Send for dynamic fan-out. Google ADK ships sequential, parallel, and loop workflow agents as named building blocks, and has an A2A section. Microsoft Agent Framework is AutoGen's successor now that AutoGen is in maintenance mode, and its Workflow abstraction descends from AutoGen's experimental GraphFlow. A2A itself is the edges between graphs owned by different teams. If you are building a static graph that will run for months, use one of these rather than writing your own runtime, which is its own kind of slop.

Other writers use other words for the same territory. The site explainx.ai calls the execution graph the "work graph" and the governance graph the "org graph". LangChain's "cognitive architecture" is the execution graph with the fixed, non-model steps drawn in. The many warnings that graph engineering "is not knowledge graphs or GraphRAG" draw the same line as the "three meanings" note at the top of this course, between the execution graph and the memory graph.

Why this course still teaches the drawing and not a framework. Every one of those tools asks you the same three questions before it can run: what are the nodes, what are the edges, what is in the state. None of them answers those questions for you. The fake-edge test, the clean-context rule, the counting merge, and the anchors are the answers, and they are identical in LangGraph, ADK, a dynamic workflow, and a bash script. LangChain's own summary of what it learned is this course's thesis in one sentence: put model reasoning in the right places, with the right context, at each step. What the frameworks add is a runtime for the static case. What the skeptics add is the reminder that the word is optional. The step up from one loop to a coordinated set of nodes when the work is wide is real either way, and so is the mistake of reaching for it when the work is not.


Sources & further reading​

Inside this book

  • Loop Engineering: the beat, the spine, the maker-checker split, and the ratchet. Every node in this course is a loop from there.
  • Harness Engineering: typed output and worktree isolation, promoted here to every node and every worker.
  • Trusting the Checker: the next course. How to know the clean-context verifier is any good.
  • Leaving the Laptop: where the fleet goes to live when the laptop closes.
  • Human-Agent Teams: what a drawn graph becomes on an org chart.

Primary sources

  • Yubin Kim et al., Towards a Science of Scaling Agent Systems (Google Research, Google DeepMind, MIT, arXiv 2512.08296, December 2025). At https://arxiv.org/abs/2512.08296, with the lab write-up at research.google. The controlled evaluation behind Concept 10. Coordination helps on parallelizable tasks and hurts on sequential ones, with sequential-dependency density and tool density as the predictors. Check the percentages against the paper.
  • Sydney Runkle and Harrison Chase, 3 Years of Graph Engineering with LangGraph (LangChain blog, July 22, 2026). At https://www.langchain.com/blog/3-years-of-graph-engineering-with-langgraph. The source for the node scale in Concept 2, the "graphs are usually not DAGs" and dynamic-edge lessons in the Concept 8 note, and the deep-research move from a fixed graph to a harness in Concept 10.
  • Shann Holmberg, post of July 20, 2026 ("the difference is who decides the path, the agent or you"). At x.com/shannholmberg/status/2079096565344739643. Harrison Chase's reply in the same thread is at x.com/hwchase17/status/2079219804951683380. Dale Everett, Loops are just shitty graphs (July 19, 2026), is at x.com/daleverett/article/2078969402046009374.
  • AI Builder Club, Graph Engineering Guide (2026) (July 20, updated August 28, 2026). At https://www.aibuilderclub.com/blog/graph-engineering-guide-2026. The best-maintained running account of the discussion: the five-layer stack, the decision table, the framework prior art (LangGraph, ADK, Microsoft Agent Framework, A2A), and the catalog of skeptics quoted in the appendix.
  • Adnan Masood, Graph Engineering for AI Agents: The Practitioner's Guide to Designing Multi-Agent Systems as Governed Topologies (Medium, August 4, 2026). At https://medium.com/@adnanmasood/graph-engineering-for-ai-agents-the-practitioners-guide-to-designing-multi-agent-systems-as-f9a4559aa693. Typed handoff contracts, hardcoded policy routers, deterministic and human-checkpoint nodes, and governance as a property of structure, worked through an invoice-dispute case.
  • Aishwarya Srinivasan, Graph Engineering Explained (Substack, late August 2026). At https://aishwaryasrinivasan.substack.com/p/graph-engineering-explained. The clearest separation of the execution meaning from the knowledge-graph meaning, plus a rule for when the graph earns its complexity.
  • Yash Thakker (explainx.ai), Graph Engineering: After Loops, This Is How You Wire Multi-Agent Orgs (2026) (July 18, 2026, updated through September 5, 2026). At https://explainx.ai/blog/graph-engineering-ai-agents-multi-agent-organizations-2026. The "org graph" and "work graph" vocabulary, and a log of the company-as-graph products shipping on top of Claude Code.
  • Google, Agent Development Kit docs. At https://adk.dev/, for the sequential, parallel, and loop workflow agents named in the appendix. LangGraph docs are at https://docs.langchain.com/oss/python/langgraph/overview.
  • Anatoli Kopadze, Graph Engineering explained: what it is, when to use it and when not to (X article, July 24, 2026). At https://x.com/AnatoliKopadze/status/2080668775796314331. The source for Parts 1 to 3: the node contract, the fake-edge test, the diamond with a verifier node on the edge, the three-question verifier, the three traps and their fixes, the anchors, the skip-when list, the specs Part 4 adapts, and the Bun figures he relays in Concept 11. The most widely shared popular treatment of the execution graph.
  • Anthropic, Introducing dynamic workflows in Claude Code (May 28, 2026, and the page now notes general availability). At https://claude.com/blog/introducing-dynamic-workflows-in-claude-code. Generated orchestration, tens to hundreds of parallel sub-agents, results checked before they are folded in, resumable progress, and the Bun port as Anthropic reports it. The reference docs, not the announcement, are the source for Part 4: the ultracode keyword and "use a workflow" opt-in, the keyword not firing from claude -p or scheduled prompts, no mid-run user input, agent() resolving to null on failure, the /deep-research workflow and its unverified-not-disproved rule, saving via /workflows, size guidelines, the Large workflow warning, and the limits of 16 concurrent agents and 1,000 per run. Reference docs: code.claude.com/docs/en/workflows.
  • Jarred Sumner, Bun in Rust (bun.com blog, July 8, 2026). At https://bun.com/blog/bun-in-rust. The port's own numbers as Concept 11 gives them (lines of Zig in, workflows, agents at a time, reviewers per implementer, cost at API pricing), and the note that Claude Code ships on the Rust port from v2.1.181.
  • Anthropic, How we built our multi-agent research system (Anthropic Engineering, 2025). At https://www.anthropic.com/engineering/multi-agent-research-system. The orchestrator-worker architecture that Part 2 calls the diamond in production, its breadth-first advantage, and the roughly fifteen-times token cost Concept 11 cites. The multiple is against ordinary chat interactions, not against a single-agent run of the same task.
  • Erik Schluntz and Barry Zhang, Building Effective Agents (Anthropic Engineering, December 19, 2024). At https://www.anthropic.com/engineering/building-effective-agents. The composable workflow patterns, of which the diamond is parallelization plus evaluator-optimizer, composed.
  • Peter Steinberger, post of July 18, 2026 ("Are we still talking loops or did we shift to graphs yet?"), on X at x.com/steipete/status/2078277297791189132. The twelve words that named the season. The "loop engineering is dead" posts were written by others: Hamel Husain's article and Santiago Valdarrama's post, both jokes about the industry's habit of renaming things.
  • Carlos E. Perez (Intuition Machine), From Loop Engineering to Graph Engineering? (July 19, 2026). At https://medium.com/intuitionmachine/from-loop-engineering-to-graph-engineering-d3ebeb08511c. The source of the governance note in Concept 9: the support-bot story, the four failures, the circular-graph warning, anchors and frozen nodes.
  • Andrej Karpathy, autoresearch (March 7, 2026). At https://github.com/karpathy/autoresearch. Also AgentHub (published around March 9-10, 2026, and no longer public). Both are the sources of the memory note's commit-DAG half. For AgentHub's removal, see this contemporaneous write-up.
  • Anthropic, Knowledge Graph Construction with Claude (Cookbook, March 23, 2026). At https://platform.claude.com/cookbook/capabilities-knowledge-graph-guide. The source of the memory note's knowledge-graph half.
  • Graph Engineering: The Karpathy Loop, Improved 1000x by Itself (independent synthesis PDF, July 2026). By its own front page, not affiliated with or endorsed by Karpathy or Anthropic. A useful study note. Read its primary sources first.
  • TechCrunch, on Karpathy joining Anthropic's pretraining team, May 19, 2026. At https://techcrunch.com/2026/05/19/openai-co-founder-andrej-karpathy-joins-anthropics-pre-training-team/

All links current as of early September 2026. Every feature, limit, and cost figure here moves fast, so confirm against the live source before you rely on it.


The one-line summary​

The model was never the bottleneck, the line you drew was. Draw the run as nodes with contracts and edges that carry data, and cut every arrow that carries none. Run what is left as a diamond. Fan out in separate rooms on the cheapest model that matches the gold set, reduce with code where you can, verify with a skeptic who has not seen the work, and synthesize from survivors with the count on the first line. Cap the width, declare the budget, keep a human as the last yes, and anchor the whole thing in something no model wrote. A graph buys breadth, not judgment. Knowing when the work is wide enough to need one, and when a loop was the answer all along, is the skill that outlives every rename.

Flashcards Study Aid​


Test Your Understanding​

Checking access...