Reviewer
reviewer はすべての変更操作に セカンドサイン するペルソナです。他の worker と違い、coordinator が spawn することは決してありません —— カタログから意図的に除外されています。唯一の spawner は ReviewGate デコレーターで、Class が "write" または "destructive" のすべての ツールをラップします。
reviewer は「監視者を誰が監視するか?」という問いへの答えです。
これを無効化しないでください
reviewer こそが、Ongrid に host_restart_service や execute_skill を そもそも与えても安全と言える根拠です。ゲートをスキップするのは明示的な 設定選択であり、監査証跡に現れます。ペルソナをフォークして「常に approve」 にすると、監査ログ にすべての判断が記録 されます —— 監査人は気づきます。
ReviewGate デコレーター
ツールデコレーターチェーン内の位置 (chain.go):
tenant_bind → REVIEW_GATE → timeout → audit → ratelimit → metric → <inner tool>なぜこの順序か:
timeoutの外側。 reviewer 自体が独自のターン予算を持つgraph.Invokeです。内側ツールの 15 秒タイムアウト内に包むと、 reviewer も 15 秒で終わらせる必要があり、非現実的です。ゲートは独自の 60 秒上限を持ちます (DefaultReviewerTimeout)。auditの外側。 拒否時に合成的な実行行を書きたくありません。 ゲートは代わりにchat_mutating_proposals行を書きます。監査は内側 ツールの 実行 のみをログし、それは approve 時のみ発生します。tenant_bindの内側。 提案ペイロードには operatoruser_idが 含まれ、tenant_bindが ctx から解決します —— ゲートはtenant_bindが これを設定した 後に 走る必要があります。
トリガー条件
デコレーターはラップしたツールの Class を検査します:
| Class | ゲートの挙動 |
|---|---|
"read" | 素通り。内側ツールが実行される。 |
"write" | 捕捉。reviewer を spawn。承認時のみ内側ツール実行。 |
"destructive" | "write" と同じ。両クラスがゲートを通る。 |
bag 内の現状の Class: "write" ツール:
host_restart_service—— 正典の変更スキル。execute_skill—— マーケットプレースインストールされたあらゆるスキル を走らせるマーケットプレースシム(ゲートはスキル本文を読んで分類でき ないので、すべてゲートします)。AgentTool—— はい、dispatch プリミティブ自体が"write"です。 worker を spawn してリソースをコミットするからです。ただ実務的には reviewer が AgentTool 呼び出しをゲートすることは稀です —— 後述の ペルソナの allowlist を参照。
提案ペイロード
捕捉時、ゲートはこう構築します:
{
"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 はツールのメタデータから派生し、single_device | cluster | tenant_wide のいずれかです。reviewer は「合理的か」判断の 重み付けに使います —— tenant_wide アクションは single_device より 厳しい吟味を受けます。
reviewer ペルソナ
フロントマターのハイライト (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. 回滚路径已知主な観察点:
max_turns: 5。 reviewer は遠回りしません。5 ターンで決定。ペルソナ プロンプトは明示的に "看不清就 reject" と言います。model: anthropic/claude-opus-4-7。 重要パスの呼び出しは組織の デフォルトに関わらず最強モデルが入ります。レビューを速いモデルに格下げ すべきではありません —— 誤承認のコストが遅いレビューのコストをはるかに 上回ります。background: true。 reviewer は非同期で走ります。coordinator の UI はレビューでブロックしません。完了時にレビューのtask_notificationが 戻ってきます。(現在の配線では内側ツールが reviewer の返答までブロック しますが、UI はブロックしないので、ユーザーは実行中「review pending」 を見ます。)disallowed_toolsワイルドカード*_skill。 reviewer はあらゆる スキルを実行できません。コンテキストの読み取り(get_incident_detail、get_edge_summary、テレメトリクエリ)はできますが、決して動作しません。run_shellなし、host_restart_serviceなし、kill_processなし。 たとえペルソナ本文が指示しても、ランタイムフィルターがこれらのツールを 剥がします。多層防御です。
5 ステップワークフロー
ペルソナ本文から、reviewer は次を走らせます:
- SOP を探す。
get_sop_text(action)で公式手順。SOP がなければ reject("no SOP for action <X>")。 - 対象の状態を確認。
get_edge_summary(device_id)。デバイスがオフ ライン / 再起動ループ中 / 直近 5 分以内に変更操作あり → reject。 - 並行操作のチェック。
query_logqlでaudit:エントリのうち、 過去 10 分間に同じ対象に触れたものを探す。並行操作あり → reject ("parallel operation detected; wait for X to complete")。 - 理由とアラートの整合性検証。 参照されたインシデントを
get_incident_detailで取得。理由がアラート内容と矛盾 → reject (「operator が症状を読み違えた可能性」)。 - 判断。
- Approve:3 つの核ゲートがすべて通った場合。出力
{decision: approve, sop_id, rollback_path, gates_passed}。 - Reject:それ以外。出力
{decision: reject, reason, missing_gates}。
- Approve:3 つの核ゲートがすべて通った場合。出力
3-of-3 ルール
クリティカルリマインダーは明示的です:
reject 是默认选项,approve 必须三条都满足:
- 找得到对应 SOP 且明确覆盖此场景
- 当前没有并行的同类操作(看告警 / 看运维窗口)
- 回滚路径已知
「よく分からない」は「reject」と同義です。これは意図的なキャリブレーション です —— 誤承認(本番ダメージ)と誤拒否(追加ラウンドトリップ 1 回)の コスト非対称性が、後者を強く好みます。
出力フォーマット
reviewer の最終返信(<task-notification> 経由で coordinator にポスト バック):
**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.}デコレーターは Decision: approve をパースします(大文字小文字無視、返信 の最初の非空白行に現れる必要があります)。それ以外 ——「approve with caveats」のような曖昧な言い回しを含む —— は reject として扱われます。
approve 時に起こること
デコレーターは:
- status=
approved、reviewer の判断テキスト、SOP id を持つchat_mutating_proposals行を書く。 - 呼び出しを内側ツールへ素通りさせる。
- (チェーン下流の)監査デコレーターが実行行を書く。
- 内側ツールが通常の結果を coordinator LLM に返す。
coordinator LLM は通常のツール結果を見て進みます。
reject 時に起こること
デコレーターは:
- status=
rejected、reviewer の理由、欠落ゲートを持つchat_mutating_proposals行を書く。 - reviewer の理由をラップした
ErrReviewRejectedを返す。 - 監査デコレーターは実行行を 書きません(実行は起きていません)。
coordinator LLM はエラーメッセージ —— review rejected: <reviewer reason> —— を見て、ユーザーに状況を説明することが期待されます。同じ ツール呼び出しをリトライすべきではありません。重複排除保護 + 拒否理由の 短期 LRU が LLM をループから守ります。
エッジケース
ユーザーが operator かつ admin の場合?
reviewer はそれでも走ります。「admin だからレビューをスキップ」フラグは ありません。監査可能性こそが要点です —— reviewer の判断行は「このアクション は SOP-X に対して時刻 T にロールバック Y 付きで承認された」と語る 紙の証跡 です。admin オーバーライドは証跡を消し去ります。
get_sop_text の SOP が無い場合?
今日 SOP コーパスは疎です —— get_sop_text は計画中のツール(HLD-003 PR-D)です。現状 MVP では reviewer はプレースホルダーを使ってヒューリス ティックにフォールバックします:本番タグのデバイス上のクリティカル アクションは提案コンテキストに明示的な force_approve_no_sop: true が 必要で、coordinator は明示的なユーザー確認の後にのみセットできます。これは SOP コーパスが整備されたら置き換えられます。
reviewer がタイムアウトしたら?
60 秒のゲートタイムアウトが発火します。デコレーターは ErrReviewTimeout を返します。coordinator LLM はタイムアウトエラーを見て、ユーザーに報告 すべきです —— リトライではありません。継続的な reviewer タイムアウトは manager 側の問題(恐らくモデルレイテンシ)です。監査ログで SRE がパターン を見られます。
読み取り専用の worker ツールは?
worker の読み取り専用ツール呼び出し(query_promql、get_host_load 等) は Class: "read" で、決して ゲートを発動させません。"write" / "destructive" のツールだけです。reviewer 自身は Class: "read" の ツールしか持たないので、reviewer worker 自身がネストした ReviewGate を 発動させることはありません。
ゲートのカスタマイズ
フォークで変えたくなるもの:
- reviewer モデル。 組織が Anthropic アクセスを持たない場合、フロント マターの
model:を持っている最強モデルに書き換えてください。ゲートは ペルソナが宣言したものを使います。 - 60 秒の上限。 reviewer が定常的に長引くなら
ReviewGateコンストラクタ オプションで上書きしてください。30 秒未満には下げないでください。 reviewer は 5 ターン × LLM + ツールラウンドトリップの余裕が必要です。 - reviewer ペルソナ本文。 チームごとのチェックリスト(PCI スコープ、 変更凍結ウィンドウ、オンコールカレンダー)を追加。最終判断行が パース可能なら本文の内容はゲートにとってどうでもよいです。
変えてはいけないもの:
name: reviewer—— ゲートが name で引く (DefaultReviewerAgent)。disallowed_toolsのワイルドカード*_skill—— reviewer は自身が アクションを実行してはなりません。多層防御として、ランタイムフィルター がこれを強制し、プロンプト任せにはしません。
ツールごとのカスタム reviewer(例:db 特化のもの)には、デコレーター コンストラクタが異なるツールを異なる reviewer ペルソナに振り分けられる ように reviewerAgent オーバーライドを受け付けます。控えめに使って ください —— 複数 reviewer は監査証跡を分散させます。