mcpField
A
agent-observability-trace-rca

agent-observability-trace-rca

github.com/datadog-labsテスト・品質180561 回インストール6 日前に更新
リポジトリ

agent-observability-trace-rca について

agent-observability-trace-rcaは、Datadog LLM tracesを調べ、本番LLMアプリの障害を診断するエージェントスキルです。評価結果、実行時エラー、構造上の異常に応じて分析経路を選び、MCPツールまたはpupコマンドラインを利用します。

主な機能

  1. 01利用可能なシグナルから分析モードを選択
  2. 02トレースとスパンの検索・調査
  3. 03スパン階層をたどったエラー追跡
  4. 04評価スコアと推論内容の確認
  5. 05エージェント実行タイムラインの調査
  6. 06MCPツールまたはpupコマンドラインの利用

活用シーン

  1. 01LLM評価失敗の原因特定
  2. 02本番トレース内の実行時エラーの調査
  3. 03レイテンシやエージェントループの異常分析
  4. 04評価器や期間ごとの障害比較

MCP 対応

Datadog LLM Observability MCPツールが利用可能な場合はそれを使い、そうでない場合は同等のpupコマンドライン呼び出しにワークフローを置き換えます。スパンを検索し、評価、トレース、コンテンツの詳細を取得します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/datadog-labs/agent-skills --skill agent-observability-trace-rca

インストール後、Claude Code で/agent-observability-trace-rcaを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
__init__.py
evaluator.py
example_config.json
executor.py
evals/data/
llm_obs_trace_rca_v1.json
evals/prompts/
judge_rubric.txt

詳細

バックエンド

検出 — 各呼び出しの開始時に、何かを実行する前に、使用するバックエンドを決定します。

  1. ユーザーが呼び出しのどこかに --backend pup を指定した場合 → ほかの MCP ツールの有無にかかわらず、ただちに pup モードを使用します。手順 2~4 はスキップします。
  2. 有効なツールリストに MCP ツールがあるか確認します。判定の基準は、使用可能なツールに mcp__datadog-llmo-mcp__list_llmobs_evals が含まれているかどうかです。
  3. MCP ツールがある場合 → 一貫して MCP モードを使用します。このスキルのワークフローのセクションに記載されたとおりに MCP ツールを呼び出します。
  4. MCP ツールがない場合 → Bash で pup --version を実行し、pup が実行可能か確認します。"version" を含む JSON レスポンスが返れば、pup が利用可能です。
  5. pup が応答した場合 → 一貫して pup モードを使用します。このファイルの末尾にあるツールリファレンスの付録に従って、すべての MCP ツール呼び出しを対応する pup の呼び出しに置き換えます。
  6. どちらも利用できない場合 → 処理を停止し、次の内容をユーザーに伝えます。

    "Datadog MCP サーバーも pup CLI も利用できません。MCP サーバー(claude mcp add --scope user --transport http datadog-llmo-mcp 'https://mcp.datadoghq.com/v1/mcp?toolsets=llmobs')を接続するか、pup をインストールしてください。"

--backend pup は呼び出し引数のどこに指定しても受け付けられ、残りの引数をスキルのロジックに渡す前に取り除きます。

pup の呼び出しルール:

  • Bash で呼び出します:pup llm-obs <subcommand> [flags]
  • pup は常に JSON を出力します。MCP の結果のように JSON を [{"type": "text", "text": "<json>"}] から取り出す必要はありません。直接解析してください。
  • pup が認証エラーを返した場合は、pup auth login を実行するようユーザーに伝え、処理を停止します。
  • 並列化:1 回のメッセージで複数の Bash ツール呼び出しを発行します(呼び出しごとに pup コマンドを 1 つ指定)。
  • 時間指定フラグ:pup は期間を表す文字列(1h、7d、30m)および RFC3339 タイムスタンプを受け付けます。now- を先頭に付けた文字列は使用しないでください。スキルの --timeframe 引数を変換する際は、接頭辞を取り除きます:now-7d → 7d、now-24h → 24h、now-30d → 30d。
  • pup llm-obs spans search の --summary は、ペイロードのフィールドを重要なメタデータのみに絞ります。コンテンツが不要な一括処理や検索の段階で使用してください。

呼び出し ID: 各呼び出しの開始時、MCP ツールを呼び出す前に、8 文字の 16 進数の呼び出し ID(例:3a9f1c2b)を生成します。呼び出し全体を通して同じ ID を使用してください。

インテントタグ付け: MCP ツールを呼び出すたびに、telemetry.intent の先頭に skill:agent-observability-trace-rca[<inv_id>] — を付け、その後に呼び出しの理由を記述します。最初の MCP ツール呼び出しのみ、代わりに skill:agent-observability-trace-rca:start[<inv_id>] — を使用します(:start サフィックスに注意してください)。最初の呼び出しの例:skill:agent-observability-trace-rca:start[3a9f1c2b] — task-cruncher に設定されている評価を検出し、分析モードを推定するフェーズ 0

エージェントのオブザーバビリティトレース RCA — 本番環境の LLM トレースから根本原因を分析

本番環境のトレースを検索し、症状から根本原因までスパンツリーをたどって、LLM アプリケーションが失敗する理由を診断します。このスキルは、利用可能なシグナルに基づいて最適な分析モードを自動的に選択します。

モードシグナル自動選択される条件
評価シグナルLLM ジャッジの判定と推論(合格率/不合格率、スコアリング)アプリに評価器が設定されている場合
エラーシグナル実行時エラー(@status:error、エラー種別、スタックトレース)評価器が設定されていない場合、またはユーザーがエラー/クラッシュについて明示的に尋ねた場合
汎用構造上の異常(レイテンシ、エージェントのループ、検索のミス)mode=generic による明示的な上書き、またはフェーズ 1 で強いシグナルが見つからない場合

モードは最初のユーザー向け出力で (質問せずに)通知され、1 行の上書きヒントが示されます。

方法

