Acceptance criteria are the conditions a piece of work must meet for the person who asked for it to accept it. They describe what the software does that someone could observe, not how it's built. The test of a good one is simple: two people reading it, or a person and an automated test, would agree on whether the work passes without asking anyone. Most acceptance criteria I've reviewed in 15 years of product and design work fail that test. They restate the requirement in slightly firmer language. Below are six acceptance criteria examples rewritten from vague to testable, a template you can copy, and the reason this matters more as of October 2026, when a growing share of code is written by agents that take your words literally.
What are acceptance criteria?
Acceptance criteria are the conditions a piece of work must meet for the person who asked for it to accept it. They describe observable behavior, not implementation. Good ones are specific enough that two people, or a person and a test, would agree on whether the work passes without having to ask anyone.
That last clause is the one teams skip. A criterion like "search results are relevant" feels like it says something. Then the demo happens, the product owner types a query, and the argument starts. Was that result relevant? To whom? Compared to what?
Acceptance criteria exist to move that argument earlier. The cheapest time to disagree about what "done" means is before anyone has written code.
What makes acceptance criteria testable?
A criterion is testable when it names a starting state, an action, and an observable result, with no words that need interpretation. Phrases like fast, intuitive, or user-friendly fail that test. Numbers, named states, exact messages and explicit edge cases pass it. If you can't imagine the failing case, the criterion isn't finished.
I use one question as a filter: what would a failing result look like? If I can describe it precisely, the criterion is testable. If I can't, the criterion is a wish.
Most fixes come from replacing adjectives with thresholds. "Fast" becomes "within 2 seconds on the staging dataset."
The rest come from naming the edge case out loud: empty input, the maximum size, the expired link, the second click. And if the user sees text, write the text. Otherwise someone will invent it at 6pm the day before release.
What are some acceptance criteria examples?
The six examples below each start with a criterion that sounds reasonable and fails in practice, then rewrite it twice. The middle version adds specifics. The final version is testable: it names the state, the action and the result. They cover search, password reset, file upload, discount codes, notifications and keyboard access.
These are composites written to show the pattern, not criteria from a real backlog. The numbers are placeholders for whatever your product actually needs.
| Sounds fine | Better | Testable | |
|---|---|---|---|
| Search | Search returns relevant results. | Search matches product names and descriptions. | Given a product named "Trail Runner 2," when a user searches "trail runner," then that product appears in the first 5 results. When a search matches nothing, the page shows "No results for [query]" and a link to browse all products. |
| Password reset | Users can reset their password easily. | Users get a reset email with a link. | When a user requests a reset for a registered email, they receive one email within 5 minutes. The link works once and expires after 60 minutes. An expired or used link shows "This link has expired" and a button to request a new one. |
| File upload | Users can upload large files. | Uploads support files up to 50 MB. | A PDF, PNG or JPG up to 50 MB uploads successfully. A 51 MB file is rejected before upload starts with "Files must be 50 MB or smaller." Any other file type is rejected with "Upload a PDF, PNG or JPG." |
| Discount code | Discount codes work at checkout. | Valid codes reduce the order total. | Given a cart of $80 and an active 10% code, when the code is applied, the total shows $72. An expired code shows "This code has expired" and the total is unchanged. A second code replaces the first; codes never stack. |
| Notifications | Users are notified promptly. | Users get a notification when they're mentioned. | When a user is mentioned in a comment, they receive an in-app notification within 1 minute. If they're mentioned 5 times in one thread within 10 minutes, they receive one notification, not five. |
| Keyboard access | The form is accessible. | The form works with a keyboard. | Every field and button on the form can be reached with Tab in visual order and activated with Enter or Space. Focus is always visible. After a failed submit, focus moves to the first field with an error. |
Look at the middle column. That's where most real backlogs stop. It reads like progress, and it still leaves the important questions open: what happens at 51 MB, what the expired link says, whether codes stack. The third column answers them before a developer has to guess.
Should acceptance criteria use Given/When/Then?
Use Given/When/Then when the behavior depends on a starting state, because the format forces you to name it. Use a plain checklist when the criteria are independent constraints, like limits or formats. Mixing both in one story is fine. The format matters less than whether each line can fail.
Given/When/Then comes from behavior-driven development, associated with Dan North and Chris Matts, and it's the shape behind the Gherkin syntax that many test tools read. Its real gift is the "Given." Most ambiguous criteria are ambiguous because they never said what was true before the action. The discount example only works because it starts with a specific cart.
The checklist form is better for constraints that don't depend on state. File size limits, allowed formats, character counts. Forcing those into Given/When/Then makes them longer without making them clearer.
Here's the template I keep in a snippet, with both forms:
Story: As a [role], I want [capability] so that [outcome].
Acceptance criteria: behavior
- Given [starting state], when [action], then [observable result].
- Given [starting state], when [action], then [observable result].
Acceptance criteria: constraints
- [Limit or format, with the number]
- [Exact message shown when the limit is broken]
Edge cases checked
- Empty / zero:
- Maximum:
- Repeated action (double click, second request):
- Expired or invalid state:
Out of scope for this story
- [What a reviewer might expect but this story deliberately doesn't do]
The "out of scope" section is the one people delete and shouldn't. It's where you write down the argument you're choosing not to have yet.
How are acceptance criteria different from the definition of done?
The definition of done is the team's standing quality bar, and it applies to every piece of work: reviewed, tested, documented, deployed. Acceptance criteria apply to one story and describe what that story must do. A story can meet its acceptance criteria and still not be done, if it skipped the team's bar.
The Scrum Guide defines the definition of done. It doesn't define acceptance criteria, which is part of why teams blur the two. A useful way to keep them apart: acceptance criteria answer "does it do the right thing?" The definition of done answers "is it finished to our standard?"
The confusion shows up as stories with criteria like "code is reviewed" or "tests pass." Those aren't wrong. They belong in the team's definition of done, so they don't have to be repeated in every story.
Why do acceptance criteria matter more when AI agents write the code?
Because an agent will satisfy exactly what you wrote, including the gaps. A human developer fills ambiguity with judgment and questions. An agent tends to fill it with a plausible guess. Testable acceptance criteria are the closest thing a team has to a specification an agent can be checked against.
I wrote about this shift in agentic software engineering: when agents do more of the implementation, the human work moves toward specification and verification. Acceptance criteria are where those two meet. The same line that tells the agent what to build tells the reviewer what to check.
The middle column of the table above is the dangerous one here. "Uploads support files up to 50 MB" will produce code that accepts 50 MB files. It says nothing about what happens at 51, so the agent picks something. Sometimes it picks well. The point of the third column is that you don't have to find out.
This connects back to scope, too. An MVP is the smallest thing that tests your core hypothesis, and acceptance criteria are how you keep it small on purpose. Every criterion is a commitment. Writing them down is how a team notices it's committed to more than it meant to.