Apparently I've Been Doing Graph Engineering

Audience: Engineers building agent systems past the point where one agent handles it.
Reading time: ~19 minutes.

A term went past in my feed in July: graph engineering. I read one of the guides out of mild professional obligation, got a third of the way down, and stopped, because the thing being described was open in another window.

My first reaction was the cynical one. We’ve been building agent flows for two years. Nodes, edges, a fan-out, a join, retries, a judge at the end. LangChain shipped in 2022, and LangGraph exists specifically because enough people kept discovering that sufficiently complex agent workflows turn into stateful graphs. New label, old practice, congratulations to whoever runs the content calendar.

Then I read the rest of the guide and found four things my repo didn’t do.

So the honest answer to “haven’t I been doing this for two years” is: kinda. Long enough to have opinions, not carefully enough to have noticed what I was skipping. Which is roughly what a good label is for.

Rungs and Ceilings

The progression people draw looks like this:

prompt  ->  context  ->  agent  ->  graph  ->  hypervisor

Every one of those is real, and every one of them describes what you are deliberately designing at that moment. At the prompt rung you’re designing what you say to the model. At the context rung you’re designing what it can see. At the agent rung you’re designing what it can do. At the graph rung you’re designing how the pieces compose. Each rung leaves the previous ones intact, the way a compiler didn’t eliminate machine instructions, it just stopped making you arrange them by hand.

The guides are the trade-press version of this. There’s also a 64-page survey with thirty-five authors on it, Graph Engineering in the Era of LLM Agents, that draws almost the same ladder and splits one of my rungs in half. Theirs runs prompt, context, harness, loop, graph. The split is worth stealing: harness engineering is what the agent can reach, meaning tools, memory and skills, and loop engineering is how it keeps going, meaning plan, act, observe, verify, adapt. They compress the pair into Agent = Loop(LLM + Harness), which is the most compact definition of an agent I’ve run into. My single agent rung was doing both jobs, and that hides the fact that you can hit a ceiling on either one by itself. Good tools with a bad loop is a real failure mode, and it looks nothing like the reverse.

The part that gets skipped when this diagram goes around is that it’s not a maturity model. Nobody is behind for being on rung two. The ladder is a match between problem complexity and the level at which you have to think, and you climb because you hit a ceiling, not because a rung exists.

I’ve argued the first version of this ceiling at length in The Bitter Lesson of Agentic Coding: the state-of-the-one-shot is the upper bound on project complexity a model reliably handles in a single pass. Inside that bound you don’t need methodology, specs, or verification loops. Vibe coding works there because the model really is that good. The bound moves outward every model generation and it never goes away, and the failure mode when you cross it is unmistakable: 80% done fast, then “make it better” produces lateral movement instead of convergence.

Every rung has its own version of that. The context ceiling is where better prompting stops helping because the model can’t see the thing it needs. The agent ceiling is where better tools and better system prompts stop helping because the problem needs two passes with different postures, and one agent doing both in one pass is biased toward confirming its own work. The survey states that failure more precisely than I had: when the same agent writes the code and evaluates it, it can mistake its own judgment that the code is correct for evidence that the code is correct, and handing it a different role in the prompt does not fix that. The graph ceiling is the one this article is about, and I’ll get to it.

The useful discipline is knowing which ceiling you’re actually against. Most agent systems that feel stuck are not stuck at the rung they’re being debugged at. If your researcher agent is 70% accurate and you’ve spent two weeks on its prompt, the prompt is probably not the problem.

What the Term Actually Claims

Here’s the definition I’d been carrying around, and I suspect it’s a common one: graph engineering is making sure the agent flows that interact with each other have good observability, are wired together sensibly, measurably produce better results, and have enough scaffolding that you can see whether they’re drifting or converging.

That’s a decent description of competent work. It’s also broader than the term, and broader in a way that hides the interesting part. Most of what I just described is agent reliability engineering. It’s how you find out whether a system is any good. It doesn’t say anything about what the system is.

The narrower claim is the one worth having: graph engineering is treating the topology of computation as an explicit engineering object. Not the agents, the shape.

Because here’s the thing about the shape: it was always there. In the LangChain era you composed primitives, and the composition was a graph. It just lived in your Python, spread across a for loop, a Promise.all, three if statements and an early return. Nobody wrote it down, nobody diffed it, and nobody ran an experiment against it, because it wasn’t an object. It was a side effect of control flow.

