Browse the documentation

Intake: ask first, then act

Why a pack asks before it acts, how an intake.yaml defines its questions field by field, how answers get a status, and a complete design read with real output. Includes how to write your own.

On this page
  1. Why ask first
  2. Every answer has a status
  3. The intake.yaml file, field by field
  4. The loop: plan, ask, record, render
  5. A complete example: the Design pack’s design read
  6. Write an intake for your own pack
  7. Safety and limits

An intake is the list of questions a pack needs answered before it starts working. Without one, an agent that gets a thin request fills the gaps with guesses and you find out in the deliverable. With one, the agent asks a few questions at a time, in your language, records each answer with its status, and produces a brief that becomes the contract for everything the pack does next. Read this page if you use a pack that ships an intake (in 0.23.0, the Design pack), or if you want to give your own pack one.

Ask first, then swarm The intake questions, the budget of 26 and the approval step, waves of sub-agents, and a tally that says simulated units are not people.
Transcript

Before a pack acts, it asks. The intake puts a few questions at a time and marks the must-haves. Where you have no answer, it proposes a default, or records the question as unknown with its risk. The answers become a brief, and nothing in it is invented. Next, the swarm. By default, a run may use 26 sub-agents before the assistant must ask you. Ask for more, and the run waits, marked needs approval, until a person says yes. Once approved, sub-agents work in waves of ten by default, each reading one brief and writing one answer. The runtime validates every answer file and counts only the valid ones. This tally is demo data, and it opens with its disclosure: simulated units are not people. Read the rates as an upper bound, and confirm them with real people.

Described transcript

Why ask first

A pack acts on what it knows. Designing a screen for "a dashboard" without knowing who uses it, on which device and for what job produces a generic template that fits nobody. The cost of the missing answer is not visible until the work is done. An intake moves that cost to the front: each question says whether the pack can start without it, what it proposes if you do not care, and what goes wrong if you do not know.

Three files take part. The intake (intake.yaml) ships with the pack. The answers file is JSON and is written only by bmad-plus intake record. The brief is Markdown and is written only by bmad-plus intake render. Your assistant does the asking; the command never asks anything and never calls a model.

Every answer has a status

The three statuses, and nothing else
StatusMeaningHow it is recordedHow the brief shows it
answeredYou said it.--set id=VALUEAnswer: followed by the value
defaultedYou let the pack’s proposed default stand. It is a proposal, not a fact you gave.--default idAnswer (proposed default, not confirmed by the user):
unknownYou do not know. The question’s risk is copied with the answer, so it travels into the deliverable.--set id=UNKNOWNAnswer: unknown, then the risk, and a line under "Open questions"

The pack is ready when every must-have question is either answered or marked unknown with its risk. Being "ready" does not mean the risks are gone: the brief lists them under "Open questions", and a deliverable built on an unknown must-have is expected to repeat the risk in its opening paragraph. A value you chose yourself is recorded with --set even when it equals the default; --default is only for "I accept what you propose".

The intake.yaml file, field by field

The validator is strict: an unknown field, a wrong type or a broken rule is an error, never silently ignored. The same validator runs when you call bmad-plus intake check and when BMAD+ itself is built.

Top-level and section fields
FieldRequiredRule
schema_versionyesMust be 1.
idyesA lowercase slug starting with a letter (letters, digits, hyphens). Names the intake; the answers file refers to it.
packyesA lowercase slug: the id of the pack the intake belongs to.
titleyesNon-empty text. Becomes the first line of the brief.
languagenouser (ask in the user’s language, the default) or a tag such as fr or en-GB.
max_per_messagenoInteger from 1 to 20; 6 when absent. The most questions the assistant asks in one message.
sectionsyesNon-empty list of sections. Each has an id (slug, unique), a title and a non-empty questions list.
Question fields
FieldRequiredRule
idyessnake_case, starting with a letter, unique across the whole file (not only its section).
askyesThe question, as the assistant will put it. Write it as you would ask a person.
kindyestext, choice, number, boolean or list.
choicesfor choiceAt least two distinct non-empty values. Refused on any other kind.
min, maxnoBounds for a number. Refused on any other kind; min may not exceed max.
defaultnoA value valid for the kind. Forbidden on a must-have question: the user answers it.
must_havenotrue when the pack cannot start without an answer or an explicit "unknown".
risk_if_unknownfor must-haveWhat goes wrong if the answer stays unknown. Required when must_have is true; allowed otherwise.
feedsnoList of artifact anchors such as brief.md#audience. Informative: it tells a reader which part of the work the answer feeds.
Kinds and how a value is typed on the command line
KindAccepted valueLimits
textAny non-empty text; line breaks and tabs allowed, other control characters refused.At most 4000 characters.
choiceExactly one of the listed choices.Anything else is refused with the list of valid values.
numberA finite number, within min and max when set.Out of range is refused.
booleantrue, yes, y or 1 for true; false, no, n or 0 for false.Anything else is refused.
listItems separated by commas on the command line: --set "highlights=faster install, new swarm command".Non-empty; at most 50 items.