解決 → 検索 → 観察 → オープンコーディング → 軸足コーディング → 根本原因の追跡 → 推奨事項

使い方

What's wrong with <ml_app> over the last <timeframe>
Why is <ml_app> failing today
Analyze eval failures for <eval_name> on <ml_app>
Look at the errors on <ml_app> over the last <timeframe>
Root-cause low scores on <eval_name>

入力

入力必須デフォルト説明
ml_appはい(または eval_name)—分析するアプリケーションです。
eval_nameいいえ—対象とする評価器を1つ以上指定します。Eval Signal モードが有効になります。複数の評価を分析する場合は、リストを渡します。
timeframeいいえnow-24hどのくらい前までさかのぼって調べるかを指定します。
modeいいえ推定明示的なモード指定です:eval、errors、generic。推定を完全にスキップします。
failure_filterいいえ—範囲を絞り込みます:"errors"(Error Signal パスにルーティング)、"high latency"(取得後に所要時間で並べ替え)、"low scores on <eval>"(eval_name に昇格)、ツール名またはスパン名(@name:<x> クエリ)。

ml_app と eval_name のどちらも指定されていない場合は、ユーザーに確認してください。

利用可能なツール

評価の検出と概要
ツール目的
list_llmobs_evalsml_app に設定されているすべての評価を検出します。Phase 0 のモード推定で使用します。
get_llmobs_eval_aggregate_stats指定した期間における評価の合格率/不合格率またはスコア分布を取得します。
get_llmobs_evaluator評価器の完全な設定を取得します:プロンプトテンプレート、評価基準、スパンフィルター、サンプリング、プロバイダー。非推奨の get_llmobs_eval_config の代わりに使用してください。
トレースとスパンの探索
ツール目的
search_llmobs_spansタグ、スパン種別、ステータス、クエリ構文でスパンを検索します。カーソルでページネーションします。Phase 1 の開始点です。
get_llmobs_span_detailsメタデータ、評価(スコア、ラベル、推論)、status、エラーフィールド、所要時間、および利用可能なフィールドとサイズを示す content_info マップを取得します。
get_llmobs_span_contentスパンフィールドの実際の内容を取得します。path パラメーターで JSONPath による対象の抽出をサポートします。
get_llmobs_traceスパン種別ごとのスパン数を含む、スパンツリーとしてトレース階層全体を取得します。
find_llmobs_error_spansエラー種別、メッセージ、スタック、伝播コンテキストを含む、トレース内のすべてのエラースパンを取得します。
expand_llmobs_spans折りたたまれたトレースノードの子を読み込みます。
get_llmobs_agent_loopエージェント実行の時系列(LLM 呼び出し、ツール呼び出し、判断)を取得します。空を返す場合があります。Phase 4b のフォールバックを参照してください。
get_llmobs_span_content の主なパターン
フィールドパス取得できる内容
messages$.messages[0]システムプロンプト(最初のメッセージ。通常は system ロール)
messages$.messages[-1]最後のアシスタントの応答
messages(パスなし)ツール呼び出しを含む会話全体
input / output—スパンの入出力
documents—取得されたドキュメント(RAG アプリ)
metadata—カスタムメタデータ(プロンプトのバージョン、機能フラグ、ユーザーセグメント)
search_llmobs_spans の使用方法

query 文字列には必ず @ml_app:"<ml_app>" を含めてください。構造化された ml_app パラメーターは信頼できず、他のアプリのスパンを返すことがあります。 構造化パラメーターだけに頼らないでください。

便利なクエリフラグメント — スペースで結合します(AND):

目的クエリ
エラーのみ@status:error
スパンに評価が存在する@evaluations.custom.<eval_name>:*(存在のみ。合否はクエリではなく get_llmobs_span_details から読み取ります)
名前で特定のツールを指定@name:<tool_name>

専用パラメーター(span_kind、root_spans_only、ml_app)は query と併用できますが、query は tags より優先されます。

並列化のルール
  1. get_llmobs_span_details:trace_id ごとに span_ids をグループ化し、各トレースの span_ids を最大20件のバッチに分割します。1ページ分のすべてのバッチを単一のメッセージで送信してください。
  2. get_llmobs_span_content:各呼び出しは独立しています。必ずすべてを単一のメッセージで送信してください。
  3. get_llmobs_trace / find_llmobs_error_spans / get_llmobs_agent_loop:異なるトレースに対する呼び出しは、単一のメッセージで並列化してください。
  4. パイプラインの並列処理:1ページ目の結果について、すぐに get_llmobs_span_details を開始してください。すべてのページの収集を待たないでください。

分析ワークフロー

出力の規律:フェーズ 0~5 は内部分析です。これらのフェーズでユーザーに表示する出力は、フェーズ 1 のシグナル概要と、フェーズ 2 および 3 の必須チェックポイントのみです。推論を説明したり、中間的な調査結果を要約したり、フェーズ 4 の詳細調査結果を文章として出力したりしないでください。詳細な調査結果はすべて、フェーズ 6 のレポートにのみ記載してください。


フェーズ 0:入力を解決してモードを推定する

最初に、分類コンテキストを確認します。 会話内に # Session Classification Summary ヘッダーがあるか確認してください。見つかった場合は、以下のステップ 0Sに進み、それ以外のフェーズ 0 のステップとフェーズ 1 をすべてスキップします。

ステップ 0S — 分類出力から失敗バケットを抽出する

標準的な引き継ぎ形式は、# Session Classification Summary セクション内のユニットごとの詳細テーブルです。ユニットごとに 1 行を抽出します。

フィールドソース
trace_idID 列のリンク URL:リンクの href から trace_id= または session_id= クエリパラメーターを解析します
verdictVerdict 列
failure_modeFailure Mode 列(合格した行では none)
detailReason 列 — フェーズ 2 の推論入力として使用します(評価ジャッジの推論やエラーメッセージと同じ役割)
app_type# Session Classification Summary のヘッダー行から取得します(例:Root span kind: agent)。存在しない場合は LLM を使用します