So the shift isn’t from no-graph to graph. It’s from implicit graph to declared one, and from “how good is my researcher agent” to “what computational topology produces the best answer for this class of problem.”

The survey cuts the same claim into three views, and I’ve found them useful for locating what’s actually missing in a given system. Task organization covers what work must be done, how it decomposes, and what can run in parallel. Agent coordination covers who does the work and how information moves between them. Runtime state management covers where the system currently is, how it notices a fault, and how it recovers. My four gaps below scatter across all three, which is either evidence the taxonomy is well chosen or evidence that I was negligent in every available direction.

That second question has real engineering content. Take a research system. You could run it as a chain:

Researcher -> Writer -> Critic -> Writer

Or you could run it as something with actual structure:

             +-> Researcher A -+
             |                 |
Question ----+-> Researcher B -+-> Synthesizer -> Verifier
             |                 |                     |
             +-> Researcher C -+                     v
                                              confidence gate
                                               /           \
                                          answer         research
                                                          again

The questions that fall out of the second diagram are not prompt questions. Do the researchers share context or stay blind to each other? How many branches? Where do they converge? Does the verifier see the original evidence or only the synthesis? What confidence triggers another traversal? Which branch deserves the expensive model? When does the thing stop?

None of those are answerable by writing a better prompt, and all of them are answerable empirically, because you can hold the prompts and the models roughly constant and vary the shape. That’s the part that earns the term. You now have a knob you can turn.

And you don’t need multiple agents for any of it. A single-agent system has a topology too:

             +---- retrieval ----+
             |                   v
Input -> classify -> reason -> confidence
             |                   |
             +---- calculate ----+
                                 v
                              verify
                             /      \
                         retry      answer

Calling each of those boxes an agent makes the architecture harder to see, not easier.

Which brings up the joke that’s been sitting there the whole time. Graph engineering is not a post-LangGraph invention. LangGraph is an infrastructure response to exactly this realization, which is why it’s called that. The people who built it can reasonably watch this discourse and say: yes, we noticed, it’s in the name. What the new term adds is a change of emphasis, from using a graph framework to optimizing graph architecture. You can use LangGraph and do almost no graph engineering. You can do serious graph engineering in Temporal, in an actor system, or in a single file of plain JavaScript.

I know that last one is possible because that’s what I did.

What the Checklist Found

PanelForge is an exploration in code: one HTML file, no build step, no framework, no orchestration runtime. A claim goes in, a panel of models argues about it, and a verdict comes out with its arithmetic shown. First commit is 2026-05-01. The guides naming this stuff started appearing around July, so the repo predates the vocabulary by a couple of months, which is a coincidence with no significance other than clearly a lot of us were exploring these agentic techniques along similar lines. I wasn’t following a checklist. I built the shape the problem wanted.

                     claim, paragraph, or bare URL
                                  |
                          [ Claim Intake ]
                                  |
      +-----------+-----------+-----------+-----------+
      |           |           |           |           |
  [ Primary   [ Prove-   [ First-    [ Quant-    [ Counter-
   Sources ]   nance ]   Principles ] itative ]   Evidence ]
      |           |           |           |           |
      +-----------+-----------+-----------+-----------+
                                  |
                       [ computePanelMatrix ]  <- plain JavaScript
                                  |
                          [ Red Team ]
                                  |
                      [ Verdict Arbitrator ]
                                  |
                     Supported / Leans True / Mixed /
                     Leans False / Contradicted / Unverifiable

Eight model calls per run across six vendor families, five seats in parallel. Two details matter more than the picture. computePanelMatrix is not a model, it’s a function that averages three axes across the seats that came back well-formed and maps the result to a suggested verdict band by arithmetic anyone can read. Asking a model to average five numbers is how you get five different averages. And the First-Principles seat is deliberately starved: it receives the raw claim and nothing else, no search, no intake stub, no other seat’s findings, because circular reporting can fill the open web with the claim itself and that’s the one seat that can’t be fooled by it.

So far this is a piece going well for me. Now the checklist.

The topology is implicit. The edges live in the control flow of runPanel, not in a data structure. You cannot read the graph without reading the function, you cannot diff a topology change, and nothing stops a future edit from quietly adding an edge. The ASCII diagram above is maintained by hand, which means it is a comment, which means it will eventually be a lie.

That one is the whole thesis of this article, sitting in my own repo, as a defect. The graph exists. It just isn’t an object.

