Prompts
Prompts are budgeted pongo2 templates. A layered loader lets a project override one file while the rest continues to update with the app. Pack authors declare host compatibility through compatibility.extension_api, not a prompt version.
The template dialect, archetypes, heading contract, playbooks, and assembly order are in the product repository: agent-prompt-template.md and prompt-assembly.md.
The four planes
| Plane | What it is | Pack path |
|---|---|---|
| Persona | The agent’s stable system prompt | agents/prompts/, shared/archetypes/, shared/partials/ |
| System injects | Per-turn context blocks | guidance/ inject templates |
| Tool feedback | The rendered body of a structured reject or banner | guidance/reject/ |
| Kicks | Short imperative nudges at lifecycle moments | guidance/ kick templates |
Templates own layout only. The host owns facts, tool lists, and char budgets.
The loader
Every template — entry files and every {% include %} target — resolves through layered roots, higher wins:
site > {repo}/.paintedwolf/prompt_files/ > bundled
In a multi-root project each root contributes its own .paintedwolf/prompt_files/, and the active root’s layer wins. Resolution is per-file.
Two rules matter:
- Fail closed. A parse error in your winning overlay is an error, never a silent fallback to the bundled copy.
- Override the file, keep the tree. Replacing a partial updates every prompt that includes it.
A project prompt_files/ entry or a pack unit you own: holds that path at your bytes. Unowned bundled files keep updating with the app.
Always render and read an override the way a session will:
pw prompts render --agent implementer --project . --check
pw prompts render partials/finish-handoff.md --project . --var focus=triage
--check enforces required headings and the byte budget. Reading the result catches empty or misspelled variables.
Lifecycle injects
Prompt content that fires at a moment is an inform binding on the same anchor catalog used by rules: rules block, bindings inform.
A workflow can ship phase-entry guidance with an injects: entry — no engine code:
# workflow.yaml
injects:
- on: phase.entered
selector: { surface: phase, phase: plan, workflow: recon-pack }
effect: inform
render: coordinator-recon-pack-plan # <your pack>/guidance/coordinator-recon-pack-plan.md
tier: workflow
Workflow-tier bindings only fire inside their workflow, and they win over builtin bindings for the same anchor. Cross-workflow guidance lives under host/bindings/ with tier: builtin. The binding grammar is in agent-prompt-template.md.
Overriding from a project
| You want to | Do |
|---|---|
| Adjust one agent’s persona | Override agents/prompts/<id>.md under {repo}/.paintedwolf/prompt_files/ |
| Change a shared behavior everywhere | Override the partial, not each agent |
| Add phase guidance to your workflow | injects: in your workflow.yaml |
| Ship personas + prompts to other repos | Put them in an extension pack under agents/ |