Vibe Coding with PRDs: How to Keep AI Coding Agents on Track

Vibe coding breaks down on complex features. A PRD for AI coding agents fixes that: what to put in it, how to structure it, and when to skip it.

Claude Fable 5.1, GPT-6 Astra and Claude Opus 5.5 are the most capable models yet for vibe coding. The techniques for working with them change constantly: context engineering, prompt loops (remember the Ralph loop?), long markdown instruction files, meta-harnesses. Most of them worked around weaknesses in the harnesses (like Claude Code) or in the models themselves, especially short context windows, and they stop being useful once those weaknesses are fixed.

PRDs for AI coding agents are different. They compensate for something no model upgrade fixes: a settled decision about what you're building. If anything, a smarter agent just builds the wrong thing faster and with more confidence.

Once that decision is written down, you and the agent have a shared reference to check against when the session resets, when a second agent joins, or when the code stops matching what you wanted.

Quick recommendation: write a PRD for any feature that spans more than one session, touches several layers of your app, or will be built by more than one agent. Give it non-goals, edge cases, and checkable acceptance criteria, and have the agent build it one story at a time. For a change that fits in one session, Claude Code plan mode is enough.

What is a PRD (Product Requirements Document)?

A PRD describes what a feature should do, who it's for, and how you'll know it works. Product teams have used them for decades to align engineers, designers, and stakeholders before anyone writes code.

A classic PRD deliberately stays out of the how; that's engineering's job. A PRD written for an agent can't. The agent is the engineer, and it fills every gap you leave with a guess. It asks when it notices it's unsure, and most of the time it doesn't notice. So an agent-facing PRD also spells out:

  • Constraints: the stack, patterns, and boundaries the implementation must respect
  • Non-goals: what's explicitly out of scope, so the agent doesn't build it anyway
  • Edge cases: empty states, failures, permissions, limits
  • Acceptance criteria: concrete enough that the agent can check its own work against them

Where vibe coding breaks down

Vibe coding works well at first. For the first few prompts, the agent quickly builds whatever you ask for.

Those early results make you trust the agent more than the code deserves, and you stop checking. Even frontier agents leave problems behind that you won't notice until they cause bugs.

Decisions you never made

Every gap in your prompt is a decision the agent makes for you: the data model, the error handling, what happens when a user has no team. It rarely tells you, so you discover these choices weeks later, with more code built on top of them. A PRD makes you take those decisions up front, when they're cheap to change.

Session amnesia

Decisions made in chat are lost when the context resets. The next session reopens them or contradicts them without saying so, and you end up with two auth patterns and three ways to format dates. A PRD stores those decisions outside the context window, where the next session can read them.

Agents stepping on each other

Run parallel agents, or hand work from one to another, and each one works toward its own task with its own assumptions. Without a shared reference, they undo each other's choices. The PRD gives them all the same reference.

Stale comments

Agents write comments describing what the code does, then later change the code without updating them. The next agent reads the comment, trusts it over the code, and builds on a false premise. Outdated comments put false information into the agent's context.

Code that only grows

Agents add code more readily than they refactor it. Every feature leaves helpers, wrappers, and dead branches behind. More code means more context, and more context means worse edits next time. Non-goals and a clear scope in the PRD stop the agent from building things nobody asked for.

Security gaps nobody specified

Agents implement the main flow well. Permissions, rate limits, and who-can-see-what are rarely in the prompt, so they're rarely in the code. If your PRD lists them as edge cases and acceptance criteria, they get built and checked. If it doesn't, they may never get built.

What should a PRD define?

