Raju H
Blog

Spec-Driven AI Explained: A Working Professional's Guide (with Real Examples)

Why spec-driven AI beats vibe-coding in production, the four-paragraph spec that ships a feature without 12 retries, and how to apply it whether you write code or not.

Raju H

AI Builder · Dhaka

· 8 min read

TL;DR

Spec-driven AI is the practice of writing a precise, machine-readable specification before prompting the model — so the AI knows what success means, not just what you want. The result: 1-2 prompt iterations instead of 10-12, code that survives production, and outputs you can verify without re-reading every line. It works for engineers, product managers, analysts, and anyone whose job involves producing structured artifacts.

What spec-driven AI actually means

The default way most people use AI is: type what you want, read what comes back, type a correction, read again. Repeat 8-15 times. This is sometimes called vibe coding — you're vibing with the model, feeling your way toward the answer.

Vibe coding works fine for low-stakes drafts (a tweet, a quick email, a throwaway script). It collapses the moment you need:

  • Code that will run in production with real users
  • A document that downstream teams have to trust
  • An output that needs to be consistent across multiple runs
  • Anything where "almost right" is materially worse than "wrong and rejected"

Spec-driven AI inverts the loop. Before the first prompt, you write a specification: a structured description of what success looks like, what failure modes you want to prevent, and what constraints the output must respect. Then you hand the spec to the model and ask for an implementation. Two outcomes:

  1. The first output is usually close enough that one round of feedback gets you to done.
  2. Where it's not close, the gap is debuggable — you can point at a specific constraint in the spec that the output violated, instead of vague dissatisfaction.

A recent arXiv paper calls this "treating specifications as executable contracts from which AI agents derive code." Red Hat's developers blog frames it as eliminating the ambiguity tax — the cost of every clarification round you'd otherwise pay. JetBrains' Junie team describes it as scoped patches reviewed individually rather than full features generated in one shot.

What a real spec looks like

I'll show you a concrete one. This is the spec I wrote before implementing bKash payment processing on this site:

## Trap 1: Idempotency
`bkashPaymentId` is the idempotency key. On callback, look up by
`bkashPaymentId`; if already `paid`, return success without
re-executing or re-updating.

## Trap 2: Callback verification
bKash Tokenized Checkout has no webhook signature. The `executePayment`
API call IS the verification — only mark a row `paid` when execute
returns `transactionStatus: "Completed"`.

## Trap 3: Seat-hold TTL
Pending registrations count toward `seatLimit` for 15 minutes; older
pending rows are excluded from seat-count math.

## Trap 4: Stale-pending cleanup
Runs on every seat-count read — no cron.

Six paragraphs. Notice what's there:

  • Named constraints, not aspirations. "Idempotency" is a contract the output must satisfy. "Make it idempotent if possible" is not.
  • Failure modes as much as success modes. Trap 2 isn't "verify the payment" — it's "don't trust the query string alone." Spec-driven AI is mostly about preventing wrong outputs, not generating right ones.
  • Specific column names + API field names. bkashPaymentId, executePayment, seatLimit. The model can't infer your schema; you tell it.
  • No prose explanation of why. A model doesn't need motivation, only constraints. The audience for the spec is the model, not you a year from now (the comments in the code are for you).

I handed that spec to Claude Code, told it the stack, and got working code in one afternoon. The first version had three things to fix; all three were boundary issues (bKash fee passthrough, refund semantics, sandbox URL switching) that weren't in the spec because I hadn't thought of them yet. None were the kind of "AI hallucinated nonsense" you fight with vibe coding.

Why vibe coding fails in production

Three reasons, all rooted in the same problem: the model doesn't know what success means.

  1. The model defaults to the most common pattern. If you ask for "a bKash integration," you get the most common bKash integration online, which is the demo version with no idempotency. The model isn't wrong — it's giving you what 90% of tutorials show. You wanted the 10% production version, but you didn't say so.

  2. You can't test what isn't specified. A spec is a checklist. Without it, you have no way to know whether the output is "done" — you just keep tweaking until something feels right. With it, you can check each constraint and stop when they all pass.

  3. Subsequent prompts compound the drift. Every "fix this" prompt adds entropy. By prompt 8 the model is producing a Frankenstein of your earlier requests, none of which it was ever asked to optimize together. A spec is the anchor that prevents drift.

