Spec-Driven Development sdd-1 20 min

What Makes a Spec Agent-Readable

Learning Objectives

  • identify the four elements of an agent-readable spec
  • write a spec that includes scope, constraints, output format, and acceptance criteria
  • evaluate a spec for common failure modes
  • apply the four-element framework to an existing AI task

Core Concepts

What an Agent-Readable Spec Is

An agent-readable spec is a structured task description that eliminates ambiguity about what the agent should do, what it should not do, what the output looks like, and how to verify it is correct.

It is not a user story. It is not a comment in a ticket. It is a precise instruction set written with the understanding that the agent cannot ask clarifying questions mid-task, infer organizational context, or know which of several valid interpretations you actually want.

An agent-readable spec has four elements: scope, constraints, output format, and acceptance criteria. Every agent task needs all four.


Element 1: Scope

Scope defines what the agent is responsible for in this task and, critically, what it is not.

Without scope, agents expand. Asked to "build the booking page," an agent might generate the booking form, the confirmation email, the calendar sync logic, and a first pass at the admin view. You wanted the form. Now you have four things to review instead of one.

Scope is not about limiting the agent's capability. It is about giving the agent a clear boundary so it can focus its output on what you actually need.

Weak scope: "Work on the availability feature."

Strong scope: "Generate the backend API endpoint that accepts an availability window (start time, end time, timezone) submitted by the host user and writes it to the database. Do not implement the frontend form, email triggers, or calendar sync. Those are handled in separate tasks."

The scheduling platform has at least a dozen discrete components: booking page, availability manager, calendar sync, email notifications, conflict detection, admin dashboard, time zone handling, and more. A spec that does not define scope will bleed across these boundaries every time.


Element 2: Constraints

Constraints define the rules the agent must operate within. They cover the technical environment, the codebase conventions, the libraries in use, and anything the agent must not do.

Without constraints, agents make choices. They choose a library you are not using, a pattern that does not match your conventions, or an approach that works in isolation but breaks in your stack.

Constraints are not about restricting creativity. They are about preventing the agent from solving the right problem in a way that does not fit your system.

Weak constraints: "Use our tech stack."

Strong constraints: "The backend is Node.js with Express. The database layer uses Prisma with PostgreSQL. Use the existing availabilityService.ts module for business logic. Do not introduce new npm packages. Follow the error handling pattern used in bookingController.ts: all errors returned as { error: string } with appropriate HTTP status codes."

Constraints on the scheduling platform might also include: the booking page must support mobile browsers, availability windows must be stored in UTC internally, and the conflict detection logic must use the existing detectOverlap() utility rather than re-implementing it.


Element 3: Output Format

Output format defines exactly what the agent should produce: the file, the data structure, the document type, the length, the shape.

Without output format, agents produce whatever format feels natural given the prompt. Ask for "a component" and you might get a full file with imports, or a snippet, or pseudocode with comments. Ask for "a summary" and you might get a paragraph when you needed a table.

Weak output format: "Give me the component."

Strong output format: "Produce a single React functional component in TypeScript saved as BookingPage.tsx. Export it as the default export. Include prop types defined inline using a Props interface. Do not include mock data or placeholder API calls: use the useBookingSlots hook from hooks/useBookingSlots.ts for data fetching."

Output format also applies to non-code outputs. If you are asking an agent to generate documentation, specify the heading structure, the target length, and whether it goes into a .md file or a code comment block. If you are asking for a test suite, specify the test framework, the file name, and how many test cases are expected.


Element 4: Acceptance Criteria

Acceptance criteria define how you know the output is correct. They are the conditions the result must satisfy before it is considered done.

Without acceptance criteria, "done" is undefined. The agent has no signal for when to stop, and you have no checklist for when to approve.

Acceptance criteria do not need to be exhaustive. They need to be unambiguous. Each criterion should be a statement you can evaluate as true or false.

Weak acceptance criteria: "Make sure it works."