The loop: plan, ask, record, render

  1. Plan

    The command lists which questions to ask next: must-haves first, then the others in file order, at most max_per_message. It exits 0 when ready and 2 when a must-have is still open.

    In your project terminal
    npx bmad-plus intake plan --intake FILE --answers FILE

  2. Ask

    The assistant asks those questions in one message, in your language, with the choices or bounds, and proposes the default where there is one. It does not pad the message and does not ask what is already recorded.

  3. Record

    Each answer is checked against the question’s kind and bounds and refused if it does not fit (nothing is written). UNKNOWN records the risk; --default records the proposal. A question can be set only once per call.

    In your project terminal
    npx bmad-plus intake record --intake FILE --answers FILE --set id=VALUE --default other_id

  4. Repeat until ready

    Plan again. When it says ready, stop asking, even if optional questions remain: the assistant names the open ones and moves on unless you want to continue.

  5. Render the brief

    The brief lists every section and every answer with its status, then the open questions with their risks. It is the input of the pack’s next step.

    In your project terminal
    npx bmad-plus intake render --intake FILE --answers FILE --out brief.md

A complete example: the Design pack’s design read

The only intake shipped in 0.23.0 belongs to the Design pack. Atelier, its agent, runs it before any design work (/design read). It has 13 questions in 5 sections, and 3 of them are must-haves: the surface, the audience and the job the page must do. The three dials (variance, motion, density) and the stack carry no default on purpose: a dial you leave open is set by Atelier from the surface, and the brief records that it was inferred.

The 13 questions of design-read
Question idSectionKindMust-haveDefault
surface_kindsurfacechoice (12 values, from landing to other)yesnone
audienceaudiencetextyesnone
jobaudiencetextyesnone
brand_assetsassetschoice: none, partial, fullnonone
design_systemassetschoice (9 values)nonone
aesthetic_familydirectionchoice: minimalist, brutalist, soft-editorial, premium-dense, nonenonone
variance, motion, densitydirectionnumber 1 to 10nonone (inferred by Atelier)
stackconstraintstextnonone (read from the repository)
accessibility_targetconstraintschoice: AA, AAAnoAA
languagesconstraintstextnoone language, LTR
required_statesconstraintslistnonone

Here is a real run of the 0.23.0 CLI on this intake (a dashboard for accountants, answers typed in French). Validity first, then the plan with its exit code 2, then three answers, then the brief.

Design read: check, plan, record, render
npx bmad-plus intake check .agents/skills/pack-design/intake.yaml
.agents/skills/pack-design/intake.yaml: valid intake design-read (design), 13 questions, 3 must-have.
npx bmad-plus intake plan --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json
design-read (design): not ready — 0 answered, 0 defaulted, 0 unknown, 13 not asked yet.
Must-haves still open: surface_kind, audience, job
Ask next (at most 6 per message):
  - surface_kind [choice] Which surface is this? A marketing landing page, a dashboard, a data table, a form, an auth or onboarding flow, a mobile screen, an email, a chat or AI surface, a checkout, a settings page, or something else? (must-have; choices: landing, dashboard, table, form, auth, onboarding, mobile, email, ai-chat, checkout, settings, other)
  - audience [text] Who uses it, and in what situation (device, time pressure, expertise, frequency)? (must-have)
  - job [text] What is the one job this page must get done, and how will you know it did? (must-have)
