Free playbook: A practical operating model for AI across the SDLC
Blog/The AI-Ready Spec Template: What Agents Need to Execute

The AI-Ready Spec Template: What Agents Need to Execute

Most specs tell an agent what to build but not enough to build it right. Here are the fields an AI coding agent actually needs — and where the solo-developer version leaves gaps a team has to close.

Diagram of an AI-ready spec template: objective, scope and out-of-scope, testable acceptance criteria, system context, and open questions feeding a coding agent that executes without guessing — contrasted with an underspecified spec the agent fills with a guess

Hand an AI coding agent a two-line ticket and it will not stop and ask what you meant. It will fill every gap you left — the data model, the error handling, the service that owns the write — with a plausible guess, and it will ship that guess as clean, tested code. The spec you wrote decides how many of those guesses it has to make.

An AI-ready spec template is a reusable document structure that gives a coding agent everything it needs to execute a task without guessing: a precise objective, testable acceptance criteria, the relevant system context, explicit out-of-scope lines, and — the field most templates omit — a place to mark what is still unknown instead of inventing an answer. It is the difference between an agent that executes a decision and one that makes the decision for you.

Key Takeaways

  • An agent never returns an error for an underspecified spec. It guesses, builds the guess cleanly, and the gap only surfaces in review or production.
  • An AI-ready spec needs five things a one-line prompt doesn't carry: objective, bounded scope, independently testable acceptance criteria, real system context, and explicit open questions.
  • The load-bearing field is the one that lets the agent say "I don't know." GitHub's Spec Kit builds this in as a [NEEDS CLARIFICATION] marker — a spec that can flag its own gaps beats a spec that hides them.
  • Keep the spec about what and why, not how. Success criteria should be, in Spec Kit's words, "technology-agnostic and measurable"; the agent chooses the implementation.
  • The solo version of this template assumes one author who knows the whole system. On a team, the system-context field is exactly what no single person can fill — which is where the template stops being a document problem and becomes a workflow problem.

What makes a spec "AI-ready"

A spec is AI-ready when an agent can execute it without inventing anything load-bearing. That is a higher bar than "a human could follow it." People fill gaps from shared context — they know which service owns billing, that the team dropped a vendor last quarter, that one endpoint is not idempotent. An agent has none of that unless the spec carries it, so every omission becomes a decision the agent makes silently on your behalf.

This reframes what a spec is for. A traditional ticket communicates intent to a colleague who will use judgment to fill the rest. An AI-ready spec communicates intent to an executor with no judgment about your system — only fluency. The same ambiguity that a senior engineer resolves correctly from memory, an agent resolves confidently and sometimes wrongly. Spec-driven development for teams exists because that shift changes what you have to write down.

flowchart LR U["Thin spec\nmissing context"]:::bad --> G["Agent fills gaps\nwith a guess"]:::bad --> W["Clean code,\nwrong system"]:::bad R["AI-ready spec\nscope + context + unknowns"]:::accent --> E["Agent executes\nthe decided task"]:::accent --> OK["Right build,\nreviewable"]:::accent classDef bad fill:#fff5f5,stroke:#e25555,color:#c04040 classDef accent fill:#fdf6f8,stroke:#853953,color:#853953

The five things an agent needs before it writes code

An AI-ready spec answers five questions the agent would otherwise answer for itself: what outcome, within what boundary, proven how, against what existing system, and what remains undecided. Miss one and the agent doesn't stall — it substitutes its own answer. These five map closely to the sections GitHub's open-source Spec Kit marks mandatory, plus the one most specs leave out.

1. Objective — the outcome, not the implementation. State what the user should be able to do and why it matters, precisely enough that "done" is unambiguous. Spec Kit frames the whole method as "Define what and why before deciding how to build it." The how is the agent's job; pin it in the spec and you've traded the model's strength for your own guess.

2. Scope and explicit out-of-scope. Bound the task on both sides. The out-of-scope list does more work than the in-scope one, because it stops the agent from "helpfully" refactoring an adjacent module or adding a feature nobody approved. An unbounded scope is an open invitation to scope the work itself.

3. Acceptance criteria that are independently testable. Write each criterion so the agent — and a reviewer — can check it mechanically. Spec Kit requires that each user story be "INDEPENDENTLY TESTABLE" and expresses scenarios as "Given [initial state], When [action], Then [expected outcome]." That format is not ceremony; it is the contract the agent builds against and you verify against.

4. System context — what already exists. Name the services, data models, and APIs the task touches, and what to reuse instead of rebuild. This is the field solo guides assume you hold in your head. It is also the one that prevents the most expensive class of error: the agent building a second notifications table because it never knew the first one existed.

5. Open questions the spec can't yet answer. Every real task has unknowns at writing time. An AI-ready template gives them a home so the agent surfaces them instead of papering over them — the single field covered next.

