Curriculum/Multi-Agent Systems
The Critic Does Not Write
Fixes go back to the worker as a new assignment. A critic with write tools is a second worker arguing in production, and the audit trail dies.
When the critic is blocked (missing evidence, tests red), it returns a block reason, not a secret patch. “I’ll just fix it myself” from the critic is how you lose the audit trail: the worker’s allow-list, the planner’s step, and the HITL gate no longer describe what hit production.
The roles lesson said the critic usually has no writes. This lesson is the runtime rule: even if a model critic emits edit, the dispatcher refuses. The only legal critic verb is review (or handoff to a human). Review with issues reassigns the worker. Review with no issues stops the job (or sends it to apply, which is still not the critic).
This is separation of powers, not etiquette. Courts that can rewrite the law are legislatures. Critics that can refund are billing workers with a smug preamble.
What the critic may return
A critic packet is data, like a brief:
ok— boolean from a rubric, not from moodissues— list of checkable strings (tests red,missing delay,unknown cite s9)assign—workerorstoporhumanevidence_ids— what it looked at
Issues go back to the worker. A critic with write tools is a second worker.
Critic returns a score, not a patchIt may not return a patch hunk. It may not call edit, refund, or send_email. If the rubric needs a fact, the critic reads an artifact the worker already produced (test report, doc). Reading is not writing. If the report is missing, that is an issue: missing evidence, reassign or handoff — do not invent a pass.
Retries. The blackboard stores attempt so the worker sees the fix list. Cap retries (3 is a common product number). If the same issue repeats, that is a spec bug or a worker that cannot satisfy the rubric. Handoff to a human. Do not let the critic grab edit on attempt 4. That teaches the system that the way out of a loop is to break isolation.
Repeated issues are gold. If “missing delay” happens on 40% of jobs, the writer prompt or the docs artifact is wrong. Fix the producer. Do not add critic writes “until the writer learns.” Writers do not learn across customers unless you change weights or prompts in a reviewed deploy. Critic writes are a one-off that becomes the product.
Grounding. If tests exist, the critic reads the report. “Looks good” while tests are red is a fail of the critic, not a style note. If citations exist, the critic checks ids against the board. Ungrounded critics belong in the debate lesson’s failure pile; here they are simply out of contract.
Walkthrough: tests are red
Worker finished a patch. Tests red. Three critic behaviors:
Illegal write. Critic emits edit. Runtime: critic_cannot_write. World unchanged. Trace shows the refuse. This is the fixture you keep forever.
Legal reject. Critic emits review with issues ["tests red"]. Runtime: ok: False, assign: worker. Worker gets attempt+1 and the issue list. No new file bytes from the critic.
Legal stop. Critic emits review with empty issues (and the report is actually green in a real system). Runtime: assign: stop. Apply or finish may run in code, not as a critic side effect.
A fourth failure: critic says “tests are fine” in prose and still tries edit to “clean up comments.” Refuse the write. Score the critic eval as a false-pass if the report was red. Prose does not override the packet.
Run to execute this in your browser. Nothing is sent to a server.
What printed: edit is critic_cannot_write. review with issues reassigns the worker and keeps the issue list. review with no issues stops. The function never mutates a repo. That is the point. Writes stay on the worker allow-list.
If you add send_email as a name, it must hit the same WRITES set. Do not special-case “email is just a comment.” Email is a side effect. Critics comment on the board.
HITL is not a critic with writes
A human approver may apply a refund. That human is not the model critic. If you fold HITL into “the critic clicks apply,” you will eventually let the model critic click apply. Keep apply in the sequential subgraph (orchestration part): extract → policy → HITL → apply. The critic of a draft is upstream of HITL. Neither the critic nor the worker skips HITL.
Seniority does not grant writes. “Staff engineer critic” is a prompt. The allow-list is empty of writes for every critic rank.
How agents use this
The blackboard stores attempt so the worker sees the fix list. Cap retries. If the same issue repeats, that is a spec bug — handoff to a human, do not let the critic grab edit.
Fixture: two-step job, tests red, critic must not change files. Replay in CI. If a framework update lets the critic node inherit the worker’s tools, this fixture is how you notice.
Log critic.assign and critic.issues. On-call debugging “why did we loop” starts here. Log denies when the critic tries a write. A weekly count of critic_cannot_write is a model-behavior metric, not a reason to open the allow-list.
The worker’s prompt may include the issue list. It must not include a hidden patch from the critic. If you find yourself pasting critic thoughts into the worker “as a hint,” you are smuggling writes as text. Put issues as structured strings only.
When debate appears later, the judge has the same no-write rule. The opponent attacks in a packet. Nobody ships from the peanut gallery. A judge that can edit is a third worker, and the debate subgraph becomes a race. Keep apply downstream in code.
Check your understanding