All posts
Architecture Published Updated 22 min

Graph engineering with Claude Code: the 14-step roadmap I use when linear agents stall

A straight-line agent is a degenerate graph. Claude Code dynamic workflows move orchestration into JavaScript so subagents fan out, verify, and converge without stuffing every intermediate result into one context window. Here is the 14-step roadmap I map onto production work, with topology diagrams, contracts, and the patterns I already ship.

Jigar JoshiJigar JoshiAgentic AI Architect and Consultant
In this post (8 sections)

Introduction

On July 20, 2026 a graph engineering roadmap blew up on X for a reason that has nothing to do with vibes. Teams finally have language for what they feel when a lone Claude session collapses mid-migration: the work has a shape, and a single context window is the wrong container for that shape.

I have been drawing the same boxes on whiteboards for months. Sequential vs parallel. Maker vs verifier. Diamond topologies for research and audits. The one-page visual is now a graph engineering with Claude note (vertical workflow, side-by-side steps, four phases). Claude Code's dynamic workflows are the first product surface that makes those drawings runnable without hand-rolling a custom orchestrator. This post is the long-form behind that map.

v2.1.154+
Claude Code minimum for dynamic workflows
Dozens–100s
Agents per workflow run (script holds the loop)
Zero
Model tokens spent on coordination (code, not chat)
14
Steps from linear script to self-routing graph

What "graph engineering" means here

Not Neo4j. Not knowledge graphs for RAG (different job; see agentic RAG when retrieval is the bottleneck). Graph engineering here means: model the agentic workflow as nodes (jobs) and edges (data dependencies), then execute that topology with a script Claude writes and you can rerun.

Per Anthropic's docs, workflows differ from subagents and agent teams because the script holds the loop, branching, and intermediate results. Claude's context keeps the final answer. That is the unlock for dozens to hundreds of agents per run without drowning the session.

Where the plan lives (orchestration stack)
Your objectiveMigration, audit, research question, architecture choiceWorkflow script (JavaScript)Loops, barriers, branching, intermediate variables. Zero model tokensSubagent fleetEach node = one agent() with its own context and schemaTools / MCP / worktreesRead, write, search, scoped per node, not shared blindlySession answerOnly the final synthesis returns to Claude's chat context
Subagents vs skills vs agent teams vs workflows
DimensionSubagents / skillsAgent teamsDynamic workflows
Who decides next stepClaude, turn by turnLead agent, turn by turnThe script
Where intermediates liveContext windowShared task listScript variables
What is repeatableWorker / prompt definitionTeam definitionThe orchestration itself
ScaleA few tasks per turnA handful of peersDozens to hundreds per run
Best forDelegated slicesLong-running peersAudits, migrations, cross-checked research

The straight-line trap (why this matters)

Degenerate graph: the straight line
Aread filesBcheck weatherCsummarizeDdraft PR

Nine out of ten multi-step agents I audit are polite queues. Step one finishes. Step two starts. Step three waits.

Half those waits never needed to happen because no data crossed the boundary. B does not consume A. The weather node has no edge to anything. You still pay for the wait in a linear script.

Redrawn: independence becomes fan-out
A + Bparallel readsReduceJS flattenCsummarizeDdraft PR

Cut arrows that carry no data. Independent nodes run together. C only needs A. D needs C. Fake edges disappear and wall-clock time drops without changing the models.

Smell test for every "and then": does the next step read the previous step's output? If no, there is no edge.

The 14-step roadmap

I group the fourteen steps into four stages: vocabulary, the diamond, resilience, and economics. Skip stage one and every later diagram is theater.

Stage A: Steps 1–4: vocabulary and contracts

  1. 01
    1. Nodes are jobs. Edges are what flows
    A node is one bounded job with input in and output out. An edge exists only when data actually moves. Draw boxes and arrows on a whiteboard before you write a prompt. If you cannot draw the arrow, the two boxes are independent.
  2. 02
    2. Your linear script is a degenerate graph
    A→B→C→D is valid and slow. Redraw: cut arrows that carry no data. Independence is what you exploit for fan-out. Same decision rule as sequential vs parallel workflow.
  3. 03
    3. Give every node a contract
    Bounded input, bounded output, one job. Prefer JSON Schema on agent() returns so the next node consumes validated shapes. Validation at the tool-call layer beats "parse free text and pray."
  4. 04
    4. Treat the edge as a data contract
    Flatten, dedupe, and filter in plain JavaScript when you can. An agent that only merges arrays is rent on wiring. Save model tokens for judgment.
// Node with a real contract: bounded in, validated out, one job.
const ITEM = {
  type: 'object',
  additionalProperties: false,
  properties: {
    title:  { type: 'string' },
    url:    { type: 'string' },
    impact: { type: 'string', enum: ['high', 'medium', 'low'] },
  },
  required: ['title', 'url', 'impact'],
};