Strong acceptance criteria:

  • The POST /api/availability endpoint returns 201 when given a valid availability window
  • It returns 400 with { error: "Invalid time range" } when the end time is before the start time
  • It returns 409 with { error: "Overlapping availability" } when the submitted window overlaps an existing window for the same host
  • The Prisma create call writes startTime, endTime, and timezone to the Availability table
  • No new dependencies are added to package.json

Acceptance criteria are also what you use to run a review agent. A separate agent can be given the output and the criteria and asked to evaluate whether each criterion passes.


Why All Four Elements Are Required

Each element does a different job. Remove one, and a specific failure mode appears.

Missing element What goes wrong
Scope The agent produces more than you need, or works on the wrong thing
Constraints The agent makes implementation choices that do not fit your system
Output format The agent produces the right logic in the wrong shape
Acceptance criteria Neither you nor the agent knows when the task is done

A spec is only agent-readable when all four are present. A partial spec is a prompt. It may work. It may not. You cannot know in advance.

Key Points

  • An agent-readable spec has four elements: scope, constraints, output format, and acceptance criteria
  • Scope tells the agent what to work on and what to leave alone
  • Constraints tell the agent what rules to follow inside your specific system
  • Output format tells the agent what to produce and how to shape it
  • Acceptance criteria tell both the agent and you when the task is done
  • A spec missing any one of the four will produce a predictable failure mode

Tools, Prompts, or Templates

Spec Readability Checklist

Before handing a spec to an agent, most teams make the same four mistakes: they leave scope open-ended, they omit constraints because "the agent should know our stack," they describe output vaguely, or they write acceptance criteria that cannot be evaluated. This checklist closes all four gaps in under two minutes.

Use it on any spec before running it through an agent. Use it again when reviewing specs written by teammates. If any item is unchecked, the spec is not ready.

Spec Readability Checklist

SCOPE
[ ] The task has a clear start and end boundary
[ ] Out-of-scope components are explicitly named
[ ] The spec does not depend on the agent knowing project history

CONSTRAINTS
[ ] The language, framework, and runtime are specified
[ ] Relevant existing files, modules, or utilities are named
[ ] Libraries or patterns the agent must not use are listed
[ ] Any performance, security, or compliance constraints are stated

OUTPUT FORMAT
[ ] The file name and location are specified (for code)
[ ] The data structure or return type is defined
[ ] The document type, format, and length are stated (for non-code)
[ ] The export or interface pattern is specified

ACCEPTANCE CRITERIA
[ ] Each criterion is a true/false statement
[ ] Success cases are covered
[ ] At least one failure or edge case is covered
[ ] Criteria are specific enough to evaluate programmatically or manually

Discussion Prompt Look at the last three tasks your team handed to an AI agent. How many of the four elements were present in each? Where did the output fall short?


Actionable Takeaways

  1. Take one AI task your team ran this week and score it against the four elements. If any element is missing, rewrite that section of the spec now.
  2. Add the Spec Readability Checklist to your team's task template or ticketing system so it runs before any agent task is submitted.
  3. The next time an agent produces the wrong output, diagnose which element was missing before re-running the task. Do not just add detail: add the right element.
  4. Write scope as two statements: what is in and what is explicitly out. The "out" statement is the one most teams skip.
  5. Write acceptance criteria as a list of evaluable conditions, not a description of intent. "The form validates input" is not a criterion. "The form returns an error if the selected time slot is in the past" is.

Practical Examples

Example 1: Weak Spec vs. Strong Spec (Availability API)

A developer on the scheduling platform needs the backend endpoint that saves a host's availability window.

Weak spec handed to the agent:

Build the availability endpoint. It should save the time slot to the database and handle errors.

This spec is missing all four elements in some form. There is no scope boundary (does this include frontend? calendar sync?), no constraints (which ORM? which error format?), no output format (a file? a snippet? which controller?), and no acceptance criteria (what counts as correct error handling?).

Strong spec:

Scope: Implement the POST /api/availability endpoint in controllers/availabilityController.ts. This task covers the controller function and the Prisma write only. The frontend form, email trigger, and calendar sync are out of scope and handled in separate tasks.

Constraints: Use Express and Prisma with the existing prisma client instance from lib/prisma.ts. Follow the error response format used in controllers/bookingController.ts: { error: string } with HTTP status codes. Do not add new npm packages.