There’s no checkpoint or resume. A run that fails at the Arbitrator throws away eight completed calls, including a deep-research seat that’s the expected cost dominant. That gap costs real money today, at roughly forty cents a run. The literature’s name for the fix is better than mine: event-sourced execution history, where the log is the system of record and any validated prior state can be replayed or forked. Somebody wrote a paper called The Log Is the Agent arguing exactly that, and it’s a fair description of what PanelForge should have been doing since commit one.

There’s no conditional routing. Every run takes the same path through the same eight nodes. A claim with no traceable origin still pays for a deep-research provenance seat. A trivially checkable claim gets the full panel. The topology is fixed at design time, so the system can’t spend less on easy problems, which is the cheapest available win and I don’t have it.

There are no interrupts. No approval gate before an expensive node, no human review before the verdict renders.

I’d argue one of those may never land in a project with this shape, since full checkpointing may end up smaller in scope than the guides assume when there’s no build step to hang it on. That’s a scoping decision, and it’s different from not having noticed.

The reason I’m walking through my own gaps is that this is the actual answer to “is it just a label.” A label that makes you look at a working system and notice its topology isn’t an object, and that it can’t route around cost, and that a late failure discards everything upstream, has done a day’s work. Those aren’t observability gaps. Adding tracing wouldn’t have surfaced any of them. They’re structural, and they were invisible to me until something handed me the right category.

PanelForge is mid-effort and I want to be clear about that. It’s one live run deep, the run that proved the wire format and immediately produced a bug the mock fixtures could never have caught. The point is that it’s a real system where the vocabulary earned its keep.

Topology as a Tunable Object

Once the shape is explicit, it becomes something you can measure and search.

Take a topology G and measure Quality(G), Cost(G), Latency(G), Reliability(G). Now the engineering problem is finding the G that maximizes quality subject to constraints on the other three. That’s a different activity from wiring agents together. It’s closer to architecture search, and it has the property that makes architecture search interesting: the answers are frequently not what you’d have guessed.

You might find that planner into five workers into a judge is worse than two independent planners into a router into two specialists into an evidence verifier. You might find the judge contributes nothing and you’ve been paying for it for six months. You might find that three parallel researchers improve factuality a lot and the fourth adds almost nothing, so the marginal researcher is pure cost. You might find that letting workers talk to each other reduces accuracy, because they anchor on each other’s mistakes, which is the finding I’d least like to discover and most expect to be true. You might find the expensive reasoning model belongs at exactly one node instead of everywhere, which is the single largest cost lever most systems have and almost nobody has measured.

Every one of those is a claim about the shape. None of them are reachable by prompt iteration, and none of them show up in a trace viewer, because a trace viewer tells you what happened, not what would have happened under a different topology.

One of those turned out to be settled and another has a literature I hadn’t read, both of which I found out by reading a bibliography instead of running the experiment. The one I said I’d least like to discover is the one that replicates. Shen et al. trace how correct and incorrect outputs propagate through topologies of varying sparsity, and report that moderately sparse ones perform best, because they suppress error propagation while still letting the useful information circulate. Denser is not better past a point. The real answer is a sweet spot rather than the flat don’t-let-them-talk I was bracing for, which is a more useful result and slightly worse for my rhetoric. The dead-judge question has a literature of its own, though not a verdict. AgentPrune cuts redundant connections out of the message graph and AgentDropout removes low-contribution agents and their edges between rounds, both on the premise that a good deal of a working graph isn’t earning its cost. Neither one indicts judges specifically. They establish that the useless node is a normal thing to find, which is not the same as finding mine.

The architecture-search comparison a few paragraphs up is not a loose analogy, and I was mildly deflated to learn how not-loose it is. MaAS represents agents and operators as an agentic supernet and searches that space, and supernet is a term of art lifted straight out of neural architecture search. GPTSwarm treats language agents as optimizable graphs and tunes node behavior and edge connections together. ADAS searches over code-defined workflows to automate the design of agentic systems, and AFlow runs an LLM-guided search over executable workflow code, which makes the structure itself the object being optimized. The vocabulary transferred wholesale because it’s the same problem wearing a different hat.

One caveat from the survey I hadn’t taken seriously enough, and it’s the kind that voids results quietly. End-task success doesn’t tell you the topology did anything. A better score can come from a stronger base model, a longer context, more samples, or simply more money spent per run, none of which is your graph getting smarter. Claiming the structure earned its keep takes structural ablations and intervention studies, which in practice means holding spend fixed and cutting a node to see what breaks. Skip that and you’re measuring your vendor’s most recent release and filing it under architecture.

