Skip to content
Pillar · Definition of done

Definition of done for AI agents

By Cat Williams-Treloar, Founder·Updated Oct 10, 2026·15 min read
14 sections

The short answer

A definition of done for AI agents is a short checklist every job must pass before the agent calls it finished. Each line names something you can check, such as a test, a page or a result, and the agent records how it checked each one. "Done" then means checked, not just claimed.

Ask ClaudeAsk ChatGPT

A definition of done is the list of things that must be true before a piece of work counts as finished. For AI agents, it is a short checklist every job passes before the agent says "done", with a record of how each line was checked.

TL;DR
  • An agent stops when the work looks done. A definition of done turns "looks done" into "checked".
  • There are two levels: your team's standard for every job, and the Done When lines for this job.
  • Write each line as "given a state, when an act, then something you can check". One check per line.
  • For every line, the agent records evidence you can follow: a test, a URL, a thread. A line it couldn't check stays unchecked.
  • Merged is not shipped. Done means it works where your customers are, and someone checked.

When to use it: any job you hand to Claude Code, Cursor, Codex or Grok that a customer will touch. When not: a throwaway experiment on a branch nobody will merge. Even then, one line helps.

Why an agent's own "done" isn't enough

Agents finish confidently. They may have written the code, but not run it, or run it locally but not where your customers are. Merged isn't deployed, and deployed isn't checked. Without a checklist, you only find the gap when a customer does.

Anthropic's own advice for Claude Code names the problem plainly: "Claude stops when the work looks done." Without a check it can run, looking done is the only signal the agent has, and you become the person who notices every miss. The same guide's fix is the one this page is built on: give the agent a check that passes or fails, and have it show evidence rather than asserting success.

This isn't a flaw in one model. Any builder, person or agent, works toward the finish line they can see. If the line is vague, the finish is vague.

What is a definition of done?

The idea comes from Scrum. The 2020 Scrum Guide calls it "a formal description of the state of the Increment when it meets the quality measures required for the product." Work that misses it "cannot be released or even presented at the Sprint Review." For the short version, see definition of done in the glossary.

Fig 2.1 · All or nothing
All or nothing. A job that is done except for one line is not done. Shown as a solved cube.
A job that is done except for one line is not done.

Two parts of that idea still hold. It is shared, so everyone means the same thing by done. And it is all or nothing: a job that is done except for one line is not done.

What changes with agents is who reads it. A team of people can carry an unwritten standard in their heads. An agent can't. It starts each session with whatever you wrote down, and nothing else. So the standard has to be written, short and checkable from outside the code.

The other change is the gate. Scrum puts the check at a review meeting. A small team running agents may ship 5 times a day with no meeting at all. The gate moves to the live product: does the line hold where customers are?

How is a definition of done different from acceptance criteria and Done When?

People use these 3 terms loosely, and the overlap causes most of the confusion. Here is how they split.

Definition of doneAcceptance criteriaDone When
Applies toEvery jobOne item, often a user storyOne job an agent holds
Who writes itThe team, onceWhoever writes the itemWhoever holds the job: you or your agent
ExampleTests pass, nothing else broke, it's deployed where it should beExporting preserves all saved filtersGiven a customer with 3 saved filters, when they export, then the file keeps all 3
FormA short standing listOften a sentence or a ruleGiven a state, when an act, then something you can check
How it's checkedMostly by CI and habitOften by a person, at reviewLine by line, with evidence for each
ChangesRarelyPer itemPer job, then frozen once checked

Done When lines are acceptance criteria written so an agent can check them on its own. The definition of done is the standard all of them sit on top of. A job is finished when it meets both.

Two levels of done

  1. Your team's standard, true for every job: tests pass, nothing else broke, it's deployed where it should be. See definition of done.
  2. This job's lines, true for this job only. These are acceptance criteria written so an agent can check them.
Fig 4.1 · Where each level lives
Your team's standard lives with the project, in AGENTS.md. This job's lines live in its spec.

