Prompt Engineering for the Paperclip / opencode Agent Fleet¶
Actionable, stack-specific prompt-engineering reference for the agents this repo
operates: paperclip orgs (revenue fleet + engineering orgs) running on
opencode_local adapters, served small local models behind LiteLLM
(ADR-0030), with instruction bundles reconciled from JSON by
apps/ai/paperclip-dispatcher/files/org_reconciler.py.
This is not a generic essay. Every technique below is followed by how we apply it here against the real render path and the org JSON schema. Author changes against this doc; measure them with §7.
Sources (verified 2026-07-14): Anthropic prompt-eng-interactive-tutorial
(chapters: basic structure, be clear & direct, assign roles, separate
data/instructions, format output & prefill, think step by step, use examples,
avoid hallucinations, chaining, tool use); OpenAI prompt-engineering guide
(message roles & instructions, structure with Markdown/XML, few-shot, context,
version prompts in code, tailor to model type); promptingguide.ai/techniques
(zero/few-shot, CoT, self-consistency, decomposition, ReAct, Reflexion, RAG).
0. The one fact that reframes everything: our agents are SMALL local models¶
The fleet does not run frontier reasoning models. It runs, per
northlight-org.json and the sibling org configs, models like
cauda4b/qwen3-5-4b, caudab580/qwen3-8b-b580, gptoss20b/gpt-oss-20b,
cauda27b/qwen3-5-27b, and cuda4090/qwen3-coder:30b.
OpenAI's guide states the rule directly: reasoning models benefit from high-level goals; GPT-class (non-reasoning) models require explicit, detailed instructions. Our models are the second kind, only smaller. The practical consequences that drive every choice in this doc:
- Structure beats prose. A small model follows a numbered procedure and a fixed output template far more reliably than a paragraph of intent.
- One concrete example is worth a page of rules. Few-shot is the single highest-ROI technique for these models (§3.6).
- Ambiguity is not "handled" — it is guessed. A frontier model asks; a 4B model confabulates. So the definition of done and the acceptance criteria must be explicit and self-checkable, not implied.
- Every token competes for a tiny effective context. The
opencode_localadapter compaction (runtimeConfig.heartbeat.sessionCompaction) and served context (~26k for the B60 tiers) mean the bundle must be dense. Cut ceremony, keep contracts.
1. Where a prompt actually lives in this stack¶
There is no free-text "system prompt" you edit per agent. The layers, outermost to innermost:
| Layer | Owner | What it carries | How to change it |
|---|---|---|---|
Instruction bundle AGENTS.md |
org_reconciler.render_agent_instructions |
role frame, priorities, boundaries, tool rules, execution contract | edit the renderer and/or the org JSON fields it reads |
Per-agent capabilities |
org JSON agents.<name>.capabilities |
the ## Expertise blurb |
edit org JSON (also pushed to the agent's API capabilities) |
desiredSkills |
org JSON | procedural skills injected on assignment | curate the list; author skills under files/skills/ |
Managed issue / routine description |
org JSON managedIssues / manualRoutines |
the task prompt (acceptance criteria) | edit the marker-stamped description |
| Retrieval | cauda-kb MCP + Hindsight |
current repo/project facts, working memory | see knowledge-training design |
The bundle is generated, not stored: render_agent_instructions(name,
desired) builds the markdown and the reconciler PUTs it to
/api/agents/{id}/instructions-bundle/file. Because that renderer is shared by
all fleet orgs, a change there changes every org unless it is gated on
config only one org carries (see §5).
2. Role framing (Anthropic ch. "Assign roles"; OpenAI "Identity")¶
Give the agent a specific persona and a single accountable outcome, not a job title. "You are Northlight's Lead Engineer; you own that the deployed site passes its release gate" outperforms "You are an engineer."
How we apply it here. The renderer already opens with
You are Northlight's {title}. Your Paperclip role is {role}. The pilot adds an
optional per-agent mission (one sentence naming the outcome the agent is
accountable for) that renders as a Mission line in ## Description. Keep it
to one sentence; the role frame is a scalpel, not a biography.
3. The technique catalog, mapped to our render path¶
3.1 Be clear and direct (Anthropic ch2)¶
Tell the agent exactly what to do and in what order. Prefer imperatives over
description. Here: the ## Priorities and ## Paperclip Execution Contract
sections are the clear-and-direct surface; keep them imperative and short.
3.2 Separate data from instructions (Anthropic ch4; OpenAI XML)¶
Delimit the task data from the standing instructions so the model never
executes the data. Here: the task prompt lives in the issue description;
the bundle is standing instruction. Managed-issue descriptions carry an HTML
marker (<!-- northlight-managed: ... -->) and an ## Acceptance criteria
block — keep acceptance criteria as an explicit, delimited list, never prose.
3.3 Structured reasoning / think step by step (Anthropic ch6; promptingguide CoT + decomposition)¶
For non-trivial work, force a short plan before action. Not "chain-of-thought
theatre" — a compact, checkable procedure. Here: the pilot adds a
## Decision Procedure section (restate criteria → name the evidence → plan the
smallest change → act → verify against every criterion → report). This is the
decomposition + "give the model time to think" tactic, sized for a small model.
3.4 Explicit output contract (Anthropic ch5 "format output"; OpenAI structured output)¶
Define the exact shape of the response. A fixed template with named fields and a
closed vocabulary of status tokens turns free-form status updates into
machine- and reviewer-checkable records. Here: the pilot adds a
## Output Contract section — a fixed issue-comment template (What changed /
Evidence / Verification / Disposition / Next owner) and a closed disposition
vocabulary (DONE, NEEDS-REVIEW, BLOCKED, IN_PROGRESS, DELEGATED,
NEEDS-INFO). This is the highest-leverage change: it raises review-pass-rate,
cuts clarification loops, and produces a clean, mineable teacher signal for the
tiny-specialist distillation loop.
3.5 Definition of done + avoid hallucinations (Anthropic ch8)¶
Give the model an explicit success test and an explicit "if you cannot verify,
say so" escape hatch, so it stops fabricating completion. Here: the pilot
adds a per-agent definitionOfDone (3–4 role-specific bullets the agent
self-checks before setting DONE) and the existing boundary "never report
completion for a plan, draft, local build, or commit alone" is reinforced by the
contract's required Verification field.
3.6 Few-shot examples (Anthropic ch7; OpenAI; promptingguide few-shot)¶
One or two concrete demonstrations of a good and a bad output beat any amount of
rule text — especially for small models. Here: the pilot adds a
## Worked Example section with one compliant DONE comment and one compliant
BLOCKED comment, authored once at org level and shared by every agent. Keep
examples short and real; a wrong example teaches the wrong thing.
3.7 Reviewer rubric (eval-driven; "show the grader")¶
If work is graded, show the grader's checklist to the producer so it self-checks
first. Here: the pilot adds a ## Reviewer Rubric mirroring what the
pipeline review stage / human gate actually checks. Producers that see the
rubric fail it less often — the direct mechanism for higher review-pass-rate.
3.8 Tool-use discipline (Anthropic "tool use"; ReAct)¶
Make the agent verify a tool exists before relying on it and never claim a probe
it did not run. Here: the ## Tool Permissions section already lists the
read-only cauda-kb MCP tools and says to inspect the real inventory and report
a missing tool instead of pretending. Keep this; it is the anti-confabulation
guard for the action half of ReAct.
3.9 Decomposition & delegation (promptingguide; OpenAI "split tasks")¶
Break big work into scoped sub-issues with one accountable parent; route
implementation to the right report. Here: the agent tree
(reportsTo) + pipelines + the "delegate bounded implementation, keep one
accountable parent, do not generate watchdog storms" boundary encode this.
Prefer a pipeline template over a bag of plain issues for repeatable multi-stage
work (see the org design reference §3).
3.10 Retrieval over recall (promptingguide RAG; OpenAI context)¶
Have the agent retrieve current facts instead of trusting training memory.
Here: cauda-kb MCP (search_knowledge, search_web, fetch_web_page,
search_arxiv, ...) + Hindsight working memory. The knowledge-training design
owns currency; the bundle's job is to tell the agent to retrieve rather than
assume.
3.11 What we deliberately do NOT use¶
Self-consistency (sample-N-and-vote), Tree-of-Thoughts, and multi-agent debate cost N× tokens/GPU for marginal gain on constrained tasks and fight the scale-to-zero GPU budget. Reflexion-style self-critique is captured cheaply by the Decision-Procedure "verify" step and the reviewer rubric, not a second pass.
4. Anti-patterns this fleet has actually hit¶
- Monolithic capability blob. Cramming role, rules, and output format into
one
capabilitiesparagraph. Fix: structured sections (§3.4, §3.5). - Implied acceptance criteria. A managed issue whose "done" is vibes. Small
models then declare done on a local build. Fix: explicit
## Acceptance criteria+definitionOfDone. - Fabricated review / metrics / credentials. Covered by boundaries + the contract's Verification field; never soften it.
- Watchdog issue storms. An agent re-opening recovery issues instead of advancing the one it holds. Fix: the "one accountable parent, no duplicate recovery work" priority.
- Brand bleed (open bug, 2026-07-14).
render_agent_instructionshardcodes "Northlight" / "thedesknook.com" / "global and English-first" and is applied to all orgs, so e.g. the Epoch & Engine CEO is told "You are Northlight's Editor-in-Chief." Tracked as a follow-up (§6); the pilot does not fix it because that is a fleet-wide change, not a one-org pilot.
5. Authoring & extending the Northlight instructionProfile¶
The pilot makes the enhanced sections opt-in and data-driven. The renderer
emits them only when the active org config has an instructionProfile block, so
the other eleven orgs render byte-identical (regression-guarded by
test_instruction_profile_is_opt_in_and_northlight_only). To roll the pattern
to another org later, add an instructionProfile to that org's JSON — never by
editing the shared renderer's hardcoded text.
instructionProfile (org-level) shape:
"instructionProfile": {
"version": "pe-v1",
"decisionProcedure": ["step 1", "step 2", ...], // → ## Decision Procedure
"outputContract": {
"intro": "one line",
"template": ["What changed: ...", "Evidence: ...", ...],
"dispositions": ["DONE", "NEEDS-REVIEW", "BLOCKED", ...]
}, // → ## Output Contract
"reviewerRubric": ["check 1", "check 2", ...], // → ## Reviewer Rubric
"workedExamples": { "done": "…", "blocked": "…" } // → ## Worked Example
}
Per-agent optional fields (agents.<name>):
mission: one-sentence outcome frame → Mission line in## Description.definitionOfDone: 3–4 role-specific bullets →## Definition of Done.
Both are render-only and inert to reconcile_agents; absent fields fall back to
the current output. Keep additions short — every line costs context on a 4B.
6. Validation & rollout discipline¶
- Validate the JSON: it must parse and satisfy
validate_config_model(the reconciler refuses to write on an inconsistent model). Runpytest apps/ai/paperclip-dispatcher/files/test_org_reconciler.py. - Prove zero blast radius: the opt-in test asserts the 11 non-Northlight orgs contain none of the new section headings.
- One org at a time: bundles are DB-backed and reconciled onto the live fleet. Changing a bundle changes live agent behaviour on the next reconcile. Pilot, measure (§7), then decide before widening.
- Open follow-up: parametrize the hardcoded brand strings
(
"Northlight", delivery chain, "global and English-first") offCFGso the brand-bleed bug (§4) is fixed fleet-wide — a separate, reviewed change.
7. Eval-driven iteration — measure it in the paperclip DB¶
Prompt changes are hypotheses. Measure them against the same DB the
tiny-specialist shadow gate reads (heartbeat_runs, issues, review_decided
events). Baseline a 2-week window before the change, compare the 2 weeks after,
scoped to company_id = fc8ac674-… (Northlight).
Primary metrics (the pilot's hypothesis):
| Metric | Definition | Source | Expected direction |
|---|---|---|---|
| Done-rate | terminal runs ending succeeded ÷ all terminal runs |
heartbeat_runs.status |
up |
| Review-pass-rate | approve ÷ (approve + request_changes + reject) |
pipeline review_decided events |
up |
| Clarification/rework loops | request-changes + re-open transitions per completed issue | issue events | down |
| Contract adherence | share of run comments matching the Output-Contract template & disposition vocabulary | comment text / heartbeat capture | up |
Contract adherence doubles as the distillation quality signal: a higher share of schema-shaped agent outputs is exactly criterion 4 ("clean teacher signal obtainable today") in the tiny-specialist design — so this pilot also raises the ceiling on which Northlight tasks can be distilled onto a 2B specialist later.
Iterate: if review-pass-rate does not move, the rubric and the producer's definition-of-done have drifted apart — align them, not the threshold.
8. Coordinated designs¶
- [
.workingdir2/tiny-specialist-fleet-design.md] — the distill→train→serve→ relearn loop and the 2-week shadow gate on review pass-rate. This doc's Output Contract feeds that loop's teacher signal and shares its success metric. - [
.workingdir2/knowledge-training-management-design.md] — MLflow system of record + the "Hindsight remembers, RAG retrieves, Wiki publishes, Skills instruct" split. Retrieval (§3.10) is that system's job; the bundle only directs the agent to use it. - [
.workingdir2/paperclip-org-design-reference.md] — the goal→project→issue→ workspace→run structure the bundle operates inside.