There’s a second thing that falls out of taking the shape seriously, and I think it’s the more valuable one long-term. Early agent development anthropomorphized everything. You have a researcher agent, a critic agent, a manager agent, and they talk to each other. It’s a comfortable abstraction because we already know how to reason about a small company.

Graph thinking strips a lot of that away. The best system for a given problem might not contain four durable agents at all. It might contain seventeen transient inference operations, three deterministic transformations, two retrievals, a parallel evidence branch, one persistent state object and a conditional verification loop. computePanelMatrix is one of those deterministic transformations, and every time I’ve been tempted to make it a model call the honest answer has been that I want it to be a model call because it feels more agentic, not because it would be better.

One Rung Up

Everything above still has a human in the middle of it. I design the graph. I measure it. I pick a better one. The system executes what I chose.

Which raises the obvious question: why am I designing the graph?

If a system has real evals, real telemetry and a reward signal, the topology is exactly the kind of thing it could pick for itself. And once it’s picking, it isn’t picking once. It’s picking per task, under the current budget, given what it just learned twelve seconds ago.

I wrote about the destination in Agent-Hypervisors in mid-2025, describing a system that designs, deploys, monitors and learns to optimize entire fleets of agents, sitting above the orchestration layer. What I didn’t have then was a clean name for the rung directly underneath it, which made the boundary between the two harder to state than it needed to be. Graph engineering supplies that. The line is now short:

Graph engineering asks whether this is the right graph. The hypervisor asks which graph should exist for this workload, right now, under these constraints, and then afterward, what it should do differently next time.

Formally, graph engineering optimizes G. Hypervisor engineering learns a policy that produces G:

Gt = π(xt, Bt, H)

where x is task state, B is the available budget, and H is everything the fleet has learned from prior runs. Not a literal specification. A statement about which side of the equals sign the topology lives on.

That reframes the scheduling problem too. Today the question tends to be which model a given agent gets. The deeper question is what the next unit of computation should be at all, given everything known so far. At any point you can retrieve, reason, branch, simulate, verify, ask a human, call a tool, compress context, abandon a hypothesis, or stop. Each option has an expected improvement and a cost, and the hypervisor’s real job is to keep picking the best ratio.

A system with a dollar to spend might put five cents into understanding the problem, ten into evidence, twenty into three independent hypotheses, then notice that two agree and one strongly disagrees. The predetermined graph says finish the graph. The right answer is that the disagreement is now the most valuable place in the entire run and deserves another twenty-five cents. Traditional hypervisors allocate compute to workloads. This one allocates cognition to uncertainty. No agent framework I know of is any good at this, and PanelForge is a fine example of the failure: it will happily spend deep-research money on a claim with no provenance to trace, because that decision was made by me, in May, for all claims.

Underneath that sit two loops that get conflated constantly and shouldn’t be:

INFERENCE-TIME LOOP  (within one run)

  state -> choose computation -> observe -> update state
    ^                                            |
    +--------------------------------------------+


EXPERIENCE LOOP  (across many runs)

  executions -> telemetry / evals -> learn policy -> better hypervisor
      ^                                                     |
      +-----------------------------------------------------+

The first is adaptive orchestration and you can build a crude version today with hand-written confidence thresholds. The second is system learning, and you could have it with no adaptivity at all: analyze a hundred thousand runs offline, ship a better static graph next week. They’re independent capabilities. The interesting system has both, and the outer loop is improving the inner loop’s policy.

The survey draws that same line, which is reassuring the way finding someone else’s proof of your lemma is reassuring. It separates runtime adaptation from persistent system evolution and gives the reason plainly: conditional routing or a temporary worker assignment changes one trajectory and leaves the organization used by the next task exactly as it was. Getting the outer loop needs structural credit assignment, which is the genuinely hard part and which nobody has, plus enough machinery to validate a proposed structural change and then commit it or roll it back. It also flags something I’d missed entirely, which is that these graphs can’t evolve independently of each other. Change the task graph and the capabilities the team needs change with it. Swap an agent and you may have quietly invalidated communication paths and permissions that other parts of the system were counting on.

