Reviewer
reviewer ist die Persona, die jede mutierende Operation gegenzeichnet. Im Gegensatz zu den anderen Workern wird sie nie vom coordinator gespawnt — der Katalog schließt sie absichtlich aus. Der einzige Spawner ist der ReviewGate-Decorator, der jedes Tool umhüllt, dessen Class "write" oder "destructive" ist.
Der reviewer ist die Antwort auf eine Frage: „wer beobachtet den Beobachter?"
Nicht deaktivieren.
Der reviewer ist das, was Ongrid überhaupt sicher macht, host_restart_service oder execute_skill zu geben. Das Überspringen des Gates ist eine explizite Konfigurationsentscheidung und erscheint im Audit-Trail. Wenn Sie die Persona zu „always approve" forken, zeigt das Audit-Log jede Entscheidung — Auditoren werden es bemerken.
Der ReviewGate-Decorator
Position in der Tool-Decorator-Chain (chain.go):
tenant_bind → REVIEW_GATE → timeout → audit → ratelimit → metric → <inner tool>Warum genau diese Reihenfolge:
- Außerhalb von
timeout. Der reviewer ist selbst eingraph.Invokemit eigenem Turn-Budget. Ihn innerhalb des 15s-Timeouts des inneren Tools zu wickeln, würde den reviewer zwingen, in 15s fertig zu werden — unrealistisch. Das Gate trägt seine eigene unabhängige 60s-Decke (DefaultReviewerTimeout). - Außerhalb von
audit. Ablehnungen sollten keine synthetische Ausführungszeile schreiben. Das Gate schreibt stattdessen einechat_mutating_proposals-Zeile. Audit loggt nur die Ausführung des inneren Tools, was nur bei Genehmigung passiert. - Innerhalb von
tenant_bind. Die Vorschlags-Payload enthält den Operatoruser_id, dentenant_bindaus dem ctx auflöst — das Gate muss nachdemtenant_bindihn aufgefüllt hat, laufen.
Auslösebedingung
Der Decorator inspiziert die Class des umhüllten Tools:
| Class | Gate-Verhalten |
|---|---|
"read" | Durchlassen. Inneres Tool läuft. |
"write" | Abfangen. reviewer spawnen. Inneres läuft nur bei Genehmigung. |
"destructive" | Gleich wie "write". Beide Classes durchlaufen das Gate. |
Konkrete Class: "write"-Tools heute in der Tasche:
host_restart_service— das kanonische mutierende Skill.execute_skill— der Marketplace-Shim, der jedes marketplace-installierte Skill ausführt (das Gate kann den Skill-Body nicht zur Klassifizierung lesen, also gatet es sie alle).AgentTool— ja, das Dispatch-Primitive selbst ist"write", weil es einen Worker spawnt und daher Ressourcen committet. Der reviewer gatet AgentTool-Aufrufe in der Praxis allerdings selten — siehe die Persona-Allowlist unten.
Die Vorschlags-Payload
Beim Abfangen baut das Gate:
{
"action": "host_restart_service",
"target": {"device_id": 7, "service": "nginx"},
"reason": "User reported 502; nginx error log shows OOM",
"blast_radius": "single_device",
"operator": "user_42",
"context_summary": "<coordinator's running summary of the conversation>"
}blast_radius ist einer von single_device | cluster | tenant_wide, abgeleitet aus den Metadaten des Tools. Der reviewer verwendet ihn, um die „ist das vernünftig"-Entscheidung zu gewichten — eine tenant_wide-Aktion sieht höherer Prüfung gegenüber als eine single_device.
Die Reviewer-Persona
Frontmatter-Highlights (wörtlich aus agents/reviewer.md):
name: reviewer
description: SOP 二审 reviewer worker,对 mutating / destructive 提案做静态审查
permission_mode: read-only
max_turns: 5
model: anthropic/claude-opus-4-7 # 关键路径用最强
background: true # async: spawn returns immediately
tools:
- get_incident_detail
- get_edge_summary
- query_promql
- query_logql
- get_sop_text # planned (HLD-003 PR-D)
disallowed_tools:
- "*_skill" # wildcard — no skill execution
- run_shell
- execute_skill
- host_restart_service # explicitly: reviewer cannot itself act
- kill_process
critical_reminder: |
你是高危操作二审 reviewer。reject 是默认选项,approve 必须三条都满足:
1. 找得到对应 SOP 且明确覆盖此场景
2. 当前没有并行的同类操作(看告警 / 看运维窗口)
3. 回滚路径已知Schlüsselbeobachtungen:
max_turns: 5. Reviewer reden nicht um den heißen Brei. Fünf Turns zum Entscheiden; das Persona-Prompt sagt explizit „看不清就 reject".model: anthropic/claude-opus-4-7. Der Critical-Path-Aufruf bekommt das stärkste Modell, unabhängig vom Default der Org. Reviews sollten nicht auf ein schnelles Modell heruntergestuft werden — die Kosten einer falschen Genehmigung überwiegen die Kosten eines langsamen Reviews bei weitem.background: true. Reviewer läuft asynchron. Die UI des coordinators blockiert nicht auf dem Review; dietask_notificationdes Reviews postet zurück, wenn fertig. (In der aktuellen Verdrahtung blockiert das innere Tool bis der reviewer zurückkehrt — aber die UI nicht, sodass der Benutzer „Review ausstehend" sieht, während es läuft.)disallowed_tools-Wildcard*_skill. Der reviewer kann kein Skill ausführen. Er kann Kontext lesen (get_incident_detail,get_edge_summary, Telemetrie-Abfragen), aber nie handeln.- Kein
run_shell, keinhost_restart_service, keinkill_process. Selbst wenn der Persona-Body es ihm sagen würde, entfernt der Runtime-Filter diese Tools. Defense in Depth.
Der 5-Schritte-Workflow
Aus dem Persona-Body läuft der reviewer:
- Das SOP finden.
get_sop_text(action)für die offizielle Prozedur. Kein SOP → reject mit"no SOP for action <X>". - Zielzustand prüfen.
get_edge_summary(device_id). Device offline / in Restart-Loop / letzte mutierende Aktion innerhalb von 5min → reject. - Parallele Operationen prüfen.
query_logqlfüraudit:-Einträge, die dasselbe Ziel in den letzten 10 Minuten berühren. Parallele Aktion → reject mit"parallel operation detected; wait for X to complete". - Den Grund gegen Alarme validieren.
get_incident_detailfür den referenzierten Incident. Grund widerspricht dem Alarminhalt → reject („Operator hat das Symptom möglicherweise falsch gelesen"). - Entscheiden.
- Genehmigen, wenn alle drei Kern-Gates passieren. Ausgabe
{decision: approve, sop_id, rollback_path, gates_passed}. - Ablehnen andernfalls. Ausgabe
{decision: reject, reason, missing_gates}.
- Genehmigen, wenn alle drei Kern-Gates passieren. Ausgabe
Die Three-of-Three-Regel
Der Critical Reminder ist explizit:
reject 是默认选项,approve 必须三条都满足:
- 找得到对应 SOP 且明确覆盖此场景
- 当前没有并行的同类操作(看告警 / 看运维窗口)
- 回滚路径已知
„Nicht sicher" ist äquivalent zu „reject". Dies ist eine bewusste Kalibrierung — die Kostenasymmetrie zwischen einer falschen Genehmigung (Produktionsschaden) und einer falschen Ablehnung (ein zusätzlicher Round-Trip) begünstigt letztere stark.
Ausgabeformat
Die endgültige Antwort des reviewers (zurückgepostet an den coordinator via <task-notification>):
**Decision: approve | reject**
**Gates**
- ✓ SOP-007 covers restart nginx
- ✓ node-01 status online; last mutating 17min ago
- ✓ No parallel operation
- ✓ Rollback: `systemctl start nginx`
**Notes**
{1-2 sentence risk note; included even on approve.}Der Decorator parst auf Decision: approve (Groß-/Kleinschreibung egal, muss in der ersten nicht-leeren Zeile der Antwort erscheinen). Alles andere — einschließlich mehrdeutiger Formulierungen wie „approve with caveats" — wird als reject behandelt.
Was bei Genehmigung passiert
Der Decorator:
- Schreibt eine
chat_mutating_proposals-Zeile mit status=approved, dem Entscheidungstext des reviewers und der SOP-ID. - Lässt den Aufruf zum inneren Tool durchfallen.
- Der Audit-Decorator (Downstream in der Chain) schreibt die Ausführungszeile.
- Das innere Tool gibt sein normales Ergebnis an das coordinator-LLM zurück.
Das coordinator-LLM sieht ein normales Tool-Ergebnis und fährt fort.
Was bei Ablehnung passiert
Der Decorator:
- Schreibt eine
chat_mutating_proposals-Zeile mit status=rejected, dem Grund des reviewers und den fehlenden Gates. - Gibt
ErrReviewRejectedzurück, das den Grund des reviewers umhüllt. - Der Audit-Decorator schreibt keine Ausführungszeile (keine Ausführung erfolgte).
Das coordinator-LLM sieht eine Fehlermeldung — review rejected: <reviewer reason> — und soll die Situation dem Benutzer erklären. Es sollte denselben Tool-Aufruf nicht wiederholen; der Dedupe-Schutz plus ein kurzfristiges LRU auf Ablehnungsgründe halten das LLM vom Loopen ab.
Edge Cases
Was, wenn der Benutzer der Operator und Admin ist?
Der reviewer läuft trotzdem. Es gibt kein „Review überspringen, weil du Admin bist"-Flag. Auditierbarkeit ist der Punkt — die Entscheidungszeile des reviewers ist die Papierspur, die sagt „diese Aktion wurde gegen SOP-X mit Rollback Y zur Zeit T genehmigt". Admin-Override würde die Spur löschen.
Was, wenn kein get_sop_text-SOP existiert?
Heute ist der SOP-Korpus dünn — get_sop_text ist ein geplantes Tool (HLD-003 PR-D). Im aktuellen MVP verwendet der reviewer einen Platzhalter und fällt auf eine Heuristik zurück: kritische Aktionen auf produktionstagged Devices brauchen explizites force_approve_no_sop: true im Vorschlagskontext, was der coordinator nur nach expliziter Nutzerbestätigung setzen kann. Dies wird durch den SOP-Korpus ersetzt, sobald er gefüllt ist.
Was, wenn der reviewer timeout?
Der 60s-Gate-Timeout feuert. Der Decorator gibt ErrReviewTimeout zurück. Das coordinator-LLM sieht einen Timeout-Fehler und soll ihn dem Benutzer berichten — nicht wiederholen. Anhaltende reviewer-Timeouts sind ein Manager-seitiges Problem (wahrscheinlich Modell-Latenz); das Audit-Log lässt den SRE das Muster sehen.
Was ist mit Read-Only-Worker-Tools?
Read-Only-Tool-Aufrufe der Workers (query_promql, get_host_load, etc.) haben Class: "read" und triggern das Gate nie. Nur "write" / "destructive"-Tools tun das. Der reviewer selbst trägt nur Class: "read"-Tools, sodass ein Reviewer-Worker selbst kein verschachteltes ReviewGate triggern kann.
Das Gate anpassen
Dinge, die Sie in einem Fork ändern könnten:
- Das Reviewer-Modell. Wenn Ihre Org keinen Anthropic-Zugang hat, schreiben Sie das Frontmatter-
model:auf das stärkste Modell, das Sie haben. Das Gate verwendet das, was die Persona deklariert. - Die 60s-Decke. Überschreiben Sie über die
ReviewGate-Konstruktor-Option, wenn Ihr reviewer regelmäßig länger braucht. Gehen Sie nicht unter 30s; der reviewer braucht Raum für 5 Turns × LLM + Tool-Round-Trips. - Den Reviewer-Persona-Body. Fügen Sie teamspezifische Checklisten hinzu (PCI-Scope, Change-Freeze-Fenster, On-Call-Kalender). Das Gate kümmert sich nicht um den Body, solange die endgültige Entscheidungszeile parsebar ist.
Dinge, die Sie nicht ändern dürfen:
- Den
name: reviewer— das Gate sucht ihn per Name nach (DefaultReviewerAgent). - Den
disallowed_tools-Wildcard*_skill— der reviewer darf selbst keine Aktionen ausführen; Defense in Depth sagt, dass der Runtime-Filter dies erzwingt, nicht der Prompt.
Für einen pro-Tool-benutzerdefinierten reviewer (z. B. einen DB-spezifischen) akzeptiert der Decorator-Konstruktor einen reviewerAgent-Override, sodass verschiedene Tools zu verschiedenen Reviewer-Personas geroutet werden können. Verwenden Sie es sparsam — mehrere reviewer fragmentieren den Audit-Trail.