skip to content

When does an agent plan need a dependency DAG instead of a linear todo list?

level: seniorimportance: should knowfreq 48%

answer

  1. total order versus partial order
  2. most plans over-constrain themselves
  3. edges buy two specific things
  4. concurrency and blast radius
  5. stages as the cheap middle option

basics

~20 s

A linear list is enough while every step genuinely depends on the one before it. Model an explicit dependency graph once steps are independent, once you want to run branches concurrently, or once a step's real prerequisites are not the item directly above it.

solid answer

~50 s

A todo list encodes a *total* order, which is a lie whenever the work is only *partially* ordered — and that lie costs you two things: concurrency you could have had, and the ability to reason about what a failed step actually blocks. Take an M&A due-diligence agent over 12,000 documents: collect must precede dedupe, and dedupe must precede both privilege screening and summarization, but privilege screening and summarization do not depend on each other. Written as a list, those two look sequential and a failure in one appears to block the other. Written as a DAG, the independent branches are visible, and when privilege screening stalls you can see that summarization is unaffected. The cost is that a graph is more machinery for the model to maintain, so I keep a list until either concurrency or blast-radius reasoning actually pays for the edges.

code

yaml · 16 lines
yaml
tasks:
  - id: collect
    desc: Pull all documents from the data room
    depends_on: []
  - id: dedupe
    desc: Collapse near-identical document versions
    depends_on: [collect]
  - id: privilege_screen
    desc: Flag attorney-client material
    depends_on: [dedupe]
  - id: summarize
    desc: Summarize each contract family
    depends_on: [dedupe]
  - id: assemble
    desc: Write the diligence memo
    depends_on: [privilege_screen, summarize]

go deeper

for a junior

Know the difference: a todo list says every step follows the previous one, while a dependency graph says only the stated links are real. Be able to point at two steps in a plan that could happen in either order.

for a middle

Explain that a list imposes a total order on partially ordered work, and give a concrete pair of steps that share an input but not an ordering, plus what a graph would let you do with them.

for a senior

Show the design judgment: name what the edges are for — concurrency and reasoning about what a failure blocks — justify each edge by data flow or shared state, and say when a plain list or a staged plan is the better call.

for a principal

Own the standard: decide fleet-wide whether plans carry explicit dependencies, since that choice determines whether failure impact can be computed automatically or has to be reasoned about by a human on every incident.

## Two ways to write the same plan A plan is a set of subtasks plus an ordering. The cheapest representation is a linear todo list — an ordered sequence, worked top to bottom, each item ticked off as it completes. The richer representation is a directed acyclic graph: nodes are subtasks, edges are "must finish before", and anything with no path between it is independent. The difference is not cosmetic. A list encodes a **total order**: every item is claimed to come after every item above it. A DAG encodes a **partial order**: only the stated edges are real, and everything else is free. Most real work is partially ordered, so a list systematically over-constrains it. ## Where the edges actually come from A genuine edge exists when one subtask consumes something another produces, or changes state the other reads. In practice they come from three places: 1. **Data flow** — step B's input is step A's output artifact. 2. **State mutation** — A writes to a resource B reads, so B sees a different world depending on order. 3. **Gating decisions** — A determines whether B should run at all, or with what scope. Everything else is incidental sequencing: an artifact of the order the model happened to emit the steps in, not a constraint. ## A worked example An M&A due-diligence agent is given 12,000 documents. Its decomposition is roughly: **collect** the documents from the data room, **dedupe** near-identical versions, **privilege-screen** for attorney-client material, **summarize** each contract family, and **assemble** the final memo. The real edges are: collect → dedupe; dedupe → privilege-screen; dedupe → summarize; privilege-screen → assemble; summarize → assemble. Note what is *missing*: there is no edge between privilege screening and summarization. They read the same deduplicated corpus and write different artifacts. Written as a list, those two sit one above the other and look ordered. Two consequences follow. First, you serialize work that could have run as two branches, roughly doubling wall-clock for that stage. Second, when privilege screening fails on a batch, the list gives you no way to answer "what is still safe to proceed with?" — the graph answers it immediately: summarization is untouched, assembly is blocked. ## When the edges do not matter A DAG is not free. It is more structure for the model to emit correctly, more state to keep in sync, and more machinery in whatever executes the plan. Keep the list when: - the plan is short and genuinely sequential — each step consumes the last one's output; - there is no concurrency available anyway, because a single bottleneck resource serializes everything; - the steps are cheap enough that serializing them costs less than the complexity of the graph. The honest rule of thumb: introduce edges when you will *use* them — to run branches concurrently, or to compute what a failure blocks. Modelling dependencies you never query is ceremony. ## Representing it so a model can hold it The graph has to survive contact with an LLM that re-reads it every turn. What works is keeping it small and explicit: each node gets a stable id, a one-line description, a status, and a `depends_on` list of ids. Anything not listed is independent — stating that convention in the plan itself matters, because otherwise the model re-imposes reading order as if it were dependency order. A flat file of such nodes reads as a list *and* carries the edges, which is usually the right compromise over a nested structure the model has to mentally flatten. A middle option is a **staged plan**: an ordered sequence of stages, with the items inside a stage unordered and independent. That captures most of the available concurrency with far less structure than arbitrary edges, and it is easy for a model to maintain. It is the right default for pipelines whose shape is stage-like. ## What interviewers are listening for Strong answers frame this as "is the work totally ordered or partially ordered?" and then name the two things edges buy — concurrency and blast-radius reasoning — rather than asserting that graphs are simply better. They also acknowledge the cost, and they note the crucial caveat: a DAG makes the *claimed* structure explicit, it does not make it *correct*. The model can assert an edge that does not exist or omit one that does, which is exactly why edges should be justified by data flow or shared state rather than by narrative plausibility.

  • How would you represent a dependency graph so an LLM can maintain it every turn?
    Keep it flat and explicit: one line per node with a stable id, a short description, a status, and a `depends_on` list of ids. State the convention that anything not listed is independent, otherwise the model quietly re-reads document order as dependency order. Nested structures force the model to flatten them mentally each turn, which is where corrupted edges creep in.
  • When is a staged plan good enough instead of a full DAG?
    When the work is naturally pipeline-shaped: an ordered sequence of stages, with the items inside each stage independent of one another. That captures most available concurrency with far less structure to maintain, and it is much harder for a model to corrupt than arbitrary edges. Reach for a full graph only when real dependencies genuinely cross stage boundaries.
  • What can go wrong when the model itself proposes the dependency edges?
    It can assert edges that do not exist — serializing independent work for no reason — or omit real ones, which is worse because two steps then race over shared state. Plausible narrative order is not data flow. The mitigation is to require each edge to name what is passed or shared, and to have the executor, not the model, enforce ordering.

A todo list is a single assembly line where each station waits for the one before it; a dependency graph is the same factory drawn honestly, showing that painting and packaging materials are prepared on separate benches and only meet at final assembly.

saying these in an interview costs you the question

  • Claims every agent plan should be modelled as a graph
  • Treats list position as if it encoded a real dependency
  • Assumes a DAG makes the model's claimed dependencies correct
  • Adds edges that are never queried by anything
  • Sees only concurrency, missing the failure-scope reasoning edges enable

context