const result = await agent(source.prompt, {
  label: `research:${source.key}`,
  schema: ITEM,              // forces structured output
  agentType: 'general-purpose',
});
// result is a shape the next node can trust, not free text.

Stage B: Steps 5–7: the diamond that pays rent

Put fan-out and fan-in together and you get the workhorse topology of every serious agent graph: the diamond. One node splits, many nodes work, one node merges.

Diamond topology: fan out → reduce → synthesize
Splitscope jobFan-outN agentsReduceJS / SetSynthesizeone agent

The workhorse of serious agent graphs. One node splits the job, many nodes work in parallel, one node merges.

Canonical form: fan out → reduce in plain JavaScript → synthesize with one agent. Market scans, dependency audits, and research reports share this skeleton.

  1. 01
    5. Fan out with parallel()
    N independent sources or files become N concurrent subagents. parallel() is a barrier: it waits for the set. Failed thunks should resolve to null so one flaky agent does not sink the batch. Always .filter(Boolean) before the next stage. Excess work queues when concurrency hits core limits; pass a hundred thunks and they still finish.
  2. 02
    6. Fan in at a barrier
    Use a barrier only when a stage needs the whole set together (cross-source dedupe, ranking, early-exit on empty). If the middle transform has no cross-item dependency, you wanted a pipeline, not a sync point.
  3. 03
    7. The diamond: split → work → merge
    Canonical form: fan out → reduce in code → synthesize with one agent. Market scans, dependency audits, and research reports are the same skeleton with different prompts. Once you see the diamond, you stop asking "how do I add more steps" and start asking "where is the split, where is the merge."
phase('Research');

// Nine sources, nine agents, all at once.
const raw = await parallel(
  SOURCES.map((s) => () =>
    agent(s.prompt, {
      label: `research:${s.key}`,
      phase: 'Research',
      schema: ITEM_SCHEMA,
      agentType: 'general-purpose',
    }),
  ),
);

const collected = raw.filter(Boolean); // drop nulls from failed agents

// Edge: plain JS, zero tokens
const flat = collected.flatMap((c) => c.items);

phase('Curate');
const curated = await agent(
  `Dedupe and rank these by impact:\n${JSON.stringify(flat)}`,
  { phase: 'Curate', schema: CURATED_SCHEMA },
);
Barrier vs pipeline (the decision that burns latency)
QuestionPrefer barrier (parallel stage)Prefer pipeline
Does the next stage need every prior result together?Yes (dedupe across sources, compare findings)No (each item transforms independently)
Can fast items finish while slow ones continue?No until the barrier clearsYes
Is "cleaner looking stages" your reason?Not enoughDefault here
ExampleCurate/rank all research hitsPer-file migrate → test → commit
Cost riskIdle agents waiting on the slowest peerHarder to reason about global invariants

Stage C: Steps 8–11: routing, verification, failure, cycles

Runtime router: classify once, branch in code
Classifyseverityif highfull auditif lowquick passMergereport

Classify with an agent when you need judgment. Pick the downstream path in code (if / switch on validated output).

Claude decides at the node. The script owns the edge. No emergent "Claude skipped the audit" surprises, because the skip would have to be written into the graph.

  1. 01
    8. Route the edge at runtime
    Classify with an agent if you need judgment. Pick the downstream path in code (if/switch on validated output). You want Claude at the node and deterministic routing at the edge. No emergent "Claude decided to skip the audit" surprises, because the skip would have to be written into the graph.
  2. 02
    9. Put a verifier on the edge
    Maker ≠ verifier. Same golden rule as independent verifier loops. Three patterns: adversarial refute (N skeptics; keep only survivors), perspective-diverse lenses (correctness / security / repro), judge panels that score competing drafts and graft winners.
  3. 03
    10. Isolate nodes so one failure cannot poison the graph
    Tolerate missing inputs at fan-in. When agents write in parallel, isolate with git worktrees or sandboxes. Containment is a topology property, not a prompt. A thunk that throws inside parallel() should become null, not a full abort.
  4. 04
    11. Add a cycle only if it converges
    Loop-until-dry for unknown-size discovery. Stop after K empty rounds. Dedupe against everything seen, not only confirmed results, or rejected findings reappear forever and your budget dies rediscovering dead ends.
Verifier on the edge (maker ≠ verifier)
Makerfind / draftVerifierrefute / scoreGatepass or dropDownstreamonly survivors

Maker finds or drafts. Verifier tries to kill the finding. Only survivors continue downstream.

Patterns that work: adversarial refute, perspective-diverse lenses (correctness / security / repro), and judge panels that score competing drafts. Same golden rule as independent verifier loops.

// Router: agent classifies, code picks the edge.
const { severity } = await agent(
  `Classify this diff's risk:\n${diff}`,
  {
    schema: {
      type: 'object',
      properties: { severity: { enum: ['low', 'high'] } },
      required: ['severity'],
    },
  },
);

