braintrust-tracing skill
Braintrust tracing for Claude Code - hook architecture, sub-agent correlation, debugging
Is the braintrust-tracing skill safe?
Clean: nothing in its files matched our rules. We read 1 file in the folder on 2026-09-28.
No findings.
Install the braintrust-tracing skill
A skill is a folder. Copy it into your agent's skills folder and the agent loads it when the task matches its description.
git clone --depth 1 https://github.com/parcadei/Continuous-Claude-v3.git /tmp/Continuous-Claude-v3 mkdir -p ~/.claude/skills cp -r /tmp/Continuous-Claude-v3/.claude/skills/braintrust-tracing ~/.claude/skills/braintrust-tracing
In the Claude apps, zip the folder and upload it from the Skills settings. The folder on GitHub
The instructions your agent would load
SKILL.md as published, without the frontmatter. Read it on GitHub
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)|
+----------+----------+
Hook Event Flow
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 run
- totalTokens, totalToolUseCount - metrics
- content - full agent response/summary
- tool_input.prompt - original task prompt
- toolinput.subagenttype - agent type (e.g., "oracle")
SubagentStop hook receives the sub-agent's sessionid:**
- This equals the sub-agent's orphaned trace rootspanid
- Allows correlation between parent Task span and child trace
The Correlation Pattern
Current state: Sub-agents create orphaned traces (new rootspanid).
Correlation method:
- Query parent session's Task spans for agent metadata
- Match agentId or timing with orphaned traces
- Sub-agent's sessionid = its trace's rootspan_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.childsessionid -> orphaned trace rootspanid
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 TRACETOBRAINTRUST=true in .claude/settings.local.json
- Verify API key: echo $BRAINTRUSTAPIKEY
- Check logs: tail -20 ~/.claude/state/braintrust_hook.log
- Sub-agents not linking:
- This is expected - sub-agents create orphaned traces
- Use --agent-stats to find agent activity
- Correlate via timing or agentId in parent Task span
- Missing spans:
- Check currentturnspan_id in session state
- Ensure Stop hook runs (turn finalization)
- Look for "Failed to create" errors in log
- State corruption:
- Remove session state: rm ~/.claude/state/braintrustsessions/.json
- Clear global cache: rm ~/.claude/state/braintrust_global.json
Key Files
Environment Variables
Session Learnings
What We Learned About Sub-Agent Tracing (Dec 2025)
Attempted: Inject trace context via PreToolUse into Task prompts.
Result: Failed - SessionStart only receives session metadata, not the prompt.
Discovery: Task spans already contain rich sub-agent data:
- metadata.agenttype - agent type from subagenttype
- metadata.skill_name - skill from Skill tool
- tool_input - full prompt sent to agent
- tool_output - agent response
Current correlation path:
- Parent session Task span has agentId and timing
- Sub-agent creates orphaned trace with rootspanid = session_id
- SubagentStop provides the sub-agent's session_id
- Manual correlation: match timing or use session_id link
Future work: Write childsessionid to Task span metadata from PostToolUse after SubagentStop.
What We Learned About Sub-Agent Correlation
More skills from parcadei/Continuous-Claude-v3
- Aagent-context-isolationAgent Context Isolation
- Aagent-orchestrationAgent Orchestration Rules
- Aagentic-workflowAgentic Workflow Pattern
- Aagentica-claude-proxyGuide for integrating Agentica SDK with Claude Code CLI proxy
- Aagentica-infrastructureReference guide for Agentica multi-agent infrastructure APIs
- Aagentica-promptsWrite reliable prompts for Agentica/REPL agents that avoid LLM instruction ambiguity
- Aagentica-sdkBuild Python agents with Agentica SDK - @agentic decorator, spawn(), persistence, MCP integration
- Aagentica-serverAgentica server + Claude proxy setup - architecture, startup sequence, debugging
- Aagentica-spawnSpawn Agentica multi-agent patterns
- Aanalytic-functionsProblem-solving strategies for analytic functions in complex analysis
- Aast-grep-findAST-based code search and refactoring via ast-grep MCP
- Aasync-repl-protocolAsync REPL Protocol