mcpField
B
braintrust-tracing

braintrust-tracing

github.com/parcadeiエージェントワークフロー3.9k497 回インストール39 週間前に更新
リポジトリ

braintrust-tracing について

braintrust-tracing は、Braintrust で Claude Code のセッションを追跡するためのガイドとフック設定です。セッション、ターン、ツール、LLM のスパンを記録し、独立したサブエージェントのトレースを事後に関連付ける方法も説明します。

主な機能

  1. 01セッションとターンのスパンを記録
  2. 02ツールと LLM のスパンを取得
  3. 03セッションごとの追跡状態を保存
  4. 04トレース分析コマンドを提供
  5. 05サブエージェントの事後関連付けを説明

活用シーン

  1. 01Claude Code セッションの活動確認
  2. 02フックログによるスパン欠落の調査
  3. 03親とサブエージェントのトレースを使ったデータセット構築

MCP 対応

このプロジェクトは、Claude Code のセッショントレースを Braintrust に送るフックを説明するもので、MCP サーバーではありません。README に MCP 連携の説明はありません。

インストール

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

$npx skills add https://github.com/parcadei/continuous-claude-v3 --skill braintrust-tracing

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

詳細

Claude Code の Braintrust トレーシング

サブエージェントの相関付けを含む、Braintrust で Claude Code のセッションをトレースするための包括的なガイドです。

アーキテクチャの概要

                         PARENT SESSION
                    +---------------------+
                    |  SessionStart       |
                    |  (creates root)     |
                    +----------+----------+
                               |
                    +----------v----------+
                    |  UserPromptSubmit   |
                    |  (creates Turn)     |
                    +----------+----------+
                               |
          +--------------------+--------------------+
          |                    |                    |
+---------v--------+  +--------v--------+  +--------v--------+
| PostToolUse      |  | PostToolUse     |  | PreToolUse      |
| (Read span)      |  | (Edit span)     |  | (Task - inject) |
+------------------+  +-----------------+  +--------+--------+
                                                    |
                                         +----------v----------+
                                         |   SUB-AGENT         |
                                         |   SessionStart      |
                                         |   (NEW root_span_id)|
                                         +----------+----------+
                                                    |
                                         +----------v----------+
                                         |   SubagentStop      |
                                         |   (has session_id)  |
                                         +---------------------+

フックイベントのフロー

フックトリガー作成するもの主なフィールド
SessionStartセッション開始時ルートスパンsession_id、root_span_id
UserPromptSubmitユーザーがプロンプトを送信ターンスパンprompt、turn_number
PreToolUseツールの実行前(Task プロンプトを変更)tool_input.prompt
PostToolUseツールの実行後ツールスパンtool_name、input、output
Stopターン完了時LLM スパンmodel、tokens、tool_calls
SubagentStopサブエージェント終了時(スパンなし)サブエージェントの session_id
SessionEndセッション終了時(ルートを確定)turn_count、tool_count

トレース階層

Session (task span) - root_span_id = session_id
|
+-- Turn 1 (task span)
|   |
|   +-- claude-sonnet (llm span) - model call with tool_use
|   +-- Read (tool span)
|   +-- Edit (tool span)
|   +-- claude-sonnet (llm span) - response after tools
|
+-- Turn 2 (task span)
|   |
|   +-- claude-sonnet (llm span)
|   +-- Task (tool span) -----> [Sub-agent session - SEPARATE trace]
|   +-- claude-sonnet (llm span)
|
+-- Turn 3 ...

サブエージェントのトレース:できること、できないこと

できないこと

SessionStart は Task プロンプトを受け取りません。

PreToolUse を通じて Task プロンプトにトレースコンテキストを挿入してみました。

# PreToolUse hook injects:
[BRAINTRUST_TRACE_CONTEXT]
{"root_span_id": "abc", "parent_span_id": "xyz", "project_id": "123"}
[/BRAINTRUST_TRACE_CONTEXT]

しかし、SessionStart が受け取るのはセッションのメタデータのみで、変更後のプロンプトは受け取りません。挿入したコンテキストは失われます。

できること

親セッションの Task スパンにはすべての情報が含まれます。

  • agentId - サブエージェントの実行を識別する ID
  • totalTokens、totalToolUseCount - メトリクス
  • content - エージェントの応答/要約全体
  • tool_input.prompt - 元のタスクプロンプト
  • tool_input.subagent_type - エージェントの種類(例:「oracle」)

SubagentStop フックはサブエージェントの session_id を受け取ります。

  • これはサブエージェントの孤立したトレースの root_span_id と一致します
  • 親の Task スパンと子のトレースを相関付けられます
相関付けのパターン

**現在の状態:**サブエージェントは孤立したトレース(新しい root_span_id)を作成します。

相関付けの方法:

  1. 親セッションの Task スパンをクエリして、エージェントのメタデータを取得します
  2. agentId またはタイミングを使って、孤立したトレースと照合します
  3. サブエージェントの session_id は、そのトレースの root_span_id と同じです

今後の解決策(未実装):

