Insights & Blog

Spec-Driven Development with AI Coding Agents: Requirements, Tests and Acceptance Criteria

Give AI coding agents a reviewed behavior contract with requirement IDs and independent acceptance tests. Includes a worked traceability example and a local artifact validator.

By Hetal KIT Solution

Spec-driven AI development: reviewed behavior and requirement IDs connect to independent tests, focused code changes and a traceable release decision.

Spec-Driven Development with AI Coding Agents: Requirements, Tests and Acceptance Criteria

Spec-driven development gives an AI coding agent a reviewed behavior contract before implementation and links each requirement to acceptance evidence. The specification should describe outcomes, constraints and failure cases. It should not merely repeat the implementation the agent happens to generate.

Key takeaways

  • Use stable requirement identifiers and observable outcomes.
  • Separate business behavior from implementation preferences.
  • Keep unresolved decisions visible rather than letting the agent invent them.
  • Trace requirements to tests, code changes and review decisions.
  • A complete traceability table does not prove correct behavior; the tests still need review and execution.

Specify the outcome and its boundaries

A useful specification answers who can do what, on which resource, under which conditions and with what result. Include invalid and conflicting cases. “Build a secure endpoint” leaves important decisions unstated; “a user from another tenant cannot retrieve this record” is an observable requirement.

Distinguish three kinds of information: required behavior, technical constraints and open questions. For example, preserving a public API is a constraint; deciding whether a missing resource returns one business error or another may be an unresolved product decision.

ArtifactUseful contentWeak substitute
Behavior requirementObservable actor/action/outcome“Make it work well”
ConstraintCompatibility, data and execution boundariesUnstated assumptions
Acceptance scenarioInitial state, action and expected result“Tests should pass”
Decision logOwner, options and resolved choiceAgent guesses hidden policy
Traceability recordRequirement to test and review evidenceA checkbox with no supporting result

Keep the specification concise enough to review. A large generated document full of repeated claims can obscure the actual contract. Prefer a small authoritative record with links to relevant architecture and examples.

A worked support-request specification

Consider a fictional tenant-scoped support-request API. The task is to allow a user to read a request they are permitted to access. The examples below use fixture identities and records, not production data.

Purpose: retrieve a support request through the existing API
R1: An authenticated user may read an authorized request in their tenant.
R2: A user must not retrieve another tenant's request by guessing its ID.
R3: An unauthenticated caller receives the defined authentication failure.
R4: A missing request produces the approved not-found behavior.
R5: The response excludes internal-only diagnostic fields.

Constraints:
  preserve the current public response contract except approved additions
  use existing identity and repository abstractions
  do not add external services or production credentials

Open decision:
  confirm the approved disclosure policy for forbidden versus missing IDs

R2 and R4 need a coordinated decision about information disclosure. The agent should not silently choose a policy because one HTTP status is easier to implement. The product and security owners should settle the intended external behavior.

R5 needs an explicit response-field allowlist or equivalent reviewed contract. “Do not leak sensitive fields” is too vague if nobody has named which fields belong in the response.

This is a teaching example, not a complete authentication design. Real applications may have role, ownership, collaboration and resource-specific rules beyond tenant membership.

Map requirements to independent acceptance cases

RequirementGiven / whenExpected evidence
R1Authorized user retrieves an allowed fixture requestApproved response fields and successful result
R2User requests another tenant’s fixture identifierApproved denied/disclosure behavior; no record content
R3No valid caller authenticationDefined authentication failure
R4Allowed user requests a nonexistent identifierApproved not-found behavior
R5Internal-only fields exist on the stored fixtureFields absent from the response contract

Keep the acceptance cases owned by the evaluator. The assistant may propose additional cases, but should not rewrite expected outcomes merely to make its implementation pass.

Map each requirement to the relevant test identifier and result, then to the code/review artifact. One test can support several requirements, and a requirement can need several tests. The map should describe evidence rather than force an artificial one-to-one relationship.

Include regression cases for bugs discovered during review. If R2 fails through an alternate route, add that route to the acceptance set and correct the implementation. Do not simply update the specification to bless the defect.

