Skip to content

Reviewer

reviewer はすべての変更操作に セカンドサイン するペルソナです。他の worker と違い、coordinator が spawn することは決してありません —— カタログから意図的に除外されています。唯一の spawner は ReviewGate デコレーターで、Class"write" または "destructive" のすべての ツールをラップします。

reviewer は「監視者を誰が監視するか?」という問いへの答えです。

これを無効化しないでください

reviewer こそが、Ongrid に host_restart_serviceexecute_skill を そもそも与えても安全と言える根拠です。ゲートをスキップするのは明示的な 設定選択であり、監査証跡に現れます。ペルソナをフォークして「常に approve」 にすると、監査ログ にすべての判断が記録 されます —— 監査人は気づきます。

ReviewGate デコレーター

ツールデコレーターチェーン内の位置 (chain.go):

text
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 の内側。 提案ペイロードには operator user_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 を参照。

提案ペイロード

捕捉時、ゲートはこう構築します:

json
{
  "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 より逐語):

yaml
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_detailget_edge_summary、テレメトリクエリ)はできますが、決して動作しません。
  • run_shell なし、host_restart_service なし、kill_process なし。 たとえペルソナ本文が指示しても、ランタイムフィルターがこれらのツールを 剥がします。多層防御です。

5 ステップワークフロー

ペルソナ本文から、reviewer は次を走らせます:

  1. SOP を探す。 get_sop_text(action) で公式手順。SOP がなければ reject"no SOP for action <X>")。
  2. 対象の状態を確認。 get_edge_summary(device_id)。デバイスがオフ ライン / 再起動ループ中 / 直近 5 分以内に変更操作あり → reject。
  3. 並行操作のチェック。 query_logqlaudit: エントリのうち、 過去 10 分間に同じ対象に触れたものを探す。並行操作あり → reject ("parallel operation detected; wait for X to complete")。
  4. 理由とアラートの整合性検証。 参照されたインシデントを get_incident_detail で取得。理由がアラート内容と矛盾 → reject (「operator が症状を読み違えた可能性」)。
  5. 判断。
    • Approve:3 つの核ゲートがすべて通った場合。出力 {decision: approve, sop_id, rollback_path, gates_passed}
    • Reject:それ以外。出力 {decision: reject, reason, missing_gates}

3-of-3 ルール

クリティカルリマインダーは明示的です:

reject 是默认选项,approve 必须三条都满足:

  1. 找得到对应 SOP 且明确覆盖此场景
  2. 当前没有并行的同类操作(看告警 / 看运维窗口)
  3. 回滚路径已知

「よく分からない」は「reject」と同義です。これは意図的なキャリブレーション です —— 誤承認(本番ダメージ)と誤拒否(追加ラウンドトリップ 1 回)の コスト非対称性が、後者を強く好みます。

出力フォーマット

reviewer の最終返信(<task-notification> 経由で coordinator にポスト バック):

markdown
**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 時に起こること

デコレーターは:

  1. status=approved、reviewer の判断テキスト、SOP id を持つ chat_mutating_proposals 行を書く。
  2. 呼び出しを内側ツールへ素通りさせる。
  3. (チェーン下流の)監査デコレーターが実行行を書く。
  4. 内側ツールが通常の結果を coordinator LLM に返す。

coordinator LLM は通常のツール結果を見て進みます。

reject 時に起こること

デコレーターは:

  1. status=rejected、reviewer の理由、欠落ゲートを持つ chat_mutating_proposals 行を書く。
  2. reviewer の理由をラップした ErrReviewRejected を返す。
  3. 監査デコレーターは実行行を 書きません(実行は起きていません)。

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_promqlget_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 は監査証跡を分散させます。