Skip to content

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_local adapter 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 capabilities paragraph. 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_instructions hardcodes "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). Run pytest 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") off CFG so 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.