Agentic Engineering / Rung 5
Graph Engineering
Many agents as a dependency graph. Nodes are work. Edges are what has to finish first. The artifact stops being an answer and becomes a project.
Where The Ladder Stops Being About One Agent
A loop improves one artifact. A graph moves a project.
Every rung below this one answers a question about a single worker. Prompt engineering writes the instruction. Context engineering decides what the agent knows. Harness engineering picks which agent, model, tools and permissions run the job. Loop engineering turns one turn into an act, observe, correct cycle that stops on its own. This page assumes all four.
Graph engineering is what comes next, once you have several trustworthy workers and a job bigger than any one of them can hold. The shift is sharp and most people feel it as a loss first: you stop writing prompts and start designing the relationships between work. Each node’s prompt gets shorter. The interesting decisions move into the shape.
Two words carry the model. A node is one unit of work with an owner, a defined input, a defined output and a condition that says when it is done. An edge is a dependency: B may not start until A produced what B needs. Draw enough of both and you have a graph. If no chain of edges leads back to where it started, the jargon for that shape is a directed acyclic graph, or DAG. You do not need the word to use the idea, only to read the tools that already solved this.
Real Projects Are Not Lines
Watch work arrive on a real change and you see four shapes.
One task unlocks another. The schema decision lands before the migration is written, and the migration runs before the backfill means anything. A chain is the only shape a linear script gets right.
Some investigations are independent. Three scouts reading three subsystems never need to talk. Running them in sequence does not make the answers better, it makes them later. Anthropic reported cutting research time by up to ninety percent on complex queries by moving that breadth-first work into parallel subagents.
Some outputs need a second pair of eyes. A build nobody independent has looked at is a proposal, not a result. Review is a node with inputs and a verdict.
Some failures must route backwards. A rejected build goes back to a builder, not forward to delivery. A pipeline that only moves forward turns every rejection into a stall or a shipped defect.
None of this is new. Stuart Feldman built Make at Bell Labs in April 1976 because a colleague fixed a bug in a file that never got recompiled. His answer was to stop describing a sequence of commands and start describing targets and dependencies, then derive the order from that. Everything since refines the same move, from Bazel and Gradle to Airflow, Argo, Dagster and Temporal: walk the graph in topological order, start each task the moment its own inputs are ready. The LLM part is new. The scheduling part is fifty years old, and that literature is better than most of what has been written about agents.
A Graph Written Down
One hardware family, re-rendered across a site, split across scouts, builders, a reviewer and a human. The file is the design.
$ cat missions/s21-hub.graph.yaml
exit_conditions:
- schema validator reports 0 errors on 12 sample URLs
- reviewer verdict is accept
- human co-sign recorded
nodes:
scout-templates:
role: scout
model: local/qwen3-coder
task: list every template that renders an S21 spec block
scout-schema:
role: scout
model: local/qwen3-coder
task: map the schema emitters that touch S21 SKUs
build-renderer:
role: builder
needs: [scout-templates, scout-schema]
claims: [inc/miner-data.php, inc/schema-markup.php]
worktree: true
build-tests:
role: builder
needs: [scout-schema]
claims: [tests/schema/]
worktree: true
review-render:
role: reviewer
needs: [build-renderer]
context: fresh
may_reject: true
on_reject: build-renderer
max_rounds: 3
gate-human:
role: approval
needs: [review-render, build-tests]
integrate:
role: delivery
needs: [gate-human]
join: all_success
Read it as sentences. The scouts have no needs, so they start together. build-tests needs only the schema map, so it starts when that scout returns instead of waiting for a sibling it does not depend on. The reviewer gets fresh context, may say no, and its rejection points at one node rather than the whole run. The human is an actual node between review and integration. The exit conditions sit at the top, written before the run.
Fan-Out Is Easy. The Join Is Where It Goes Wrong.
Fan-out is one node producing many. Six files, six readers. That is the half every framework demos. The join is where the branches come back, and the default nearly everywhere is a barrier: nothing past the line starts until everything before it has finished.
Barriers are old and well understood. Valiant’s bulk synchronous parallel model formalised them in 1990, Google’s Pregel built large-scale graph processing on supersteps separated by them, and LangGraph’s execution model is explicitly Pregel-inspired, advancing one super-step at a time with parallel nodes inside each step. The payoff is real: a barrier makes state merging deterministic.
The cost is the straggler, and it is worse with agents than with threads because agent runtimes vary wildly. One node reads four files in twenty seconds. Its sibling hits an unexpected dependency and takes eleven minutes. A barrier charges you eleven minutes for both, and three barriers charge you three times.
Use a barrier when the next node genuinely reads every upstream output: synthesis, ranking, deduplication, merge. Use a plain dependency edge everywhere else, because most nodes need two upstreams and not twelve. Airflow has carried this distinction for years as trigger rules, and the vocabulary transfers straight across.
| Join rule | Releases the next node when | Right when |
|---|---|---|
| Barrier | Every branch in the fan-out has finished | The next node truly reads all outputs: synthesis, merge, ranked summary |
| Plain dependency edge | That node's own named inputs are ready | Your default. Most nodes depend on two upstreams, not the whole layer |
| All success | Every upstream finished without failing | Integration and delivery that must never run on a broken branch |
| All done | Every upstream finished, pass or fail | Cleanup, teardown, cost accounting, run reports |
| Any failure | At least one upstream failed | Escalation, rollback and alert paths |
| Quorum | N of M independent nodes agree | Cross-checked research where any single reader can be wrong |
Pipelines Beat Phases
When the same work happens to many items there are two shapes and only one is good. Phases: audit all four hundred files, then fix all four hundred, then verify all four hundred. Three barriers, three stragglers, nothing finished until the end, nothing shippable if the run dies at eighty percent.
A pipeline sends each item through audit, fix and verify on its own. File 1 is done while file 399 is still being read, and one file that cannot be fixed does not hold the other 399. Claude Code’s dynamic workflows expose exactly this, with agent() spawning one worker and pipeline() running one per item.
Small nodes buy something less obvious. In that runtime a resumed run replays in start order: cached results stop at the first agent that did not finish, and every agent that started after it runs again even if it completed. The documented conclusion is that many small agents preserve more progress than a few long ones. Node size is your unit of recovery.
Routing, Retry, Escalation
An edge does not have to be unconditional. A conditional edge carries a question, evaluated against the state the graph has accumulated, and LangGraph implements it as routing functions that inspect state and name the next node. The value is that the failure path lives inside the model. If retrieval returns nothing, widen the search. If that returns nothing, escalate to a human. As edges those are visible and reusable. As improvisation inside one agent’s turn they are invisible and different every run.
Retry
Same node, different input. The failure and what was already tried get appended before it runs again. A retry that changes nothing is a coin flip and keeps landing on the same face. Cap the rounds in the graph file, not in the prompt.
Escalate
Different node. A stronger model, a wider tool set, a specialist role, or a human. Escalation stops a bounded retry from becoming a dead end. It has to change something structural, not ask again more loudly.
Abandon
Mark the branch failed and let the graph continue. This must be a declared outcome, or every unsolvable node becomes an infinite retry and the run ends when someone gets tired rather than when the work is done.
Termination inside one node belongs to loop engineering. What belongs here is the budget across nodes, because a graph can be well behaved at every node and still run forever if rejections bounce between a builder and a reviewer.
Two Agents, One File
The fastest way to lose a day to multi-agent work is letting two agents edit the same file. It does not announce itself. One rewrites a function, the other read the version from before that write, and you get a diff neither intended.
Use both defences. The logical one is a claim: before a node starts it takes an exclusive lease on the paths it intends to touch, and a node that cannot get its claim waits or fails. The physical one is a worktree: each builder gets its own checkout over the same repository, so simultaneous writes are not addressing the same bytes. Claude Code ships both, and is direct about the alternative, since its agent teams are not worktree-isolated and you must partition the files instead.
# physical isolation: one checkout per builder, one shared .git
$ git worktree add ../wt/build-renderer -b agent/build-renderer
$ git worktree add ../wt/build-tests -b agent/build-tests
# logical isolation: who may touch what, for how long
$ printf '%s\n' inc/miner-data.php inc/schema-markup.php > .claims/build-renderer
$ printf '%s\n' tests/schema/ > .claims/build-tests
# a claim is only real if something refuses when it is violated
$ git worktree list
Here is the caveat most guides skip. Worktrees prevent file collisions. They do not prevent logical conflicts. Two builders in perfect isolation can still make incompatible assumptions, and both branches can be individually correct and jointly broken. That is why integration is its own node with its own reviewer.
A Model Per Node, Not Per Project
Once work is nodes, the model becomes a property of the node instead of a setting for the session. Enumerating files, extracting a list and applying a mechanical transform are jobs a small local model does well, and they are usually the highest-volume nodes. Architectural decisions, adversarial review and integration are where a stronger model earns its cost, and they are usually the rarest. Getting that backwards is the most common reason a graph is expensive without being good.
The economics are not theoretical. Anthropic reports that multi-agent implementations typically use three to ten times the tokens of a single-agent approach for equivalent tasks, and that their research system used roughly fifteen times the tokens of a chat interaction. A graph that spends a frontier model on file enumeration multiplies that for nothing.
This is where local-first inference becomes arithmetic rather than ideology. DCENT_ADE discovers and manages Ollama and LM Studio, supports LAN inference and supports assigning models to roles, so the high-volume mechanical nodes can run on hardware you own. Cloud stays an explicit, consented boundary, never an invisible fallback. Which model runs where is a harness engineering decision. The graph is where you make it per node.
Finished, Not Abandoned
A graph without exit conditions is a habit. It ends when the person watching gets bored or the budget runs out, and neither is a result.
Write them before the run, in terms something other than an agent can check. A validator returns zero errors on a named sample. A suite passes. A reviewer returned accept. A human signed. Insist on external checkability, because a self-assessed exit condition is not a condition, it is a mood, and models are agreeable. Declare the failure exits too: maximum rejection rounds, maximum nodes, and what happens to an abandoned branch. A node budget is the difference between a run you can leave alone and one you have to babysit.
How DCENT_ADE Models This
DCENT_ADE is our local-first, open-source agentic development environment, and its coordination layer, Orion, exists to hold what this page describes. Boards and missions carry the shape of the work, missions decompose into trees rather than lists, claims record who may touch what, and a mailbox lets agents pass findings without shouting into a shared context. Workspace-scoped memory keeps notes as native-scoped local Markdown with bounded read, write, append, list and search.
Mission Control names the lifecycle in roles: Coordinator, Scouts, Builders, Reviewers, human approval, then integration and delivery. Read as a graph, the Coordinator owns the fan-out decision, Scouts are the parallel investigation layer whose outputs become edges into the builders, Builders hold claims and work in isolated worktrees, Reviewers receive review packets, human approval is a node rather than a notification, and MergeGate with human co-signing sits in front of integration.
Two decisions do more work than the diagram. The Tauri and Rust native host holds the sensitive authority: no general spawn, SQL or fetch authority in the WebView, a native-owned harness catalog, native-side egress controls. With many agents running, blast radius is a design parameter. The awareness layer then distinguishes busy, idle, awaiting input and finished from real terminal behaviour, because a dependency graph is only as good as its knowledge of when a node is done. An orchestrator that guesses fires joins early and hands reviewers half-written files. Hence the house rule: DCENT_ADE’s development rules reject fake agents, simulated activity, fabricated telemetry and optimistic availability indicators, and the current catalog execution layer refuses to claim a Git merge it does not perform.
The Gauntlet Graph Loop
Our own build doctrine is the two-node version, documented at gauntlet loops: a builder produces a real artifact, an independent critic gets fresh context and judges the actual result, and if it loses against the quality bar the largest gap goes back to a builder. The critic must be able to reject, and the evidence must be real: real pixels, real files, real tests, real git effects. That method is live-proven in the strongest sense available to us, because it is how DCENT_ADE itself is built.
The stated ambition is the graph version, which we call the Gauntlet Graph Loop. The gauntlet loop it extends was named publicly by Matt Shumer; the graph form is our extension of it, not a rebrand of his. Not one agent repeatedly improving one answer, but a dynamically coordinated graph of specialised agents and evaluators moving a whole project toward measurable exit conditions, with gates that can reject and route the largest gap back to a specific builder, and a human co-signing before anything is integrated. The graph itself becomes the thing you tune, rewire and re-run.
That is direction, and we are naming it as direction. The roles, claims, worktree isolation, review packets and human co-signing are how the architecture is designed and how we work today, with Claude Code, Codex, Gemini and OpenCode running side by side under one host. A fully automatic graph scheduler that rewires itself against exit conditions is not a shipped feature and we will not describe it as one. The brute-force cousin, where the same prompt runs in a loop with fresh context every iteration, is RALPH loops, and that is Geoffrey Huntley’s work rather than ours.
One last honesty note. The correct default is still the simplest thing that works. Anthropic’s guidance is that multi-agent systems suit heavy parallelisation and information exceeding a single context window, and suit tightly interdependent work far less, which describes plenty of ordinary coding. Reach for a graph when the work genuinely forks.
Standing On Other People’s Work
Dependency graphs were solved long before language models existed. Make, Bazel, Airflow, Argo, Dagster and Temporal did the hard thinking about ordering, retries, branches and joins. LangGraph brought that model to LLM workflows: typed shared state, conditional edges, checkpointing, and interrupts that pause a run for human input and resume it later. Anthropic published what broke in a production orchestrator-worker system, not only what worked. Claude Code, OpenAI’s Codex, Gemini and OpenCode are the harnesses under our own graphs. We invented none of it.
DCENT_ADE is free, open and as-is. No gatekeeping, no paid tier, nothing held back for a premium version. If you use it commercially or it saves you real time, a voluntary subscription or donation is expected and never enforced: d-central.tech/fund.
Related products, repair, and setup paths
- how D-Central diagnoses ASIC repairs
- ASIC troubleshooting library
- ASIC manuals and repair guides
- replacement hashboards
- ASIC control boards
- ASIC power supplies
- S19 family replacement hashboard
- C52 replacement control board
- APW12 S19 power supply
- compare specs in the ASIC miner database
- compare ASIC miner specs
- ASIC miner database
- ASIC repair services
- Antminer S19 specs and profitability
- buy a tested Antminer S19
- Antminer S19 maintenance guide
- Antminer S19 repair service
- Antminer S21 specs
- Bitmain Antminer S21
- Antminer S21 maintenance guide
- BM1370BC S21 Pro chip
Last reviewed August 13, 2026.