Keep it focused: one feature, split into a handful of stories. Its job is to answer the questions the agent would otherwise answer for you. Using weekly report emails as an example:

  1. Problem and scope. What's missing, for whom, and what's in versus explicitly out. Non-goals are the easiest way to limit scope; without them, an agent will build adjacent features you didn't ask for. Example: in: weekly email summary, opt-in per user. Out: daily schedules, PDF attachments, external recipients.
  2. Behavior. Flows and states from the user's side. Describe behavior, not implementation: "reports go out Monday at 8:00 local time" belongs here; "add a cron job" doesn't.
  3. Constraints. Stack, existing patterns to reuse, things not to touch. This is where an agent PRD differs from a classic one: the agent is the engineer, so it needs to know the project's conventions.
  4. Edge cases. Agents handle the main flow well and miss these. If you only write one section, write this one. Example: recipients in different time zones, a week with no activity, a team that downgrades mid-cycle.
  5. Acceptance criteria. Checkable statements the agent can verify its own work against, ideally as tests. If a criterion can't be checked, the agent can't verify it. Example: a user who opted out receives nothing; a week with no activity sends no email.
  6. Decisions and open questions. What's been decided and why, and what hasn't been decided yet. The first prevents session amnesia; the second tells the agent where to stop and ask instead of guessing.

Leave out step-by-step implementation plans. They depend on the PRD, and they become outdated as soon as the code changes.

How the Makerkit PRD is structured, and why it suits agents

At Makerkit, I built an MCP server that helps AI agents write PRDs and build features from them. The Makerkit kits' MCP server includes PRD tools too; this standalone server works in any project. The format is more detailed than a typical markdown spec, because each part of it addresses one of the failures above.

Most "PRDs for AI" are a markdown file the agent reads once and loses track of as the session goes on. The Makerkit PRD MCP server (@makerkit/prd-mcp, MIT) stores each PRD as a typed JSON document in .prds/.

Because the document is structured, the agent never loads the whole file: it asks the MCP server for one story, and gets back that story plus only the context it needs. That means fewer tokens and less context rot. Writes are just as targeted. Marking a story done or recording a decision updates one validated field, instead of an agent rewriting the whole document and accidentally changing parts it wasn't supposed to touch.

Stories are the unit of work

A PRD holds the big picture: problem, users, scope, non-goals, constraints, permissions, data models. Agents don't work on the big picture, though. They work on one story at a time:

{
"id": "US002",
"title": "Send the weekly report",
"userStory": "As a team member, I want a weekly summary email so I can follow project activity without logging in.",
"acceptanceCriteria": [
"Sends Monday at 8:00 in the recipient's time zone",
"Skips weeks with no activity",
"Users who opted out receive nothing"
],
"dependencies": ["US001"],
"status": "not_started",
"testSeams": ["sendDueReports"],
"securityNotes": ["Include only projects the recipient can access; check membership at send time, not at opt-in"]
}

get_next_story returns the next story whose dependencies are all completed. get_story returns that story along with only the context it needs: the PRD summary and scope limits, its dependencies and their hand-off logs, and the log of the most recently finished story. The agent gets a short brief instead of the whole document, which keeps the context window small and relevant.

Undecided items are tracked explicitly

The Makerkit PRD makes undecided items explicit: open questions, open edge cases, and sections marked not applicable. Agents fill gaps with guesses, so the format makes gaps visible:

  • Open questions record the question, why guessing would be harmful, the options, a recommended answer, and the stories they block. check_plan marks a plan as not ready while a question blocks a story, and get_story hands the agent every open question attached to its story, so it stops and asks. Answering a question records a decision and removes the question.
  • Edge cases are either open or decided. A decided case requires an expected behavior. An open case tells the agent to ask instead of assuming.
  • Not applicable is explicit. If an internal tool has no rollout plan, you mark it with a reason, and the agent stops inventing one.

Decisions persist across sessions

The decision log records each decision with its rationale, a status (proposed, accepted, superseded) and a topic such as design:navigation or story:US001:data-model. When a session resets, the next agent reads what was decided and why (get_story includes the design decisions; get_prd returns the full log), so it doesn't reopen it. When a story is deleted, the decisions about it are marked superseded automatically, so outdated decisions don't stay active.

Hand-off logs

When an agent finishes a story, it writes a log entry in three parts:

  • What's new: what a human can now try
  • Technical notes: decisions, gotchas, and file locations for the next agent
  • Deviations: where the work departed from the PRD, and why

Deviations make review faster. Instead of reading hundreds of lines of diff to find what the agent changed its mind about, you read a short list.

"Done" means verified