SubagentStop fires -> writes session_id to temp file
PostToolUse (Task) -> reads temp file -> adds child_session_id to Task span metadata

これにより、Task.agentId + Task.child_session_id を孤立したトレースの root_span_id にリンクできます。

状態管理

セッションごとの状態ファイル
~/.claude/state/braintrust_sessions/
  {session_id}.json       # Per-session state

各セッションファイルには次の情報が含まれます。

{
  "root_span_id": "abc-123",
  "project_id": "proj-456",
  "turn_count": 5,
  "tool_count": 23,
  "current_turn_span_id": "turn-789",
  "current_turn_start": 1703456789,
  "started": "2025-12-24T10:00:00.000Z",
  "is_subagent": false
}
グローバル状態
~/.claude/state/braintrust_global.json   # Cached project_id
~/.claude/state/braintrust_hook.log      # Debug log

デバッグ用コマンド

トレーシングが有効か確認する
# View hook logs in real-time
tail -f ~/.claude/state/braintrust_hook.log

# Check if session has state
cat ~/.claude/state/braintrust_sessions/*.json | jq -s '.'

# Verify environment
echo "TRACE_TO_BRAINTRUST=$TRACE_TO_BRAINTRUST"
echo "BRAINTRUST_API_KEY=${BRAINTRUST_API_KEY:+set}"
Braintrust に直接クエリする
# List recent sessions
uv run python -m runtime.harness scripts/braintrust_analyze.py --sessions 5

# Analyze last session
uv run python -m runtime.harness scripts/braintrust_analyze.py --last-session

# Replay specific session
uv run python -m runtime.harness scripts/braintrust_analyze.py --replay <session-id>

# Find sub-agent traces (orphaned roots)
uv run python -m runtime.harness scripts/braintrust_analyze.py --agent-stats
フックの実行をデバッグする
# Enable verbose logging
export BRAINTRUST_CC_DEBUG=true

# Test hooks manually
echo '{"session_id":"test-123","type":"resume"}' | \
  bash "$CLAUDE_PROJECT_DIR/.claude/plugins/braintrust-tracing/hooks/session_start.sh"

# Test PreToolUse (Task injection)
echo '{"session_id":"test-123","tool_name":"Task","tool_input":{"prompt":"test"}}' | \
  bash "$CLAUDE_PROJECT_DIR/.claude/plugins/braintrust-tracing/hooks/pre_tool_use.sh"
トラブルシューティングのチェックリスト
  1. トレースが表示されない場合:

    • .claude/settings.local.json の TRACE_TO_BRAINTRUST=true を確認します
    • API キーを確認します:echo $BRAINTRUST_API_KEY
    • ログを確認します:tail -20 ~/.claude/state/braintrust_hook.log
  2. サブエージェントがリンクされない場合:

    • これは想定どおりです。サブエージェントは孤立したトレースを作成します
    • --agent-stats を使ってエージェントのアクティビティを確認します
    • 親の Task スパン内のタイミングまたは agentId を使って相関付けます
  3. スパンが見つからない場合:

    • セッション状態の current_turn_span_id を確認します
    • Stop フックが実行されること(ターンの確定)を確認します
    • ログに「Failed to create」エラーがないか確認します
  4. 状態が破損している場合:

    • セッション状態を削除します:rm ~/.claude/state/braintrust_sessions/*.json
    • グローバルキャッシュをクリアします:rm ~/.claude/state/braintrust_global.json

主要なファイル

ファイル目的
.claude/plugins/braintrust-tracing/hooks/common.sh共通ユーティリティ、API、状態管理
.claude/plugins/braintrust-tracing/hooks/session_start.shルートスパンを作成し、サブエージェントのコンテキストを処理
.claude/plugins/braintrust-tracing/hooks/user_prompt_submit.shユーザーメッセージごとに Turn スパンを作成
.claude/plugins/braintrust-tracing/hooks/pre_tool_use.shTask プロンプトにトレースコンテキストを挿入
.claude/plugins/braintrust-tracing/hooks/post_tool_use.shツールスパンを作成し、エージェント/スキルのメタデータを取得
.claude/plugins/braintrust-tracing/hooks/stop_hook.shLLM スパンを作成し、Turn を終了
.claude/plugins/braintrust-tracing/hooks/session_end.shセッションを終了し、学習内容の抽出を開始
scripts/braintrust_analyze.pyトレースされたセッションをクエリして分析
~/.claude/state/braintrust_sessions/セッションごとの状態ファイル
~/.claude/state/braintrust_hook.logデバッグログ

環境変数

変数必須デフォルト説明
TRACE_TO_BRAINTRUSTはい-"true" に設定すると有効になります
BRAINTRUST_API_KEYはい-Braintrust の API キー
BRAINTRUST_CC_PROJECTいいえclaude-codeプロジェクト名
BRAINTRUST_CC_DEBUGいいえfalse詳細ログ
BRAINTRUST_API_URLいいえhttps://api.braintrust.devAPI エンドポイント

セッションから得た知見

サブエージェントのトレースについて分かったこと(2025年12月)

試みたこと: PreToolUse を介して Task プロンプトにトレースコンテキストを挿入しました。

結果: 失敗しました。SessionStart が受け取るのはセッションのメタデータのみで、プロンプトは受け取りません。

判明したこと: Task スパンには、すでにサブエージェントに関する豊富なデータが含まれています。

  • metadata.agent_type - subagent_type によるエージェントの種類
  • metadata.skill_name - Skill ツールによるスキル
  • tool_input - エージェントに送信された完全なプロンプト
  • tool_output - エージェントの応答

現在の相関付けの手順:

  1. 親セッションの Task スパンには agentId とタイミング情報がある
  2. サブエージェントは root_span_id = session_id の孤立したトレースを作成する
  3. SubagentStop からサブエージェントの session_id を取得する
  4. 手動で相関付ける:タイミングを照合するか、session_id のリンクを使用する

今後の作業: SubagentStop の後、PostToolUse から Task スパンのメタデータに child_session_id を書き込みます。

サブエージェントの相関付けについて分かったこと

問題
  • Task ツールで起動したサブエージェントは、孤立した Braintrust トレースを作成する
  • 親セッションには agentId を含む Task スパンがあり、サブエージェントには別の session_id がある
  • 両者を結び付ける組み込みの仕組みがない
機能しない方法

1. PreToolUse によるプロンプトへの挿入

SessionStart フックが受け取るのはセッションのメタデータ(session_id、type、cwd)のみで、プロンプトは受け取りません。挿入されたトレースコンテキストは参照されません。

フックが受け取る内容:

{
  "session_id": "...",
  "type": "start|resume|compact|clear",
  "cwd": "...",
  "env": {...}
}

プロンプトのフィールドが存在しないため、SessionStart ではコンテキストを挿入できません。

2. SubagentStop → PostToolUse のファイル受け渡し

競合状態が発生します。これらはタイミングが保証されない独立した非同期フックです。

  • サブエージェントのセッション終了時に SubagentStop が実行される
  • Task ツールの完了時に PostToolUse(Task)が実行される
  • 両者の実行順序は保証されない
  • 相関付け用のファイルに書き込むと競合が発生する

3. PreToolUse による相関付けファイル

SessionStart には、どの Task がサブエージェントを起動したかを示すコンテキストがないため、task_span_id にアクセスできません。PreToolUse はプロンプトを変更しますが、SessionStart が確実に参照できる状態ファイルは作成しません。

機能すること

データセット構築のための事後マッチング:

親セッションの Task スパンには、次の情報が含まれます。

  • agentId - サブエージェントの実行を識別する ID
  • totalTokens、totalToolUseCount - 集計されたメトリクス
  • content - エージェントの応答/要約全体
  • tool_input.prompt - 元のタスクプロンプト
  • tool_input.subagent_type - エージェントの種類(例:「oracle」)
  • 開始/終了タイムスタンプ

サブエージェントのセッションには、次の情報が含まれます。

  • session_id(孤立したトレースの root_span_id と同じ)
  • 開始/終了タイムスタンプ
  • すべての内部スパンとツール呼び出し

相関付けの方法:

  1. 親セッションのトレースをエクスポートします(親の root_span_id をクエリします)
  2. サブエージェントのトレースをエクスポートします(親の時間枠内に作成されたすべてのセッションをクエリします)
  3. 次の情報で照合します。
    • タイミング:Task スパンの終了時刻 ≈ サブエージェントセッションの終了時刻
    • メタデータ:Task プロンプトの subagent_type
    • ID:SubagentStop フックから session_id を取得できます(取得してログに記録できます)
アーキテクチャに関する考察

SessionStart の入力は意図的に最小限に抑えられており、プロンプトやツールのコンテキストは含まれません。

interface SessionStartInput {
  session_id: string;
  type: "start" | "resume" | "compact" | "clear";
  cwd: string;
  env: { [key: string]: string };
  // NO: prompt, tool_context, task_span_id, parent_span_id
}

この設計上の境界により、フックの実行時にリアルタイムで相関付けすることはできません。

推奨事項

サブエージェントとの相関付けを含むエージェント実行データセットを構築するには、次の手順を実施します。

  1. セッション内でのログ記録: SubagentStop の session_id をログまたは状態に記録します
  2. セッション後のエクスポート: Braintrust API をクエリして、親とサブエージェントのトレースを取得します
  3. オフラインでの相関付け: スクリプトでタイミングとメタデータを基にトレースを照合します
  4. リアルタイムのリンクを試みない: フックには必要なコンテキストがありません

スクリプトの例:

# 1. Export parent session
braintrust_analyze.py --replay <parent-session-id> > parent_traces.json

# 2. Query for orphaned sub-agent traces (those created during parent's time window)
braintrust_analyze.py --agent-stats > all_agent_traces.json

# 3. Correlate in Python:
#    - Parent Task spans -> agentId, timestamps, subagent_type
#    - Orphaned traces -> root_span_id, timestamps
#    - Match by timing and type

この方法は信頼性が高く、テスト可能であり、フックに暗黙の状態を維持させる必要もありません。

コメント