Incident investigator
incident-investigator は Ongrid のワーカーの中で最も深いものです。 coordinator はユーザーが症状の要約ではなく 根本原因 を求めたときに このペルソナへ dispatch します。観測されたアラートからその発生源("patient zero" —— ペルソナプロンプト内では 0 号病人)まで 因果連鎖 をたどり、 構造化されたレポートを返します。
これが RCA の裏側のペルソナです
HLD-013 の因果 RCA パイプライン(テスト環境、2026 年 5 月ロールアウト)は このペルソナの上に構築されています。/incident/<id> → Get RCA を実行すると、 manager がインシデント ID をプロンプトに事前埋め込みしてこのワーカーを spawn します。
coordinator がこれを選ぶとき
ペルソナファイルがトリガーパターンを宣言しています。フロントマターをそのまま 引用します。
when_to_use: |
coordinator 在用户问以下场景时 spawn 本 worker:
• "这条告警的根因是什么 / 到底是谁导致的"
• "incident 123 怎么排查 / 受影响范围 / 持续多久"
• "这个告警是不是误报 / 跟上次那个相关吗"
• "这台机器 mem 飙了,看一下"訳すと:ユーザーが 何 (what) ではなく なぜ (why) を訊いてきたとき すべてです。investigator の成果物は「現在の状態」のスナップショットではなく、 発生源までの因果連鎖です。
Tool bag
ペルソナでホワイトリストされたもので、ランタイムフィルターがそれ以外を すべて剥がします。
tools:
- query_knowledge # KB / vault / uploads
- get_incident_detail
- query_incidents
- correlate_incident # metric+log+trace pulled together
- query_change_events # config / rule / device mutations
- query_promql
- query_logql
- query_traceql
- get_edge_summary
- query_alert_rules
- query_devices
- get_host_load
- get_host_processes
- expand_topology
- find_topology_node
- host_find_large_files
- host_du_summary
- host_stat_file
disallowed_tools:
- execute_skill
- host_restart_service
- run_shell
permission_mode: read-only主な帰結:
- 読み取り専用。
host_restart_serviceもexecute_skillもrun_shellもありません。調査の結論としてサービスの再起動が必要となれば、coordinator への 提案 として返します。coordinator は変更を伴う意図でspecialist-opsに dispatch し、reviewer が ゲートします。 - トポロジーと変更イベント。 specialist と比べたユニークな強みは、
expand_topology+find_topology_node(サービスグラフを上流にたどる)とquery_change_events(アラートのfired_at周辺の最近の設定 / ルール / デバイスの変更と症状を相関)です。 - クロスホスト bash とホストごとのプローブは持ちません。 それらは specialist(
specialist-network、specialist-compute、specialist-disk) にあります。investigator は可観測性データプレーン上で調整します。
5 ステップワークフロー
ペルソナ本文がワークフローを規定しています。すべての調査は次のように 進みます。
- KB 優先(必須)。
incident_idが手に入った時点で、ルール名 + 症状 を自然言語クエリにしてquery_knowledgeをちょうど 1 回呼びます (例:"swap_high 告警怎么排查")。ヒット(score ≥ 0.6)したら プレイブックに従い、最終回答に(参考 KB: <title>)の引用を付けます。 ミスならステップ 1 へ進みます。 - 症状 + ブラスト半径。
get_incident_detailでルール名 / severity / target /fired_at/ labels。これは 因果連鎖の末端(結果) であり、 根本原因ではありません。ここで止まらないでください。 - タイムライン。
correlate_incidentが同じインシデントウィンドウで metric + log + trace を一度に引きます。fired_at/ 最初の逸脱時刻で ソート。最も早い シグナルが発生源候補。下流の高 CPU / 高レイテンシ は通常、原因ではなく結果です。「最も大声」≠「最も早い」。 - 上流に一段だけ因果ホップ。 明確な目的を持って 1 つだけ ツールを 選びます。
- 何が変わった? →
query_change_events(around_ts=fired_at)。 プロダクト側の変更が 0 号病人であることが多い。 - 依存関係? →
expand_topology上流(下流のブラスト半径ではない) /find_topology_node。 - 呼び出し元チェーンをトレース? → 最も遅いスパンの起点を
query_traceqlで探す。 - 最初のエラー? →
query_logqlを device_id で grep し、fired_atより前 の最も早い ERROR / PANIC / OOM を取る。 - 誰が先に動いた? → 最初に逸脱したメトリクスを
query_promqlで 特定。
- 何が変わった? →
- 再帰。 上流候補を新しい現在地として扱い、ステップ 3 を以下のどちらか になるまで繰り返します。
- 底に到達 —— システム内の上流がもう残っていない。リーフがプロセス / 1 件の変更 / 外部依存 = 0 号病人。
- シグナル枯渇 —— これ以上進めない。「到達した最深層 + 続けるなら どのシグナルが必要か」を報告。
- 検証。 提案した根本原因は下流連鎖全体を説明する必要があります —— 時系列的に症状より 先行 し、大きさと方向が整合すること。そうで なければ「仮説」へ格下げし、その旨を明記。
18 ツール予算 —— 深く掘れ、空回りするな
ペルソナは厳しい反復規律を強制します。本文より:
你有 ~18 个工具调用预算(够上溯 4-6 层)。深挖允许,但死分支立刻砍:
- 工具返回空(
result:[]/streams:[]):第一次空可换思路;第二次 空立刻停这条线,换方向或就此上溯为止。- 同一工具失败 / 空 ≥2 次 → 必须换工具或换方向,禁止反复换表达式空转 (v0.7.51-55 的失败都栽在这).
- 每一步都要朝"再上溯一层"前进 — 调之前问自己 "这步能让我更接近源头吗"。
- 上溯到 4-5 层仍未触底、或预算用到 ~15:停,输出"目前最深一层 + 缺失 信号",别为凑满空转。
フロントマターの max_turns: 40 はハード上限です。eino のグラフは MaxStep = MaxIterations*2+2 と数えるので、40 → MaxStep=82 → だいたい 41 ChatModel ターンです。18 ツール予算はプロンプト内の より柔らかい ガイダンスで、キャップはランタイム側の安全網です。
デッドブランチは妥協なし
investigator のプロンプトでこれは明示的な「やるな」ルールになっています。 初期の v0.7.51-55 の eval では、ワーカーが空のレンジクエリにデータを 返させようと PromQL 式を入れ替えるのに 30 ターン以上を浪費する事例が 観測されたからです。1 回の空結果は情報、2 回目の空結果は「学べることは すでに学んだ」の合図 —— ピボットするか上昇するかしてください。
出力フォーマット
coordinator への最終返信は、この形の逐語 Markdown です。
**根因(0 号病人)**
{One-line patient zero — process / change / upstream service+node /
config. Concrete identifiers (pid + cmdline / service name / change
key) — this is the source of pinpoint_target. If we didn't hit bottom:
"未触底,最深到 X;要继续需 Y 信号".}
**因果链**
{Source → … → alert symptom. One line per hop, each with "why this
caused the next" plus evidence (PromQL / LogQL / trace span /
process line).}
**现象**
{1-2 sentences: when did it start / which host / what crossed
threshold / for how long.}
**置信度与验证**
{High / medium / low + reason. Plus: "what query or action would
further validate or falsify this root cause".}coordinator はこれを合成してユーザー向け回答にします(1 言語、1 段落、KB ヒット時は引用付き)。investigator の生 Markdown はセッションに ワーカーの Result としてそのまま永続化され、RCA UI が Reasoning ディスクロージャの下にそのまま表示します。
F1 e2e テスト
F1 はこのペルソナをテスト環境上のシードインシデントに対して動かす end-to-end eval です。形:
searxngプロセスが 30 分間 RSS 95% にピン留めされた状態で、node-01(device_id=7)に合成swap_highインシデントを seed。- 期待する labels +
fired_atでインシデントが発火するようアラート パイプラインを配線。 prompt = "rca incident 1234"で investigator を dispatch。- 最終返信に以下を含むことを assert:
现象にswap_highルール。根因(0 号病人)に pid + コマンドラインを伴うsearxngプロセス。因果链に少なくとも 2 つの因果ホップ(症状 → 上流)。- seed した KB に対応プレイブックがあれば
(参考 KB: …)引用。
HLD-013 の初版は F1 に失敗しました —— DB に default_provider がセットされて おらず、resolver が glm モデル名で openai にフォールバックし、chat モデルが エラーを返し、ワーカーが空の分析を返したからです。教訓:F1 は副作用として LLM resolver もカバーするので「RCA は本当に end-to-end で配線されたか?」の 正典ゲートになっています。
短く切り上げる典型的な理由
ペルソナは正直に「0 号病人に到達せず」を返します。たとえば:
- 原因がクラスタの外 —— DNS プロバイダー、上流 API、電源など。
query_change_eventsは manager のスコープ外のインフラ変更は見えません。 - トレースデータが欠落 —— 該当サービスについて TraceQL クエリが スパンを返さない。トレースなしで investigator は呼び出し元チェーンを たどれません。「缺失 trace 信号」と報告します。
- トリガーを指し示すログ行がローテーション済み —— Loki の保存期間が 最初の調査までの時間より短い。investigator はそう述べ、繰り返し調査用 に保存期間延長を推奨します。
この正直さは設計通りです。自信ありげな誤答は「シグナル X までは到達した が、続けるには Y が必要」より悪いのです。
チューニング
このペルソナをフォークするとき現実的に変えたくなるもの:
- ドメイン特化の KB ヒットを追加 —— あなたの よくある障害モードに 対するプレイブックを書いて vault 経由で出荷すれば、investigator の
KB firstステップが発見します。 - ツールホワイトリストの調整 —— トレーススタックが Tempo でないなら
query_traceql系を追加する、ディスク検査を investigator にインラインで dispatch させたくないならhost_du_summaryを外す(デフォルトは ワーカー自身の出力経由でspecialist-diskに委譲しますが、速い場合に 自前で検査できるツールも 持っています)。 - 予算の引き締め —— モデルのトークン単価が気になるなら
max_turnsを 25-30 に下げます。ペルソナ本文の 18 呼び出しソフト予算がすでにほとんどの 調査をその範囲内に収めます。
組み込みの上に自分のフォークをマウントする方法は カスタムエージェント を参照してください。