The actual production instructions of the Producer agent and its adversarial glossary reviewer, quoted verbatim and annotated
This page reproduces the real instructions running in production — the system prompts of the Producer (采编) agent, its produce_course skill, its adversarial glossary_reviewer sub-agent, and the root agent’s delegation contract. Every quoted block is verbatim from the repository files (agent/instructions.md, agent/subagents/producer/instructions.md, agent/subagents/producer/skills/produce_course.md, agent/subagents/producer/subagents/glossary_reviewer/instructions.md); elisions are marked with […]. The prompts are bilingual because the agent works in both languages; nothing is cleaned up for presentation.We publish them for the same reason the Truth Layer page exists: this system’s correctness does not live in its prompts. Every requirement that matters is enforced by a deterministic gate downstream, so there is no secret incantation to protect — and nearly every unusual line below encodes a specific operational lesson from running the system against real documents — each rule exists to make one predictable class of error structurally impossible. Reading the prompts is reading the system’s accumulated design reasoning.
The staging tool fetches, cleans, aligns, and persists a course skeleton — paragraphs, zero terms — and deliberately returns a success value while the topic row stays running. The prompt has to say, in bold, that this success does not mean the task is finished, because a model that sees ok:true will naturally stop there — and the seam between stages 1 and 2 of the five-stage pipeline (see Document Workshop) is exactly where declaring victory early is plausible. The mechanical backstop: a skeleton with no accepted glossary never flips to done.
The heart of the producer prompt is the 工坊纪律 (“workshop discipline”) — how to read a document of hundreds of thousands of characters without ever loading it whole into context.
This discipline exists because term extraction is only as good as how the document gets read: a stateless, per-paragraph extraction pass has no way to notice patterns that span paragraphs, and the failure mode it produces — plausible-looking but ungrounded glossary entries — is invisible until an adversarial reviewer or a human checks it against the source text. The windowed, file-backed approach below is the fix: one continuous read of the whole document, with state that survives outside the model’s own memory. Three rules deserve unpacking:
“绝不一次把正文全读进上下文” — the design spec cites measured long-context recall degradation for the production model; curating a full document from memory reliably produces junk, so the prompt forbids it outright.
“禁止 grep 驱动主 pass” — search only finds what you already thought to look for; the glossary’s value is the terms an interpreter would not have predicted. The main pass must be a sequential full-coverage read; grep is demoted to a recall tool in the second pass.
“每轮立即落盘,读过即弃” — the sandbox filesystem, not the conversation history, is the source of truth. Candidates are appended to a file after every window and a progress file is rewritten every round, so context compaction or a session restart loses nothing.
A gate rejection is normally an instruction, not a failure — the agent fixes the flagged terms and resubmits in the same session. But one class of rejection is unfixable from inside the session: the identity gate, which fires when the fetched document is not the document the topic names. No amount of resubmission changes a deterministic gate’s verdict when the underlying mismatch is something only a human or the upstream cockpit can correct — so the fix here is not a smarter retry, it is teaching the prompt to distinguish “the gate wants a better glossary” from “the gate will say the same thing forever.”
4. Why the course payload is written to a file, not passed inline
From agent/subagents/producer/skills/produce_course.md:
**Write it to a UNIQUE file** with `write_file` — `/workspace/course_<short-unique>.json` where `<short-unique>` is derived from THIS document (e.g. the source domain + a few digits, like `course_catl_01.json`). **Do not use a fixed `course_data.json`** — parallel采编 subtasks run concurrently and a shared filename makes them clobber each other. Then call `save_course_from_file({ path: "/workspace/course_<short-unique>.json" })` with that same path. Do NOT pass the whole course as a single `save_course` argument; that argument gets too large to emit once your context holds the full bilingual text. (Only for a tiny course may you call `save_course` directly.)
Two design constraints sit behind this rule: a tool-call argument has a practical size ceiling, and concurrent sibling subtasks each need a distinct filename so they don’t collide. Writing the course to a uniquely-named sandbox file and passing the path satisfies both at once — the save tool reads the full bilingual text from the file instead of taking it as an argument, and deriving the filename from the document keeps parallel subtasks from clobbering each other.
The reviewer sub-agent’s instructions open with its entire philosophy:
You are the **glossary reviewer** — an adversarial second reader for interpreting-course termglossaries. Your job is to FALSIFY, not to praise. A reviewer who rubber-stamps is useless.
It is deliberately isolated — declarative sub-agents get their own sandbox, so it cannot read the producer’s files even if it wanted to:
You have a fresh context and NO access to the producer's sandbox or history. Everything you needis embedded in the message that delegated this review to you:[…]Do not ask for files. Do not try to fetch anything. Judge only what is in front of you. If thepacket is missing something you need, say so in your verdict rather than guessing.
Verbatim excerpt: the five rejection categories (glossary_reviewer/instructions.md)
## What to flag (be specific, cite the term)1. **Fabricated / misaligned** — a `zh` or `en` that is not actually a verbatim substring of the quoted source, or a pair whose two sides are not translations of each other (e.g. 武汉保卫战 = "Wuhan" is a fragment mismatch, not a term).2. **Below the bar** — everyday words a CET-6 candidate knows cold (法律/发展/合作/重要…), even inside a technical text. A tiny high-value glossary beats a padded one.3. **Heading echo** — whole section/stage titles copied in as if they were terms (「初步遏制疫情蔓延势头」is a heading, not a term).4. **Non-official rendering** — a term whose English gloss is a plausible paraphrase but NOT the established/official rendering an interpreter must pre-study (call out the term and, if you know it, the expected official form — but do NOT invent one you are unsure of).5. **Missed terms (recall)** — genuinely interpreting-worthy terms visible in the sampled windows that the glossary omitted. List them so the producer can add them.
These five categories define what a clean glossary looks like — fragment mismatches, padded basic vocabulary, headings ingested as terms — the same bar whether it’s the review sub-agent or a human interpreter checking the work. The charter also guards against the opposite failure:
Bias to `revise` when in doubt on a specific term, but only raise issues you can point to concretely— vague "could be better" is noise. If the glossary is genuinely clean, `pass` it honestly; areviewer who never passes anything is as useless as one who never fails anything.
The reviewer’s verdict is advisory. It travels with the submission as a reviewerVerdict field for the quality record, but the mechanical gates decide acceptance regardless of what the reviewer said. An adversarial second model raises quality; it is never the enforcement layer.
The root agent’s instructions (agent/instructions.md) make delegation non-negotiable:
When a message starts with `产课任务:`, do not perform production yourself. Immediatelydelegate the task to the `producer` subagent and return its final result, preserving the`PRODUCER_RESULT` line exactly.The same delegation rule applies to any queued source that already has `topicId` and`sourceUrl`, even if the message is not literally prefixed with `产课任务:`.
And the producer’s instructions end with the matching output contract:
Final response contract:- On success, end with one line: `PRODUCER_RESULT {"ok":true,"slug":"<saved-slug>","terms":<number>,"reason":""}`- On failure, end with one line: `PRODUCER_RESULT {"ok":false,"slug":"","terms":0,"reason":"<plain reason>"}`The final `PRODUCER_RESULT` line is required so the drainer can mark the queue item correctly.A failure explanation without this exact final marker is a protocol failure. Never finish withprose-only failure text; when production fails, set `slug` to `""` and `terms` to `0`.
The queue drainer is a program, not a reader of prose: it parses this one line to mark the queue item. A beautifully written failure explanation without the marker is, by the prompt’s own words, a protocol failure — the drainer cannot see it. The marker is the narrowest possible interface between free-text agent output and deterministic infrastructure, and the contract is stated in both prompts so neither agent can drop it.
Every instruction above is enforced twice — once by the prompt, once by a gate that verifies independently — which keeps the system reliable across context compaction or a model upgrade with different habits. So each is paired with a mechanism that does not care whether the prompt was followed: terms are verified verbatim against the source at save time, density floors reject thin glossaries, the identity gate rejects mismatched documents however often they are resubmitted, and a missing PRODUCER_RESULT marker fails the task rather than passing unnoticed. The prompt makes the compliant path the cheapest path; the gate makes the non-compliant path a dead end. The full gate stack is in Document Workshop; the philosophy is in Truth Layer. Publishing the prompts is part of the same discipline: a system whose quality depended on hiding its prompts would be a system trusting prompts too much.