Skip to content
BlackFig

Writing a product spec for an AI agent or developer

AntPublished Updated 4 min read

Quick answer

A good product spec says who the feature is for, what is in and out of scope, the data it touches, each flow step by step, every state including empty and error, the rules and edge cases, and testable acceptance criteria. The same spec works for an AI coding agent and a developer, as long as it is specific.

On this page
  1. Why it matters
  2. Problem and users
  3. Scope
  4. Data
  5. Flows and states
  6. Rules and edge cases
  7. Acceptance criteria
  8. Context for the builder
  9. The template
  10. 1. Problem
  11. 2. Users
  12. 3. Outcome
  13. 4. Scope
  14. 5. Data
  15. 6. Flows
  16. 7. States (per screen)
  17. 8. Rules and edge cases
  18. 9. Notifications
  19. 10. Acceptance criteria
  20. 11. Tests
  21. 12. Open questions
  22. Instructions for the builder
  23. Using the spec with an agent
  24. Common misses
  25. Next step

The quality of what comes back from an AI coding agent, or a developer, depends on what you hand over. A vague prompt like "add a booking system" gets you a plausible-looking feature built on guesses: guessed data, guessed permissions, guessed edge cases. A spec replaces those guesses with decisions.

Below is the checklist I use to write one, a template you can copy, and the most common gaps.

Why it matters

AI tools are very good at building what you describe. They're poor at noticing what you didn't. A developer might stop and ask "what happens if the slot is already taken?" An agent usually just picks something and carries on.

Anthropic's Claude Code docs make the same point about its instruction files: the more specific and concise your instructions, the more consistently Claude follows them, and "Use 2-space indentation" beats "Format code properly". That applies just as much to a feature spec.

A spec also protects you. It's the thing you check the result against, and it's what a new developer reads when they pick up the project after you.

Problem and users

Problem and users

  • One sentence on the problem, in the user's words
  • Who the feature is for, by role (for example host, vendor, admin)
  • What they do today without it
  • How you'll know it worked: one measurable outcome

Scope

The out-of-scope list matters more for an agent than a person. Without it, agents tend to tidy up nearby code, rename things and add features nobody asked for.

Scope

  • In scope: the specific things this spec covers
  • Out of scope: what is deliberately left for later
  • Files, folders or modules the work should not touch
  • Any existing components or patterns to reuse

Data

Data

  • Every table or model the feature reads or writes
  • New fields, with types, required or optional, and defaults
  • Relationships between records and what happens when one is deleted
  • Who can read and change each record
  • Any personal data involved, and why it's needed

Flows and states

Write each flow as numbered steps from the user's point of view. Then list the states for each screen. This is where AI-built apps are weakest: the happy path works, and loading, empty and error states are missing.

Flows and states

  • Each user flow as numbered steps
  • For each screen: loading, empty, partial, error and success states
  • What the user sees on mobile, if it differs
  • Emails, notifications or webhooks the flow triggers

Rules and edge cases

Rules and edge cases

  • Validation rules for every input, with limits
  • Permission rules: who can do what, and what others see instead
  • Conflicts and double actions, such as double-clicks, two users at once, retries
  • Money, time zones and dates: currency, rounding, which time zone is stored
  • What happens when an external service is down

Acceptance criteria

Acceptance criteria turn the spec into a test. Write them as statements that are either true or false when you try the feature.

Acceptance criteria

  • Given, when, then statements for the main flow
  • At least one criterion for each error and edge case above
  • Tests the builder should write, and which existing tests must still pass
  • How you'll check it by hand: the device, browser and test account

Context for the builder

A spec describes what to build. Separate instruction files describe how to work in the codebase, and every task needs them. AGENTS.md is an open format for that, read by a long list of coding tools including Cursor, OpenAI Codex, GitHub Copilot's coding agent and Gemini CLI. It suggests covering the project overview, build and test commands, code style, testing and security. Claude Code uses CLAUDE.md, and can read AGENTS.md when there's no CLAUDE.md in the project. Its docs suggest keeping each CLAUDE.md under 200 lines.

So keep the split clean: conventions in AGENTS.md or CLAUDE.md, one feature per spec file, and link the spec in the prompt.

Context

  • Stack and versions (for example Next.js 15, React 19, Postgres)
  • Where the spec file lives and which issue or ticket it belongs to
  • Commands to run the app, the tests and the linter
  • An instruction to ask questions before starting if anything is unclear

The template

Copy this into docs/specs/feature-name.md in your repository and fill it in. Delete any section that genuinely doesn't apply, rather than leaving it blank.

# Spec: [Feature name]
 
Status: Draft | Ready | Built
Owner: [Name]
Last updated: [YYYY-MM-DD]
 