Output format: A single exported async function createAvailability added to controllers/availabilityController.ts. The function signature must be (req: Request, res: Response) => Promise<void>.

Acceptance criteria:

  • Returns 201 with the created availability record on success
  • Returns 400 with { error: "Invalid time range" } when end time is before start time
  • Returns 409 with { error: "Overlapping availability" } when the window overlaps an existing record for the same host
  • Stores startTime, endTime, and timezone in the Availability table via Prisma

The agent receiving the second spec has no meaningful ambiguity to resolve. It knows the file, the function signature, the error format, the database layer, the boundaries of the task, and the conditions that define success.


Example 2: Diagnosing a Failure

A product manager on the scheduling platform asked an agent to summarize the admin dashboard requirements. The agent produced four paragraphs of flowing prose. The PM needed a bullet list for a slide deck.

Diagnosis: missing output format. The scope was acceptable (admin dashboard requirements only), the constraints were not relevant for a written summary, and the acceptance criteria were implicit (cover all the requirements). The only missing element was output format.

Revised spec addition:

Output format: A flat bullet list. Each bullet covers one requirement in 10 words or fewer. No prose paragraphs. No section headings. The list will be pasted directly into a slide, so brevity is the constraint.

The agent's second output was usable in thirty seconds.


Example 3: Scope Bleed

A technical director asked an agent to "set up email notifications for the scheduling platform." The agent produced: an email service wrapper, a notification trigger in the booking controller, a confirmation email template, a reminder email template, an unsubscribe flow, and a note about GDPR compliance requirements.

The director wanted only the booking confirmation email for the MVP.

Diagnosis: missing scope boundary. The task had no explicit "out of scope" statement, so the agent expanded to a reasonable interpretation of "email notifications." This is a common failure mode on greenfield features where "the whole thing" is technically in scope eventually, but not in this sprint.

Revised scope statement:

Scope: Implement the booking confirmation email only. This is the transactional email sent to the client immediately after a booking is confirmed. Out of scope for this task: reminder emails, host notification emails, unsubscribe handling, and email preference settings.


Implementation Workflow

This workflow takes an existing AI task from your current work and applies the four-element framework to it. By the end, you will have a rewritten spec you can hand to an agent with confidence.

  1. Pick a task. Choose one AI task your team has run recently or is planning to run on the scheduling platform. It can be a code generation task, a documentation task, or a review task. Write down the original prompt or task description as it was given.

  2. Score the original. Read the original task description and check it against the four elements. For each element, mark it as present, partial, or missing. Note what information is absent.

  3. Write the scope statement. Define the boundary of the task in two sentences: one stating what the agent will produce, one stating what is explicitly out of scope. For the scheduling platform, name the specific component (booking page, availability API, calendar sync, admin dashboard, notification system) and name at least one adjacent component that is out of scope.

  4. Write the constraints block. List the technical constraints that apply. Include: language and runtime, relevant existing files or modules the agent should use, libraries or patterns it must not introduce, and any conventions it must follow. For the scheduling platform, this means specifying the framework (Node/Express or React), the ORM (Prisma), and any existing utilities to reuse.

  5. Define the output format. Describe exactly what the agent should hand back. For code: file name, location, function or component name, and type signature. For a document: format (bullet list, table, markdown), target length, and where it will be used. Be specific enough that two different agents reading the spec would produce output in the same shape.

  6. Write the acceptance criteria. Write three to five evaluable statements. Start each with "Returns," "Produces," "Contains," "Does not," or a similar assertable verb. Cover at least one success case and one failure or edge case. For the scheduling platform, an edge case for the booking page might be: "Displays an error state when no availability windows are returned from the API."

  7. Run the Spec Readability Checklist. Apply the checklist to your rewritten spec. If any item is unchecked, revise the corresponding section before proceeding.

  8. Submit the spec to an agent and compare outputs. Run the original prompt and your rewritten spec through the same agent. Compare the two outputs. Note which acceptance criteria the rewritten spec's output satisfies that the original did not. Keep the rewritten spec as a template for similar tasks.