Keep the two apart. Your standard goes in your rules file, AGENTS.md, which Claude Code, Cursor, Codex and Grok can all be pointed at. The job's lines go at the end of the job's plan, the spec. If "tests pass" appears in every spec, it belongs in the standard. If "the export keeps filters" appears in the standard, it belongs in a spec.

A team standard for a small product runs about 5 to 8 lines. Here are 5:

  • The test suite passes, and no test was skipped or deleted to get there.
  • The type check and the linter pass.
  • The change is on the live branch and deployed to production.
  • Nothing outside the job's files changed without a note saying why.
  • Any customer-facing words were read by a person.

That's often enough. Before you add a line, ask whether it's something that has slipped through before. If not, leave it out, and stop at about 8.

Then tell the agent how to use it. One instruction near the top of AGENTS.md does most of the work: "Before you say a job is done, check every line of our standard and every Done When line in the spec. For each one, say how you checked it and where I can see it. If you couldn't check a line, say which and why." Agents follow a rule they can see far better than one they're expected to infer. Claude Code reads AGENTS.md when there's no CLAUDE.md, and a CLAUDE.md can import it with an @AGENTS.md line, so one file covers all your agents.

If a rule must hold every time with no exceptions, such as "the test suite passes", make it a check that runs on its own, in CI or a hook, rather than a sentence the agent is trusted to remember. Keep the written standard for the things only a reader can judge.

How to write lines an agent can check

Use "Given a state, when an act, then a result you can see":

  • Given a customer with saved filters, when they export, then the file keeps every filter.
  • Given the pricing page, when it loads on a phone, then nothing scrolls sideways.

If you can't picture the line failing, it isn't a check.

One check per line. If a line says "and", split it.

The form is older than coding agents. Martin Fowler credits Daniel Terhorst-North and Chris Matts with it, as part of behavior-driven development. "Given" is the state of the world before the act. "When" is the act. "Then" is the change you expect. It works for agents for the same reason it worked for people: it forces you to say where you start, what happens and what you'll look at.

A few rules make a line checkable:

  • Observable from outside the code. A page, a file, an email, a row, a status code. "The function is refactored" can't be seen by a customer.
  • It can fail. If you can't picture the line failing, it isn't a check. "Works well" never fails.
  • Numbers, not adjectives. "Under 2 seconds", "exactly 1 email", "within 5 minutes". Fast, simple and clean can't be verified.
  • Name the place. On staging, on production, on a phone. Where it was checked is part of the line.
  • One edge per job, at least. The happy path is the line agents check without being asked. The empty list, the expired card and the member without access are the lines that catch real bugs.
  • Written before the build. A line written after the code tends to describe what was built, not what was needed.

Three to six lines covers most jobs. If you need 10, the job is probably two jobs.

What do good and bad lines look like?

Here are 10 lines as people often write them, and the same lines rewritten so an agent can check each one. They're made up to show the pattern.

Vague lineA line an agent can checkWhat changed
Export works.Given a customer with 3 saved filters, when they export to CSV, then the file holds only rows that match all 3.A state, an act and a result you can count
The page is fast.Given the pricing page on a mid-range phone, when it loads in a mobile performance test, then the main content shows in under 2 seconds.A number and a way to measure it
Handle payment errors gracefully.Given the card is declined, when a customer pays, then they see "Your card was declined. Try another card." and no order is created.The exact words and the side effect
Users can reset their password and get an email.Split it: given a user on the sign-in page, when they ask to reset, then an email arrives within 5 minutes. Then: given that email, when they open the link after 1 hour, then it says the link expired.One check per line, plus the edge
Tests pass.Given an invoice 3 days overdue, when the daily job runs, then exactly 1 reminder is queued for it."Tests pass" belongs in the team standard. The line says what the test proves
Looks good on mobile.Given the settings page 375 pixels wide, when it loads, then nothing scrolls sideways.A width and a result anyone can see
Only admins can delete projects.Given a member without the admin role, when they send a delete request for a project, then it is refused with a 403.The act is the risky one, not the button
Works in production.Given production after the deploy, when a new person signs up, then the welcome email arrives within 5 minutes.The place and a real act
Don't break checkout.Given the existing checkout tests, when the suite runs on this branch, then every one passes with none skipped or removed.Closes the gap where a failing test quietly disappears
Customers love the new onboarding.Given a new account, when the owner finishes step 3, then the dashboard shows their first project.A feeling is an outcome to watch later, not a line to check today

