All articles in AI coding agents
AI coding agents

Acceptance criteria for AI coding agents

For an agent, acceptance criteria are the contract. Write each so a test can check it, add the "must not" cases, and tie every criterion to its test.

7 min read

For a person, acceptance criteria are a reminder of what was agreed. For a coding agent they are the contract. The agent will satisfy what the criteria say, as literally as they say it, and it will not satisfy what they leave out. Criteria written as intentions ("handles errors gracefully", "works on mobile") produce code that passes the agent's own reading of the intention, which is rarely yours.

This article covers how to write criteria an agent can build to and a test can check, the criteria agents most need and rarely infer, and how to keep each criterion tied to the test that proves it.

What makes a criterion usable by an agent

A good criterion has four properties.

  • Observable. It describes behaviour you can see from outside the code: a response, a screen state, a stored value, a message. "Uses a cache" is not observable; "a second request within a minute returns without querying the database" is.
  • Decidable. A test can pass or fail on it. "Fast" is not decidable; "returns within 300 ms for a 1,000-row backlog on the CI runner" is.
  • Bounded. One behaviour per criterion. A criterion with "and" in the middle is usually two.
  • Explicit about the edges. It says what happens at the boundary: empty input, the maximum, the failure case, the user without permission.

The difference in practice:

Written as an intentionWritten as a criterion
Handles errors gracefullyIf the export request fails, the button returns to its idle state, a message names the failure, and no partial file downloads.
Works for large backlogsAbove 5,000 rows, the user confirms before the export starts; below that, the export starts immediately.
Is secureA user never receives stories from a project they cannot open, including through a filter that names that project.
Uses the right datesDates are written in UTC as ISO 8601, for example 2026-09-27T14:05:00Z, whatever the viewer's time zone.
Keeps existing behaviourThe backlog's current filter and sort results are unchanged, and the existing backlog tests pass without edits.

Each rewrite is longer. Each also turns into a test in a few minutes, which is the point.

The "must not" criteria agents rarely infer

Most criteria describe what should happen. The ones agents most need describe what must not. A person on your team knows that a list must not show another customer's rows, that an export must not include deleted items, and that a migration must not lock a large table during business hours. An agent knows none of this unless the story or the repository tells it.

Write negative criteria for:

  • Access boundaries. Who must not see or change the thing.
  • Data that must not leave. Deleted, archived, private or other-tenant records.
  • Behaviour that must not change. The existing contract of anything the change touches.
  • Resources that must not run away. Unbounded queries, loops over user input, retries without backoff.

Rules that apply to every story belong in the repository instead. Stride's own instruction file states several of this kind, such as that every read query filters out deleted rows and that every identifier arriving in a request is checked against the caller's workspace before it is used. Repository rules cover every story; negative criteria in the story cover the cases specific to it.

Given/When/Then, when it helps

The Given/When/Then form of Gherkin is useful when behaviour depends on state: given a filtered backlog with 12 stories, when the user exports, then the file has 12 rows in the same order. It forces the setup to be explicit, which is exactly the part agents otherwise invent.

It is not required. A plain sentence that is observable, decidable and bounded works as well, and for simple rules it reads better. Use Given/When/Then where the setup matters and plain prose where it does not. If your team already practises acceptance test-driven development, the criteria and the acceptance tests can be the same text.

Keep every criterion tied to its test

A criterion without a test is a promise nobody checks. When an agent implements a story, ask it to write at least one test per criterion first, named or tagged so that the mapping is visible in the pull request. The reviewer can then read down the criteria and find the test for each one, instead of trusting a summary.

Stride keeps this mapping in the product. Each acceptance criterion has a stable identifier, test cases link to the criterion they cover, and a coding agent connected over MCP can create test cases from a story's criteria with those links already in place; asking again for a criterion that already has a case returns the existing case rather than a duplicate. You can get the same effect in any tracker with a naming convention. What matters is that the link exists and that someone reads it, which is the traceability matrix in its lightest form.

Criteria are not implementation notes

"Use a hash map", "add a column to the stories table" and "call the existing export helper" are not acceptance criteria. They constrain how, not what. Put them in the story's constraints or pointers, where the agent treats them as guidance, and keep the criteria about behaviour. Mixing the two produces stories where the agent satisfies the implementation note and misses the behaviour, and it makes the criteria harder to test.

How many criteria a story needs

Three to seven is typical. Fewer than three usually means the edges are missing: there is a happy path and nothing about failure, permissions or limits. More than seven usually means the story is really two, and splitting it gives each half a smaller diff and a cleaner check. The number matters less than the coverage; a story with four criteria that include the failure case and the permission boundary is better specified than one with nine happy paths.

Who writes them, and who approves them

AI is good at drafting acceptance criteria from a story description, and it tends to think of edge cases a tired person skips. Stride drafts them when it writes a story, and most assistants can do the same. The drafting is not the risk. The risk is approving a criterion nobody read, because a wrong criterion produces a correct-looking wrong feature, complete with passing tests.

So review criteria harder than you review code. Read each one and ask: if the agent satisfies exactly this, and nothing more, will the story be done? Add the "must not" cases, cut the vague ones, and split anything that has grown past seven.

Stride drafts test cases from a story's acceptance criteria and keeps each one linked to the criterion it covers, whether a person or a coding agent created it.

See test cases drafted from acceptance criteria

Frequently asked questions

What makes an acceptance criterion testable?
It describes behaviour you can observe from outside the code, a test can pass or fail on it, it covers one behaviour, and it says what happens at the edges: empty input, the limit, the failure case and the user without permission. "Handles errors gracefully" fails all four; "if the export fails, the button resets and a message names the failure" passes.
Should acceptance criteria for coding agents use Given/When/Then?
Use it when behaviour depends on state, because it forces the setup to be explicit, and the setup is the part agents otherwise invent. For simple rules, a plain sentence that is observable and decidable works as well and reads better.
Can AI write acceptance criteria?
Yes, and it often catches edge cases a person skips. The risk is approving criteria nobody read: a wrong criterion produces a correct-looking wrong feature, complete with passing tests. Review AI-drafted criteria harder than you review the code.
How many acceptance criteria should a story have?
Usually three to seven. Fewer than three tends to mean the failure, permission and limit cases are missing; more than seven usually means the story is really two stories.