## 1. Problem
[One or two sentences, in the user's words.]
 
## 2. Users
- Primary: [role] who wants to [goal]
- Also affected: [role]
 
## 3. Outcome
We'll know this worked when [measurable outcome] within [time].
 
## 4. Scope
In scope:
- [Thing 1]
- [Thing 2]
 
Out of scope (do not build):
- [Thing for later]
 
Do not change:
- [Files, folders or modules to leave alone]
 
Reuse:
- [Existing components, hooks or utilities]
 
## 5. Data
| Table / model | Field | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- | --- |
| [bookings] | [starts_at] | [timestamptz] | [yes] | [none] | [stored in UTC] |
 
Relationships: [a booking belongs to one host and one vendor]
On delete: [if a host is deleted, their future bookings are cancelled, not deleted]
Access: [hosts read and update their own bookings; vendors read their own; admins read all]
Personal data: [vendor phone number, shown to the host only after booking is confirmed]
 
## 6. Flows
### Flow A: [name]
1. User [does something] on [screen].
2. System [responds].
3. User sees [result].
 
### Flow B: [name]
1. ...
 
## 7. States (per screen)
| Screen | Loading | Empty | Error | Success |
| --- | --- | --- | --- | --- |
| [Bookings list] | [skeleton rows] | [message + "Create your first booking" button] | [inline message + retry] | [list, newest first] |
 
## 8. Rules and edge cases
- Validation: [title 3 to 80 characters; price 0 to 10,000 GBP, 2 decimal places]
- Permissions: [non-owners get a 404, not a 403]
- Conflicts: [two bookings for the same slot: the second gets "Slot no longer available"]
- Time: [store UTC, display Europe/London]
- External services down: [if Stripe fails, the booking stays "pending" and the user sees a retry option]
 
## 9. Notifications
- [Email to host when a booking is requested: subject, key content]
 
## 10. Acceptance criteria
- [ ] Given [context], when [action], then [result].
- [ ] Given [context], when [action], then [result].
- [ ] Error: given [context], when [action], then [result].
- [ ] Mobile: [flow A] works at 375px wide with no horizontal scroll.
 
## 11. Tests
- Write: [unit tests for the conflict rule; an end-to-end test for flow A]
- Must still pass: [existing test suite]
 
## 12. Open questions
- [Question] (owner: [name])
 
## Instructions for the builder
- Read AGENTS.md / CLAUDE.md first.
- Ask questions before starting if anything above is ambiguous.
- Keep changes inside the scope above. List any other change you think is needed instead of making it.
- When done, report which acceptance criteria you checked and how.

Using the spec with an agent

Writing the spec is half the job. How you hand it over decides whether it gets followed.

Commit it before any code. The spec goes into the repository first, so the agent reads the same version you approved, and the history shows what changed later.

Ask for questions and a plan, not code. My first prompt is usually: read docs/specs/feature-name.md, list anything ambiguous, then propose a plan. Then I answer the questions in the spec file itself, not only in the chat. Answers that live in a chat disappear when the session ends. Answers in the spec survive for the next session, the next agent and the next developer.

Build one flow at a time. Ask for flow A, check it against its acceptance criteria, then move to flow B. Small slices make it obvious when something drifts, and they keep each diff small enough to actually read.

Review the diff against the scope. Before you accept anything, compare the changed files with the "do not change" list. If the agent touched something outside it, ask why before merging. Sometimes there's a good reason, and then the spec should say so.

Close the loop. When the feature ships, set the status to Built and note what changed during the build. A spec that matches the code is documentation. One that doesn't is a trap for whoever comes next.

The same process works with a developer. The only real difference is that a good developer will push back on the spec without being asked, which is exactly what you want.

Common misses

These are common gaps in specs written for AI tools:

  • No out-of-scope list. The agent rewrites a shared component and breaks three other pages.
  • Only the happy path. No empty, error or loading states, so the build has none either.
  • Permissions left implicit. "Users can edit bookings" without saying which users and which bookings. This is how data leaks between accounts.
  • Time zones ignored. Dates stored in local time, then shown wrong after the clocks change.
  • Acceptance criteria that can't fail. "It should be fast and intuitive" isn't testable. "The list loads in under a second with 1,000 bookings" is.
  • The spec lives in a chat. It disappears with the conversation. Put it in the repo.

Next step

If you're moving a prototype towards a real product, my prototype to product guide puts the spec in context with payments, hosting and launch. If you're rebuilding from a no-code tool, writing a spec of what the current app does is step one, and my guide to turning a no-code app into a coded product covers the rest. The launch checklist is useful once the build is done.

Specs are a big part of how I work: the Validation Sprint (from £3,500, 1 to 2 weeks) ends with user flows, a clickable prototype and a build plan with a fixed quote, and the MVP Build (from £12,000, typically 4 to 6 weeks) builds against that plan. My Rescue Sprint takes an existing prototype to production, at a fixed price after a technical assessment (from £750). Book a call if you'd like a spec written with you.

The launch checklist for founders, as a PDF

About 40 checks across legal, payments, domain and email, analytics, backups and support.

You get the PDF now and two short follow-ups over the next week. Reply “stop” and the rest never arrive.

Questions founders ask

Is a spec for an AI agent different from one for a developer?

The content is the same. The difference is that an agent won't ask clarifying questions unless you tell it to, so gaps get filled with guesses. Be more explicit about scope, states and what not to change.

How long should a product spec be?

As short as it can be while still answering every question the builder would ask. For one feature that's usually one to three pages. Split anything longer into separate specs.

Where should I keep the spec?

In the repository, next to the code, as a Markdown file. Agents and developers can both read it there, and changes are tracked with the code.

What's the difference between a spec and CLAUDE.md or AGENTS.md?

The spec describes what to build. CLAUDE.md or AGENTS.md describes how to work in the codebase: commands, conventions and rules that apply to every task.

Ant

Product designer who builds MVPs, based in Nottingham. 10+ years designing digital products, and the only person at BlackFig. More about me