Your agent does not need a better memory. It needs a smaller question. This is a field guide to work graphs: what they are, why 2026 is when they became necessary, and how to run one on any harness. It ends with 140 days of our own graph, measured, including the parts that make us look bad.
You closed the laptop on Friday with an agent halfway through a job. On Monday you open a fresh session and it knows nothing. Not what it finished. Not what it was about to do. Not the thing it discovered on Friday that made the original plan wrong.
So you explain it again. You paste the plan back in. It starts work that is already done, or it starts work that cannot be done yet because something else has to land first, and you only find that out after it has written the code.
Steve Yegge, who built the tool most of this playbook draws on, described the same thing with a blunter word.
"and the agents would get dementia. Okay. They'd get really confused because all they know is what's on disk. All they know is what you've prompted them right in the context."
That is the whole problem in one sentence. All they know is what is on disk, plus what you just told them. Everything else died with the last session.
The instinct is to fix this with a bigger context window. It does not work, and the reason is arithmetic. IBM put it plainly in the most watched talk in our source set.
"the biggest context windows available today are pretty big. I mean, it could be like 1 million tokens or even more than that, but that still has a ceiling."
A ceiling is a ceiling no matter how high you raise it. And the same talk names the real shape of the problem, which is not storage at all.
"humans are actually pretty good at forgetting. I do it all the time and as frustrating as that can be, it can be quite useful. But for agents, forgetting is an engineering problem."
Most people reach for a plan file. A PLAN.md, a checklist, a markdown to-do list the agent reads at the start of every session. This is better than nothing and it is where almost everyone starts. It also stops working quickly, for three reasons that have nothing to do with the file format.
A list has no order that means anything. Ten unchecked boxes look identical. Nothing in the file says that box seven cannot start until box three lands.
A list has no links. When box three turns out to be impossible, nothing tells you that boxes seven, nine and twelve just became impossible too.
A list grows. It does not shrink, because nothing computes what is finished and removes it.
"if you have markdown files, they're not prioritized. There's certainly no dependencies like there aren't links between them."
The failure mode at the end of that road is not a missing file. It is too many files.
"I started my my probably two months ago the the sort of like PRD and agents are updating them when they land the plane. And I have 256 documents that are insane."
Two hundred and fifty six planning documents is not a memory system. It is a landfill. The agent cannot read them all, so it reads the ones you point at, which means you are back to being the memory.
Durable tasks, linked by dependency, that outlive the agent's session.
That is the whole idea. Three properties, and each one is load bearing.
Once those three hold, a question that used to require judgment becomes a query. "What should I work on next" stops being something the agent reasons about from a half remembered plan, and becomes something it looks up.
"now has address. It's Google maps for your plan."
Three different things get called a work graph. Only one of them is this.
| The other thing | What it actually is | Why it is not this |
|---|---|---|
| Asana's Work Graph | A data model inside a project management product, connecting tasks, people and goals. | It is built for humans in one company's app. It is not addressable by an agent on your machine, and dependency is a reporting feature, not a scheduler. |
| A DAG orchestrator Airflow, Prefect, Dagster | A pipeline runner. You define steps and their order, and it executes them on a schedule. | The graph is the program. It is authored ahead of time and it runs the same way every time. A work graph is data that changes while work happens, and agents write to it. |
| An agent framework graph LangGraph and similar | A state machine describing how one agent run moves between steps. | It governs control flow inside a single run. It disappears when the run ends. A work graph is the thing that survives the run. |
The tell is simple. If it dies when the session ends, it is not a work graph. If it was fully written before any work started, it is a pipeline, not a work graph.
We screened 26 talks for this playbook. Every general LangGraph tutorial we pulled scored at or near zero on work-graph language, while the talks about durable task graphs scored high. The two topics genuinely are different subjects, and the search results treat them as the same one. That is why this section exists.
Here is what the practitioners say changes. Read these as claims, not as proof. We test them against our own data later on this page.
"Beads is your beads is your your session to session memory."
"you need something to like remind them of everything where you're at between sessions."
The second claim is about what stops being your job once the graph exists.
"anymore, right? Every agent, I didn't have to cradle them and a hold them in my arms to keep working with the context that they gained because all the context was in the beads, right?"
And the third is about scale, which is where the dependency links start paying for themselves.
"Ready work can be claimed usually by a larger audience. It could potentially be bid on. There can be all kinds of ways you could like present that stuff, right?"
A work graph needs three things and nothing else. Everything a tool adds on top is convenience.
A node is one piece of work. It needs an id, a title, and a state. Everything else is optional. If a node cannot be finished in one sitting, it is too big and should be split, because the point of the graph is that a session can pick a node up and put it down.
An edge says one node blocks another. This is the only edge type you truly need. Most systems add a parent link so work can nest, and that is worth having, but blocking is the one that does the scheduling.
A state says where the node is. Open, claimed, closed. Three is enough. Add more only when you can name the query that needs them.
"It has dependencies. It can be blocked by other work. It can have a parent epic. You have everything you need to like locate it."
Below is one real node from our own graph, drawn from the export this page is built on. It is a single piece of work blocked by 18 other nodes. Three of them are finished, one is running, and the rest have not started. Because fourteen blockers are still open, this node is not ready, and no agent should pick it up. That verdict is computed, not remembered.
swarm-agents-e9bv, an epic-shaped task, blocked by 18 others. States read from our own export on 2026‑08‑31. This is the deepest node in a graph of 1,328.Everything above exists to support one operation. Given the graph, return the nodes that are open and have no open blockers. That set is the ready work.
# the entire idea, in one line of logic
ready(graph) = { n in graph : n.state == open
and no b in blockers(n) has b.state != closed }
This is worth dwelling on, because it is the part people skip. The ready query replaces a judgment with a lookup. Before it exists, "what should I do next" is answered by an agent reasoning over a plan it partly remembers. After it exists, the answer is computed from durable state, and it is the same answer whichever agent asks, at whatever hour, in whatever session.
That single change is what makes the rest possible. An agent that can ask for ready work does not need to be told where it left off. It does not need the plan re-pasted. It does not need you.
Open your task system right now and try to answer this without reading anything: which items are unblocked at this moment? If you cannot get that answer as a query, you have a list, not a work graph. The format does not matter. Markdown is fine. The query is what matters.
A work graph is not a product. It is a shape. Here is the identical ready query in three completely different storage layers, from the smallest thing that works to a real database. Pick the one that matches your scale, and know that you can move between them because the shape does not change.
Nodes are lines in a file. Blocking is a field. This is genuinely enough to start, needs no install, and is readable by any harness in existence.
# tasks.md, one node per line
- [ ] wg-1 set up staging DNS blocks:
- [ ] wg-2 deploy the API blocks: wg-1
- [x] wg-3 write the schema blocks:
- [ ] wg-4 point the client at staging blocks: wg-2 wg-1
# ready work: open nodes whose blockers are all closed
closed=$(grep -o '^- \[x\] [a-z0-9-]*' tasks.md | awk '{print $3}')
grep '^- \[ \]' tasks.md | while read -r line; do
blockers=$(echo "$line" | sed -n 's/.*blocks:\(.*\)/\1/p')
ready=1
for b in $(echo "$blockers"); do
echo "$closed" | grep -qx "$b" || ready=0
done
[ "$ready" = 1 ] && echo "$line"
done
Two tables. The ready query becomes a single statement, and it stays correct at any size.
CREATE TABLE node (id TEXT PRIMARY KEY, title TEXT, state TEXT, priority INT);
CREATE TABLE edge (node TEXT, blocked_by TEXT);
-- ready work
SELECT n.id, n.title FROM node n
WHERE n.state = 'open'
AND NOT EXISTS (
SELECT 1 FROM edge e JOIN node b ON b.id = e.blocked_by
WHERE e.node = n.id AND b.state != 'closed'
)
ORDER BY n.priority;
This is where a real implementation earns its keep, because two agents claiming the same node at the same moment is a genuine race and you do not want to solve that yourself.
bd ready # open work with no active blockers bd create "deploy the API" -p 1 bd dep add wg-4 wg-2 # wg-4 is blocked by wg-2 bd update wg-2 --claim # atomic: only one agent wins bd update wg-2 --status closed
Same graph, same query, three substrates. Nothing above is specific to one vendor, one language, or one agent harness. That is the property that makes this worth learning rather than buying.
The single most important design decision is also the least discussed: the graph must not live inside the agent. Not in its context. Not in its scratchpad. Not in a session file the tool manages for you.
The reason is that everything inside the harness is scoped to a run. When the run ends, it goes. A developer building agent workflows put the rule about as plainly as it can be put.
"it's all persisted uh outside of the context window. So there's like a real Trello board somewhere."
There is a real board somewhere. That is the test. If you cannot point at the file or the table that holds the graph, and open it without the agent running, then the graph is not durable and you will lose it.
Putting it outside buys four things at once:
"it's all saved in Git."
Because the graph sits outside, the harness becomes a detail. Any agent runner that can execute a shell command or read a file can use the same graph, and they can use it at the same time.
| Harness | How it reads the graph | What you write down |
|---|---|---|
| Claude Code | A shell command in the session, or a line in CLAUDE.md telling it to ask for ready work before starting. | "Before starting work, run the ready query. Claim the node you pick. Close it before the session ends." |
| Cursor, Windsurf, and other editors | The same shell command from the integrated terminal, or a rules file entry. | Identical instruction. The graph does not know which editor is asking. |
| Codex and other CLI agents | The command directly, since the graph is just a file or a database on the machine. | Identical instruction. |
| A cron job with no human at all | Query for ready work, take the top item, do it, close it, exit. | This is the case that proves the design. If a scheduled script can use your work graph unattended, the graph is genuinely durable. |
The instruction you write is nearly identical in every case, which is the point. You are not integrating with a harness. You are leaving a file where any of them can find it.
You do not need to install anything to start. Do this in the next ten minutes and you will have a working graph.
The starter graph and a script that measures the health of any graph are on the companion page.
Open the work graph template, which carries a copyable starter graph and the scorecard script described below.
We did not build the tool this section measures. We do not sell it, we are not affiliated with it, and we make no money if you adopt it. We run a work graph, we measured it honestly, and the least flattering data on this page is our own. Every figure below is computed at build time by a script from a raw export, not typed in by a person.
We have run a work graph in one working repository since 2026-04-13. As of 2026-08-31 it holds 1,328 nodes, 191 dependency edges and 2,503 recorded events across 140 days. Of those nodes, 797 are open, 514 are closed and 16 are in progress.
That is the flattering paragraph. Here is the rest of it.
We ran a work graph for 140 days and used it as a list.
The graph is barely a graph. 84.5 percent of our nodes have no edge at all. We have 175 blocking edges and 16 parent links across 1,328 nodes. We built the dependency structure for the work we thought was complicated and skipped it everywhere else, which means for most of the graph the ready query returns the same thing a plain list would.
The median node closes in 42 minutes. That is not a victory lap. A node that is created and closed inside an hour was mostly a note being written down after the fact, not a piece of work scheduled ahead of time. The graph was recording history more often than it was directing traffic.
We create far faster than we close. In 2026-08 we opened 643 nodes and closed 173.
| Month | Created | Closed | Ratio |
|---|---|---|---|
| 1970-01 | 0 | 814 | 0.0 : 1 |
| 2026-04 | 2 | 1 | 2.0 : 1 |
| 2026-05 | 45 | 16 | 2.8 : 1 |
| 2026-06 | 296 | 160 | 1.9 : 1 |
| 2026-07 | 342 | 164 | 2.1 : 1 |
| 2026-08 | 643 | 173 | 3.7 : 1 |
And the backlog is aging. Median open age 26 days, with 325 nodes past 30 days, 150 past 60 and 34 past 90. Alongside 39 open items at top priority, that is a system recording intent faster than it retires it.
We are publishing this because the alternative is a playbook that tells you how well this works while quietly not measuring whether it worked for us. The doctrine on this page is sound and our practice of it was mediocre. Both things are true, and only one of them is usually printed.
Each failure below is tied to one measure, so you can detect it in your own data instead of guessing. Our reading of our own graph is in the last column.
| Failure | What it looks like | The measure that catches it | Ours |
|---|---|---|---|
| Graph as list | Nodes get created but nobody links them, so the ready query is meaningless. | Edge density under about 30 percent. | 15.5% present |
| Ledger not scheduler | Nodes are created and closed almost at once. The graph records what happened rather than deciding what is next. | Median close latency measured in minutes. | 42 minutes present |
| Backlog rot | Creation outruns closure and the graph becomes a place ideas go to die. | Create to close ratio above about 1.5 to 1. | 3.7 : 1 present |
| Phantom work | Old open nodes nobody will ever do, which poison every ready query with noise. | Backlog median age, and the count past 90 days. | 26d, 34 past 90 present |
| Unclaimed work | Agents do work without claiming it, so two of them can collide and you cannot tell who did what. | Claim rate against node count. | 12% present |
| Priority inflation | Everything urgent means nothing is. Top priority stops sorting anything. | Count of open nodes at the top priority. | 39 open watch |
Five of six are present in our own graph. We are not writing that from humility. It is what the script returned, and we would rather print it than publish a playbook that cannot survive being pointed at its author.
Two of these have independent confirmation from people running many agents at once. Version drift is a real operational cost:
"Yeah, sometimes beads doesn't um work like it it needs to figure out how to use beads first and like it goes through a couple errors. Version mismatch. Okay."
And the reason a shared durable graph beats having agents talk to each other:
"But the problems that you have with multi-agents is similar to what we saw last week. So I can't have them all listen to each other because they'll poison their the context."
The six numbers above are not our opinion of our graph. They come from a script, and the script works on any task system that can export its nodes and edges as JSONL. It does not require the tool we happen to use.
Take it, run it, and you get the same six measures for your own work, computed the same way, so your numbers are comparable to ours.
# works on any export with one JSON object per line node measure-our-graph.cjs --issues nodes.jsonl --deps edges.jsonl # field names different? map them, no code changes needed node measure-our-graph.cjs --issues jira.jsonl --deps links.jsonl \ --map id=key --map status=state --map created_at=createdDate \ --map closed_at=resolutionDate --map depends_on_id=blockedBy
Definitions matter more than the numbers. If yours are computed differently, the comparison is worthless.
| Measure | Definition | Healthy | Ours |
|---|---|---|---|
| Edge density | Share of nodes carrying at least one dependency edge, of any edge type, in either direction. | Above 30% | 15.5% |
| Median close latency | Median of closed timestamp minus created timestamp, across every closed node. | Hours to days, not minutes | 42 minutes |
| Create to close ratio | Nodes created divided by nodes closed, in the worst single calendar month. | Under 1.5 : 1 | 3.7 : 1 |
| Backlog median age | Median age in days of all open nodes, measured at the export date. | Under 30 days | 26d |
| Claim rate | Share of nodes that ever received a claim, assign or start event. | Near 100% with agents | 12% |
| Open top priority | Count of open nodes at the graph's highest priority value. | Single digits | 39 |
The healthy column is a judgment, not a measurement, and we are stating it as ours rather than as a standard. The definitions are the part that has to be exact.
This page argues for a thing, so it owes you the cases where the thing is a mistake.
There is also a real cost that shows up once several agents write to the same graph. Yegge, talking about the security side of agent systems, named the tradeoff that applies here too.
"which means you can't give them security at the same time as you give them correctness. They'll do a half-ass job of both. And you don't want a half-ass job of either of those, it turns out."
We have written about agent memory before, and the two playbooks solve different halves of the same problem. Reading them in the wrong order will waste your time, so here is the split.
| The Hive Mind Playbook | This playbook | |
|---|---|---|
| Owns | The file based brain. What the agent knows. | The work graph. What the agent should do next. |
| Answers | "What is the state of this project, and what did we decide before?" | "Which piece of work is unblocked right now, and who is on it?" |
| Shape | Markdown files a session reads at startup, plus retrieval over them. | Nodes and dependency edges a session queries. |
| Read it when | Your agent keeps losing project context and re-deciding settled questions. | Your agent keeps doing finished work, or starting work that is blocked. |
They compose. The brain holds the knowledge, the graph holds the queue, and neither one substitutes for the other. Read the Hive Mind Playbook for the knowledge half.
Every quote on this page was verified verbatim against the video's own caption track by a script before it was allowed on the page. 50 quotes were proposed, 40 passed, and the rest were discarded for being paraphrased, merged across a speaker turn, or silently corrected. Timestamps in the citations link directly to the moment in the video.
We fetched and screened 26 talks and kept 13 across 12 channels and 614 minutes of runtime. A video was kept only if its transcript carried at least five deduplicated mentions of work graph language, and only if it had at least a thousand views, because a talk nobody watched is not evidence of practice.
This playbook was commissioned with Reddit as a named source. There is no Reddit on this page, and rather than quietly drop the requirement we are showing the work. On 2026-09-06 we ran every route we could think of. 11 routes, no usable content. The table below is generated by a script that re-runs the probes, so it reports what happened rather than what we remember happening.
| Route | Result | Verdict |
|---|---|---|
| reddit.com search JSON | HTTP 403, 189,908 bytes | blocked |
| old.reddit.com search HTML | HTTP 200, 352,128 bytes | interstitial |
| old.reddit.com listing JSON | HTTP 200, 352,822 bytes | interstitial |
| r.jina.ai text proxy | HTTP 403, 5,801 bytes | blocked |
| redlib.catsarch.com mirror | HTTP 403, 5,699 bytes | blocked |
| safereddit.com mirror | HTTP 200, 4,370 bytes | interstitial |
| libreddit.privacydev.net | HTTP 502, 552 bytes | blocked |
| api.pullpush.io archive | HTTP 200, 13,143 bytes | no-content |
| WebFetch tool | harness refuses: unable to fetch from www.reddit.com | blocked |
| WebSearch allowed_domains=reddit.com | API 400: domain not accessible to the search user agent | blocked |
| WebSearch unfiltered, reddit-targeted query | zero reddit.com URLs returned in the result set | blocked |
One route deserves a fair hearing. The third party archive answers normally and returns real data, so calling it blocked would be wrong. Its index simply stops at 2025-05-19, several months before the tools this playbook is about existed. It is reachable and empty on this subject, which is a different thing from being blocked.
We did not cite a single Reddit thread by title from a search result without reading it. A title is not evidence, and a citation you cannot open is worse than an admitted gap. If you can reach these threads from your network, your reading of them is better than ours, because ours does not exist.
measure-our-graph.cjs on 2026‑08‑31.