flowchart TB O["Objective\nwhat & why"]:::accent --> AG S["Scope\n+ out-of-scope"]:::accent --> AG A["Acceptance criteria\nGiven / When / Then"]:::accent --> AG C["System context\nreuse, don't rebuild"]:::accent --> AG Q["Open questions\nflag, don't guess"]:::accent --> AG AG["Agent executes\nno silent decisions"]:::gate classDef accent fill:#fdf6f8,stroke:#853953,color:#853953 classDef gate fill:#ffffff,stroke:#1A1A1A,color:#1A1A1A

Why "mark the unknowns" is the load-bearing field

The field that separates an AI-ready template from a prettier ticket is the one that lets the spec admit it doesn't know something. An agent has no instinct to pause on ambiguity; it defaults to the most statistically likely completion. A spec that forces unknowns into the open converts a silent guess into a visible question — and a visible question is one a human can answer before any code exists.

Spec Kit encodes this directly. Its spec template seeds ambiguity markers like [NEEDS CLARIFICATION: retention period not specified] and shows authors how to mark unclear requirements rather than resolve them by assumption. The mechanism is almost embarrassingly simple, and it is the whole game: a spec that can flag its own gaps is safe to hand to an executor that cannot. A spec that hides its gaps hands them to the agent to fill.

In practice the rule is: if you catch yourself about to write a requirement you're not sure about, write the uncertainty instead. [NEEDS CLARIFICATION] on a retention window costs a sentence. The agent's confident guess at that retention window costs a migration, a review cycle, and possibly a compliance conversation. This is the same logic behind front-loading disagreement in collaborative planning — an agent will produce clean code from a wrong instruction without a flicker of doubt, so the doubt has to live in the spec.

The AI-ready spec template

Here is a complete, copy-paste AI-ready spec template. It is deliberately technology-agnostic — Spec Kit's instruction that success criteria be "technology-agnostic and measurable" applies to the whole document, because the implementation is what you want the agent to propose, not what you want to dictate. Fill every field; leave [NEEDS CLARIFICATION] wherever you'd otherwise guess.

# Spec: <feature name>

## Objective (what & why)
<One or two sentences. The outcome a user gets and why it matters.
No implementation, no tech stack.>

## Scope
In scope:
- <bullet>
Out of scope:
- <bullet — the things the agent must NOT touch or add>

## Acceptance criteria
<Each one independently testable. Use Given/When/Then.>
- Given <initial state>, When <action>, Then <expected outcome>.
- ...

## System context
- Services / modules this touches: <names>
- Existing data models or APIs to reuse (not rebuild): <names + where>
- Known constraints (non-functional): performance, security, data handling
- Interfaces / contracts changed: <endpoint, schema, event>
- Repositories affected: <repo list — one spec, every repo the feature spans>

## Open questions
- [NEEDS CLARIFICATION: <the thing you don't yet know>]
- ...

## Approvals
- Product sign-off: <who / when>
- Engineering sign-off: <who / when>

Two fields make this an AI-ready template rather than a generic spec skeleton. Open questions gives ambiguity a place to live so it reaches a human, not the agent. Repositories affected pins the fact that a feature rarely lives in one repo — and that one approved spec should span all of them rather than fragmenting into per-repo files that drift apart. Both are the fields a solo author skips, because a solo author carries that context in their head.

Where the solo template breaks on a team

The template above is necessary on a team and not sufficient, because its hardest field — system context — assumes a single author who knows the whole system. That assumption is exactly what a team lacks. A PM knows the customer and has never read the notification service; a developer knows their three services and not the other thirty-seven. Hand either of them the template and the system-context section gets filled from partial knowledge, confidently and incompletely.

flowchart LR PM["PM\nknows customers"] --> Doc["System context\nfilled from memory"]:::bad Dev["Dev\nknows 3 of 40 services"] --> Doc Doc --> Agent["Agent executes\nthe gaps as written"]:::bad classDef bad fill:#fff5f5,stroke:#e25555,color:#c04040

So the template surfaces the real problem rather than solving it: a good structure cannot manufacture context nobody in the room holds. Closing that gap takes three things the document alone can't provide. The spec has to be grounded in the live codebase, so the system-context field is answered from what the code actually contains today instead of what someone remembers. It has to stay one approved artifact across every repo the feature touches, not a copy per repository. And its sign-off has to travel with the work as it flows into Jira, Linear, and each coding agent, so the approved scope is what gets built. That connective layer — grounding the plan in the code and keeping one approved source of truth across repos — is what Enact is built to provide.

An AI-ready spec template is the right starting point, and for a solo project it may be the whole answer. On a team, treat it as a checklist for what the agent needs, then ask the harder question the template makes unavoidable: who can actually fill the system-context field, and how do you know what they wrote is still true? Get that right and the agent executes a decision. Skip it and the agent decides for you — cleanly, confidently, and at the speed that made you adopt it in the first place.

A template is only as good as the context in it

See how Enact grounds the spec in your real codebase and keeps one approved plan across every repo an agent touches.

See the plan workflow →

Frequently Asked Questions