Three more optional questions follow in the real output (brand_assets, design_system, aesthetic_family). The exit code is 2: not ready.
npx bmad-plus intake record --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json --set surface_kind=dashboard --set "audience=Comptables en cabinet, sur ordinateur, en fin de mois" --set "job=Repérer les factures en retard et relancer en un clic"
Recorded surface_kind, audience, job in _bmad-output/design/intake.json.
design-read (design): ready — 3 answered, 0 defaulted, 0 unknown, 10 not asked yet.
npx bmad-plus intake render --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json --out _bmad-output/design/brief.md
Brief written to _bmad-output/design/brief.md (3022 bytes); the intake is ready.
head -n 3 _bmad-output/design/brief.md
# Design read
<!-- owned by bmad-plus intake design-read; written by bmad-plus intake render, do not edit -->

The "Ask next" list that record prints after each batch is left out here. The last command shows the first three lines of the brief.

Output captured from a real run. Source: bmad-plus 0.23.0, 2026-10-19

The second transcript continues with a different scenario (a landing page for a coffee bar) and shows the other two statuses: a default accepted with --default, a value chosen with --set, and a dial marked unknown. Note that the plan stays "ready" with an unknown dial because it is not a must-have, and that the brief that follows reads the status of each answer.

Design read: defaults, unknown, and the brief
npx bmad-plus intake record --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json --set surface_kind=landing --set "audience=Urban professionals who buy coffee most days; on a phone, on the way to work, a few seconds of attention" --set "job=Get a first-time visitor to open a loyalty card; success is the sign-up button being tapped"
Recorded surface_kind, audience, job in _bmad-output/design/intake.json.
design-read (design): ready — 3 answered, 0 defaulted, 0 unknown, 10 not asked yet.
npx bmad-plus intake record --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json --set brand_assets=partial --default design_system --default aesthetic_family --set motion=3 --set variance=UNKNOWN
Recorded brand_assets, motion, variance, design_system, aesthetic_family in _bmad-output/design/intake.json.
design-read (design): ready — 5 answered, 2 defaulted, 1 unknown, 5 not asked yet.
Unknown: variance
npx bmad-plus intake render --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json --out _bmad-output/design/brief.md
Brief written to _bmad-output/design/brief.md (3043 bytes); the intake is ready.
The "Ask next" lists printed by record are left out.

Output captured from a real run. Source: bmad-plus 0.23.0, 2026-10-19

Part of the rendered brief (_bmad-output/design/brief.md)
# Design read
<!-- owned by bmad-plus intake design-read; written by bmad-plus intake render, do not edit -->

Intake `design-read` of pack `design` — 5 answered, 2 defaulted, 1 unknown, 5 not asked yet. Ready.

## Who and why

### audience (must-have)

Who uses it, and in what situation (device, time pressure, expertise, frequency)?

Answer:
    Urban professionals who buy coffee most days; on a phone, on the way to work, a few seconds of attention
Feeds: brief.md#audience

### design_system

Is a design system or component library already in use?

Answer (proposed default, not confirmed by the user):
    none
Feeds: brief.md#design-system

### variance

Layout variance, from 1 (symmetric and safe) to 10 (asymmetric and bold)? Leave it open and Atelier sets it from the surface.

Answer: unknown
Feeds: brief.md#dials

## Open questions

- variance: unknown
- density: not asked yet
- stack: not asked yet
- accessibility_target: not asked yet
- languages: not asked yet
- required_states: not asked yet

Atelier then builds from this brief. The rules it follows come from the Design pack: an answer keeps its status through every deliverable (a default or an inference is flagged where it was used, an unknown must-have travels with its risk), and a dial left open is set from the surface and recorded as inferred.

Make a pack ask before it acts

Use with the Design pack installed, or with any pack that ships an intake, before the first deliverable.

In your AI assistant
Run the design intake before you build anything. Use bmad-plus intake plan to see what is open, ask me at most six questions at a time in my language with must-haves first, propose the defaults, record what I do not know with its risk, then render the brief and show it to me before you start.

