Three parts carry that, and they’re easier to argue about separately, because “graph engineering” gets used for all three at once:
- A stage is one named piece of the job, and the thing framework docs call a node. It takes an input and leaves an output the next stage can use or be held against. It can also get a fresh context or narrower access, when the job needs that boundary.
- An edge is a rule about order. It says what has to finish before the next stage starts, or that the run stops here to be checked before anything continues.
- The runner is what holds the stages to those rules. Without one, the edges are a description of what you hoped would happen.
The label is newer than any of that. What spread in July 2026 was a name rather than a specification, grouping branching, parallel work, checks and human approvals under one word. The shapes were already in workflow runtimes under duller names, so the new part was what to call them.
What the structure buys is narrow. Where a model does the work, the judgement about whether it went well is made by that same model looking at its own output, unless something at the boundary takes it off them.
It isn’t the only place to enforce something. A harness can run a fixed check between turns inside one agent session, with no stages at all.
The difference is whether the check is optional. A skill can run the tests halfway through, and plenty do, but it decides whether to run them and it decides what a failure means. Put the check on a stage boundary and neither is a decision any more: it runs because the run got there, and a failure stops the next stage starting.
Stages also give you a handoff the next stage can be held against, and a boundary that permissions and evidence can differ across.
Four things share the word
Everything above is the first row of this table. The others are real objects too, which is why two posts about “graphs” can have nothing to do with each other.
| What someone means | What the nodes are | How long it lives |
|---|---|---|
| Control or execution graph | agents, plain functions, tools, people | the run |
| Task or dependency graph | pieces of work, each blocked or ready | one plan, then it’s replaced |
| Organisation graph | agent roles, who owns what, who can do what | months |
| Knowledge or context graph | entities and how they relate, for memory or retrieval | as long as the memory does |
The fourth is the easiest to confuse with the first, because knowledge graphs, and GraphRAG which builds retrieval on top of one, were a going concern well before this July. A quick test while reading: a piece that keeps talking about embeddings and entity resolution is about memory, and none of it will help you decide how a run is shaped. A piece talking about retries, permissions and approvals is about execution.
“Loop” is unstable the same way. It gets used for one agent choosing its path inside a single pass, which is the agentic loop, and for running whole passes at the same goal with fresh context each time, which is loop engineering. Those are different jobs with different failures, and the longer argument is largely about which one anybody means.
Why one long skill limits what you can prove
Start with work written as one skill: a single set of instructions the agent loads and follows end to end, calling tools as it goes. That’s quick to write, it’s what most harnesses make easiest, and for a bounded job it may well be the right shape.
What it costs is checkability, and that’s structural: however well the skill is written, all of it happens in one context. There is no seam, and a check needs a seam: somewhere that something which didn’t do the work gets to look at the result before anything else proceeds.
A long pass can still run hard checks between its turns. What it doesn’t give you on its own is a piece that can be rerun by itself, a clean context after a failure, or narrower access for one part of the job. Three practical risks follow.
- A wrong step travels. If the model misreads a schema at step two, that misreading sits in its context for the rest of the job, and later steps are built on it consistently. Tool output can still contradict it, but nothing is obliged to go and look.
- Retrying means retrying the lot. There’s no smaller unit to send back, and the failed attempt is still in the context when it tries again, which is a poor place to start from.
- Access is set for the pass, not the step. If one part of the job has to write to production, every turn in that pass can.
Splitting the work into stages doesn’t make the model better at any individual piece. It gives the runner a fixed boundary. A check can run there, access can change there, and failed work can return there instead of starting from nothing.
The three checks are stages, each line into diagnose is an edge, and the gate collecting all four verdicts is where the runner does its work: nothing reaches the person until every one of them is clear.
The gate is deterministic on purpose: it applies a rule you wrote rather than forming a view about the findings. Put a model in that seat and the run’s one hard answer becomes another opinion.
Notice what alternates. The checks are fixed steps: same code in, same answer out, and no opinion about it. Diagnosing the failure and writing the fix are the parts that genuinely need a model. Then the patch fans out. The suite reruns as a fixed check, and three separate models read the patch on three different questions: does it do the right thing, what does it now let through that it didn’t before, and what’s wrong with it. That last one is asked adversarially on purpose, because a reviewer told to find fault finds different things from one asked to approve. None of the four is the model that wrote the patch. They report into one gate, and a single failure sends the patch back to be fixed rather than restarting the whole run. Written as one skill the whole thing is a single instruction, “fix the failing tests and merge”, and every decision inside it belongs to one model, including the last one about whether the tests really passed.
What changes when nobody’s watching
There’s a fair objection to that diagram. A good coding agent does all of it on its own. Point one at a failing branch and it runs the suite, reads the failures, patches them and runs it again. For one merge request with you watching, that agent is the right tool and the graph is overhead you’d be mad to take on.
Three things change when you aren’t watching.
- The rerun has to be something the agent can’t decide it passed. Inside one agent the suite result is a tool call like any other, and what it means is settled in the same context that wrote the fix. On a boundary it’s a condition, and a fail stops the next stage whatever the agent concluded.
- The reviews can’t be the author. A context that just wrote something has already been persuaded by it, which is why the reviews sit in their own stages, on different models, with no memory of writing the patch. A better model doesn’t fix this. An agent can hand its patch to a fresh context to review, and while you’re watching that’s fine. Once you aren’t, whether the review ran at all, and what its verdict was allowed to stop, are still decisions the agent owns.
- Nobody is there to merge. The step that quietly carried the whole example, you glancing at the diff, isn’t there at all once the run goes overnight. What stops a bad fix has to have been written down beforehand.
And then there’s volume. One merge request is a job for one agent. Two hundred of them overnight is a different question, because somebody has to read two hundred diffs in the morning, and that somebody is you. What changes as you add agents is that ladder.
What belongs to a tool, and what belongs to the model
Renaming a symbol across a codebase is a useful example of work handed to an agent that isn’t agent work. A language-aware rename finds and edits the typed references in one deterministic step, and does it more completely than a model reading files one at a time. A graph whose stages are “read the file, decide the new name, edit the file” spends tokens on what the tooling already does exactly.
The useful split runs inside the job rather than around it:
| The work | Who should do it | Why |
|---|---|---|
| Find the uses | The tool | Search returns the textual matches and the type checker resolves the typed ones. Neither sees a name that only exists in a serialised key or a config file, which is its own reason to have a check afterwards. |
| Decide whether the new name is right | The model | It’s a judgement about meaning, and there’s no rule to run. |
| Apply the rename | The tool | Deterministic, reversible, and the same every time. |
| Work out why a test broke afterwards | The model | Needs reading and inference across things that aren’t linked. |
| Confirm the suite passes | The tool | The answer is a fact. A model reporting it is a claim about a fact. |
That table is the argument for the shape. A run that alternates the two is worth more than either on its own: the deterministic steps follow a fixed rule and give the runner a machine-readable answer, and the model only gets asked the questions that need judgement. Interleaving them deliberately, with the conditions between stages enforced by the runner rather than requested in a prompt, is what a playbook is.
It also explains how a graph disappoints. Splitting work into five boxes and putting a model in each one gives you five chances to be confidently wrong instead of one, and it looks like rigour from the outside. More boxes help when the boxes do different jobs.
Why one verifier isn’t enough
Some work has no fixed check. Nothing runs green to tell you a migration plan is sound or a summary is accurate, and that’s often exactly the work you’d most like to stop reading yourself.
The obstacle is the failure mode. A wrong answer sounds exactly like a right one. Nothing throws, nothing hedges, so the signal you’d normally catch a problem by isn’t there at all. Ask the same model to check its own work in the same context and you get the answer back a second time, with more supporting detail attached.
So a verification stage only earns its boundary if it’s independent of the thing it’s checking:
- A different model. This is a bet on different blind spots rather than a guarantee of them. How far model errors correlate is an open question, but two runs of one model in one context is the case where they plainly don’t diverge.
- A fresh context. A verifier that watched the work happen has already been talked into the answer.
- An adversarial stance. “Review this” invites agreement, and an open-ended review prompt encourages it. A reviewer told to find what’s wrong with it goes looking instead, and turns up different things from the same model reading the same work.
- A different vantage. “Is this correct?” and “what does this now allow?” are not the same audit. So are “does this fit what’s already here?” and “what happens the first time this runs at volume?” Each one is blind to what the others are for.
Those run at the same time and converge, which is the fan-out shape from earlier pointed at checking rather than doing. Agreement between reviewers who were set up to disagree is a reason to look at something first, not proof it’s right. The cost is more findings to sort, some of them wrong, so the stage needs a written rule for what blocks. A review panel is this applied to code, including what it costs and when it’s the wrong tool.
The reason this matters isn’t rigour for its own sake. Work where a fan-out of independent checks can issue the verdict is work that can run while you’re doing something else, and every class of work you move into that set is one you stop having to read. What changes as you add agents walks that ladder step by step.
When a line earns its place
A line earns its place for four reasons, and one with none of them is decoration.
| Why the line is there | What it looks like |
|---|---|
| Parts don’t wait on each other | Forty competitor pages read at once, then one summary that needs all of them. |
| Something has to hold before the rest continues | The month’s totals reconcile before the report goes anywhere. |
| Access changes across it | The step reading customer records and the step sending mail outward don’t get the same credentials. |
| A rejection needs somewhere particular to go | A failed check goes somewhere specific rather than nowhere. |
More worked examples, and what each one would lose as a single skill:
- Incident triage. Gather the errors, the deploy diff and recent alerts, then decide, then maybe roll back. The gathering happens at once, and the rollback is a place a person has to be able to stand in the way. As one skill, the rollback decision is made by the same context that just convinced itself it understood the incident.
- A migration across two hundred tables. Each table is independent, so they run in parallel, and each one’s check is “does the row count match and does the app still boot”. As one skill it’s a single enormous context that will lose the early tables by the time it reaches the late ones.
- Anything touching money or customers. The step that works out the refund and the step that issues it want different credentials, and the boundary between them is where a person can be required. A skill has one set of permissions for its whole length.
- Publishing. Draft, then review against written criteria, then a person releases it. The review only means something if the reviewer isn’t the writer, and inside one context it always is.
And where the boxes cost you:
| Where splitting hurts | Why |
|---|---|
| Drafting a reply to a support ticket | One model call. Read, reason, draft and tone-check is four prompts doing what one already did, and every handoff loses a little context. |
| A ten-minute job you’ll run twice | The graph costs more to write and keep working than the task costs to do. |
| Boxes that rename the phases of one prompt: understand, plan, reason, answer | No stage leaves anything the next one can wait on or check, so the drawing is the only thing that changed. |
There’s measured support for the parallelism row. Google Research’s 180-configuration study from January 2026 found that splitting financial-analysis work across agents beat a single agent by 80.9%, while splitting strictly sequential planning work made every configuration they tried worse. Benchmarks rather than production, so take the direction and leave the decimals.
What a failed check is allowed to do
The dashed edge in the diagram is the most consequential line on it, and it needs three decisions that are easy to skip.
Who decides it gets taken? If the stage that failed decides for itself whether to have another go, you’ve drawn boxes around a model grading its own work. If the runner reads a fixed check and routes the work back, the edge is enforcement.
How many times? An unbounded backward edge can keep spending without ever reaching a terminal result. Bound it, and decide what happens when the bound is hit, because “it kept trying” is not a result.
Where does it land? Back to the stage that got it wrong, not to the start. Restarting throws away the work that was fine and pays for it a second time.
Do you need to care about this?
If your agent work is one skill today and it’s doing its job, nothing here says stop. The questions underneath the word are the ordinary ones you’d ask about any process:
- What can run at the same time?
- What has to be true before the next part starts?
- Where does access change?
- What is a failure allowed to do?
Those answers tell you whether a graph would clarify the work and where its boundaries belong. Something still has to enforce the checks and the access rules once you’ve drawn them, and that something is the runner rather than the picture.
Is graph engineering the same as a workflow?
When should I split a skill into stages?
Do agent graphs have to be acyclic, like a DAG?
Do I need a framework to build one?
Read the longer argument
→Which decisions belong to you, and which belong to the model.