Skip to content

Prompt templates

Paseka renders bee prompts from version-controlled Markdown files under .paseka/prompts/. Templates use Go text/template syntax. At dispatch time the runtime fills in context variables, writes the result to .paseka/runs/<traceId>/<agentId>/prompt.txt (and optionally system.txt), and passes rendered strings to the adapter.

Implementation: internal/prompts.


1. Directory layout

.paseka/prompts/
├── _partials/           # shared snippets (not used as top-level bee templates)
│   ├── emit-howto.md
│   ├── emit-insight.md
│   ├── emit-signal.md
│   ├── emit-verification.md
│   └── emit-task-completed.md
├── default.md           # colony-wide fallback
├── scout.md
└── builder.md
Path Role
.paseka/prompts/*.md Bee prompt templates
.paseka/prompts/_partials/*.md Reusable partials included via {{template "name" .}}
~/.config/paseka/<slug>/ No prompts — secrets and machine-local state only

Prompts belong in the git repo so the colony shares the same instructions across machines.


2. Linking a template to a bee

Each bee references template files (relative to .paseka/prompts/) in its config:

# .paseka/bees/scout.yaml
role: scout
adapter: pi
system_template: scout-system.md   # role / standing instructions (optional)
prompt_template: scout.md          # user/task turn
worktree: true
Field Artifact Role
system_template (optional) system.txt Identity and standing instructions — injected by the adapter, not shown as the first chat turn
prompt_template prompt.txt User/task message for AFK runs; optional kickoff for interactive chat

Colony-wide fallbacks when a bee omits a field:

# .paseka/colony.yaml
defaults:
  prompt_template: default.md
  system_template: default-system.md   # optional

When system_template is unset, behavior matches the previous single-template model (full prompt as positional argv only).


3. Supported variables

The runtime passes a single context object (prompts.Context) to every template. In templates, reference fields as {{.FieldName}}.

Variable Type Description
{{.Bee}} string Bee role from bees/<role>.yaml (e.g. scout, builder).
{{.TraceID}} string Flight trail id for the current task chain. From --trace or generated by runtime.
{{.TraceTitle}} string Resolved human Flight Trail title. From latest INSIGHT/trace.title, then feature.requested title, then first task title; empty when unresolved.
{{.WorktreeBranch}} string Resolved git branch for the trace worktree. From latest INSIGHT/worktree.branch, else paseka/<traceId>.
{{.AgentID}} string Unique id for this agent invocation. Generated per run.
{{.TaskID}} string Optional task id within the trace. From DispatchRequest.TaskID when dispatching a queued subtask.
{{.ColonyRoot}} string Absolute path to the git repository root.
{{.Workspace}} string Absolute cwd for the adapter: colony root, or .paseka/worktrees/<traceId>/ when worktree: true.
{{.Task}} string Task body (nectar). From CLI --body, Queen Console session launch, or bus event payload.
{{.Intent}} string Normalized task intent for partial routing within the bee's vocabulary. Empty or unknown caller input becomes the bee's default intent.
{{.IntentRaw}} string Caller-supplied intent before normalization (CLI --intent, task ledger, or bus payload).
{{.Insights}} []string Narrative INSIGHT strings projected from prior runs on the trace. See insight kinds.
{{.ResultFile}} string Absolute path to the human-readable summary.md log for this run under .paseka/runs/<traceId>/<agentId>/.
{{.ArtifactsDir}} string Absolute path to the trail comb for handoff files: .paseka/runs/<traceId>/artifacts/. Runtime announces this run's comb delta on successful exit; write files here during the run. Beekeeper annotated review packets use review-comments.md under this directory (see partial artifacts-review-comments). Standing procedure memory uses checkpoint.json and optional journal/ here (see partial standing-checkpoint).
{{.Interactive}} bool true for interactive paseka bee chat sessions; false for AFK dispatch.
{{.IsLastWorkTask}} bool true at AFK ledger task dispatch when the current task is the sole incomplete non-final work task; false for chat, ad-hoc bee run, and all other paths. Gates must-emit trace.summary and pr.body guidance in emit partials.
{{.Adapter}} string Resolved adapter name (cursor, pi, claude, opencode, script).

Field sources (MVP)

Variable Set by
Bee, TraceID, TraceTitle, AgentID, TaskID, ColonyRoot, Workspace, Task, Intent, IntentRaw, Insights, ResultFile, ArtifactsDir, Interactive, IsLastWorkTask, Adapter internal/runtime.Dispatcher at dispatch time; Interactive is true in internal/sessions for chat
IsLastWorkTask taskledger.IsLastWorkTask at AFK ledger task dispatch (DispatchModeTask) only; always false for CLI bee run, direct signal dispatch, and chat
TraceTitle runs.ResolveTraceTitle from prior trace events and task projections
Task paseka bee run --body (required unless using inline prompt)
Intent / IntentRaw paseka bee run --intent, paseka task create --intent, or intent on task.plan / task.ready payloads
Insights Runtime projection from prior narrative INSIGHT events on the trace, merged with any manual DispatchRequest.Insights
ResultFile Computed from colony root + trace + agent ids
ArtifactsDir .paseka/runs/<traceId>/artifacts/ (created lazily)

Variables not available in templates today:

  • Bee adapter params (model, yolo, etc.) — configured in bees/*.yaml, not exposed to templates.
  • Arbitrary bus event fields — only Task, Intent, and Insights are surfaced in MVP.

Bus event publishing is instructed through emit partials: emit-howto (safe CLI mechanics for all bees) plus type-scoped partials (emit-insight, emit-signal, emit-verification, emit-task-completed) included only by bees that may publish those types.


4. Template syntax

Paseka uses standard Go text/template with no custom functions.

Interpolation

Colony: {{.ColonyRoot}}
Flight trail: {{.TraceID}}
Agent: {{.AgentID}}

Conditionals

{{if .Task}}
## Task
{{.Task}}
{{else}}
No task body provided.
{{end}}

Loops

## Prior discoveries
{{range .Insights}}- {{.}}
{{end}}

When Insights is empty, the range produces no lines.

Partials

Partials live in .paseka/prompts/_partials/. The file name without .md is the template name:

_partials/emit-howto.md  →  {{template "emit-howto" .}}
_partials/emit-insight.md  →  {{template "emit-insight" .}}
_partials/emit-signal.md  →  {{template "emit-signal" .}}
_partials/emit-verification.md  →  {{template "emit-verification" .}}
_partials/emit-task-completed.md  →  {{template "emit-task-completed" .}}
_partials/builder-intent-feature.md  →  {{template "builder-intent-feature" .}}
_partials/standing-checkpoint.md  →  {{template "standing-checkpoint" .}} (included from emit-howto)
_partials/watch-intent-tick.md  →  {{template "watch-intent-tick" .}} (Watch/Medic standing ticks)

Builder Bee uses intent partials for mission-specific guidance while keeping one stable role prompt. The top-level builder.md routes by {{.Intent}} and falls back to builder-intent-general.

Per-bee intent vocabulary

Each bee may define an intent vocabulary used for {{.Intent}} normalization and Queen Console intent pickers:

  1. Explicit — intents: and optional default_intent: in bees/<role>.yaml (see bee config).
  2. Discovered — when intents is omitted, runtime scans _partials/<role>-intent-*.md (e.g. builder-intent-feature.md → feature, drone-intent-grilling.md → grilling).

At dispatch, empty or unknown caller input normalizes to the bee's default intent (general when present, otherwise the first discovered intent). The raw requested value remains in {{.IntentRaw}} when it differs from {{.Intent}}.

Bees without YAML intents and without <role>-intent-* partials have no intent vocabulary; {{.Intent}} stays empty unless the caller passes a recognized value.

Include only the emit partials your bee role may publish:

{{template "emit-howto" .}}
{{template "emit-insight" .}}

Partials are loaded before the main template and can use the same variables ({{.TraceID}}, etc.).


5. Override precedence

When resolving which template to render, the first non-empty source wins:

Priority Source Example
1 (highest) Inline prompt paseka bee run builder --prompt "Fix {{.Task}}"
2 Bee local overlay .paseka/bees/builder.local.yaml → prompt_template / system_template
3 Bee config .paseka/bees/builder.yaml → prompt_template / system_template
4 (lowest) Colony default .paseka/colony.yaml → defaults.prompt_template / defaults.system_template

*.local.yaml files are gitignored — use them for machine- or developer-specific template overrides without committing.

Inline prompts are still parsed as text/template bodies (partials are available).


6. Rendering pipeline

bee config + CLI flags
        │
        ▼
  Resolve template (precedence §5)
        │
        ▼
  Load partials from _partials/
        │
        ▼
  Execute text/template with Context (§3)
        │
        ├─► Write system.txt (when system_template configured)
        │
        ▼
  Write .paseka/runs/<traceId>/<agentId>/prompt.txt
        │
        ▼
  Adapter injects system context (per adapter) and runs external agent
        │
        ▼
  Runtime normalizes summary, writes log artifact, may auto-publish `INSIGHT/run.summary`

Bus events are published separately through paseka event emit --stdin (live by default; --defer for end-of-run handoffs) as described in the emit partials. Each bee includes emit-howto plus only the type partials it may publish. Runtime may also synthesize INSIGHT/run.summary after a successful AFK run when the bee policy allows.


7. Examples

Builder bee

# .paseka/prompts/builder.md
You are Builder Bee. Implement the task in the workspace.

Intent: {{.Intent}}

## Task
{{.Task}}

{{if eq .Intent "bugfix"}}
{{template "builder-intent-bugfix" .}}
{{else}}
{{template "builder-intent-general" .}}
{{end}}

{{template "emit-howto" .}}
{{template "emit-insight" .}}

Known builder intents (discovered from builder-intent-* partials): general (default), feature, bugfix, test-fix, refactor. Drone uses drone-intent-* partials (general, grilling, breakdown) and routes on {{.IntentRaw}} in its template; grilling includes drone-emit-grilling, breakdown includes drone-emit-breakdown. Scout uses scout-intent-* partials (intake default via bee default_intent, survey manual); intake includes scout-emit-intake.

Scout bee with bus-event partial

# .paseka/prompts/scout.md
You are Scout Bee. Your job is problem discovery, not implementation.

Colony: {{.ColonyRoot}}
Flight trail: {{.TraceID}}
Intent: {{.Intent}}

## Task
{{.Task}}

## Prior discoveries
{{range .Insights}}- {{.}}
{{end}}

## Mission guidance
{{if eq .Intent "intake"}}
{{template "scout-intent-intake" .}}
{{template "scout-emit-intake" .}}
{{else}}
{{template "scout-intent-survey" .}}
{{end}}

{{template "emit-howto" .}}
{{template "emit-insight" .}}
{{template "emit-signal" .}}

Inline one-shot prompt

paseka bee run builder --prompt "Hotfix only: {{.Task}}" --body "null pointer in auth"

Renders to: Hotfix only: null pointer in auth

CLI with task and trace

paseka bee run builder --body "add OAuth login" --trace trace-auth-01

{{.Task}} and {{.TraceID}} are filled; other fields come from runtime defaults.


8. Constraints and validation

Rule Behavior
Template path Must be relative to .paseka/prompts/
Path traversal .. and absolute paths are rejected
Missing template Dispatch fails with a clear error
Missing partial Dispatch fails at parse time
Empty template chain Error: prompts: no template configured

9. Shared partials

Core partials shipped by paseka init under .paseka/prompts/_partials/:

Partial Role
emit-howto Safe CLI publish contract via paseka event emit --stdin (live default, --defer for handoffs including task.plan + post-plan task.ready; no type enumeration)
emit-insight INSIGHT kinds for narrative and prompt memory (run.summary, review.note, context.note, human.feedback, task.plan) plus operational trace.title / trace.summary / pr.body / worktree.branch
emit-signal SIGNAL kinds (task.ready — defer after plan, taskId only)
scout-emit-intake SIGNAL/feature.classified, deferred INSIGHT/task.plan, deferred SIGNAL/task.ready (Scout intake intent only)
drone-emit-grilling SIGNAL/spec.ready + optional context.note (Drone grilling intent only)
drone-emit-breakdown deferred INSIGHT/task.plan, deferred SIGNAL/task.ready, optional context.note (Drone breakdown intent only)
emit-verification Review-gate VERIFICATION kinds (verification.success, verification.failed)
emit-task-completed Commit-gate VERIFICATION/task.completed (receiver only)
cursor-interactive-kickoff Brief greet-and-wait footer for interactive Cursor chat (hivewright-task, drone-task)

Bees include only the type partials they may publish. For example:

Bee Emit partials
builder emit-howto, emit-insight
scout emit-howto, emit-insight, emit-signal; on intake also scout-emit-intake
drone emit-howto; on grilling also drone-emit-grilling; on breakdown also drone-emit-breakdown
guard emit-howto, emit-verification, emit-insight
main-guard emit-howto, emit-verification, emit-insight
receiver emit-howto, emit-task-completed
hivewright emit-howto, emit-insight
archivist emit-howto, insight-intro, archivist-emit-insight; on task also archivist-intent-task, on chronicle also archivist-intent-chronicle

MUTATION is not taught in prompts — runtime auto-publishes code.proposal.isolated or code.proposal.root from baseline-attributed workspace diffs (tracked changes in the adapter cwd; review truth is working-tree git diff, not staged-only). Guard and main-guard prompts instruct disk review via git diff.

See insight kinds for the full INSIGHT taxonomy and prompt-memory rules.

paseka event emit --stdin <<'EOF'
{"traceId":"<traceId>","agentId":"<agentId>","type":"INSIGHT","payload":{"kind":"task.plan","tasks":[{"taskId":"task-1","title":"..."}]}}
EOF

Use {{.TraceID}} and {{.AgentID}} inside partials so examples match the current run. See task ledger.


  • architecture overview — colony layout, adapter contract, runs/worktrees
  • bee config — bee role YAML (prompt_template and other fields)
  • task ledger — task queue protocol and lifecycle
  • pull-request delivery — pr.body must-emit on {{.IsLastWorkTask}}
  • glossary — bee language vs technical terms (TraceID / Flight Trail, Task / Nectar)
  • Agent run file protocol — request.json, summary.md, events.ndjson under .paseka/runs/