Reviewing the prompt surface
The workflow for reviewing or engineering beebox's agent-facing prompt surface — the agent guide, chat/reactor system prompts, schema instructions, box skills, and rules. Read this when auditing the assembled prompt stack for overlap/redundancy/staleness/contradiction, checking what an agent actually sees in some situation, or after any change to prompt-generating code. prompt-audits.md is the companion lens catalog for the hunt step. (For routing a single new instruction to the right box surface, use the bbx-context skill.)
The prompts are how every agent comes to understand Bee Box — what it is, what its role is, what the rules are. They are generated code (src/core/agent-guide/, src/core/chat/session/prompts.ts, src/core/reactor/prompts.ts, schema instructions, src/core/box/skills-content.ts), assembled into a per-situation context stack. Review the assembled stack, not the source files: judge what an agent actually reads, end to end.
See the assembled context
cd beebox pnpm agent-context --list # the known situations pnpm agent-context chat --box ~/src/boxes/test1 # full chat stack, layer by layer pnpm agent-context reactor --box ~/src/boxes/test1 --card-type recipe pnpm agent-context chat --box ~/src/boxes/test1 --skill calendar --output scratch/ctx.md
Each report shows every layer with its loading class and word count, plus the always-loaded total. pnpm prompt-report is the complementary flat inventory of every prompt in the system; agent-context is the per-situation composition.
Boxes go stale. The box-side layers (CLAUDE.md, agent guide, skills, rules) are what bbx init last wrote — re-run bbx init on the box after changing generator code, or the report shows the old world. That staleness being visible is a feature, not a bug.
The layering model
Every agent's context is a stack; each layer has a loading class:
- Identity prompt (always) — per situation: chat, chat-thread, reactor, procedure. Says what the agent is and covers only that situation's surface.
- Box knowledge (always) — box CLAUDE.md → compiled briefing + the agent guide. Loaded by every agent; the scarcest budget.
- Situational — schema
instructionsfor the card types in play,.claude/rules/path globs, the per-turn<chat-app>snapshot. - On-demand — skill bodies, the package docs (
node_modules/beebox/box-docs/*) and box-compiled docs (_content/docs/generated/*), guide cards the agent is pointed at.
Skills are two things at once: the description is always-loaded (it's the trigger) and must be pure routing — no mechanics; the body is on-demand and owns its domain's mechanics. A guide mention of a skill's domain is usually the first overlap — the description is the pointer.
The guide/skill boundary is read vs. write: the always-loaded guide keeps the query surface (bbx calendar [timespan]); the skill owns authoring mechanics (VTIMEZONE, conflict resolution).
Principles
- One home per concept. ABOUT_CARDS/PROVENANCE own card concepts; a schema's
instructionsown that type's fields; a skill owns its domain. Everything else points, via theSECTIONregistry (agent-guide/sections.ts) so references can't drift from headings. Re-teaching is the disease; per-section drift is how prompts rot. - Deliberate duplication only. The Laws may restate what a mechanics section carries — high-stakes, high-drift rules earn it. Anything else stated twice is a bug: fix at the canonical home, make the other site defer.
- Judge cost-per-bit, not correctness alone. Always-loaded words are the scarcest resource. A 39-line list where every line says the same thing (the old CARD_TYPES) is "correct" and still a bug. Cut what the agent can infer or load on demand.
- Corrective framing where the model's prior is wrong. "Cards are not XML; anything that says so is stale" inoculates; a neutral description doesn't. State the wrong default and correct it.
- No archaeology, no dated status claims. "now", "legacy", "replaced the old…", "not wired into X yet" address agents with stale priors (none exist) and become lies when the system moves. Phrase timelessly; describe behavior, not project status.
- Check for self-contradiction. Two statements about the same signal must agree ("absence means all healthy" vs "don't treat absence as all-clear" survived in one bullet). Read each section asking: does any sentence undercut another?
- Examples do double duty. Every example shows the mechanics AND models good behavior (real fields, honest values, the judgment call inline). No padding examples.
- Role before mechanics. Lead surfaces open with identity ("a personal workspace where the filesystem is state, Git is history, and you do the work") so every rule after it has a why.
- Verify claims against code. A prompt asserting a trailer, flag, or field that code doesn't emit is worse than silence. Audit prompt claims against the implementation; add
src/dev/knowledge-audits.yamlentries for conventions agents must retain (pnpm knowledge-audit). - Never hardcode personal values — resolve real per-box values (timezone, names) at
bbx initgeneration time instead of baking a sample into shared prose.
Review pass, in order
- Render the stacks (
agent-contextper situation) and read each end-to-end as the agent. - Hunt: overlap (same concept taught twice), contradiction, dated language, claims unverified against code, weight (cost-per-bit), missing role framing. prompt-audits.md is the full lens catalog for this step.
- Fix at the canonical home; turn the duplicate sites into cross-references (
SECTION/xref). - Re-render; compare layer word counts before/after.
- New conventions get knowledge audits; run them before calling the work done.
- Re-run
bbx initon live boxes so the change actually ships.
Prior art: plans/prompt-surface-cleanup-evaluation.md is the worked example of a full-surface review (what was found, what each fix traded against).
Invariants: session/prompt cache
Two things any prompt-surface edit has to respect:
- The system prompt must stay time-invariant (no timestamps, no per-turn values) — the warm session-subprocess pool only reuses a prewarmed subprocess when the system prompt is byte-identical across turns.
- Resumed sessions never re-send the system prompt, so an edit to the prompt surface is invisible to an already-open thread until its session resets.