Splitting user stories small enough for a coding agent

Stefan-Iulian Tesoi · · 7 min read

Dozens of drill bits and cutters of every size standing in a worn workshop block — the graded set you pick from when the only question that matters is which size actually fits the job

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:

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 signalWhat it looks likeThe split it implies
The title contains "and""Import contacts and dedupe them"One item per verb
The criteria disagree about the subjectSome 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 shrugAnything 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:

  1. 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."
  2. The paths it touches, because the parent's repository field does not travel automatically.
  3. Its own criteria, checkable without the siblings.
  4. Its dependencies, named as items — not implied by numbering. "Part 3" does not tell an agent that part 2 must land first; dependsOn does.

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:

  1. A valid CSV of up to 1,000 rows creates that many contacts, with a count returned.
  2. A row with an email that already exists updates that contact rather than creating a duplicate.
  3. A malformed row is rejected with its line number, and the rest of the file still imports.
  4. A file over 10 MB is refused before upload starts, with a message naming the limit.
  5. Existing contacts created before this feature get the new source field backfilled.
  6. 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.