失敗バケット = verdict が no または partial のすべての行です。

  • 5 件未満の場合 → 信頼度が低いことを記録し、そのまま続行します。
  • 空の場合 → 「分類出力に失敗は見つかりませんでした」と報告して終了します。

続行する前に、この概要を提示します。

## Classification Overview (from agent-observability-session-classify)

**ml_app**: <from summary header>  |  **Classified**: N  |  **Failures (no+partial)**: F  |  **Pass rate**: X%

| Failure Mode | Count |
|---|---|
...

Proceeding to Phase 2 using F failure traces. Mode inference bypassed — classification verdict is the signal.

その後、フェーズ 1 をスキップし、フェーズ 2 に直接進みます。以下を引き継ぎます。

  • フェーズ 2 の推論入力:(trace_id, span_id, detail) のタプル — 評価の推論やエラーメッセージと同じ構造です
  • フェーズ 4 のナビゲーション:各トレースブロックの app_type を使って、スパンのナビゲーション戦略を選びます
  • フェーズ 2~7:完全に変更せず実行します — 失敗バケットの構造は、情報源にかかわらず同一です

標準的な解決(分類コンテキストがない場合):

  1. ml_app も eval_name も指定されていない場合 → ユーザーに尋ねます。eval_name が指定されていて ml_app が指定されていない場合も → ml_app を尋ねます(eval 名はグローバルに一意ではありません。これがないと、スパン検索で同じ eval 名を共有するすべてのアプリから結果が返されます)。
  2. timeframe が指定されていない場合 → now-24h をデフォルトとして使用します。
  3. failure_filter を解決します(モード推定の前に行います)。
    • "errors" → エラーシグナルモードを強制します
    • "low scores on <eval>" → eval_name=<eval> として扱い、その後推定を続けます
    • "high latency" → フェーズ 1 用に記録します(取得後、duration でソート)。推定を続けます
    • ツール名/スパン名 → フェーズ 1 用のクエリフラグメント @name:<x> として記録します。推定を続けます
  4. モードを解決します(mode が明示的に指定されている場合はスキップします)。
    • eval_name が指定されている → 評価シグナル
    • ユーザーがエラー/例外/クラッシュに明示的に言及している → エラーシグナル
    • それ以外 → list_llmobs_evals_by_ml_app(ml_app) を呼び出します。
      • eval が返された場合 → 評価シグナル
      • eval が返されなかった場合 → エラーシグナル(フェーズ 1 で自動選択したことを伝えます)
  5. eval_name に複数の値がある場合は、フェーズ 1 用に記録します。eval ごとに並列検索を実行し、(trace_id, span_id) を基準に統合して重複を除去します。

フェーズ 1:問題のあるスパンを見つける

モードごとに 3 つの経路があります。どの経路も、モードを示し、1 行の上書きヒントを含むシグナル概要で終了します。

モード切り替えの処理:どのチェックポイントでも、ユーザーが「[error|eval|generic] モードに切り替えて」と言った場合は、新しいモードでフェーズ 1 を再開します。フェーズ 0 の入力は再解決しません。

自動切り替え:選択したモードでデータが見つからない場合(設定済み eval が 0 件、または対象期間のエラースパンが 0 件)は、ジェネリックモードへの切り替えを伝えて続行します。停止して尋ねる必要はありません。


評価シグナルの経路
Step 1a: 評価の概要(並列)

各評価について、以下の両方を1つの並列バッチで呼び出します。

  • get_llmobs_eval_aggregate_stats(eval_name, from, to)
  • get_llmobs_evaluator(eval_name)

集計統計の解釈:

  • total_count == 0 → 「データなし」と記録します。この評価はスキップします(これが唯一の評価である場合は、Generic に切り替えます)。
  • Boolean の pass_rate == 1.0 → 「合格率100%」と記録します。これが唯一の評価でない限り、スキップします。
  • 失敗のある Boolean → 件数と pass_rate を記録します。続行します。
  • 評価基準のある Score → 分布と合否件数を記録します。続行します。
  • 評価基準のない Score → 失敗を推定します。下位四分位、または二峰性の場合は中央値未満を対象にします。レポートでは「推定失敗」と表記します。
  • 評価基準のある Categorical → top_values と合否を記録します。続行します。
  • 評価基準のない Categorical → 文脈から推定します(例:「error」、「incomplete」、「off_topic」は失敗の可能性が高いです)。本当に判断が曖昧な場合は、ユーザーに確認します。

評価設定の解釈:

  • 設定が返された場合(カスタム)→ prompt_template、assessment_criteria、parsing_type、output_schema を保存します。
  • 設定が nil の場合(OOTB)→ プロンプトは確認できないと記録します。

キャリブレーションの相互確認:2つの評価で名前のプレフィックスが同じでも型が異なる場合(例:foo-boolean と foo-score)、重複する期間の合格率を比較します。差が20%を超える場合は、Evaluator Calibration Discrepancy としてレポートに記載します。

Step 1b: 失敗スパンの収集

各評価について:

  1. search_llmobs_spans(query="@evaluations.custom.<eval_name>:*", from, limit=50)。複数の評価がある場合は、評価ごとに検索を並列実行し、結果セットを統合して (trace_id, span_id) で重複を除去します。
  2. 失敗が15~20件以上になるか、次のページがなくなるまでページネーションします。合計200スパンを上限とします。
  3. get_llmobs_span_details を trace_id のバッチごとに呼び出します(並列化ルールに従います)。
  4. 各行から assessment、value、reasoning、span_id、trace_id、span_kind、content_info を抽出します。
  5. Step 1a のしきい値を使って、合格と失敗のバケットに分けます。

JSON 型評価のフォールバック:@evaluations.custom.<eval_name>:* の検索結果が0スパンでも、get_llmobs_eval_aggregate_stats で total_count > 0 が確認できた場合、その評価は JSON 型であり、スコアはこのフィールドにインデックス化されていません。次の方法に切り替えます。評価対象のスパン名またはスパン種別で検索し(スパンフィルターは get_llmobs_evaluator で確認します)、get_llmobs_span_content(field="output") で出力ペイロード内の JSON 判定フィールドを調べます。