What you should get The assistant asks the first batch (surface, audience, job and up to three more), records your answers through intake record, repeats until plan says ready, and renders _bmad-output/design/brief.md. You see which answers are yours, which are proposed defaults and which are unknown with their risks before any design work starts.

Write an intake for your own pack

Any file in your project can be an intake: bmad-plus intake check|plan|record|render take plain project-relative paths. The example below is a made-up pack called releasekit. It has two must-haves with a risk each, one default that is honest (the audience is both unless told otherwise), a bounded number and a free list.

intake/release-notes.yaml
schema_version: 1
id: release-notes
pack: releasekit
title: Release notes brief
language: user
max_per_message: 4
sections:
  - id: release
    title: The release
    questions:
      - id: version
        ask: Which version is being released?
        kind: text
        must_have: true
        feeds: [brief.md#release]
        risk_if_unknown: The notes cannot say what changed in which version.
      - id: audience
        ask: Who reads the notes?
        kind: choice
        choices: [developers, end-users, both]
        default: both
        feeds: [brief.md#audience]
  - id: content
    title: What goes in
    questions:
      - id: breaking_changes
        ask: Is anything breaking for existing users?
        kind: boolean
        must_have: true
        risk_if_unknown: A breaking change ships without a migration note.
      - id: highlights
        ask: What are the highlights, one per item?
        kind: list
      - id: max_words
        ask: How long may the notes be?
        kind: number
        min: 50
        max: 2000
        default: 300

Validate first. The file below is deliberately broken (a must-have with a default and no risk, a choice with a single value); the validator reports all three problems at once. The terminal then validates the sound file and runs the loop on it.

intake/broken.yaml
schema_version: 1
id: broken-demo
pack: releasekit
title: A deliberately broken intake
sections:
  - id: release
    title: The release
    questions:
      - id: version
        ask: Which version is being released?
        kind: text
        must_have: true
        default: "1.0.0"
      - id: audience
        ask: Who reads the notes?
        kind: choice
        choices: [everyone]

Validate, plan, record, refuse, render
npx bmad-plus intake check intake/broken.yaml
intake/broken.yaml: not a valid intake
  - sections[0].questions[0]: a must-have question needs "risk_if_unknown"
  - sections[0].questions[0]: a must-have question takes no "default"; the user answers it
  - sections[0].questions[1]: a choice needs at least two distinct non-empty "choices"
Exit code 1.
npx bmad-plus intake check intake/release-notes.yaml
intake/release-notes.yaml: valid intake release-notes (releasekit), 5 questions, 2 must-have.
npx bmad-plus intake plan --intake intake/release-notes.yaml --answers notes/answers.json
release-notes (releasekit): not ready — 0 answered, 0 defaulted, 0 unknown, 5 not asked yet.
Must-haves still open: version, breaking_changes
Ask next (at most 4 per message):
  - version [text] Which version is being released? (must-have)
  - breaking_changes [boolean] Is anything breaking for existing users? (must-have)
  - audience [choice] Who reads the notes? (choices: developers, end-users, both; default: "both")
  - highlights [list] What are the highlights, one per item?
npx bmad-plus intake record --intake intake/release-notes.yaml --answers notes/answers.json --set version=UNKNOWN --set breaking_changes=yes --default audience --set "highlights=faster install, new swarm command"
Recorded version, breaking_changes, highlights, audience in notes/answers.json.
release-notes (releasekit): ready — 2 answered, 1 defaulted, 1 unknown, 1 not asked yet.
Ask next (at most 4 per message):
  - max_words [number] How long may the notes be? (default: 300)
Unknown: version — risk: The notes cannot say what changed in which version.
npx bmad-plus intake record --intake intake/release-notes.yaml --answers notes/answers.json --set max_words=40
Intake: max_words: value must be at least 50
npx bmad-plus intake record --intake intake/release-notes.yaml --answers notes/answers.json --set max_words=250
Recorded max_words in notes/answers.json.
release-notes (releasekit): ready — 3 answered, 1 defaulted, 1 unknown, 0 not asked yet.
Unknown: version — risk: The notes cannot say what changed in which version.
npx bmad-plus intake render --intake intake/release-notes.yaml --answers notes/answers.json --out notes/brief.md
Brief written to notes/brief.md (921 bytes); the intake is ready.

Output captured from a real run. Source: bmad-plus 0.23.0, 2026-10-19

The brief it wrote (notes/brief.md)
# Release notes brief
<!-- owned by bmad-plus intake release-notes; written by bmad-plus intake render, do not edit -->

Intake `release-notes` of pack `releasekit` — 3 answered, 1 defaulted, 1 unknown, 0 not asked yet. Ready.

## The release

### version (must-have)

Which version is being released?

Answer: unknown — risk: The notes cannot say what changed in which version.
Feeds: brief.md#release

### audience

Who reads the notes?

Answer (proposed default, not confirmed by the user):
    both
Feeds: brief.md#audience

## What goes in

### breaking_changes (must-have)

Is anything breaking for existing users?

Answer:
    yes

### highlights

What are the highlights, one per item?

Answer:
    faster install
    new swarm command

### max_words

How long may the notes be?

Answer:
    250

## Open questions

- version (must-have): unknown — risk: The notes cannot say what changed in which version.

Writing questions that earn their place

  • Make a question a must-have only if the pack really cannot do useful work without it. The risk sentence is the test: if you cannot say what goes wrong, it is not a must-have.
  • Give a default only when it is honest, that is when most people would pick it and a wrong guess is cheap. A default is shown in the brief as a proposal, so it never passes for the user’s own word.
  • Prefer a choice to free text when the answer drives a decision in the pack: the value can be tested, the brief stays comparable from one run to the next.
  • Bound numbers with min and max: a refused value is caught at record, not discovered in the deliverable.
  • Keep max_per_message low (3 to 6). A long form is answered badly and skimmed.
  • Use feeds to say which artifact each answer shapes. It costs nothing and lets a reviewer trace a decision back to a question.
  • Write ask in the plain language you would use with a client. The assistant translates it for the user when language is user; do not write several languages in one file.

Where the file lives

In a project, put the file anywhere and pass it with --intake; the assistant needs to be told where it is (a line in your adapter or in the skill that drives the work). To make it part of a pack of the BMAD+ source repository, add intake: intake.yaml to the pack in registry.yaml (the path is relative to the pack directory): the build then validates it, the installer copies it and bmad-plus doctor requires it. The registry is a source-level file; it is not installed in your project. See the registry page.

Draft and validate an intake for your own workflow

Use when a recurring job in your team always starts with the same missing information.

In your AI assistant
Write an intake file at intake/release-notes.yaml for the questions we always forget before writing release notes: the version, whether anything is breaking, who reads the notes, the highlights and a length limit. Make only the version and the breaking-change question must-haves, each with the risk if unknown. Give a default only where it is honest. Then run bmad-plus intake check on it and fix every problem it reports before showing me the file.

What you should get A YAML file that intake check reports as valid, with the number of questions and must-haves printed on one line. If the first draft breaks a rule, the validator lists every problem at once (for example a must-have that carries a default), and the file is fixed before you see it.

Safety and limits

  • Answers are written only through record, the brief only through render. Do not edit either by hand.
  • render overwrites a brief only if the file starts with the ownership marker of the same intake (line 2). It never replaces a brief it did not write. record only overwrites an answers file of the same intake.
  • Neither command writes under .git/, _bmad/, .bmad-plus/ or node_modules/, nor through a symlink.
  • What you typed is printed as an indented block under Answer:, so a value can never become a heading or a list item of the brief.
  • If the intake file changes after answers were recorded, plan reports the mismatch. record --reset starts the answers file again, empty, for the same intake id; it never resets a file that belongs to another intake.
  • The pack must not start its pipeline or a swarm while a must-have is neither answered nor marked unknown. The commands do not check this themselves: it is an instruction in the autopilot and Nexus skills, which tell the assistant to run the intake of each pack involved first, in Discovery.
  • The runtime asks nothing, invents nothing and calls no model. A refused value changes nothing on disk.

See also