AI Development Tools 6 min read

Graph engineering for agents: what a prompt chain forgets

Graph engineering models an agent system as nodes and edges, not a prompt chain. Here is the idea, five patterns, and how my open-source Yaaf uses it.

Abstract illustration of teal and coral circles linked by cream lines and arrows, with one amber node at a junction and a dashed arc looping back, on a navy background.

Graph engineering means you model an agent system as a graph. The nodes are units of work or state, and the edges say what may happen next or what depends on what. In this post I go over what a prompt chain forgets, the five graph patterns a serious team ends up building anyway, and then Yaaf, my open-source platform for running teams of agents, as a worked example: the task board, the claim edge, the dependency edges, and the scheduler that decides who wakes. My verdict: draw the graph before you pick a framework, and add one edge first.

Why now? Agents used to live one chat turn, and now they run for hours. The LangGraph README describes its own job as orchestration for “long-running, stateful agents”, and that is the whole problem.

Abstract illustration of teal and coral circles linked by cream lines and arrows, with one amber node at a junction and a dashed arc looping back.
Nodes for work, edges for what may happen next, and a dashed edge back.

What is graph engineering for AI agents?

Nodes are the steps or pieces of state: a task, a worker, an approval, a memory. Edges are the rules between them. LangGraph’s graph API docs put it in one line each: “State is the shared data that nodes read and update,” and “Edges decide where control goes next.”

The idea is older than LLMs. The LangGraph README says it is inspired by Pregel, which is a 2010 Google paper about large-scale graph processing. Agents borrowed an old answer.

What does a prompt chain get wrong?

A chain of prompts, or an ad-hoc tool loop, keeps its state in one place: the text of the prompt. Four failures follow from that design. I did not benchmark them, they come from the shape.

It forgets where it is, because the position in the work lives in a growing context window. It cannot run two things at once, because a chain has one thread of text. It cannot resume after a crash, since there is nothing outside the prompt to resume from. And it lets two workers claim the same job, because nothing records that a job is taken.

The last one costs money first. Mettons two agents ask “what is next?” in the same second. With no claim recorded anywhere, both start the same task and you pay twice.

Which graph patterns does everyone end up building?

Five of them show up in almost every serious agent stack. I say which part comes from a source.

A state graph with checkpoints. Each step reads the state and writes an update, and the state is saved. LangGraph’s persistence docs say checkpointers “persist a thread’s graph state as checkpoints” and list “human-in-the-loop workflows, time travel, and fault tolerance” as what you get. The page does not say how often a checkpoint is written, so I will not claim “one per step” as LangGraph fact. It is the version I would draw.

Supervisor and worker edges. One node decides who works, the others do the work, and the edge only goes one way.

A dependency edge per requirement. Requirement B cannot start before A is true. This is a plain directed graph, and the one rule you want on insert is “no cycles.”

An interrupt edge where a human says yes. The LangGraph interrupts docs say the function “pauses graph execution and returns a value to the caller,” and that it needs a checkpointer to persist the state.

Memory as its own node type. The LangGraph README separates short-term working memory from long-term memory across sessions. Microsoft’s GraphRAG goes further and builds a knowledge graph as the memory. Its README warns that “GraphRAG indexing can be an expensive operation” and calls the project “largely in maintenance mode”, so read it as a pattern, not a dependency. Neither README gives a benchmark for graph versus chain.

How does Yaaf use graph engineering?

Bon. Now the worked example, where I am biased. Yaaf is my open-source harness for teams of agents. It is Apache-2.0, runs on your own machine with Postgres and two containers, and per the site its first commit is 14 August 2026. It is pre-1.0. The README never uses the word “graph”. I am the one saying it, because the data model is one.

The root node is the requirement: something that must be true at the end, carrying an acceptance test. I made the server refuse a task with no requirement, because that is how a project stays busy without finishing. Tasks point at requirements. The team lead can split a claimed task into subtasks, one level deep, with a ceiling of 10 open subtasks per parent, and subtasks cannot have subtasks.

Requirements carry dependency edges. Per the Yaaf docs, the edges are append-only, “kept acyclic by a check on insert,” with the critical path computed server-side. An edge that would make a cycle is refused, and the refusal names the loop.

How do claims, approvals, evidence and memory work in Yaaf?

The claim edge answers the failure from the chain section. An agent holding a claimed task cannot claim another, and only the claimant completes it. I read that in the docs and did not test the race.

The interrupt edge is the approval. Spending, legal questions and anything only a human can do always go to the chairman, at every autonomy setting. Evidence is its own node: an agent’s claim is recorded as pending and counts only after the platform fetches the URL, hashes it and checks the domain is not one the project controls. That check costs money. In an earlier post I measured my quality gate eating 51.5% of a pipeline’s spend, and I would still keep it.

Memory has two scopes, project and team, each with a curator, and at the cap new entries are refused until one is compacted or forgotten.

What does Yaaf’s own graph look like?

I can count one slice of it. The board this post was written from shows my seat 12 tasks: 6 done, 4 killed, 1 claimed, 1 ready. They are all top-level, so 0 subtasks, and they point at 7 requirements. Six of the 12 point at one requirement, the Friday Nov 6 post, and 4 of those 6 are killed attempts. The graph keeps the dead nodes attached, which is how I know that requirement had a rough day.

I cannot give you the dependency-edge count. My seat’s API returns tasks but not requirements or edges, and I will not guess one. Twelve nodes is a smoke sample, not a scale claim.

How does Yaaf decide who works next?

The scheduler is the node that spends your money. Per the feature docs, an agent wakes for four reasons: an assignment, a message, a schedule, or a heartbeat. Every wake is a paid model call, so the limits around it are the design.

Wakes per agent per hour are the runaway brake. Runs per project per day are the ceiling the whole team shares: hiring a role buys you no runs, because the allowance belongs to the project. Idle heartbeats are suppressed too, so an empty board does not buy a full-price run to conclude that there is nothing to do.

Two more. Agents trading messages with no task changing state freeze that thread until the human unfreezes it, and a run past five refusals loses its token.

What is the smallest graph you can draw today?

Three node types: task, worker, and approval. Two edges: “held by” and “waits for yes.” Put them in a Postgres table, not in a prompt. That is already more than a chain.

If you add one edge first, add the claim. Here is the standard Postgres pattern, which I did not run for this post:

UPDATE tasks SET held_by = :worker, status = 'running'
WHERE id = (SELECT id FROM tasks WHERE status = 'ready'
            ORDER BY id LIMIT 1 FOR UPDATE SKIP LOCKED)
RETURNING id;

Two workers can fire it at the same instant and each gets a different row, or none. Then add the dependency edge with a cycle check, because a loop between two requirements stalls you in a way no log explains.

Bon. That is the graph I run: a requirement at the root, the tasks under it, a claim edge that stops the double work, a dependency edge per wait, evidence as its own node, and a scheduler that pays for a wake only when it has a reason.

All of it is in the repo, including the killed tasks I left on the board. Clone it, open the board, and tell me where the graph is wrong.

Dominic Plouffe

CTO of Trellis, with exits at FuseTalk, 360pi and DeadHeat. I write about making agents and big data work together safely, and I'm building yaaf, an open-source platform for running teams of AI agents that actually finish the job: yaaf.dplouffe.ca