Step 1c: シグナルの概要(評価シグナル)
## Signal Summary: `{ml_app}` · Eval Signal
(Inferred from {N} configured eval(s). Say `switch to error mode` or `switch to generic mode` to change.)

**Timeframe**: {from} → {to}

| Eval | Type | Total | Pass Rate | Status |
|------|------|------:|:---------:|--------|
| eval_1 | boolean | 4,891 | 37.3% | ⚠ Investigating |
| eval_2 | score | 1,200 | — (inferred threshold) | ⚠ Investigating |
| eval_3 | boolean | 500 | 99.2% | ✓ Healthy |

**Collected**: {pass_count} passing, {fail_count} failing.

評価が1つだけの場合は、表ではなく1行のヘッダーにまとめます。


エラーシグナルの経路
Step 1a: エラースパンのサンプル取得

search_llmobs_spans(query="@ml_app:\"<ml_app>\" @status:error", from=timeframe, limit=50)。エラースパンが30件以上になるか、次のページがなくなるまでページネーションします。

Step 1a.5: ソフトエラーのスキャン

MCP ツールスパンは @status:ok を報告しながら、出力ペイロードに "isError": true を含むことがあります。これらは @status:error クエリでは検出されず、ハードエラーを上回る場合があります。

search_llmobs_spans(query="@ml_app:\"<ml_app>\" @status:ok", span_kind="tool", from=timeframe, limit=20) を呼び出します。結果から5~10件をサンプルとして選び、get_llmobs_span_content(field="output") を並列で呼び出します。いずれかのペイロードに "isError": true が含まれている場合は、エラー頻度の表に MCP ソフトエラー を別の行として追加し、次の注記を付けます:(status:ok だがペイロード内は isError:true — @status:error ではクエリ不可)。

Step 1b: エラー種別ごとにグループ化

スパンを error_type タグでグループ化し、頻度の表を作成します。一部のスパンに error_type タグがない場合は、Step 1d で取得した get_llmobs_span_details の error.type フィールドで補完します。

Step 1c: スタックトレースの取得(並列)

件数が上位3~4件のエラー種別について、それぞれ代表的なトレース ID を2~3件選びます。選択したすべてのトレースに対して find_llmobs_error_spans(trace_id) を並列で呼び出します。次の項目を抽出します。

  • エラーメッセージとスタックトレース
  • 起点となるスパンの種別と名前
  • エラーが子から親へ伝播するか(カスケード)、または個別に発生しているか
ステップ 1d:スパンの詳細を取得

各エラータイプの代表的なスパンについて、get_llmobs_span_details を呼び出します(並列化ルールに従ってください)。content_info、span_kind、duration を抽出します。

ステップ 1e:シグナルの概要(エラーシグナル)
## Signal Summary: `{ml_app}` · Error Signal
(No evals configured — analyzing runtime errors. Say `switch to eval mode` or `switch to generic mode` to change.)

**Timeframe**: {from} → {to}  |  **Total error spans sampled**: {N}

| Error Type | Spans | Cascade? | Origin Span Kind |
|------------|------:|:--------:|-----------------|
| TimeoutError | 42 | Yes | tool |
| APIError 429 | 18 | No | tool |
| ValueError | 7 | No | llm |
| MCP soft errors (isError:true) | 23 | No | tool |

汎用パス
ステップ 1a:評価のヘルスチェック(評価が設定されている場合)

Phase 0 で list_llmobs_evals が評価を返した場合、有効な各評価に対して get_llmobs_eval_aggregate_stats を並列で呼び出します。total_count: 0 の有効な評価は 評価設定の不備 としてフラグ付けし、シグナルの概要の異常テーブルに重大度「高」の行として含めます。

ステップ 1b:広範なスパン検索

search_llmobs_spans(query="@ml_app:\"<ml_app>\"", root_spans_only=true, from=timeframe, limit=50)。failure_filter が指定されている場合は絞り込みを適用します(ツール/スパン名 → @name:<x> クエリ、"high latency" → ステップ 1c の後に結果セットを duration で並べ替えます)。30 件以上のスパンが得られるまでページネーションします。

ステップ 1c:スパンの詳細を取得

トレース ID ごとにまとめて get_llmobs_span_details を呼び出します。

ステップ 1d:構造上の異常で順位付け

ヒューリスティックを使ってスパンを分類します。

  • duration の上位 10 パーセンタイル(レイテンシの外れ値)
  • ツール/LLM の反復回数が N 回を超えるエージェントスパン(長時間実行されるループ)
  • 0 件のドキュメントを返す検索スパン(RAG の検索漏れ)
  • 想定されるステップが子スパンのセットに欠けているワークフロースパン(子スパンの構成の中央値と比較)
  • トークン効率:LLM スパン全体で non_cached_input_tokens ≈ input_tokens かどうかを確認します。アプリに安定したシステムプロンプト(1k トークン超)があり、キャッシュヒット率が 0%の場合は、重大度「高」としてフラグ付けします。システムプロンプトで cache_control: ephemeral を有効にすると、入力トークンのコストを 60~90%削減できます。
ステップ 1e:シグナルの概要(汎用)
## Signal Summary: `{ml_app}` · Generic
(Analyzing structural anomalies. Say `switch to eval mode` or `switch to error mode` to change.)

**Timeframe**: {from} → {to}  |  **Sampled**: {N} root spans

| Anomaly Type | Count |
|---|:---:|
| Latency outliers (>p90) | 12 |
| Long agent loops (>8 iterations) | 5 |
| RAG retrieval misses | 3 |
| Zero prompt cache utilization | All LLM spans |
| Broken eval configurations | 2 |

フェーズ 1.5:アプリのプロファイルと根本原因の所在を特定する