The last row is worth a second look. "Customers love it" is a fine goal. It belongs in the spec's outcome, and you'll learn whether it came true after the ship. Done When is about what you can check the day the job finishes.

Receipts

For each line, the agent writes down how it checked: a test name, a URL, a screenshot, a thread. A line it couldn't check stays unchecked, and it says so. You can read the receipts without reading the code.

Receipt · Overdue reminders one line, one receipt
Line
  • Given an invoice 3 days overdue, when the daily job runs, then exactly 1 reminder is queued for it.
Where
  • The CI run for the branch, and the staging job log for 21 Oct.
Seen
  • 1 reminder queued for invoice 1042. A second run queued none.
How it was checked, where to follow it and what was seen.

A receipt is the evidence for one line. It answers 4 questions: how was it checked, where can I follow it, when and what was seen. A receipt that says "verified" and nothing else is a claim, not evidence.

What counts as evidence for each line?

Not all evidence is equal. Pick the strongest kind the line allows.

KindWhat it looks likeStrong whenWeak when
A testThe test name and the run that passedThe test was written from the line, before the codeThe agent wrote the test after the code, to match what it built
A staging checkA URL and what was seen thereStaging has data shaped like productionStaging is empty, so the edge case never shows up
A production checkA live URL, a log line or a record idThe line is about what customers getChecking would touch a real customer's data
By handWho, when, what they saw, a screenshotThe line is about words or layoutNobody else can repeat it
A threadA link to a message, an email or a support replyThe line is about a person receiving somethingThe thread doesn't show the result, only the request

Here's a receipt for one line, in a shape you can copy:

  • Line: Given an invoice 3 days overdue, when the daily job runs, then exactly 1 reminder is queued for it.
  • How: test, "reminders: queues one reminder per overdue invoice", plus a staging run.
  • Where: the CI run for the branch, and the staging job log for 21 Oct.
  • Seen: 1 reminder queued for invoice 1042. A second run queued none.

An honest unchecked line is also a valid result: "Unchecked: the reminder email's look in Outlook, because there's no test inbox. Worth a manual check before we announce it." That tells you exactly what's left and lets you decide.

Who verifies the work?

The agent that built the job checks every line first. That's its job, and it's cheap. But it shouldn't be the only check, for the same reason you don't proofread your own writing well: it reads what it meant, not what it wrote.

Anthropic's Claude Code guide suggests a second opinion for this reason, so "the agent doing the work isn't the one grading it." In practice, a small team can split it like this:

WhoChecksWhy
The agent that built itEvery Done When line, with a receipt for eachIt knows the change and can rerun checks fast
A second agent or a fresh sessionThe diff against the lines, and nothing else changedIt has no stake in the code being right
Your CIThe team standard: tests, types, lintIt runs the same way every time
YouAnything a customer will see or receive, anything about money or data, plus every unchecked lineThose are the calls that are yours

You don't need to read the code. You need to read the receipts, open the 1 or 2 that touch customers and decide on whatever's unchecked. That takes minutes, not an afternoon.

If you work with others, say who signs off on customer-facing work before the job starts. "Someone will look" means nobody will. Which calls should wait for you is its own topic, covered in human in the loop for AI agents.

it reads what it meant, not what it wrote.

What does "merged is not shipped" mean?