A controlled spec-to-code workflow

Draft requirements + constraints + open decisions
                    ↓ owner review
Approved behavior and acceptance scenarios
                    ↓
Agent plan → focused implementation → reported checks
                    ↓ independent verification
Requirement-to-test-to-change evidence
                    ↓
Review decision + controlled release
                    ↓
Observed defect → revised decision/test where justified
  1. Review the specification: resolve material ambiguities before implementation.
  2. Constrain the task: provide repository context, allowed tools and compatibility boundaries.
  3. Ask for a plan: identify the expected modules, tests and remaining assumptions.
  4. Implement in small changes: inspect the diff and avoid unrelated rewrites.
  5. Run independent checks: preserve expected behavior and record results truthfully.
  6. Review the trace: identify uncovered requirements and unsupported completion claims.
  7. Release normally: keep approvals, recovery and operational ownership.

The AI-assisted SDLC playbook places this workflow in the larger delivery process. The NIST SSDF provides broader secure-development context for requirements, verification and vulnerability response.

A prompt can describe allowed scope, but execution controls should reinforce it. Keep secrets, external systems and production access constrained independently of the specification text.

A small traceability-artifact validator

We ran the following Python fixture against five cases: a valid map, duplicate requirement identifiers, missing coverage, unknown identifiers and an empty expected outcome. All five cases behaved as expected. The fixture checks document consistency only; it does not execute the application or prove that a test meaningfully verifies a requirement.

def validate(requirements,tests):
    ids=[r['id'] for r in requirements]
    if len(ids)!=len(set(ids)):raise ValueError('duplicate requirement')
    referenced={r for t in tests for r in t['requirements']}
    if referenced-set(ids):raise ValueError('unknown requirement')
    if set(ids)-referenced:raise ValueError('uncovered requirement')
    if any(not t['expected'].strip() for t in tests):raise ValueError('empty expected outcome')
    return True

For example, a requirement can be referenced by a test whose assertion is wrong. This validator would not detect that. Similarly, an “expected” string can be nonempty yet meaningless. Keep human review and actual test execution as separate gates.

In a larger implementation, store stable test identifiers, result links and the repository commit. Version the specification and test map together where practical. Do not make the traceability tool another source of silent policy decisions.

Common spec-driven development failure modes

The specification describes code rather than behavior

If the spec only says which function to call, it may not explain what users should observe. Add actor, condition and outcome. Keep implementation constraints when needed, but do not confuse them with acceptance.

The agent rewrites tests to match the bug

Review changed assertions and expected values. Keep independent cases. Require a justified requirement change before accepting a new outcome.

Important negative cases are absent

Add denied access, invalid input and dependency failure scenarios appropriate to the task. Happy-path coverage alone leaves the boundary undefined.

The traceability table looks complete but has no evidence

Record which checks actually ran and the result. Distinguish a planned test from an executed test. A link to a test file is not proof of a passing run.

The specification becomes stale

Update it through the same reviewed change process as the implementation. When behavior changes, revise the requirement, scenarios and operational documentation deliberately.

For security review of generated changes, see the AI-generated code security checklist.

Common questions

How does spec-driven development improve AI-generated code quality?

It makes intended behavior and boundaries explicit, then connects implementation to independent acceptance evidence. It reduces ambiguity but does not guarantee correctness.

Should a specification contain implementation details?

Include necessary technical constraints, but separate them from observable business behavior and unresolved decisions.

Can an AI agent write the specification?

It can draft and critique it. Accountable owners must resolve policy decisions and approve the intended behavior.

Does requirement coverage prove the software works?

No. A referenced test can be weak or wrong. Review test quality and execute meaningful independent cases.

How should requirement changes be handled?

Version and review the requirement, acceptance cases and implementation together, recording the reason and decision owner.

Give coding agents a contract you can verify

Bring the feature, current constraints and examples of ambiguous requirements. Discuss AI-assisted engineering adoption with a practical specification and traceability workflow.

From insight to implementation

Turn these ideas into a practical plan

Discuss how the ideas in this article apply to your business, systems and data. We’ll help you identify a focused first step.