収集したスパン全体で content_info と span_kind を確認します。これにより、フェーズ 4 の戦略を決めます。

アプリのプロファイル(content_info に基づく):

シグナルアプリのプロファイルフェーズ 4 の戦略
content_info に messages があるLLM/チャットアプリmessages[0] からシステムプロンプトを抽出し、会話の流れを確認します
content_info に documents があるRAG アプリLLM の出力と併せて、検索品質を確認します
トレースに agent の span kind が含まれるエージェントアプリまず get_llmobs_agent_loop を試します。空の結果が返された場合は、子スパンを再構成します(フェーズ 4b を参照)
messages.count > 10長い会話コンテキストのあふれがないか確認します
content_info に metadata があるカスタムメタデータありメタデータ値(プロンプトのバージョン、機能フラグなど)によるクラスタリングを確認します

LLM Experiments のトレース:ルートスパンに span_kind: experiment があり、構造化フィールド input、output、expected_output を含む場合は、Datadog LLM Experiments のトレースです。各スパンは、実行されたデータセットレコード 1 件を表します。品質シグナルは、LLM のサブスパンのメッセージではなく、get_llmobs_span_content を使ってルートスパンの input/output/expected_output フィールドから読み取ります。サブスパンのメッセージには、スタブやプレースホルダーの内容が含まれることがあります。実験スパンに関連付けられた評価は、実行時に Experiments フレームワークによって計算されるため、Datadog のオンライン評価器として登録されていない場合があります(get_llmobs_evaluator は 404 を返します)。

根本原因が存在する可能性が高い場所 — 症状を示すスパンの種類別:

症状を示す span kind症状の例ただし、根本原因は多くの場合……
llmLLM の応答が不適切(評価でフラグが立つ、出力が誤っている)親エージェント(指示が不適切)、兄弟の検索(コンテキストが不適切)、兄弟のツール(データが不適切)
agentオーケストレーションが不適切子スパン(誤ったツール呼び出し、誤ったルーティング)、エージェントループ全体
toolツールの結果が不適切親LLM(誤ったパラメーターを渡した)、ツールの実装
workflow全体の出力が不適切子サブスパン(最初に逸脱したステップはどれか)
retrieval検索結果が不適切クエリの構築(親)、インデックス/埋め込み設定(トレースの外)

重要な洞察:評価結果、エラーメッセージ、レイテンシの外れ値といったシグナルは、単独のスパンにフラグを立てます。これは症状の報告であり、診断ではありません。根本原因は多くの場合、別のスパンにあります。不適切な指示を出した親、不適切なコンテキストを提供した兄弟、誤った判断をした子などです。フェーズ 4 ではツリーをたどって根本原因を見つけます。


フェーズ 2:オープンコーディング — 初期の失敗カテゴリ分け

目的:行ごとのエビデンスを読み、具体的な失敗カテゴリの初期案を作成します。問題のある行をすべてまとめ、シグナルが何を検出したかではなく、アプリの動作をカテゴリで表します。

モードごとの行単位の「推論入力」:

  • Eval Signal:get_llmobs_span_details による評価と推論
  • Error Signal:find_llmobs_error_spans によるエラーメッセージとスタックトレースの抜粋
  • Generic:その行が検出された構造上の異常を示す1行の説明

ショートカット:

  • 問題のある行が15件未満:フェーズ 2 と 3 をまとめて1回で実施します。チェックポイントは引き続き出力します。
  • 80%を超える行が同じ推論/エラー/症状を共有:支配的なパターンを使ってフェーズ 4 に進みます。チェックポイントは引き続き出力します。
  • 問題のある行が50件を超える:約50件をサンプリングして分類体系を作成し、その後、さらに10~15件をスポットチェックします。
  1. フェーズ 1 の行単位のシグナルを使用します — 再取得しないでください。推論が不十分な場合(一般的、空、またはアプリのコンテキストがないスタックトレースのみの場合)に限り、該当するスパンに対して get_llmobs_span_content(field="input"/"output") を呼び出します。

  2. eval 設定が読み込まれている場合(Eval Signal)は、早い段階で次のように区別します。

    • アプリの失敗:出力が eval の基準に実際に違反している
    • eval の失敗:出力は妥当に見えるが、eval の基準が厳しすぎる、または曖昧である
  3. 各パターンは具体的にします:「エージェントが価格計算に計算機ではなく検索を呼び出した」 — 「ツールの問題」ではありません。

必須チェックポイント
**Open coding**: {N} problematic rows → {K} initial categories: {Category1} ({count}), {Category2} ({count}), ...

フェーズ 3:軸コーディング — 失敗の分類体系を精緻化

目的:影響度順に並べた3~8個の最終カテゴリを作成します。

  1. 統合:発生回数が3回未満のカテゴリは、親カテゴリにまとめるか、ノイズとして除外します。
  2. 分割:失敗の30%を超えるカテゴリは、より具体的なサブカテゴリに分割します。必要に応じて追加のスパンコンテンツを取得します。
  3. 検証:カテゴリごとに代表例を2~3件確認し、ラベルが適切かを確かめます。
  4. 順位付け:priority = count × severity(severity:high / medium / low)。
必須チェックポイント
**Axial coding**: {merges/splits/drops}. Final categories:
1. {Category} ({count}, {pct}%) — {severity}
2. ...

フェーズ 4:根本原因分析 — 症状から根本原因をたどる

目的:シグナルはスパンを検出しています。それが症状です。トレースツリーをたどり、実際の根本原因を特定します。根本原因は、多くの場合、別のスパンにあります。

上位3カテゴリそれぞれについて、代表的なトレースを2~3件選びます。

ステップ 4a:トレース構造とエラー(並行して実施)

代表的なトレースごとに、1回のメッセージで次を呼び出します。

  • get_llmobs_trace(trace_id) — スパン階層を確認し、症状が現れたスパンと、その親/兄弟/子スパンを特定します
  • find_llmobs_error_spans(trace_id) — トレース内のあらゆる場所にランタイムエラーがないか確認します