let review;
if (severity === 'high') {
  review = await parallel(FILES.map((f) => () => agent(`Audit ${f}`)));
} else {
  review = await agent(`Quick review of ${diff}`);
}

Stage D: Steps 12–14: cost, topology, self-routing

Model tiering across nodes
Merge / adjudicate (expensive)Sonnet 5, Fable, or Opus. Judgment lives hereVerify lenses (mid)Independent graders; can be smaller models with strict schemasFan-out extract / classify (cheap)Flash-Lite / Haiku-class for high volume, bounded jobs
  1. 01
    12. Tier models across nodes
    Fan-out extract/classify on cheaper models. Keep merge and adjudication on Sonnet 5 / Fable / Opus as your evals justify. Every subagent inherits the session model unless you override per agent() call. Check /model before a large run. Same discipline as Gemini Flash routing and stop paying frontier prices for classification.
  2. 02
    13. Topology is your cost and latency
    Shape beats prompt polish. Wrong barriers idle expensive agents. Wrong cycles never dry. Measure cost per completed task in the unified spend dashboard, not tokens alone.
  3. 03
    14. Let Claude draw the graph
    Three doors in: (1) ask for a workflow in the prompt (or say ultracode), (2) run /deep-research for the bundled research diamond, (3) set /effort ultracode so every substantive task plans a workflow. When a run is good, press s to save the script into .claude/workflows/ as version-controlled and re-runnable by name.

How I run this on an engagement

I do not flip ultracode on day one. I force the team to draw edges on a whiteboard, pick one diamond, and prove schemas before we scale concurrency.

  1. 01
    Day 1: dependency drawing
    If the team cannot agree on edges, they are not ready for parallel(). No script until the arrows are named.
  2. 02
    Day 2–3: one diamond in staging
    Research or audit only. Schemas on every node output. Barrier only where cross-set logic exists.
  3. 03
    Day 4: autonomy and spend caps
    Wire Auto-review and pre-push /review around write nodes (governing agent autonomy). Set WebSearch and subagent session caps before ultracode.
  4. 04
    Day 5: save and promote
    Save the working script. Add model tier overrides. Only then expand to a second graph shape.
  • Keep MCP tools on fan-out nodes scoped read-first. Live connectors plus public artifacts (Week 29) multiply risk if write tools sit on shared pages.
  • Log phase, agent count, token total, and elapsed time per stage. Without that, you cannot tell whether a barrier is earning its wall-clock cost.
  • Treat saved workflows like production code: review PRs that change .claude/workflows/ the same way you review CI.

Six starter graphs worth building this week

Starter topologies mapped to real jobs
GraphShapeWhen I reach for itFirst success metric
/deep-research styleFan-out search → fetch → adversarial verify → synthesizeClaims that need sources, not vibes% of claims that survive verify
Codebase auditFan-out files → diverse-lens verify → merge findingsBug sweeps where false positives kill trustFalse-positive rate after gate
MigrationDiscover sites → parallel transform → verify → reportLarge refactors with measurable done criteriaFiles migrated / files remaining
PanelN design drafts → judge panel → graft winnersArchitecture choices with wide solution spaceJudge agreement + human pick rate
MapParallel area understand → reduce → briefOnboarding a new repo regionTime to usable brief
Loop-until-dryFind → verify → repeat until K empty roundsUnknown bug/issue cardinalityRounds to dry + unique confirmed

Common mistakes

  • Calling every edge an agent. Plumbing is free in JavaScript. Judgment is not.
  • Barriers for aesthetics. Measure idle time behind the slowest peer.
  • Skipping schemas on node outputs. Unstructured free text cannot be a reliable edge.
  • Self-grading makers. If the same agent finds and verifies, you rebuilt the straight line with extra steps.
  • Turning on ultracode before spend caps and session WebSearch/subagent caps are set.
  • Using worktrees on every node "just in case." Isolation is a seatbelt for parallel writers, not a default tax.

Conclusion

The viral roadmap is right about the diagnosis: linear agents pretend work is a queue. Production work is a graph. Claude Code workflows give you a place to put that graph that is not another overloaded chat turn. Draw the edges, contract the nodes, verify on the path, tier the models. Then let Claude write the script you would have written anyway, and save it when it works.

Sources: Claude Code dynamic workflows docs at Claude blog; public discourse on the 14-step graph engineering roadmap (Jul 20, 2026) at x.com — 2079165300625330317.

The weekly take

Agentic AI patterns, delivered Thursdays

What I am shipping, watching, and pruning out of client stacks each week. One email. No fluff.

Shipping an agentic AI project this quarter?
Book a 30-min consult
Frequently asked

Questions readers ask about this post

Share this post
LinkedIn Facebook