Backlog dependencies in an agent-run sprint
Stefan-Iulian Tesoi · · 6 min read

Make every dependency explicit on the item that has it, then check the resulting order can actually be executed. Backlog dependencies fail in a specific way: two individually sensible items each require the other's output, and nobody notices until an agent stops halfway with one criterion it cannot satisfy.
That failure is worth naming because it does not look like a planning error when it happens. It looks like an unfinished checkbox.
Why does sequencing matter more with agents?
Because a person routes around a missing dependency and an agent cannot, and the difference only shows up under load.
Hand a developer an item whose prerequisite has not landed and they build the other half, stub it, or go and ask — each a judgement about work outside the item they were given. An agent has the item and the repository, and neither tells it that the endpoint it needs is somebody else's story two rows down the same sprint.
That was survivable when a sprint contained eight items and one person held the order in their head. Sprint sequencing stops being mental arithmetic at the point where several agents pull work in parallel and the order they pull in is not the order anyone imagined.
What is a circular acceptance criterion?
Two items whose criteria each require the other to be finished first. Neither can be accepted, and both look complete in isolation.
A real shape it takes:
Item A — "The importer reads the new
sourcecolumn." Item B — "The migration backfillssourcefor rows the importer created."
Both are well written. Both name a repository, an outcome and acceptance criteria you could test. Read together they cannot both be first, and nothing in either item says so — the dependency is in the criteria, not in the description, which is where nobody looks for it. This is what circular dependencies in stories actually look like in practice: not a diagram with an arrow bending back on itself, but two tidy items that quietly reference each other's finished state.
The tell is a criterion written in the past tense about work that has not happened. "Rows the importer created" assumes an importer that creates rows — and if the item building it sits in the same sprint, that sentence is a dependency wearing the clothes of a description.
How do you record backlog dependencies on the item?
Name the other item, on the item that is blocked, in a field rather than in prose.
Prose dependencies are the ones that get missed. "After the auth work lands" is clear to whoever wrote it and invisible to anything parsing the item: there is no such thing as the auth work, only a specific item with an id, and the id is what survives being read by something that was not in the room.
| How the dependency is recorded | What a coding agent does with it |
|---|---|
| Not recorded at all | Starts, guesses at the missing half, produces a plausible wrong thing |
| In the description as prose | Starts, because nothing it can parse says otherwise |
| In the title as "part 2 of 3" | Starts, because ordinal position is not a prerequisite |
| As a dependency on the item, naming the other id | Does not start, and says why |
Only the last one changes behaviour. The first three are notes to a human reader who is not the one picking the item up.
Record which direction it runs and what specifically is needed. "Blocked by #412" beats prose; "blocked by #412 for the source column it adds" beats both, because it tells a reviewer whether a partial delivery unblocks you — and partial deliveries are most of what actually happens.
How do you find the problem before the sprint starts?
Sort the dependency graph and see whether it sorts. A cycle is the answer, and it takes about a minute.
This is one of the rare planning problems with an exact answer rather than a heuristic: a valid order exists if and only if the dependency graph has no cycle. POSIX tsort has sorted such pairs and named the cycles since the 1970s, and it takes your sprint as two columns of ids on standard input.
The manual version, for a sprint of twenty:
- Write each dependency as a pair, blocker first.
- Sort them. Anything that cannot be placed is in a cycle, and the cycle is named.
- For each cycle, split one of the items so that the half the other needs can land alone.
- Re-check the criteria, not just the descriptions, because that is where circular ones hide.
Step three is the actual work, and it is nearly always a split rather than a re-ordering. A cycle means neither item can go first, so the fix is to make a smaller piece that can — usually the schema change, the interface, or the flag, separated from everything that consumes it.
Laimonade checks the order before the sprint is handed out rather than after: an item whose dependency has not been delivered does not reach the Ready column, so sequencing backlog items is a property of the sprint rather than a meeting. A person still decides what is worth splitting when a cycle turns up. The sprint workflow sets out where that check sits.
What should an agent do when it hits a blocker?
Stop and report it against the item, naming what is missing — not improvise the missing half.
This is the behaviour that makes the whole thing safe, and it is the opposite of the instinct. Building the missing half feels helpful and produces the worst outcome available: the work now spans two items, the review covers one of them, and the other item's own agent builds it again next week.
So the rule is narrow: an agent reports the blocker and moves on. The item goes back with the missing fact named, and a person decides whether to split, re-order or accept a stub. It is also why the executor cannot mark anything done — it reaches In Review and no further, and a blocked item does not reach even that. Troubleshooting covers what a stuck item looks like from the outside.
The four defects in a backlog an agent can actually read include this one, and it is the only one of them that gets worse rather than better as the team gets faster.
Frequently asked questions
Should dependencies be links or text?
Links, always, and text as well if a human needs the reason. A link is a fact a machine can act on; prose is a note to whoever already understood the situation. The practical test is whether the dependency survives being read by something that was not in the conversation — "after the auth work" does not, and an item id does.
What if two teams own the two halves?
The dependency is the same and the resolution is slower, so record it earlier. A cross-team cycle is not a different problem, it is the same cycle with a longer feedback loop, and the cost of discovering it mid-sprint is measured in days rather than hours. Name the item and the owner on the blocked side, so the person chasing it knows who to ask.
Can an agent resolve its own blocker?
It should not, even where it could. Building the missing half converts one item into two items' worth of work reviewed as one, and the other item stays open to build the same thing again. Reporting the blocker costs a minute and keeps the unit of work and the unit of review the same size, which is the property that makes returned work checkable at all.
Does every item need a dependency field filled in?
No, and most items have none. The field matters precisely because it is usually empty: an item with a dependency is unusual, and an empty field is a statement that this item can start today. Filling it in defensively — "depends on the epic" — makes the signal useless, which is worse than leaving it blank.