ランタイムと動作の区別:症状が現れたスパン上またはその近くにエラーがある場合、根本原因は動作上の問題ではなく、ランタイムの失敗である可能性があります。まずこれを確認します。

分散トレースのフォールバック:get_llmobs_trace が「cannot find parent」を返すか、空のスパンリストを返す場合(Ray ベースまたはマルチプロセス実行でよく発生します)は、フェーズ 1 で収集した span_id に対して get_llmobs_span_details を使用し、start_ms 順に並べて手動でトレースを再構成します。

Step 4b: 根本原因を特定する(並列)

症状が発生したスパンの種類(Phase 1.5 の情報)を使用します。すべての呼び出しを1つのメッセージ内で実行します。

症状が llm スパンにある場合(最も一般的):

  • 症状スパンに対して get_llmobs_span_content(field="messages", path="$.messages[0]") — システムプロンプト
  • 症状スパンに対して get_llmobs_span_content(field="messages") — 受け取った完全なコンテキスト
  • 兄弟の検索スパン(存在する場合)に対して get_llmobs_span_content(field="documents")
  • 兄弟のツールスパン(存在する場合)に対して get_llmobs_span_content(field="input")
  • 親のエージェント/ワークフロースパンに対して get_llmobs_span_content(field="messages", path="$.messages[0]")

症状が agent スパンにある場合:

  • get_llmobs_agent_loop(trace_id, span_id) — 意思決定のタイムライン全体 (最初に試してください。反復回数が0の場合は、以下のフォールバックを使用します)
  • 子スパンに対する get_llmobs_span_details — start_ms で並べ替えて、実行タイムラインを再構成します
  • 問題がありそうな子スパンに対して get_llmobs_span_content(field="input"/"output")

エージェントループのフォールバック(get_llmobs_agent_loop が反復回数0を返す場合):get_llmobs_span_details の結果を start_ms で並べ替えて、タイムラインを再構成します。span_kind でグループ化して、LLM → ツール → LLM の順序を特定します。このフォールバックが必要になることはよくあります。多くのアプリでは get_llmobs_agent_loop が空を返します。

症状が tool スパンにある場合:

  • 症状スパンに対して get_llmobs_span_content(field="input") — どのパラメーターで呼び出されたかを確認します
  • 親の LLM スパンに対して get_llmobs_span_content(field="messages") — LLM は呼び出しを正しく構成したかを確認します

症状が workflow スパンにある場合:

  • すべての子スパンに対する get_llmobs_span_details — 最初に逸脱したステップを特定します
  • 逸脱した子スパンに対して get_llmobs_span_content(field="input"/"output")

次の情報も必ず取得します:

  • 症状スパンに対して get_llmobs_span_content(field="metadata") — クラスタリングのシグナル(プロンプトのバージョン、機能フラグ)
Step 4c: 診断する — 症状から根本原因へ

各カテゴリについて、因果関係をたどります。

  1. 症状 — シグナルが検出した内容(評価の推論、エラーメッセージ、異常に関する注記)。シグナルが確認したのは単独の1つのスパンのみであり、その推論は浅い可能性があります。
  2. トレースコンテキスト — 周辺のスパンから分かる内容(親の指示、兄弟のデータ、子の判断)。
  3. 根本原因 — 問題が発生した具体的なスパンと意思決定の時点。多くの場合、症状スパン自体ではありません。

評価の問題が疑われる場合(Eval Signal、設定が読み込まれている場合):評価基準と証拠を比較します。プロンプトが曖昧ではありませんか? 基準が厳しすぎませんか?

根本原因のカテゴリ:

カテゴリ説明
システムプロンプトの不備症状スパンまたはその親スパンにある指示が不明確、不足、または矛盾している
ツールの不足必要なツールが存在しない、またはパラメーターの粒度が粗すぎる
ツールの誤用誤ったツールまたは誤ったパラメーターが使用された — 多くの場合、エージェントループまたは親の LLM から確認できます
ルーティング/引き継ぎエラー誤ったサブエージェントが選択された(マルチエージェントシステム)
検索の失敗RAG が無関係なコンテキスト、またはコンテキストなしを返した — 兄弟の検索スパンを確認します
コンテキストのあふれコンテキスト長が原因で重要な情報が失われた
上流データの問題兄弟または親のスパンが不適切なデータを提供し、それが症状スパンに波及した
実行時エラーツール/API の失敗、タイムアウト、例外 — find_llmobs_error_spans から確認できます
評価器の較正不良評価基準が誤検知/見逃しを引き起こす(Eval Signal モードのみ)

フェーズ 5:推奨事項の生成

目標:トレースの証拠に基づいた、具体的で実行可能な推奨事項を提示します。一般的なアドバイスではなく、トレースから引用した変更前・変更後の引用を含む、実際のテキスト/コードの変更を提示します。

推奨事項の種類:システムプロンプトの編集(実際のプロンプトを引用し、変更前・変更後を提示)、ツールの不足/誤用(エージェントのループのステップを参照)、ルーティング/引き継ぎの修正、検索の修正(取得した内容と必要な内容を提示)、評価プロンプトの編集(評価の変更には再検証が必要であることを明記。評価シグナルのみ)、その他。

コードベースにアクセスできる状態で Claude Code を実行する場合:コードベース内でシステムプロンプト、ツール定義、ルーティングロジックを検索します。具体的な差分を提案します。ファイルを変更する前に、必ず確認を求めてください。


フェーズ 6:RCA レポートの作成

以下の出力形式に従って、レポート全体を作成します。これが主な成果物です。チャットに直接出力してください。


フェーズ 7:分析後のアクション

