exploring-llm-traces について
PostHog の LLM や AI エージェントのトレースを調査するためのスキルです。イベントツリー、入出力、エラー、所要時間を確認し、省略・秘匿されたデータに注意しながら概要から詳細へ調べます。
主な機能
- 01LLM トレースの検索と一覧表示
- 02個別トレースのイベントツリー確認
- 03イベントスキーマと値の検出
- 04概要を確認してから詳細を取得
- 05SQL とスクリプトによるトレース分析
活用シーン
- 01URL からトレースやセッションを調査
- 02ツールの入力・出力・エラー確認
- 03LLM に渡されたコンテキストの調査
- 04検出したイベントプロパティによる検索
MCP 対応
PostHog MCP のトレース、スキーマ、SQL ツールで LLM の活動を検索・確認します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ posthog/ skills --skill exploring-llm-tracesインストール後、Claude Code で/exploring-llm-tracesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/events-and-properties.mdexample-llm-trace.mdexample-llm-traces-list.mdscripts/extract_conversation.pyextract_span.pyprint_summary.pyprint_timeline.pysearch_traces.pyshow_structure.py詳細
MCP ツールを使った LLM トレースの調査
PostHog は、LLM/AI エージェントのアクティビティをトレースとして記録します。各トレースは、トップレベルのエージェント呼び出しから個々の LLM API 呼び出しまで、単一の AI インタラクションを表すイベントのツリーです。
利用可能なツール
| ツール | 目的 |
|---|---|
posthog:query-llm-traces-list | トレースを検索して一覧表示します。複数トレースの大きなペイロードを返す場合があります |
posthog:query-llm-trace | ID を指定して、完全なイベントツリーを含む単一のトレースを取得します |
posthog:read-data-schema | フィルタリングの前に、カスタムイベント/人物プロパティを確認します |
posthog:execute-sql | 複雑なトレース分析に使用するアドホック SQL |
イベント階層
完全なスキーマについては、イベントリファレンスを参照してください。
$ai_trace (top-level container)
└── $ai_span (logical groupings, e.g. "RAG retrieval", "tool execution")
├── $ai_generation (individual LLM API call)
└── $ai_embedding (embedding creation)
イベントは $ai_parent_id → 親の $ai_span_id または $ai_trace_id を介してリンクされています。
ワークフロー:URL からトレースまたはセッションをデバッグする
ステップ 1 — URL を分類する
まずパスを確認します。UUID のように見える値をすべてトレース ID として扱わないでください。
/ai-observability/traces/<trace_id>または従来の/llm-analytics/traces/<trace_id>//llm-observability/traces/<trace_id>は単一のトレースです。posthog:query-llm-traceで取得します。/ai-observability/sessions/<session_id>または従来の/llm-analytics/sessions/<session_id>は AI セッションであり、トレースではありません。イベントプロパティ$ai_session_idでフィルタリングして、posthog:query-llm-traces-listでトレースを取得します。
URL に date_from / date_to クエリパラメーターが含まれている場合は、その値を保持します。
どちらもなく、URL に timestamp クエリパラメーターがある場合は、そのタイムスタンプを基準にして、その前後の絶対時間範囲(たとえば timestamp - 36h から timestamp + 36h)を指定してクエリを実行します。
これにより、UI のタイムスタンプが保存されたイベントのタイムスタンプとずれている可能性がある正確なセッションリンクにも対応しながら、クエリ範囲を制限できます。
URL に明示的な日付も timestamp もない場合は、{"date_from": "-7d"} のような安全なデフォルトを使用します。
正確なトレース URL とセッション URL では、以下で使われる標準の $ai_* フィールドについて、スキーマの確認を省略します。これらは AI オブザーバビリティの組み込みフィールドであり、プロジェクト固有のカスタムプロパティではありません。
ステップ 2 — トレースの概要を確認する
トレースを確認する際は、明示的に detail: "summary" を設定します。
これにより、イベントのメタデータが返され、会話の内容は除外されるため、プロンプトや出力でコンテキストを消費せずに確認できます。
detail を省略した場合も、既存の呼び出し元との互換性のために、詳細全体が返されます。
トレース URL の場合は、次のように posthog:query-llm-trace を呼び出します。
{
"traceId": "<trace_id>",
"detail": "summary",
"dateRange": { "date_from": "-7d" }
}
セッション URL の場合は、次のように posthog:query-llm-traces-list を呼び出します。
{
"detail": "summary",
"dateRange": { "date_from": "<timestamp_minus_36h>", "date_to": "<timestamp_plus_36h>" },
"filterTestAccounts": false,
"limit": 20,
"properties": [{ "type": "event", "key": "$ai_session_id", "value": ["<session_id>"], "operator": "exact" }]
}
セッションのクエリには、URL に date_from / date_to の値があれば使用します。
URL に timestamp しかない場合は、-1h のような相対範囲を使うのではなく、そのタイムスタンプから絶対日付範囲を計算します。
正確な URL では filterTestAccounts: false を設定し、アカウントフィルターによって要求されたトレースが非表示にならないようにします。
結果には、トレースとイベントのメタデータのみが含まれます。
プロンプト、出力、スパンの状態、$ai_error、$ai_feedback_text は除外され、それらの名前はプロパティバッグの横にある _summaryOmittedKeys に一覧表示されます。
_detail: { "mode": "summary" } を含むトレースには、会話の内容は一切含まれません。
内容を読むには、detail: "full" を指定します。
結果からは、次の情報を取得できます。
- 種類(
$ai_span、$ai_generationなど)を含むすべてのイベント - スパン名(
$ai_span_name)— ツール/ステップ名です - レイテンシー、エラーフラグ、使用されたモデル
$ai_parent_idによる親子関係_posthogUrl— ユーザーが UI を開けるように、必ず回答に含めてください
ステップ 3 — 調査に必要なコンテンツを読む
トレースを選択したら、ツールの引数を詳しく調べる、モデルが受け取ったコンテキストを確認する、または会話の内容を検索する前に、detail: "full" を指定して posthog:query-llm-trace をリクエストします。
{
"traceId": "<trace_id>",
"detail": "full",
"dateRange": { "date_from": "-7d" }
}
例の期間をコピーするのではなく、元の URL または検索クエリの日付範囲を維持します。 関連するプロパティフィルターを維持して、読み取るデータを絞り込みます。ユーザーがすでにトレースを特定しており、正確な内容が必要な場合は、最初から詳細全体をリクエストできます。
どちらのモードにも、レスポンスサイズの上限が適用されます。
結論を出す前に、省略および切り詰めを示すマーカーを確認します。
ドロップされたイベント、_summaryOmittedKeys または _redactedKeys に記載された名前、あるいはサマリーにないキーワードは、トレースにそれが存在しなかった証拠にはなりません。
詳細全体を取得しても切り詰められている場合は、関連するイベントにクエリを絞り込むか、完全なデータを確認するために _posthogUrl を開きます。
どちらの詳細モードでも、以下の非公開プロパティで説明する、AI ペイロード以外のプロパティは返されません。
ステップ 4 — スクリプトで詳細全体の大きな結果を解析する
結果がファイルに保存されている場合($ai_input/$ai_output_choices 全体を含む大きなトレースなど)、解析スクリプトを使って内容を調べます。
まずサマリーを確認して全体像を把握し、その後、詳細を掘り下げます。
# 1. Overview: metadata, tool calls, final output, errors
python3 scripts/print_summary.py /path/to/persisted-file.json
# 2. Timeline: chronological event list with truncated I/O
python3 scripts/print_timeline.py /path/to/persisted-file.json
# 3. Drill into a specific span's full input/output
SPAN="tool_name" python3 scripts/extract_span.py /path/to/persisted-file.json
# 4. Full conversation with thinking blocks and tool calls
python3 scripts/extract_conversation.py /path/to/persisted-file.json
# 5. Search for a keyword across the returned properties
SEARCH="keyword" python3 scripts/search_traces.py /path/to/persisted-file.json
すべてのスクリプトで、切り詰めを制御する MAX_LEN=N env var を使用できます(0 = 無制限)。
非公開プロパティ
2 つのトレースツールが返すのは AI ペイロードのみです。
PostHog の分類で定義された $ai_* プロパティに加え、$ai_generation_id、$ai_cache_read_cost_usd、$ai_cache_creation_cost_usd、$ai_effort、$session_id、$lib、$lib_version のみが返されます。
それ以外のイベントプロパティと、すべての人物プロパティは、どちらの詳細モードでも非公開となり、各プロパティバッグの横にある _redactedKeys に名前が記載されます。
$ai_base_url と $ai_request_url は、クエリ文字列を除いて返されます。
これには、project_id や conversation_id など、プロジェクト独自のカスタムプロパティも含まれます。
非公開プロパティは PostHog 上では変更されません。
このプロパティを使った絞り込みは引き続き可能で、その値は PostHog の UI または execute-sql で確認できます。
_redactedKeys に名前がある場合、そのプロパティはイベントに存在し、値のみが非公開であることを意味します。
search_traces.py では、非公開プロパティにのみ含まれるキーワードは見つかりません。
調査のパターン
「エージェントはツールを正しく使いましたか?」
- ツール呼び出しの
$ai_spanを見つけます($ai_span_nameを確認します) $ai_input_stateを確認します。ツールにはどのような引数が渡されましたか?$ai_output_stateを確認します。ツールは何を返しましたか?$ai_is_errorを確認します。ツール呼び出しは失敗しましたか?
「コンテキストは正しかったですか?」/「適切なファイルが表示されましたか?」
- LLM が判断を下した
$ai_generationイベントを見つけます $ai_inputを確認します。これは LLM が見たメッセージ履歴全体です- それより前の
$ai_spanイベントで、検索/取得の手順を確認します - それらの
$ai_output_stateを確認します。どのような内容が取得され、LLM に渡されましたか?
「サブエージェントは動作しましたか?」
- 構造の概要で、別のスパンの子であるスパン(
$ai_parent_idを使用)を見つけます - 親スパンはオーケストレーター、子スパンはサブエージェントの各手順です
- 各子スパンの
$ai_output_stateと$ai_is_errorを確認します - 子スパンに
$ai_generationイベントが含まれている場合、それらはサブエージェントによる LLM 呼び出しです
「LLM はなぜ X と言いましたか?」
search_traces.pyを使って、そのテキストが現れる場所を見つけます。SEARCH="the text" python3 scripts/search_traces.py FILE- テキストを含むイベントとプロパティパスが表示されます
- その生成処理の
$ai_inputを確認し、LLM が X と言う前に何を伝えられていたかを確認します
UI リンクの構築
トレースツールは _posthogUrl を返します。必ずユーザーに提示してください。
リンクは手動で構築することもできます。
- トレース詳細:
https://app.posthog.com/ai-observability/traces/<trace_id>?timestamp=<url_encoded_timestamp>&event=<optional_event_id> - フィルター付きトレース一覧:
query-llm-traces-listの_posthogUrlに返されます
timestamp クエリパラメーターは必須です。トレース内の最も早いイベントの createdAt を URL エンコードして使用してください(例:timestamp=2026-04-01T19%3A39%3A20Z)。
調査結果を提示する際は、ユーザーが確認できるよう、必ず関連する PostHog URL を含めてください。
トレースの検索
posthog:query-llm-traces-list を detail: "summary" で使用して、トレースを検索およびフィルタリングします。
重要:トレーニングデータを根拠に、イベント名、プロパティ名、プロパティ値を決して推測しないでください。
プロジェクトごとに異なるカスタムプロパティが計測されています。自由形式の検索やカスタムフィルターでは、フィルターを作成する前に
posthog:read-data-schema を呼び出し、プロジェクトのデータに実際に存在するプロパティと値を確認してください。
例外は、AI オブザーバビリティのトレース/セッション URL が正確に指定されている場合です。組み込みの $ai_trace_id/$ai_session_id
フィールドを直接使用し、スキーマの確認は省略してください。
まずスキーマを確認する
トレースをフィルタリングする前に、利用可能なデータを確認してください。
- AI イベントが存在することを確認する —
kind: "events"を指定してposthog:read-data-schemaを呼び出し、$ai_*イベントを探します - フィルター可能なプロパティを確認する —
kind: "event_properties"とevent_name: "$ai_generation"(または別の AI イベント)を指定してposthog:read-data-schemaを呼び出し、記録されているプロパティを確認します - 実際の値を取得する —
kind: "event_property_values"、event_name: "$ai_generation"、property_name: "$ai_model"を指定してposthog:read-data-schemaを呼び出し、実際に使われているモデル名を確認します
その後で、プロパティフィルターを指定して query-llm-traces-list を呼び出します。
これは、project_id、conversation_id、user_tier などのカスタムプロパティでは特に重要です。これらはプロジェクトごとに異なるため、推測できません。
値がレスポンスで非表示になっていても、カスタムプロパティはフィルターとして使用できます。
$ai_* プロパティは確認する必要はありませんが、人物の email など、それ以外のプロパティは確認してください。
フィルターによる検索
posthog:query-llm-traces-list
{
"detail": "summary",
"dateRange": {"date_from": "-1h"},
"filterTestAccounts": true,
"limit": 20,
"properties": [
{"type": "event", "key": "$ai_model", "value": "gpt-4o", "operator": "exact"}
]
}
複数のフィルターは AND 条件で結合されます。
posthog:query-llm-traces-list
{
"detail": "summary",
"dateRange": {"date_from": "-1h"},
"filterTestAccounts": true,
"properties": [
{"type": "event", "key": "$ai_provider", "value": "anthropic", "operator": "exact"},
{"type": "event", "key": "$ai_is_error", "value": ["true"], "operator": "exact"}
]
}
人物プロパティでフィルタリングすることもできます(kind: "entity_properties" と entity: "person" を指定して read-data-schema で確認してください)。
posthog:query-llm-traces-list
{
"detail": "summary",
"dateRange": {"date_from": "-1h"},
"filterTestAccounts": true,
"properties": [
{"type": "person", "key": "email", "value": "@company.com", "operator": "icontains"}
]
}
外部識別子による検索
顧客は独自の ID をイベントまたは人物のプロパティとして保存していることがよくあります。
posthog:read-data-schema を使って存在するカスタムプロパティを確認し、その後でフィルタリングします。
kind: "event_properties"とevent_name: "$ai_trace"を指定してposthog:read-data-schemaを呼び出し、カスタムプロパティを確認します- 返されたプロパティとサンプル値を確認します
- 確認したプロパティキーと既知の値を使ってフィルターを作成します
posthog:query-llm-traces-list
{
"detail": "summary",
"dateRange": {"date_from": "-7d"},
"properties": [
{"type": "event", "key": "project_id", "value": "proj_abc123", "operator": "exact"}
]
}
より複雑な SQL パターンについては、次のリファレンスを参照してください。
- 単一トレースの取得 — すべてのイベントとプロパティを含む単一トレースを ID で取得します(
TraceQueryHogQL をレンダリングします) - 集計メトリクス付きトレース一覧 — 2 段階のクエリです。最初にトレース ID を検索し、次にレイテンシー、トークン数、コスト、エラー数を集計して取得します
大きなトレース結果の解析
トレースツールの結果は JSON です。インラインで読むには大きすぎる場合、Claude Code はその結果をファイルに保存します。 コンテンツの抽出やキーワード検索には、詳細をすべて含むレスポンスを使用してください。 スクリプトでは、概要から省略されたコンテンツ、プロパティバッグから非表示になったコンテンツ、または切り捨てによって削除されたコンテンツを復元できません。
保存されたファイルの形式
[{ "type": "text", "text": "{\"results\": [...], \"_posthogUrl\": \"...\"}" }]
トレース JSON の構造
results (array for list, object for single trace)
├── id, traceName, createdAt, totalLatency, totalCost
├── inputState, outputState (trace-level state)
└── events[]
├── event ($ai_span | $ai_generation | $ai_embedding | $ai_metric | $ai_feedback)
├── id, createdAt
└── properties
├── $ai_span_name, $ai_latency, $ai_is_error
├── $ai_input_state, $ai_output_state (span tool I/O)
├── $ai_input, $ai_output_choices (generation messages)
├── $ai_model, $ai_provider
└── $ai_input_tokens, $ai_output_tokens, $ai_total_cost_usd
利用可能なスクリプト
| スクリプト | 用途 | 使用方法 |
|---|---|---|
print_summary.py | リスト/セッションの合計、トレースのメタデータ、ツール呼び出し、エラー、LLM の最終出力を集計します | python3 scripts/print_summary.py FILE |
print_timeline.py | I/O の概要を含む、イベントの時系列を表示します | python3 scripts/print_timeline.py FILE |
extract_span.py | 名前を指定して、特定のスパンの入力/出力全体を抽出します | SPAN="name" python3 scripts/extract_span.py FILE |
extract_conversation.py | 思考ブロックとツール呼び出しを含む LLM メッセージを表示します | python3 scripts/extract_conversation.py FILE |
search_traces.py | すべてのイベントプロパティからキーワードを検索します | SEARCH="keyword" python3 scripts/search_traces.py FILE |
show_structure.py | 値を表示せずに JSON のキーと型を表示します | cat blob.json | python3 scripts/show_structure.py |
ヒント
- 常に
dateRangeを設定してください。時間範囲のないクエリは遅くなります。広範な一覧クエリには狭い範囲(-30m、-1h)を使用し、トレース ID や特定のプロパティ値で絞り込む狭いクエリには、広い範囲(-7d、-30d)を使用できます - ユーザーがリンク先にアクセスできるよう、回答には必ず
_posthogUrlを含めてください - スパンの
$ai_input_state/$ai_output_stateには、ツール呼び出しの入力と出力が含まれます - 生成の
$ai_input/$ai_output_choicesには、LLM との会話全体が含まれます。数メガバイトになることがあります。結果がファイルに保存されている場合は、解析スクリプトを使用してください - 生の SQL では、サイズの大きいコンテンツ(
$ai_input/$ai_output/$ai_output_choices/$ai_input_state/$ai_output_state/$ai_tools)はevents.propertiesではなく、posthog.ai_eventsテーブルにのみ存在します。列の対応関係とトレース ID を基点としたクエリパターンについては、イベントリファレンスを参照してください - 検索時に内部/テストのトラフィックを除外するには、
filterTestAccounts: trueを使用してください $ai_traceイベントはevents配列には含まれません。そのデータは、トレースレベルのinputState、outputState、traceNameを通じて提供されます