AI Coding with Spec‑Driven Development and Context Engineering

Intro

I recently spoke at GitHub Connect Israel about Context Engineering and Spec-driven Development. This post is a complementary write-up. Watch the short recap on LinkedIn: https://www.linkedin.com/feed/update/urn:li:activity:7373958947743043584/

TLDR: Prompt engineering alone is not enough. Context engineering is the basis for spec‑driven development. Together they deliver reliable AI coding: context feeds the model only what matters at the right time, while the spec becomes the source of truth for code, tests, and docs. The result is faster iteration, fewer regressions, and higher trust.


Why the shift from prompts to context

Prompt engineering focuses on phrasing. An example I like to use to show its limits: prompt an image model with “salmon in the river” and it happily draws raw fillets swimming upstream. That is what happens when wording is ambiguous and there are no constraints. Context engineering focuses on everything that surrounds the prompt: the goals, constraints, examples, tools, memory, tests, and retrieved knowledge that steer an LLM to do the next correct thing.

Tobi Lütke, CEO of Shopify, sparked this mindset shift with a related take, which Andrej Karpathy replied +1 to: https://x.com/tobi/status/1935533422589399127. Karpathy popularized this shift. He calls context engineering “the art and science of filling the context window with just the right information for the next step.”

Key idea: performance drops when we stuff the window with irrelevant or noisy inputs. The work is to curate, structure, and evaluate context so the model pays attention to the right facts.


The context confusion trap

Irrelevant information pollutes working memory and creates competition for attention. Tool overload adds latency and failure points. Cognitive overload makes the model hedge or hallucinate. Most prompt failures are actually context failures.

Avoid these anti‑patterns

  • Everything‑bagel context: dumping entire wikis or repos into the window
  • Long unstructured text with hidden requirements
  • Conflicting instructions from multiple sources
  • Tools wired in by default, not by need
  • No ground truth or tests to check outputs

A simple model for context engineering

Use this loop to design and evaluate context in any AI coding workflow.

  1. System prompts: guardrails, tone, capabilities, failure modes
  2. User inputs: the current task described crisply with acceptance criteria
  3. Conversation history: minimal rolling history, summarized and pruned
  4. Long‑term memories: durable facts about the project, team, or domain
  5. Retrieved information: RAG over docs, code, designs, and tickets, filtered for relevance
  6. Available tools: compilers, linters, package managers, repos, CI, telemetry, browsers
  7. Output schemas: structured formats, file trees, tests, and checklists the model must return

Treat the loop as a budget. Each item must earn its tokens by improving accuracy or speed. If you cannot justify a piece of context, remove it.


What spec‑driven development adds

Spec‑driven development makes the specification executable and central. You start with a living spec that describes the product in human and machine readable form. The spec generates stubs, tests, and documentation. The AI then implements code to satisfy those tests, guided by the spec. The spec remains the contract for future changes.

Benefits

  • Shared truth for product managers, engineers, design, and security
  • Fast onboarding and repeatability across repos and teams
  • Safer AI coding since generation is constrained by tests and types
  • Automatic docs that stay in sync with code

A minimal spec can include

  • Problem statement and non‑goals
  • Entities, events, and data contracts
  • User stories and acceptance tests
  • Architecture and boundaries: what is in, what is out
  • Operational SLOs and error handling policy

Specs over code – treat code as compiler output

When teams move fast with AI, it is tempting to treat generated code as the artifact. That is backwards. In traditional software we never commit the compiler output – we commit the source and regenerate the binary from scratch. Do the same with AI coding.

The valuable asset is the spec, contracts, and tests. Code and docs are derivations that can be regenerated.

Prompts are transient and hard to audit. Replace ad-hoc prompts with durable context: a written spec, examples, data contracts, and acceptance tests.

One spec can target multiple outputs: servers, clients, TypeScript or Rust types, API docs, tutorials, even talk tracks and blog posts.

A practical starter workflow with GitHub

You can apply spec‑driven development with any model. GitHub’s open‑source spec‑kit makes it simple to bootstrap.


The vibe-coding journey

  • Vibe coding – great for creativity and speed. Use it to explore ideas and learn the problem space.
  • Prompt engineering – add constraints, goals, and examples. Start testing and versioning your asks.
  • Spec-driven development – anchor the work in a repo-backed spec and tests. This delivers predictable, reliable outcomes and scales across teams.

Patterns that work in production

  • Context is layered: start from constraints and contracts, then add the smallest amount of task specific detail
  • Small batches: break work into verifiable steps that each end with a test or checklist
  • Schemas everywhere: insist on structured outputs, file trees, and patch sets
  • Selective tools: enable tools only when the step needs them
  • Continuous evals: seed a lightweight eval suite and run it on every iteration

Common failure modes and fixes

  • Model overwhelms itself with options Fix by pruning context, adding a single source of truth, and requiring one structured output
  • Generated code “mostly works” but drifts Fix by tightening contracts and tests, then regenerate with the failing case in context
  • Latency and cost spike Fix by shrinking inputs, turning off unused tools, and caching retrieved chunks
  • Security review finds unknown dependencies Fix with an allowlist in the spec and a CI check for new packages

A quick checklist

  • Do we have a written spec with contracts and tests
  • Is the current task framed with explicit acceptance criteria
  • Is the context for this step limited to what the model needs right now
  • Are outputs constrained by schemas and file trees
  • Are we running evals and acceptance tests on every iteration
  • Is the spec updated when behavior changes

Where to go next

  • Read GitHub’s announcement and try the open‑source spec‑kit
  • Recreate the context engineering loop in your own agent or IDE setup
  • Start small. Pick one service or feature. Write the spec, generate the skeleton, make one test pass, repeat

References and further reading