A story can only move to completed when the project's checks pass, and the result is recorded on the story: which checks ran, and when. By default the checks are the typecheck and lint scripts in your package.json; to change them, list every script with --check, for example --check typecheck --check lint --check test. "The agent said it's done" becomes "typecheck and lint passed at 14:02."

Shared vocabulary

The glossary stores each term with its definition and the synonyms to avoid. An agent that calls the same concept "workspace," "team," and "organization" across three files writes code no one can search.

Safe for multiple agents

Two features protect a PRD that several agents (or an agent and a human) work on at the same time:

  • IDs are never reused. With US001 to US004 in the PRD, delete US002 and the next story is still US005, because story IDs get quoted in commits and conversations.
  • Writes can be revision-checked. Every save increments a revision, and a write that carries the revision it was based on is rejected if the PRD changed since. Loop always sends it, so Loop and an agent can't silently overwrite each other.

Finally, check_plan reviews the PRD before any code is written. It flags what's missing as required (for example, stories without acceptance criteria) or recommended (for example, no edge cases, or more than five stories with no phases). A plan that fails the check isn't ready to build.

How broad should a PRD be?

One PRD per feature: one outcome a user would notice, that could ship on its own. Weekly report emails is one PRD, even though it touches the database, a background job, email templates, and settings. "The reporting system" is not.

If you start from a SaaS boilerplate like Makerkit, auth, billing, and team management already exist, so your PRDs only need to cover what's specific to your product. Those are the parts where the agent has no existing code to follow. For a full walkthrough of that workflow, see building a SaaS with Claude Code.

When a PRD grows, group its stories into phases before splitting it. Split it into separate PRDs when you see these signs:

  • Groups of stories don't depend on each other. If two sets of stories never reference each other, they're two features.
  • The parts could ship separately. If you'd release half of it without the other half, that half is its own PRD.
  • Edge cases get vague. If you're writing "handle errors appropriately" instead of naming specific cases, the PRD is too broad for you to think through properly.
  • Sloppy acceptance criteria. If you can't write a checkable statement for each story, the PRD is too broad to be useful.

Sloppy acceptance criteria are the clearest sign a PRD is too broad. A PRD that covers too much is shallow by necessity. Every section gets a sentence instead of a decision, and the agent fills the gaps with its own assumptions, which is exactly what the PRD was supposed to prevent.

Do PRDs make you slower?

Up front, yes. The interview takes time, and shaping a PRD costs tokens before any code exists.

But for a complex feature, the cost you're replacing is rework: undoing a data model the agent picked without asking, re-explaining decisions after every context reset, reviewing diffs to find what changed. That costs more time and more tokens than the PRD did. And once the PRD exists, each session loads one story instead of re-reading the codebase to work out where things stand.

For small changes, skip it. A PRD is worth writing when the feature:

  • spans more than one session
  • touches several layers (database, API, UI)
  • has edge cases you can't list from memory
  • will be built by more than one agent

A button, a copy change, or a bug fix in one file doesn't need a PRD. Just prompt it.

Reviewing PRDs in Loop

If an agent wrote your PRD, you have to read it before anything gets built. Reviewing it is the point: it's where you catch the decisions you didn't mean to make. But a full PRD in JSON is hard to review.

That's why I built Loop, an open source visual interface for the PRDs in .prds/. It lets you:

  • see stories by phase and status, and which are blocked
  • answer open questions and decide edge cases directly
  • review hand-off logs and deviations before approving a story

Run it in any project, not just Makerkit apps:

npx @makerkit/loop@latest

Loop and your agent can work on the same PRD at the same time. Every save Loop makes is revision-checked, so it never overwrites the agent's changes.

Alternatives

The Makerkit PRD isn't the only way to give agents a spec. Spec-driven development has become its own category, and the tools in it make different trade-offs. Here are the ones worth knowing (details checked against each project's official page in October 2026; for the broader tool picture, see the best vibe coding tools).

Claude Code plan mode

The zero-setup option. Plan mode has the agent research and propose a plan before writing code, and you approve or adjust it. For a medium-sized change in a single session, that's often enough (more on that in Claude Code best practices). It isn't designed as a durable record, though: there's no decision log, no story tracking, and nothing that carries open questions into the next session.

Use it when: the change fits in one session.

