Writing stories a coding agent can execute
What an agent needs that a teammate would infer: the outcome, the reason, testable criteria, what not to touch, and the check that proves it done.
A story written for a teammate leaves gaps that the teammate fills from context: the conversation at planning, last month's incident, the convention nobody wrote down. A coding agent fills the same gaps with plausible guesses. The result compiles, passes the tests the agent wrote for itself, and solves a slightly different problem from the one you meant.
In our experience that is the most common way agent work goes wrong, and it starts in the backlog, not in the model. This article covers what an agent needs from a story that a person would infer, with a template and a worked example. It assumes an agent that can read your repository, edit files and run commands, such as Claude Code, OpenAI Codex or Cursor's agent.
What changes when the reader is an agent
Four differences drive everything else.
- It starts from nothing. Each session begins with an empty context. Anything that is not in the story, in the repository's instruction files or somewhere the agent can look it up is unknown to it, including what was decided in yesterday's discussion.
- It resolves ambiguity instead of asking. A person unsure about a requirement asks. An agent usually picks the most plausible reading and carries on, unless you have told it to stop and ask. You find out at review, after the code exists.
- It optimises for the check you give it. If the only check is "the tests pass", it will make the tests pass, including tests it wrote itself. Whatever check you define is, in practice, the specification.
- It is literal about scope. Given "add CSV export to the backlog", it adds CSV export to the backlog, and not to the sprint view that shows the same list, unless the story says so.
The consequence is simple. Every gap in a story becomes a guess, and the verification step becomes the real spec. Write the story so that both are deliberate.
The anatomy of an agent-ready story
Six parts cover almost every story, and none of them is long.
- Outcome. One sentence, in terms of what a user or another system can observe afterwards. Not the implementation.
- Why. One or two sentences on the problem. It lets the agent choose sensibly between options you did not anticipate.
- Acceptance criteria. Observable, decidable statements, including the "must not" ones. They have their own article: acceptance criteria for AI coding agents.
- Out of scope and must not change. What the agent should leave alone: neighbouring features, public interfaces, existing tests.
- Pointers. The files, modules and existing patterns to follow, and any architecture decision that constrains the change.
- Done when. The commands that prove the work is complete, and the evidence to return with the pull request.
Here is a story written the usual way:
Add CSV export to the backlog.And the same story written for an agent:
Title: Export the filtered backlog to CSV
Outcome: From the backlog page, a user can download the stories they can see,
with the current filters applied, as a CSV file.
Why: Teams copy the backlog into spreadsheets for quarterly planning, and they
do it by hand today.
Acceptance criteria:
1. Export downloads exactly the stories the current filters show, in the
current sort order.
2. Columns: key, title, status, assignee, points, sprint, epic, updated (UTC).
3. Titles containing commas, quotes or line breaks open unchanged in a
spreadsheet.
4. Above 5,000 rows, the user confirms before the export starts.
5. A user never receives stories from a project they cannot open.
Out of scope: scheduled exports, Excel format, comments.
Must not change: the backlog's existing filter and sort behaviour.
Pointers: the defects page already exports CSV; follow that pattern and reuse
its pagination helper. No new dependencies.
Done when: new tests cover criteria 1 to 5, the existing backlog tests pass,
and the pull request lists each command run with its output.The second version is about a screen longer, and every line in it removes a guess. Criterion 5 is the one an agent is least likely to invent and the one you would least like it to get wrong.
Size the story to one reviewable change
Agents make large changes cheap to produce and no cheaper to review. The limit on agent work is rarely typing speed; it is the attention of the person who has to read the diff. A story that produces a pull request nobody can review in one sitting is a story that will be approved without being read.
Split a story when its acceptance criteria run past about seven, when they touch unrelated parts of the system, or when the "done when" section needs more than a handful of commands. Vertical slicing works for agents as it does for people: each slice delivers one observable piece of behaviour end to end, which also gives each slice its own clean check.
Say what not to touch
Agents widen scope in predictable ways: a refactor of the function next door, a reformatted file, an updated snapshot, a "fixed" test that was failing for a reason. Some of it is helpful, and all of it lands in your review. State the boundaries outright:
- Existing tests may not be edited or deleted to make new ones pass.
- Public interfaces, database schemas and configuration stay as they are unless the story says otherwise.
- New dependencies are named in the pull request, or not added at all.
The opposite problem is just as common. If the behaviour you are changing exists in more than one place, such as a list and its export, a web route and its API twin, or a page and its mobile layout, name every place or tell the agent to search for the siblings first. Agents fix the instance they were shown. In Stride's own repository, a fix that reached one surface and missed its sibling is a defect our reviews keep finding.
Point, don't paste
Link to files and patterns rather than pasting code into the story. The agent reads the current code; a pasted snippet is out of date the moment someone merges. The same applies to the story itself. If the agent reads it from your tracker when it starts, it sees the version someone edited this morning, not the one pasted into a prompt last week. That is the case for giving agents backlog access over MCP.
Knowledge that applies to every story, such as how to run the tests, which directories are generated and what your reviewers always ask for, belongs in the repository's instruction file, so that no story has to repeat it. See AGENTS.md and CLAUDE.md for coding agents.
Write the check before the work
Anthropic's guidance for Claude Code puts it plainly: "Give Claude a check it can run: tests, a build, a screenshot to compare." Without one, the agent stops when the work looks done, and you become the verification step.
The "done when" section is where that check lives. Good ones are commands with an expected result: a test file that must pass, a type check, a lint run, a script that compares output to a fixture. Weak ones are adjectives, such as "works correctly" or "is fast". If you cannot say how you would verify the story yourself, the agent cannot either, and the story is not ready. Writing the tests before the code is the strongest version of this; see test-first development with coding agents.
When not to hand a story to an agent
Some work is better kept with a person, or at least paired closely.
- Unresolved product decisions. If an acceptance criterion would need to say "decide whether", decide first.
- Changes nobody on the team can review. An agent-written change to cryptography, billing or permissions needs a reviewer who knows that code.
- Irreversible operations. Data migrations and anything that touches production data need a person at the controls.
- Work with no automatable check, such as subjective visual polish, unless you can give the agent screenshots to compare against.
Checklist before you hand it over
- The outcome is one sentence a user or system could observe.
- Every acceptance criterion can pass or fail, and the "must not" cases are written down.
- Out of scope and must not change are explicit, and sibling surfaces are named.
- Pointers name the files and the pattern to follow.
- "Done when" lists commands and says what evidence comes back in the pull request.
- The whole story fits one pull request a person can review in one sitting.