Spec-Driven Development: Let the Spec Drive the Code (With a Real Example) Sergio Colque Ponce, a software engineering student at Universidad Privada de Tacna, proposes Spec-Driven Development (SDD) as a methodology to improve AI coding agent accuracy by writing specifications before code. He demonstrates the approach with a URL shortener project using GitHub's Spec Kit and an OpenAPI contract, where tests validate the implementation against the spec automatically. By Sergio Colque Ponce— Software Engineering, Universidad Privada de Tacna. Full source code: github.com/srg-cp/spec-driven-development If you have used an AI coding agent — Copilot, Claude Code, Gemini CLI — you have probably lived this moment: you describe a feature, the agent produces code that compiles and looks right, and then it quietly does the wrong thing. The agent is not weak; the input was ambiguous. We have been treating coding agents like search engines when they behave more like very literal pair programmers. Spec-Driven Development SDD is the answer to that problem: instead of jumping straight to code, you write down what you want and why , refine it, and only then let the implementation follow. The specification — not the code — becomes the center of the project. The idea is old anyone who has written a Product Requirements Document will recognize it , but it has become practical again thanks to tools like GitHub's open-source Spec Kit https://github.com/github/spec-kit . Spec Kit organizes the work into a small set of Markdown artifacts, each feeding the next: The workflow is usually summarized as Spec → Plan → Tasks → Implement , and the same process is meant to work regardless of language, framework, or which of the 30+ supported agents you use. The real shift is not "more documents." It is this: when requirements change, you update the spec, regenerate the plan, and let the implementation follow — instead of patching code and hoping the intent survives. The spec is a living artifact, not a dusty Word file nobody opens. You do not need Spec Kit to practice SDD. The underlying principle is simple and tool-agnostic: The specification is the single source of truth. The code and the tests are derived from it — never the reverse. The most powerful version of this is an executable specification : a machine-readable contract that your tests and CI can check the implementation against automatically. If the code drifts away from the spec, the build fails. That is what turns a spec from documentation into a guardrail. Let me show exactly that with a small, real project you can run yourself. We want a /shorten endpoint: send a long URL, get back a short code. The SDD move is to write the contract first , before any logic. Here it is as an OpenAPI document spec/openapi.yaml : components: schemas: ShortenRequest: type: object required: url additionalProperties: false properties: url: type: string format: uri minLength: 1 ShortenResponse: type: object required: original url, short code additionalProperties: false properties: original url: type: string short code: type: string description: Exactly 7 lowercase hex characters. pattern: '^ 0-9a-f {7}$' Notice we already decided the shape of success: a response must contain original url and a short code of exactly seven hex characters. No code exists yet, but the rules are unambiguous. Now the code simply honors the contract. Its job is to satisfy ShortenResponse , not to invent its own format: python import hashlib class InvalidURLError ValueError : """Raised when the input violates the ShortenRequest schema.""" def shorten url: str - dict: if not isinstance url, str or not url: raise InvalidURLError "url is required and must be a non-empty string" short code = hashlib.sha256 url.encode "utf-8" .hexdigest :7 return {"original url": url, "short code": short code} This is where SDD stops being a slogan. The tests load the spec and validate the implementation against it. The assertions are not hand-copied from the code — they come straight from the contract: python import yaml, jsonschema from openapi spec validator import validate as validate openapi from shortener import shorten, InvalidURLError SPEC = yaml.safe load open "spec/openapi.yaml" .read def schema name : return SPEC "components" "schemas" name def test spec is a valid openapi document : validate openapi SPEC the contract itself must be valid def test response conforms to the spec : result = shorten "https://upt.edu.pe/admision/2026" jsonschema.validate instance=result, schema=schema "ShortenResponse" If someone later changes shorten to return, say, an 8-character code, the pattern in the spec no longer matches and test response conforms to the spec fails immediately. The spec is now enforced . A small GitHub Actions workflow validates the contract and runs the tests on every push. The spec is checked by a machine, on every change, forever: name: CI on: push, pull request jobs: spec-and-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.12' - run: pip install -r requirements.txt - run: python -c "import yaml; from openapi spec validator import validate; validate yaml.safe load open 'spec/openapi.yaml' " - run: pytest -v Running the suite locally is just as honest: tests/test contract.py::test spec is a valid openapi document PASSED tests/test contract.py::test response conforms to the spec PASSED tests/test contract.py::test short code matches the specified pattern PASSED tests/test contract.py::test invalid request is rejected PASSED Spec-Driven Development shines on greenfield work starting from zero, where it is tempting to just start typing , on features with real consequences where "looks right" is not good enough, and on any project handed to an AI agent that needs unambiguous intent rather than a vague prompt. It is overkill for a throwaway script — but for anything you will maintain, the spec pays for itself the first time a requirement changes. One honest caveat: keep a human in the loop . SDD with AI does not mean blind trust. You still review the spec, the plan, and the generated code at the critical steps. Spec-Driven Development is less about a specific tool and more about reversing the usual order: decide what is correct, write it down where machines can check it, and let the code and tests follow. Whether you adopt the full Spec → Plan → Tasks → Implement workflow with Spec Kit, or just keep an OpenAPI contract that your CI enforces, the payoff is the same — your software does what you actually meant, and it keeps doing it after the next change. The complete, runnable project is here: github.com/srg-cp/spec-driven-development . Clone it, change the short code pattern in the spec, run the tests, and watch the contract catch you.Thanks for reading