A merged pull request tells you the code landed on a branch. It doesn't tell you the job works, or that anyone can use it yet. Between "the agent opened a PR" and "a customer can do the thing" there are 4 separate steps, and each one can fail on its own.

  1. Merged. The code is on the main branch. Proof: the merge commit.
  2. Deployed. The code is running where customers are. Proof: the release or deploy record, and the change visible on the live site.
  3. Checked. Each Done When line holds there. Proof: a receipt per line.
  4. Told. The people who asked know it's ready. Proof: the note you sent them.

Agents tend to stop at step 1, because that's where their tools end. Deploys often wait for a person, a schedule or a pipeline the agent can't see. So a job can sit merged for days, marked done in a chat, while the customer who asked still can't use it.

The fix is a rule in your standard: "Done means checked on production, not merged." If your agent can't reach production, it says so, and the job waits at "merged, not checked" until someone can. That label is honest, and it's the one people skip.

When the agent says done but isn't

  • It checked locally, not where it runs. Ask for the live URL.
  • It checked the happy path only. Add a line for the edge case.
  • The line was vague. Rewrite it so it can fail.

Two more show up once you run several agents:

  • It removed the test that failed. Ask which tests changed, and add "none skipped or removed" to your standard.
  • It checked a line that changed. Someone reworded the line after the receipt was written, so the receipt proves something else. Freeze lines once a receipt points at them, and add a new line instead.

What does this look like on one job?

Here's a made-up example. Say a 3-person team with 60 customers has 4 accounts asking to pause a subscription instead of canceling. They hand the job to Claude Code with this spec ending:

Spec · Pause a subscription example workspace
Done when
  • Given a paying customer, when they choose Pause for 2 months, then no invoice is created in those 2 months.
  • Given a paused customer, when the pause ends, then billing restarts on the next cycle at the same price.
  • Given a customer on a yearly plan, when they open billing settings, then Pause isn't offered.
Four lines, four receipts, and done only after the Friday deploy.
  • Given a paying customer, when they choose Pause for 2 months, then no invoice is created in those 2 months.
  • Given a paused customer, when the pause ends, then billing restarts on the next cycle at the same price.
  • Given a paused customer, when they open the app, then they see "Paused until 14 Jan" in billing settings.
  • Given a customer on a yearly plan, when they open billing settings, then Pause isn't offered.

The agent builds it and reports back. Lines 1, 2 and 4 have tests written from the lines, plus runs on staging with a test account. Line 3 has a staging URL and a screenshot. Production is the gap: the deploy runs on Fridays, so every receipt says staging.

The founder reads 4 receipts and opens the screenshot. It shows the right date. She lets it stand. On Friday, after the deploy, the agent rechecks line 3 on production and adds a second receipt. Only then does the job count as done, and only then does she tell the 4 accounts.

Nobody read the code. Two people spent about 10 minutes between them. And the job was never called done while it sat merged.

What mistakes do people make with a definition of done?

  • Writing the lines after the build. Then they describe what was built. Write them first, even roughly, and let the agent sharpen them before it starts.
  • Mixing the levels. Team-wide rules in every spec, or one job's behavior in the team standard. Each copy drifts.
  • Too many lines. 10 or more lines is a sign of two jobs. Split the job and keep each list short enough to read.
  • "Tests pass" as the only line. It proves the tests ran, not that the right thing happened. Say what the test should prove.
  • No place. A line without "on staging" or "on production" gets checked wherever is easiest.
  • Hiding unchecked lines. An unchecked line isn't a failure. Pretending it was checked is.
  • Taking "done" in a chat. If there are no receipts, ask for them. A good agent will either produce them or tell you which lines it couldn't check.
  • Rewording a checked line. The receipt now points at a line that no longer exists. Add a new line instead.
  • Never pruning the standard. Add a line when something slips through. Drop a line nobody has checked in a month.
Writing a checklist by hand in a notebook
Write the lines first, even roughly, before the build.

For guarding the edges of a job as well as its finish, see scope creep.

Copy this

Put this at the end of every job plan, and have the agent fill in the receipts.

