Splitting user stories small enough for a coding agent
Stefan-Iulian Tesoi · · 7 min read

A story is small enough for a coding agent when one run produces something you can review in a single sitting, and every acceptance criterion can be checked without waiting on another item. Splitting user stories to meet that test usually means one observable outcome per item, rather than one component per item.
The distinction sounds pedantic and is the whole thing. "Add the API endpoint" and "add the form that calls it" are two components of one outcome; neither can be demonstrated alone, and an agent that finishes the first has produced nothing anyone can accept. "A user can save a draft" is one outcome that happens to touch both.
How small is small enough for an agent?
Small enough that the work and its proof fit in one pass, which is a sharper limit than the one teams used for people.
Three tests, and an item has to pass all three:
- One agent run. If the work cannot plausibly be done in a single session, the agent will either stop halfway or improvise the rest. Both are worse than a smaller item.
- Reviewable in one sitting. A diff nobody finishes reading is a diff nobody checks. This is the limit that bites first on a team where agents produce faster than people review.
- Independently checkable. Every criterion verifiable without another item landing first. A criterion that depends on unshipped work is a criterion that will be skipped.
The second test is the one teams underestimate. Agent throughput moves the bottleneck to review almost immediately, and an item sized for what an agent can build rather than for what a person can check just relocates the queue.
What are the signs an item is really six?
Four, and each points at a different split.
| The signal | What it looks like | The split it implies |
|---|---|---|
| The title contains "and" | "Import contacts and dedupe them" | One item per verb |
| The criteria disagree about the subject | Some say "the admin", others "the customer" | One item per actor |
| It names a component, not a result | "Update the billing service" | One item per observable outcome |
| The estimate is a shrug | Anything at 13 points or "we'll see" | Split until each piece is estimable, then re-add |
The third is the most common and the least visible, because a component-shaped item reads like good engineering. It is good engineering; it is just not a unit of work anyone can accept or reject. That is what vertical slicing means in practice: a vertical slice cuts through every layer to produce one demonstrable result, rather than delivering a layer at a time.
The usual story splitting techniques all point the same way. Bill Wake's INVEST criteria named the property in 2003: a user story should be Independent, Negotiable, Valuable, Estimable, Small and Testable. Every one of those is harder to satisfy with an agent than with a person, because a person fills the gaps by asking and an agent fills them by guessing.
Does splitting user stories change the estimate?
Yes, and upward — by a factor rather than a margin. That is not a failure of the split.
Take a thirteen-point story to bulk-import contacts from a CSV file: split properly it becomes six children totalling twenty-six points. The first reaction is usually that the split has gone wrong. It has not. The thirteen was never an estimate of the work; it was an estimate of the part of the work that was visible while the item was still vague. Splitting it makes three things appear that nobody had priced: a migration for existing rows, an empty state nobody had designed, and a permission check that turns out to be its own decision.
The number did not go up because the work grew. It went up because the work stopped hiding, and the earlier number was wrong in the direction that always hurts most — optimistic, late, and already committed to.
This is why re-estimating after a split is worth the ten minutes. A large item carries an estimate of its understood portion, and the gap between that and the real number is discovered at the worst possible moment. The right size for AI agent tasks is partly a sizing question and mostly a visibility question: small items are honest, and large ones are optimistic by construction.
How do you split without losing the context?
Give every child the context the parent held, rather than a pointer back to the parent.
This is where splitting most often fails on an agent-consumed backlog. A person picking up child four reads the epic, remembers the standup, and proceeds. An agent picking up child four has that item and nothing else. If the parent held the repository, the constraint and the reason, and the children hold "part 4 of 6", the split has converted one workable item into six unworkable ones.
Four things every child needs in its own text:
- The outcome, stated whole. Not "the second half of the import" but "an imported contact with a duplicate email updates the existing record instead of creating a second one."
- The paths it touches, because the parent's repository field does not travel automatically.
- Its own criteria, checkable without the siblings.
- Its dependencies, named as items — not implied by numbering. "Part 3" does not tell an agent that part 2 must land first;
dependsOndoes.
Laimonade drafts the children with those four fields filled in rather than inherited, which is the part that decays fastest when a person does it under time pressure — the fifth child of a split is always thinner than the first. A person still decides where the seams go, because that is a product judgement about what is worth shipping separately. The sprint workflow covers how the children reach an agent once they exist, and what an AI product owner actually does sets out where that sits in the role.
A worked split: one story into six
"Bulk import contacts from CSV", thirteen points, became these:
- A valid CSV of up to 1,000 rows creates that many contacts, with a count returned.
- A row with an email that already exists updates that contact rather than creating a duplicate.
- A malformed row is rejected with its line number, and the rest of the file still imports.
- A file over 10 MB is refused before upload starts, with a message naming the limit.
- Existing contacts created before this feature get the new
sourcefield backfilled. - Only a workspace admin can start an import; a member sees the button disabled with a reason.
Items five and six did not exist before the split. Item three was one clause inside the original, and it is the one that took longest. Each child names its own outcome, and none of them needs another to be accepted — which is what makes them safe to hand out in any order, or in parallel. The four defects in a backlog an agent can actually read are mostly what goes wrong when that is skipped.
Frequently asked questions
Should every story fit in one agent run?
Nearly every one, yes, and treat the exceptions as a signal rather than a category. An item that genuinely cannot be finished in one run is usually carrying a decision nobody has made, and the honest split separates the decision from the work. Where the size is real rather than hidden ambiguity, say so in the item so the reviewer knows what to expect.
How do you handle work that genuinely cannot be split?
Split what surrounds it and keep the irreducible core as one item, clearly labelled. A database migration, a cryptographic change or a protocol upgrade sometimes has no seam that produces value halfway. Everything around it usually does — the feature flag, the backfill, the read path, the rollback — and separating those shrinks the part that must land atomically.
Do split items need their own acceptance criteria?
Yes, and criteria inherited from the parent are the commonest defect in a split backlog. Each child is accepted or rejected on its own, so "as per the parent story" gives a reviewer nothing to check and an agent nothing to build against. If a criterion genuinely applies to every child, it belongs in each of them in full, not by reference.
Does splitting increase the total work?
No, but it usually increases the recorded estimate, and the two get confused. The work was always there; splitting makes the parts that were never priced visible. If your split totals are consistently double the parent, that ratio is useful information about how much your large items are hiding, and it is worth tracking on purpose.