Why Spec-First Beats Vague Prompting
You already use at least one AI coding agent. Maybe it is Claude Code in your terminal, Cursor in your editor, Copilot in your IDE, or a more autonomous agent like Devin. You have felt the magic: type a request, watch working code appear. You have also felt the other thing: the agent confidently builds something that runs perfectly and does the wrong job, and you spend the next hour describing what you actually meant one patch at a time.
That second experience is not a tooling problem. It is a method problem. This course teaches the method: spec-driven development, the discipline of writing a precise specification first, handing it to the agent, and verifying the output against that spec instead of against your gut feeling. It works the same way no matter which agent you use, because the spec lives outside the tool.
What You'll Learn
- Why vague prompting degrades as a project grows
- What "spec-first" actually means as a repeatable loop
- The difference between describing an outcome and describing a wish
- How a spec turns into your contract for verification
- Where this course fits next to tool-specific courses
The vibe-coding trap
The default way people work with agents is what Andrej Karpathy named "vibe coding": you describe roughly what you want, accept whatever comes back, run it, and react to whatever breaks. For a throwaway prototype this is genuinely fast and genuinely fine.
The trouble starts the moment the work matters. As a codebase grows, each vague prompt carries more hidden assumptions, and the agent fills every gap with a guess. The guesses are plausible, which is exactly what makes them dangerous: the code compiles, the demo works, and the bug only surfaces in the one case you never described. You end up in a patch-and-repeat cycle that gets slower as complexity rises, because you are debugging the agent's interpretation of an unwritten requirement.
Spec-first inverts this. You spend the thinking up front, in writing, and the agent executes against a target you can both see.
The spec-first loop
Spec-driven development is a four-step loop. You will run it over and over in this course.
- 1. Write the specAcceptance criteria, edge cases, constraints
- 2. Hand it to the agentContext + spec + constraints
- 3. Verify against the specTests, not vibes
- 4. IterateFix the spec or the output
The key shift is that the spec, not the code, is the source of truth. Code is the thing you derive from the spec. When the agent's output disagrees with the spec, one of them is wrong, and you fix whichever one is wrong before moving on. That single rule is what keeps quality from drifting as the project grows.
Outcome versus wish
The heart of a good spec is describing an outcome you can check, not a wish you hope the agent shares.
A wish sounds like: "Add a function to validate emails." That leaves the agent to guess what counts as valid, what happens on failure, whether empty strings pass, and what the function returns. Each guess is a place your intent and the agent's intent can silently diverge.
An outcome sounds like: "Add isValidEmail(input: string): boolean. It returns true only when input contains exactly one @ with at least one character before it and a dot-separated domain after it. Empty string returns false. Leading and trailing whitespace is trimmed before checking. It never throws."
Notice the difference. The second version is checkable. You could hand it to a colleague, or to a test runner, and get an unambiguous yes-or-no on whether the result is correct. That checkability is the whole game, and the next lesson breaks down exactly how to write it.
Why this is tool-agnostic
A natural question: doesn't my agent already have a spec feature? Many do. By 2026, GitHub's Spec Kit, AWS Kiro, OpenSpec, and the spec workflows baked into Claude Code and Cursor all offer their own flavor of this. That is good news, but it is not the skill. The skill is knowing what to put in the spec and how to verify against it. That knowledge transfers to every one of those tools, and to the next one that ships.
This course deliberately teaches the workflow, not the buttons. When you want the buttons, the companion courses cover the specific tools:
- Claude Code for terminal-based agentic coding
- Cursor and AI IDE workflows for editor-native agents
- GitHub Copilot for pair programming inside your IDE
Think of it this way: this course teaches the recipe; those courses teach the kitchen you cook it in. A great recipe works in any kitchen.
A quick before-and-after
Here is the same task, vague and spec-first, so the gap is concrete.
Vague prompt:
Build me a rate limiter for the API.
Spec-first prompt:
Build a rate limiter as Express middleware.
Acceptance criteria:
- Allows at most 100 requests per IP per rolling 60-second window.
- The 101st request in the window returns HTTP 429 with a JSON body
{ "error": "rate_limited", "retryAfter": <seconds> }.
- Sets a Retry-After response header in seconds.
- Requests from different IPs are counted independently.
Edge cases:
- Missing/unparseable IP is treated as a single shared bucket "unknown".
- The counter resets correctly at the window boundary (no off-by-one).
Constraints:
- In-memory store only; no Redis. Single-process assumption is fine.
- No new dependencies beyond what Express provides.
The vague prompt produces a rate limiter. The spec-first prompt produces your rate limiter, and gives you a checklist to verify it against. When the output is wrong, you point at the failing criterion instead of re-explaining from scratch.
Key Takeaways
- Vague prompting is fine for throwaways but degrades fast on work that matters, because the agent fills every gap with a plausible guess.
- Spec-driven development is a loop: write the spec, hand it to the agent, verify against the spec, iterate.
- The spec, not the code, is the source of truth; code is derived from it.
- Describe checkable outcomes, not wishes the agent has to share.
- The method is tool-agnostic; it works with any agent, while tool-specific courses teach the buttons.