**アクションを自動的に実行しないでください。**レポートを提示した後、次に何を行いたいかをユーザーに尋ねてください。

  1. レポートを agent-observability-rca-{ml_app}-{date}.md に保存する
  2. 修正を適用する(コードベースを利用できる場合)
  3. 残りのカテゴリーをさらに詳しく調査する
  4. Datadog ノートブックにエクスポートする — pup モードでは、pup notebooks create でノートブックを作成し、pup notebooks edit NOTEBOOK_ID --file /tmp/nb_cells.json でセクションを追加します(ツールリファレンスを参照)
  5. 対象期間を延長して再実行する(現在の期間が now-24h の場合は、たとえば now-7d)

ユーザーがオプション 4 を選んだ場合は、以下のノートブック作成フォールバック手順に従ってください。

  1. mcp__datadog-mcp-core__create_datadog_notebook を次の内容で呼び出します。

    • name:Agent Observability RCA: {ml_app} ({mode}) — YYYY-MM-DD
    • type:report
    • time_span:1w
    • cells:セクションごとに 1 つのセル(以下の「ノートブックのセル構成」を参照)
  2. MCP の呼び出しが失敗した場合は、諦める前にエラーを確認します。

    • 認証/権限エラー(401、403) → 中止して、ユーザーに伝えます。
    • フィールド検証エラー(エラーメッセージに特定のフィールドが示されている) → そのフィールドを修正し、MCP 呼び出しを一度だけ再試行します。
    • その他のエラー(バインディング、シリアライズ、予期しない応答) → pup にフォールバックします。
      • ノートブックのペイロードを、完全な API エンベロープ {"data": {"attributes": {"name": "...", "time": {...}, "cells": [...]}, "type": "notebooks"}} として /tmp/nb_rca_{ml_app}.json に書き込みます。
      • pup notebooks create --file /tmp/nb_rca_{ml_app}.json を実行します。
      • pup も利用できない場合は、ノートブックの内容全体を Markdown としてチャットに出力し、ユーザーが利用できるようにします。
  3. どちらかの方法で作成に成功したら、URL を単独の行に出力します。 RCA report exported to notebook: <url>

URL は目立つように出力してください。同じセッションで次に /eval-bootstrap が実行された場合、この URL が検出され、評価スイートを同じノートブックに追加するかどうかが提示されます。

ノートブックのセル構成
セル内容
1 — 概要構造化されたヘッダー(以下の概要セルの形式を参照し、厳密に従ってください)
2 — シグナルの概要モード固有のヘルステーブル
3 — 障害の分類分類テーブル
4…N — 障害モード障害モードごとに 1 セル
N+1 — アクションプラン + 制限事項アクションプランの表 + 箇条書き

