Braintrust Tracing
Braintrust tracing for Claude Code - hook architecture, sub-agent correlation, debugging
- Skill ID
- parcadei/continuous-claude-v3/braintrust-tracing
- Publisher
- parcadei
- Repository
- continuous-claude-v3
- Installs
- 0
- Files
- 1
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
parcadei/continuous-claude-v3/braintrust-tracingInstalls these files- SKILL.md
What this skill tells the agent
Braintrust Tracing for Claude Code
Comprehensive guide to tracing Claude Code sessions in Braintrust, including sub-agent correlation.
Architecture Overview
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) |
+---------------------+Hook Event Flow
| Hook | Trigger | Creates | Key Fields |
|---|---|---|---|
| SessionStart | Session begins | Root span | session_id, root_span_id |
| UserPromptSubmit | User sends prompt | Turn span | prompt, turn_number |
| PreToolUse | Before tool runs | (modifies Task prompts) | tool_input.prompt |
| PostToolUse | After tool runs | Tool span | tool_name, input, output |
| Stop | Turn completes | LLM spans | model, tokens, tool_calls |
| SubagentStop | Sub-agent finishes | (no span) | session_id of sub-agent |
| SessionEnd | Session ends | (finalizes root) | turn_count, tool_count |
Trace Hierarchy
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 ...Sub-Agent Tracing: What Works and What Doesn't
What Doesn't Work
SessionStart doesn't receive the Task prompt.
We tried injecting trace context into Task prompts via PreToolUse:
# PreToolUse hook injects:
[BRAINTRUST_TRACE_CONTEXT]
{"root_span_id": "abc", "parent_span_id": "xyz", "project_id": "123"}
[/BRAINTRUST_TRACE_CONTEXT]But SessionStart only receives session metadata, not the modified prompt. The injected context is lost.
What DOES Work
Task spans in parent session contain everything:
agentId- identifier for the sub-agent runtotalTokens,totalToolUseCount- metricscontent- full agent response/summarytool_input.prompt- original task prompttool_input.subagent_type- agent type (e.g., "oracle")
SubagentStop hook receives the sub-agent's `session_id`:
- This equals the sub-agent's orphaned trace
root_span_id - Allows correlation between parent Task span and child trace
The Correlation Pattern
Current state: Sub-agents create orphaned traces (new root_span_id).
Correlation method:
- Query parent session's Task spans for agent metadata
- Match
agentIdor timing with orphaned traces - Sub-agent's
session_id= its trace'sroot_span_id
Future solution (not yet implemented):
SubagentStop fires -> writes session_id to temp file
PostToolUse (Task) -> reads temp file -> adds child_session_id to Task span metadataThis would link: Task.agentId + Task.child_session_id -> orphaned trace root_span_id
State Management
Per-Session State Files
~/.claude/state/braintrust_sessions/
{session_id}.json # Per-session stateEach session file contains:
{
"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
}Global State
~/.claude/state/braintrust_global.json # Cached project_id
~/.claude/state/braintrust_hook.log # Debug logDebugging Commands
Check if Tracing is Active
# 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}"Query Braintrust Directly
# 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-statsDebug Hook Execution
# 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"Troubleshooting Checklist
- No traces appearing:
- Check
TRACE_TO_BRAINTRUST=truein.claude/settings.local.json - Verify API key:
echo $BRAINTRUST_API_KEY - Check logs:
tail -20 ~/.claude/state/braintrust_hook.log
- Sub-agents not linking:
- This is expected - sub-agents create orphaned traces
- Use
--agent-statsto find agent activity - Correlate via timing or
agentIdin parent Task span
- Missing spans:
- Check
current_turn_span_idin session state - Ensure Stop hook runs (turn finalization)
- Look for "Failed to create" errors in log
- State corruption:
- Remove session state:
rm ~/.claude/state/braintrust_sessions/*.json - Clear global cache:
rm ~/.claude/state/braintrust_global.json
Key Files
| File | Purpose |
|---|---|
.claude/plugins/braintrust-tracing/hooks/common.sh | Shared utilities, API, state management |
.claude/plugins/braintrust-tracing/hooks/session_start.sh | Creates root span, handles sub-agent context |
.claude/plugins/braintrust-tracing/hooks/user_prompt_submit.sh | Creates Turn spans per user message |
.claude/plugins/braintrust-tracing/hooks/pre_tool_use.sh | Injects trace context into Task prompts |
.claude/plugins/braintrust-tracing/hooks/post_tool_use.sh | Creates tool spans, captures agent/skill metadata |
.claude/plugins/braintrust-tracing/hooks/stop_hook.sh | Creates LLM spans, finalizes Turns |
.claude/plugins/braintrust-tracing/hooks/session_end.sh | Finalizes session, triggers learning extraction |
scripts/braintrust_analyze.py | Query and analyze traced sessions |
~/.claude/state/braintrust_sessions/ | Per-session state files |
~/.claude/state/braintrust_hook.log | Debug log |
More from parcadei
Use this skill in a project
Open any RiverX project, search the Skills panel for parcadei/continuous-claude-v3/braintrust-tracing, and install it in one click.