A 2026 Red Hat study found that "constitutional constraints" — specs treated as machine-enforced contracts — reduce security defects by 73% compared to unconstrained AI generation. That's not a small gap. That's the difference between "I shipped a demo" and "I shipped a thing my users can trust."

How to write a spec (for any task, not just code)

The shape is the same whether you're asking for code, a PRD, a marketing email, or a financial model:

1. Name the artifact and its purpose

"I need a database schema for a 5-day bootcamp registration system with bKash payments and a refundable deposit on completion."

One sentence. The model now knows what you're building and the high-level constraint (refund, 5-day, payments).

2. List the constraints as named rules

  1. Idempotency on payment callbacks via bkashPaymentId.
  2. Seat counter excludes pending registrations older than 15 minutes.
  3. Refund only the deposit; bKash service fee is non-refundable.
  4. Distinguish cancellation refunds (seat freed) from completion refunds (seat stays spent).

Numbered, named, specific. The model will treat these as a checklist.

3. Specify failure modes you want to prevent

  • Don't trust query-string status from the bKash callback.
  • Don't run a cron job; cleanup must be lazy.
  • Don't store the bKash fee rate as part of registration data — freeze the BDT amount at registration time so future rate changes don't break old refunds.

These are the lines that make the output production-grade. Most people skip this section. Don't.

4. Specify the boundary with the rest of the system

The bKash module is src/lib/bkash.ts. The schema lives in src/db/schema.ts. Server Actions in src/app/bootcamp/[slug]/register/actions.ts. Use Drizzle ORM, Postgres, Next.js 16 App Router.

Now the model knows where to put the code and what to import. No invented import paths.

That's a spec. It's usually shorter than the code that comes out of it.

For non-engineers: the same idea, different artifact

You don't need to write code for spec-driven AI to work for you.

A PRD spec might look like:

## Artifact: PRD for [feature name]

## Audience: senior engineering leadership

## Required sections (in this order):
1. Problem statement (3 sentences max, must include specific user
   pain point)
2. Current state (what happens today without this)
3. Proposed change (one-paragraph summary)
4. Success metrics (3 quantifiable, with how-measured + by-when)
5. Non-goals (what we are explicitly NOT doing)
6. Risks (top 3, each with a mitigation)

## Constraints:
- Active voice only
- No vendor-specific solution language; describe behaviour, not tool
- Each section under 100 words
- Cite at least one user research source per claim about user pain

That spec, handed to ChatGPT or Claude with a one-paragraph context dump about the actual problem, produces a near-finished PRD in one round. No bouncing between "make it shorter," "add metrics," "remove the marketing-speak." All of those were in the spec.

This is what we help product managers, analysts, and ops leads do in the bootcamp.

When NOT to use spec-driven AI

There are real cases where vibe coding is the right tool:

  • Exploration. You don't know what you want yet. The point of the conversation is to discover the shape. Specs presume you already know the shape.
  • Writing prose you'll edit personally. Specs help when the model's output is going to be used as-is. For a blog post you'll rewrite in your own voice anyway, the cost of writing a spec exceeds the saved revision time.
  • One-off scripts you'll throw away. A 15-line bash script doesn't need a spec. Just type the thing.

The rule of thumb: if the cost of "wrong but plausible-looking" is high, write the spec. If it's low, vibe.

What to do next

Pick a task you'll work on this week with AI. Before you open the chat, write four short sections:

  1. The artifact and its purpose (1 sentence)
  2. The constraints as numbered rules (3-6 rules)
  3. The failure modes you want to prevent (3-6 items)
  4. The boundary with the rest of your system (paths, schemas, tools)

Hand the spec to the model — or use the free Spec Builder to assemble one from a form. Note how many iterations the output takes versus the last similar task you vibe-coded. The first time I tried this with bKash integration, I went from 11 iterations on a previous mediocre attempt to 1 iteration that shipped. Your numbers will vary; the direction won't.

If you want to learn this end-to-end with a hands-on 5-day program, the bootcamp is what we built around this idea. If you'd rather DIY: read the Red Hat post on spec-driven development, the JetBrains Junie writeup, and the arXiv paper on specifications as contracts. Then write a spec for the next thing you'd otherwise vibe-code.

The shift in habit takes about a week. The compounding starts immediately.

Further reading

This site uses analytics to improve future bootcamps. Privacy & cookies