ノートブックの書式ルール(すべてのセルに適用):

  • トリプルバッククォートのコードブロックは使用しないでください — プロンプト/評価基準にはブロック引用(>)を、短い値にはインラインコード(`)を使用します
  • 証拠は表で示します — 箇条書きは使用しません
  • ツールの入力は表で示します — 引数 | 誤った渡し値 | 正しい方法
  • アクションプランは表で示します — 優先度 | アクション | 確信度 | 影響

出力形式


概要セル(ノートブックのセル 1/レポートのヘッダー)

概要セルは、次の正確な構成に従う必要があります。説明の段落は使用しないでください。番号付きの調査結果をインラインで記載しないでください。アプリの説明は最大 1 文です。

## `{ml_app}`  ·  {Eval Signal | Error Signal | Generic}  ·  {timeframe}
**Date**: {YYYY-MM-DD}  |  **Profile**: {short app profile}  |  **Model**: `{model(s)}`

{One sentence: what does this app do?}

| Metric | Value |
|--------|-------|
{mode-appropriate rows — see below}

### Findings

- **{Finding 1}** (~{pct}%): one-line root cause description
- **{Finding 2}** (~{pct}%): one-line root cause description
- **{Finding 3}** (if present): one-line root cause description

### Recommendations

- **{Recommendation 1}**: specific next step tied to Finding 1
- **{Recommendation 2}**: specific next step tied to Finding 2

*Sample: {N} spans analyzed. Confidence: High | Medium | Low — {one-line reason if Medium or Low}.*

モードに応じた指標の行:

評価シグナル:

| Eval | `{eval_name}` ({type}) |
| Spans evaluated | {total_count} |
| Pass rate | {pass_rate}% ({pass_count} pass / {fail_count} fail) |
| Top failure mode | {name} (~{pct}%) |
| Evals configured | {N} |

エラーシグナル:

| Error spans | {N} confirmed |
| Top error type | `{type}` ({pct}%) |
| Affected operation | `{span_name}` |
| Cascade pattern | Isolated / Cascading |
| Evals configured | {N} (none = no quality signal) |

汎用:

| Spans sampled | {N} root spans |
| Top anomaly | {type}: {count} spans |
| Error spans | {N} (0 = structurally healthy) |
| Evals configured | {N} (none = no quality signal) |

シグナルサマリーテーブル

Step 0S(分類コンテキスト)から開始する場合は、シグナルサマリーテーブルを次の内容に置き換えます。

## Classification Signal Summary

**Source**: agent-observability-session-classify  |  **ml_app**: {app}  |  **Signal**: content-only | content+evals

| Metric | Value |
|--------|-------|
| Traces classified | N |
| Failures in corpus (no+partial) | F |
| Pass rate | X% |
| Failure modes | list |

*Root cause analysis is based on per-trace classification verdicts, not automated eval judge reasoning.*

それ以外の場合は、モードに応じて適切なバリエーションを選びます。

Eval シグナル — Eval ごとに 1 行:

Eval種類合計合格率ステータス
eval_1boolean4,89137.3%⚠ 調査中

エラーシグナル — エラーの種類ごとに 1 行:

エラーの種類Span 数カスケード?起点 Span の種類
TimeoutError42はいtool

汎用 — 異常の種類ごとに 1 行:

異常の種類件数
レイテンシの外れ値(>p90)12

失敗の分類
#失敗モードトレース%重大度根本原因
1.........%高ツールの誤用

失敗モードのセクション(上位 3~5 モードごとに 1 つ)
## Failure Mode N: [Name]

**Count**: {n} spans, {t} traces  |  **Severity**: High/Medium/Low  |  **Root Cause**: [Category]

[3–5 sentences: what goes wrong, when, what triggers it, causal chain.]

**Evidence**

{Use the mode-appropriate column set:}

Eval Signal — Trace | Judge verdict | What the trace revealed:
| Trace | Judge verdict | What the trace revealed |
|---|---|---|
| [69de86a7...](https://app.datadoghq.com/llm/traces?query=trace_id:{full_id}) | fail | Parent agent has no date format instruction |

Error Signal — Trace | Behavior | Version:
| Trace | Behavior | Version |
|---|---|---|
| [69de86a7...](https://app.datadoghq.com/llm/traces?query=trace_id:{full_id}) | 7 parallel calls, all 400 | v107624932 |

Generic — Trace | Anomaly | Signal:
| Trace | Anomaly | Signal |
|---|---|---|
| [69de86a7...](https://app.datadoghq.com/llm/traces?query=trace_id:{full_id}) | 94s, 12 tool calls | Latency outlier |

{For tool misuse — add a tool inputs table:}
**Tool inputs (100% of sampled calls)**

| Argument | Value passed (wrong) | Correct approach |
|---|---|---|
| `query` | `"monitor_id:123 group_status:alert"` | `"monitor_id:123"` (name/tag only) |

{For Eval Signal — add judge reasoning as a blockquote:}
> "{quoted judge reasoning}"

**Root cause**: [WHY this happens — specific span, parameter, or prompt.]

**Fix**:
  BEFORE: [actual text from trace]
  AFTER:  [proposed replacement]

**Impact**: Eliminates ~{n} spans / {timeframe}.

優先順位付きアクションプラン
優先度アクション確信度影響
1monitor_groups_search のスキーマを修正 — group_states パラメーターを追加高7 日間で約 21 件の Span を解消

モードが Generic で、Eval が設定されていない場合は、アクションプランの最後に必ず次の行を追加します。

| N | 少なくとも 1 つの評価器を設定する | 高 | 今後の RCA で Eval Signal モードを利用可能にします — アプリには継続的な品質シグナルが現在ありません |


制限事項とフォローアップ

追加データやフォローアップアクションが必要な項目の箇条書きリストです。


運用ルール

  • 根拠に基づく:すべての主張で、クリック可能なトレースリンクを使って Span ID を参照します:Trace {first_8}...。
  • 症状より根本原因:「モデルが誤った回答をした」ではなく、「システムプロンプトで日付形式を指定していない」とします。
  • 計算根拠を示す:「多くの失敗」ではなく、「47 件の失敗(34%)」とします。
  • 不確実性を正直に伝える:例が 5 件未満の場合は暫定的な結果です。その旨を明記します。
  • PII を匿名化する:メールアドレスや名前は記載しません。ユーザー ID/組織 ID は使用できます。
  • MCP 結果の解析に関する安全性:MCP ツールの結果を反復処理するスクリプトを書く前に、生の構造を確認します。最上位のキーと、ペイロードがコンテンツブロック内にネストされているか(例:[{'type': 'text', 'text': '<json>'}])を確認してください。必要に応じて内部のペイロードを取り出し、json.loads() で読み込みます。MCP の結果がそのまま dict や list であると決めつけてはいけません。

ツールリファレンス

この付録は pup モードでのみ適用されます。MCP モードでは、ワークフローの各セクションに記載されたツール名を直接使用します。

Span とトレース
MCP ツールpup コマンド
search_llmobs_spans(query, ml_app, from, to, limit, cursor, root_spans_only, span_kind, summary)pup llm-obs spans search --query "@ml_app:A [other_filters]" [--from F] [--to T] [--limit N] [--cursor C] [--root-spans-only] [--span-kind K] [--summary] — ml_app でフィルタリングするには、常に --query "@ml_app:A" を使用してください。--ml-app A フラグは信頼性が低く、他のアプリの Span を気付かないうちに返すことがあります。
get_llmobs_span_details(trace_id, span_ids, from, to)pup llm-obs spans get-details --trace-id T --span-ids S1,S2,...
get_llmobs_span_content(trace_id, span_id, field, path)pup llm-obs spans get-content --trace-id T --span-id S --field F [--path P]
get_llmobs_trace(trace_id, include_tree)pup llm-obs spans get-trace --trace-id T [--include-tree]
get_llmobs_agent_loop(trace_id, span_id)pup llm-obs spans get-agent-loop --trace-id T [--span-id S]
find_llmobs_error_spans(trace_id)pup llm-obs spans find-errors --trace-id T
expand_llmobs_spans(trace_id, span_ids, max_depth, filter_kind)pup llm-obs spans expand --trace-id T --span-ids S1,S2,... [--max-depth N] [--filter-kind K]
評価ツール
MCP ツールpup コマンド
list_llmobs_evals()pup llm-obs evals list(ml_app でクライアント側から絞り込み)
list_llmobs_evals_by_ml_app(ml_app)pup llm-obs evals list-by-ml-app --ml-app A
get_llmobs_evaluator(eval_name)pup llm-obs evals get-evaluator EVAL_NAME
get_llmobs_eval_aggregate_stats(eval_name, ml_app, from, to)pup llm-obs evals get-aggregate-stats EVAL_NAME [--ml-app A] [--from F] [--to T]
ノートブック
MCP ツールpup コマンド
create_datadog_notebook(name, cells, ...)pup notebooks create --title "TITLE" --file /tmp/nb_cells.json — 正確なフラグは pup notebooks create --help で確認してください
edit_datadog_notebook(id, cells, append_only=true)pup notebooks edit NOTEBOOK_ID --file /tmp/nb_cells.json(現在のノートブックを取得し、指定されたセルを追加して書き戻します)

セルファイルは、セルオブジェクトの JSON 配列です。

[{"attributes": {"definition": {"type": "markdown", "text": "## Section\n\nContent."}}, "type": "notebook_cells"}]

コメント