GitHub Spec Kit

GitHub's open-source toolkit, and the project that popularized the term "spec-driven development." Work moves through slash commands (constitution, specify, plan, tasks, implement), each producing a markdown file. It supports more than 30 coding agents and is MIT-licensed.

Use it when: you want a well-known, agent-agnostic process and are comfortable reviewing a fair amount of markdown.

Kiro

AWS's spec-first IDE. A spec moves through requirements, design, and tasks, producing requirements.md, design.md, and tasks.md, with a review step between phases. It also has bugfix specs, a Quick Spec mode that skips the approval gates, and can run independent tasks in parallel.

Use it when: you're willing to adopt a new IDE to get the most integrated experience.

OpenSpec

A lightweight spec layer built for existing codebases. Instead of a full spec per feature, each change records which requirements it adds, modifies, or removes. It's MIT-licensed and needs no MCP server or API key.

Use it when: you're changing a mature codebase and want specs to follow the code with minimal process.

Task Master

An MCP server that parses a PRD you've written into a tasks.json file of tasks with dependencies, scores their complexity, and breaks the complex ones into subtasks. It works with Claude Code, Cursor, Windsurf, Codex, and others. Note the license: MIT with Commons Clause, which bars selling it or offering it as a hosted service.

Use it when: you already have a PRD and mainly want it broken into tracked tasks.

BMAD Method

The heaviest option. A team of agent personas (analyst, PM, architect, scrum master, developer, QA) plans the work, producing a PRD and an architecture document that get split into detailed story files. It's model-agnostic and MIT-licensed, but it costs a lot of tokens and takes time to learn.

Use it when: you're building something large from scratch and want a full agile process run by agents.

Where the Makerkit PRD fits

Most of these tools focus on turning a spec into tasks. The Makerkit PRD MCP server stores each PRD as typed JSON in .prds/ and focuses on what happens between sessions: open questions that block stories until you answer them, a decision log the next session reads, hand-off logs with deviations, and a completion gate that runs your checks before a story counts as done. It works with any MCP client, requires no new IDE, and is MIT-licensed.

If one of the tools above fits your workflow better, use it. Any of them beats prompting a complex feature from memory.

Conclusion

Coding agents will keep getting better, and many of today's techniques will stop being necessary. A PRD won't, because it doesn't work around a weakness in the model. It records decisions only you can make: what you're building, what you're not building, and what should happen when things go wrong.

Without those decisions, a capable agent makes them for you, quickly and without telling you. With them written down, every session, every agent, and every review starts from the same reference.

You don't need a PRD for every change. Use one for the features that span several sessions, touch several layers of your app, or have edge cases you can't list from memory. Those are the features where vibe coding usually goes wrong.

To try it, add the MCP server to your next complex feature:

claude mcp add prd -- npx -y @makerkit/prd-mcp

Run /mcp__prd__shape_prd, answer the questions, and read the PRD before the agent writes any code.

Frequently Asked Questions

Do I need a PRD for vibe coding?
Not for every change. Write one when a feature spans more than one session, touches several layers (database, API, UI), has edge cases you can't list from memory, or will be built by more than one agent. A button, a copy change, or a one-file bug fix doesn't need one.
What should a PRD for an AI coding agent include?
Problem and scope with explicit non-goals, behavior described from the user's side, constraints (stack, patterns to reuse, things not to touch), edge cases, checkable acceptance criteria, and a list of decisions and open questions. Leave out step-by-step implementation plans.
Is a PRD the same as Claude Code plan mode?
No. Plan mode produces a plan for one session that you approve before the agent writes code. A PRD is a durable record: decisions, open questions, and story progress carry over to the next session and to other agents.
How big should a PRD be?
One PRD per feature: one outcome a user would notice that could ship on its own. Split it when groups of stories don't depend on each other, parts could ship separately, or you can no longer write checkable acceptance criteria for each story.
How do I try the Makerkit PRD MCP server?
Run claude mcp add prd -- npx -y @makerkit/prd-mcp, then run the /mcp__prd__shape_prd prompt. It interviews you and writes the PRD to .prds/ in your project. It's MIT-licensed and works in any project.