---
name: build-draft
description: Write a new Introspection agent (Recipe) from its approved cases, locally, and run the cases until they pass. Use after build-brainstorm, when the cases in evals/cases/ are approved. Not for a repository without approved cases; that's build-brainstorm. Needs no login; build-review follows.
---

# Build: draft

Write the Recipe, its design and its checks on the `pr/<name>` branch, working only on this machine, and run the approved cases until they pass or every remaining failure is explained. The owner isn't needed in this step.

## Before you start

- You need the `introspection` CLI (`npm i -g @introspection-ai/cli`) and Pi. No login: everything here is local.
- Work in the repository build-brainstorm created, on its `pr/<name>` branch. Read `docs/DESIGN.md` Part A and every case in `evals/cases/` first. If a case isn't approved, stop and go back to build-brainstorm.

## Steps

1. **Choose capabilities before writing code.** For each case, pick what the agent needs from [the capabilities that exist](references/capabilities.md). Write custom code only where no capability covers a case, and say so in the design. A missing tool is fixed with a tool, not a longer prompt.
2. **Write Part B of `docs/DESIGN.md`** with [the design template](references/design-template.md): each behaviour or capability cites the cases that need it, anything no case needs is cut, and every case says how it's checked.
3. **Smoke-test the template before changing it:** run `introspection local -p "hello" -- --no-session` in the repository. It catches a missing model key or an unavailable tool now, not at the end. After you set the model, run it again and confirm the agent answers on the model you chose, not the template's. Then **write the Recipe:** instructions, skills, tools and the `package.json#pi` declarations the design calls for ([what the template gives you and how the pieces compose](references/recipe-layout.md); for Word or PDF files, [documents](references/documents.md)). Put instructions every agent shares in `SYSTEM.md`, role-specific ones in each agent's `system_instructions`, and detail the agent needs only sometimes in skills; `tools`, `skills` and `subagents` lists replace rather than merge when one agent builds on another. Choose the model and provider for local runs deliberately, one the owner's machine has credentials for, and record them in Part B; replace the template's placeholder model.
   - **Every tool you list must exist in the installed runtime.** `introspection check` doesn't verify tools; only an `introspection local` run does. If a capability isn't installed (for example `pi.documents` before its release), use its fallback and say so in Part B.
   - **Make standing knowledge reachable at run time.** Put the owner's rules, positions and situation (a playbook, a scoring guide, a brief) in a skill: `skills/<topic>/SKILL.md` with the rules and facts written out as text, the source files beside it, named by paths relative to the skill's folder so the agent can open them in a run and after deploy, and the skill listed in the agent's `skills`. Tell the agent never to search outside its workspace for them. A file no skill or instruction names is invisible to the agent, and Word and PDF files can't be read at run time without a tool. Put the exact values the owner gave (author name, output naming, side) in the instructions.
   - **Write two to four conversation starters** as Pi prompt templates in `prompts/<name>.md`, listed with `"pi": { "prompts": ["./prompts/*.md"] }` in `package.json`. People see them when they open a new conversation with the agent: in Pi as its first question, and as chips in the Introspection chat. Each is a short request a user would really type, **no more than 10 words**, in the owner's language, taken from an approved ordinary-work case so it's something the agent has been tested on (for an interviewer, "Interview me for the data engineer role"; for contract review, "Redline the contract in files/"). Give each a `description` frontmatter line that reads as the label, the same short phrase, and `suggest: true`, which marks a template as a starter; other templates stay `/` commands only. No starter for something the cases don't cover.
   - **Keep test details out of the instructions:** nothing specific to a sample input (a sample's party name, a test file path) goes into the Recipe.
4. **Give the agent its data without real credentials.** Decide which servers the cases need and how much of each to fake, and what Part B reports about them ([build's decisions about fakes](references/fakes.md)). Build the fakes as `eval-fakes` says, write each one as its `write` reference says, and bind them in an eval as `eval-author`'s `vitest-fakes` or `harbor-fakes` says. Case inputs are read from the local machine by hash; never commit a client's file.
5. **Turn the cases into checks.** Cases marked `code` become eval cases under `evals/`, each naming its case ([which runner and how they're scored](references/evals.md); write them as `eval-author` says); cases marked `person` are listed for review with how to run them.
6. **Prove it works, then show the owner.** Draft proves the agent; it doesn't run the whole case set, which deploy-test does on the platform as eval tasks against the pull request's version. Run the smoke test and one ordinary case end to end (the owner's sample, if they gave one). Tell the owner in one line before anything that takes more than a minute ("running your sample through the agent, about five minutes"). When it produces a result, show it ("here's its result on your sample; anything you'd change?") and offer them `introspection local` to try it themselves; what they say becomes cases.
7. **Run and iterate.**
   - `introspection check` validates the Recipe.
   - **A case counts as run only when the Recipe produces the result itself,** run the way a real request runs: from a folder of its own in the workspace, beside the agent's repository (`runs/<case>-<n>/`), never inside the repository and never in `/tmp`, with the case input under its `files/`, as `introspection local --work-dir <repository> -p "<the request from Part A>"`, writing the output where the request says. `run_case` sets up exactly that run and starts it in the background; use it for every case run. The documents tool opens files only inside the workspace, so that's where you can read what the run produced; never copy a run's output into the repository to read it. Proof is a fresh run whose prompt holds only what a real request brings; a run given anything more, or started inside the repository, proves nothing.
   - **Refer to the Recipe's own files relative to the skill that holds them,** never to the repository root: a real run starts in the request's folder, so `python python/helper.py` fails there.
   - **The owner's real document must work.** Synthetic excerpts you wrote can't stand in for it: they lack the structure real files have (fields, bookmarks, tracked changes, tables). Draft isn't done until the case on the owner's own sample produces a usable result; if it can't, that blocks the build, whatever the other cases show. When you ask for a sample, name the case it's for and describe the input that case's request brings, in the owner's words, so they send the right kind of file, not just any example of their work. If what they share is a different kind of input, say how it differs and ask for the right one; a new kind of input becomes a new case only if the owner asks for one, approved as in brainstorm.
   - **A partial result beats none.** When a tool refuses part of the work, the agent does the rest and reports what it couldn't do. Stopping with no output is a failure, unless a case says to stop.
   - **Never produce the agent's output yourself.** A script you run is not the Recipe, and its result proves nothing about the agent.
   - Run the cases marked `code` that are quick and local as `eval-run` says, and compare runs as `eval-compare` says. Slow cases and the full set wait for deploy-test.
   - **Follow a run with `case_status`,** passing `wait_seconds`, never a loop of `sleep` checks or a bash time limit. A run stops on its own when a tool hangs, the model goes quiet, or its budget runs out (45 minutes unless `run_case` sets another).
   - **Read the verdict before changing anything.** `working` means it's still going: wait again. `over budget while working` is a limit of the measurement, not a fault of the agent: run it again with a larger budget, or record it in Part B; never change the agent, or ask the owner to choose how it should work, because of it. `didn't start`, `failed`, `tool hung`, `model stalled`, `looping` and `finished with no output` each name what to look into, and the run's folder holds its `events.jsonl` and session for the detail. A `failed` run with the model's error is the provider (access, credentials, quota): fix that or tell the owner; never switch the agent to another model to get it through.
   - **Never weaken the agent to get a run through:** keep the designed model, thinking level and instructions. Speed and cost are optimize's job, with measurements; a proof on a weakened agent proves nothing.
   - **When the cause is a missing capability, stop and say so** in Part B and the pull request (for example "editing Word needs the `documents` tool; the fallback writes very large scripts and doesn't finish in time") instead of spending fixes on settings.
     Fix the part that owns a failure rather than adding instructions on top ([common failures](references/failures.md)). **Name the cause before each fix,** from the run's events, and change only what that cause needs; don't reword instructions after each output to steer the next run. A case that passes only right after its instructions were changed for it counts as passing when it passes again in a second run with nothing changed. If the Recipe still can't run after three fixes to the same problem, stop and record why in Part B. Stop when every case passes, or when each remaining failure has a written reason in Part B (for example, it needs a real connection deploy will make). A case that hasn't been run is recorded as planned, never as passing.
8. **Commit to `pr/<name>`** with the case results in the commit message (passed, failed with reason), and hand over to **build-review**.

## What not to do

- Don't change a case to make it pass. If a case looks wrong, note it and raise it with the owner in build-review's summary; the owner decides.
- Don't push, deploy or connect real data here; those belong to build-review and deploy.