One thing I’d sharpen about the 2025 piece. It treats agents as the unit the hypervisor schedules, and I now think that’s an interim abstraction. The virtualization analogy holds better if you let it run: a VM hypervisor schedules virtual machines, an agent-hypervisor starts by scheduling agents, and a mature one schedules computation. “Allocate eight thousand tokens of independent reasoning to hypothesis three, then retrieve primary evidence if disagreement stays above threshold” is not an agent doing anything. It’s a unit of cognition being spent. Agents are today’s natural packaging, and the schedulable resource underneath them is inference, retrieval, verification, simulation, tool use, memory access and human attention. Keeping the name and dropping the assumption gives the architecture a much longer shelf life than the current generation of frameworks.

The survey and I part ways on what sits above this rung, and the disagreement is clarifying. Its answer is ontology engineering. Making the relationships explicit doesn’t guarantee the components agree on what any of it means, so two agents can hold incompatible notions of what counts as done, or as sufficient evidence, or as an authorized action, and the graph will route between them without complaint. Its other direction is a graph-native agent operating system: tasks, agents, capabilities and state as typed, versioned, first-class objects, with scheduling, checkpointing, replay and rollback supplied by a shared runtime instead of reimplemented by every framework in turn. AIOS gets cited as the precedent.

That reads to me as a different axis rather than a competing answer. Ontology is about whether the system means the same thing by a node. The hypervisor question is about who decides which nodes exist. You can have either without the other, and a system with a learned topology and no shared semantics sounds like a genuinely bad time. The operating-system direction is the closer of the two and stops one step short, in that it’s infrastructure for structural change rather than a policy that decides which change to make. That’s roughly the distance between a scheduler’s data structures and the scheduling algorithm.

The Graph Is a Learned Artifact

Here’s the sentence I’d have wanted two years ago, and the one that makes the label worth keeping:

The graph is no longer the architecture. The graph is the execution trace that the architecture produced.

In conventional agent development, architecture and graph are the same thing. You draw the boxes, the boxes are the system. In the hypervisor model, the architecture is the policy that generates computation, and the graph you observe afterward is just what that policy instantiated for this task, under these conditions, with this budget, given what it had learned by then. Two runs of the same system can have different shapes and both be correct.

Which means the graph becomes a learned artifact, in the ML sense of learned. Not designed and then tuned. Fit.

I don’t think that’s speculative so much as overdue, because we’ve watched this movie in every other part of the stack. Hand-designed features lost to learned representations. Hand-designed network topologies lost to architecture search. The bitter lesson for software engineers is that hand-written implementations lose to well-specified goals with verification attached. The computational topology of an agent system is the last big hand-drawn artifact left in that stack, and there’s no principled reason it gets an exemption. Given a measurable reward signal and enough runs, something will fit it better than I can draw it, and the result won’t look like anything I’d have drawn, for the same reason AlphaGo’s Move 37 didn’t look like Go.

The survey’s field scan says the same thing from the other end. Across every application domain it reviews, decomposing objectives, assigning specialized roles and keeping explicit state have all become ordinary, and persistent system evolution has stayed rare. Most systems adapt inside a structure that was fixed before execution and never revise the structure itself from what the runs taught them. The distinction it lands on is one I wish I’d had several sections earlier: being graph-structured versus being graph-engineered. Plenty of things are the first. Almost nothing is the second, because the second wants structural objectives, graph-level observability, controlled mutation, and evidence that a structural change transfers to the next task instead of flattering the one you tuned it on.

That’s the uncomfortable half. The graphs I’m hand-drawing today are the ones I can read. Learned ones won’t be, and you can’t debug an architecture you don’t understand. Which is precisely why the near-term work of making topology explicit is worth doing carefully rather than skipping ahead: an explicit graph is diffable, testable, and comparable, and those three properties are what a learning system needs from you before it can take the job. Declared topology is the thing that makes the search space legible in the first place. It’s also, not coincidentally, what lets you tell whether the learned version is better.

So, have I been doing graph engineering for two years? Kinda. I’ve been hand-drawing an artifact that a later system is going to learn, without writing it down well enough to compare two of them.

The label “Graph Engineering” didn’t teach me the practice. It told me which side of the bitter lesson I was standing on, and gave me four specific things to go fix. Cheap at the price.


The exploration in code is PanelForge (Apache 2.0, one HTML file, runs offline against fixtures). The rung above this one is Agent-Hypervisors. The rung below is The Bitter Lesson of Agentic Coding, and the harness that came out of it is zat.env. The survey I keep citing is Graph Engineering in the Era of LLM Agents, 64 pages and worth the time if you want the full bibliography.