Done When lines with a receipt for each
## Done When
- Given <state>, when <act>, then <result you can check>.
- Given <state>, when <act>, then <result you can check>.

## Receipts (one per line)
1. <how checked>: <test name / URL / thread>
2. <how checked>: <test name / URL / thread>
Unchecked: <line>, because <reason>

For a fuller version with the team standard and evidence types, use the definition of done checklist.

Where Annsa fits

Every spec in Annsa ends with Done When lines. Your agent checks each one and records a receipt, and the spec shows which lines are checked before you tell anyone it shipped. Shipping and verification

A full Annsa spec: Problem, Evidence and direction, What to build, Files to touch and Done When lines, each line marked checked or unchecked

  • Each spec has 5 sections: Problem, Evidence and direction, What to build, Files to touch and Done When. You, your agent or Ask writes it. Annsa never writes a spec on its own.
  • Each Done When line takes the form given a state, when an act, then something you can check, and gets its own receipt.
  • Claude Code, Cursor, Codex and Grok record a receipt with annsa.work verify. It says whether the check was a test, on staging, in production or by hand, and where you can follow it.
  • A line that couldn't be checked is labeled on the spec. Receipts don't block a ship, so an unchecked line is your call.
  • Annsa never deploys. Shipping has two paths. Your agent can mark a priority shipped and name any line it couldn't check, which is your call. Or a merged pull request that names the priority ships it once it reaches your live branch and every Done When line has a receipt. See Done When.
  • After the ship, Share Back drafts a note to each person who asked. You review it and send it.
What you do by handWhat it costsHow Annsa does it
Ask each agent "did you check it?" in chatAnswers vanish with the sessionA receipt per line, saved on the spec
Read the diff to see what was testedAn hour per jobRead the receipts, open the ones that touch customers
Track merged vs live in your headJobs called done that nobody can useYour agent ships it and names any line it couldn't check, or a merged PR ships it once it reaches your live branch with every line receipted
Remember who askedPeople never hear it shippedA drafted note to each person who asked, for you to send

See how it fits together in Direct your agents.

Sources

Questions people ask.

Q1

What is a definition of done for AI agents?

A short checklist each job must pass, one checkable line each, with a receipt for how each line was checked.
Q2

How do I write a definition of done for Claude Code and Codex?

End each job plan with Done When lines in "given, when, then" form, and ask the agent to check each one against the live product and say how.
Q3

How do you know when an AI coding agent is really done?

When every Done When line has a receipt you can follow. An unchecked line means it isn't done yet, or you've decided that's fine for now.
Q4

How do I write acceptance criteria an AI agent can check?

One result per line, observable from outside the code: a page, a file, a test, a message. Avoid words like "fast" or "nice" that can't fail.
Q5

What is the difference between a definition of done and acceptance criteria?

A definition of done is the standard every job meets, such as tests pass and the change is deployed. Acceptance criteria are the conditions one item must meet, such as an export keeping saved filters. A job is finished only when it meets both.
Q6

What is an example of a definition of done?

A short list for every job: the test suite passes with no test skipped or removed, types and lint pass, the change is deployed to production, nothing outside the job changed without a note and a person read any customer-facing words. About 5 to 8 lines is plenty for a small team.
Q7

What does merged is not shipped mean?

A merged pull request means the code landed on a branch, not that customers can use it. The job still has to be deployed and checked line by line where customers are. Then the people who asked can be told. Agents often stop at merged, so say in your standard that done means checked on production.
Q8

Who should verify an AI agent's work?

The agent checks every line first and records how. A second agent or a fresh session reviews the change against the lines and CI runs the team standard. A person checks anything customers will see, anything about money or data and every line left unchecked.
Q9

How many Done When lines should a job have?

Three to six covers most jobs, with at least one edge case such as an empty list or a member without access. If a job needs ten or more, it is usually two jobs and should be split.

The source of direction for agent teams.

Begin with one agent and the work that matters next.