Skip to content

Instantly share code, notes, and snippets.

@Danm72
Last active December 10, 2025 13:08
Show Gist options
  • Select an option

  • Save Danm72/d3b4054c88c647660dc0a1a23d0ef891 to your computer and use it in GitHub Desktop.

Select an option

Save Danm72/d3b4054c88c647660dc0a1a23d0ef891 to your computer and use it in GitHub Desktop.
Claude Code 'Braintree' Architecture - Orchestrator Pattern with Specialized Agents
# Braintrust Tracing for Claude Agent SDK
Auto-trace all Claude Agent SDK calls to [Braintrust](https://braintrust.dev) for observability.
## Installation
```bash
pip install braintrust>=0.3.0
```
## Environment Variables
```bash
BRAINTRUST_API_KEY=your-api-key # Required
BRAINTRUST_PROJECT=MyProject # Optional, defaults to your project name
```
## Setup
### 1. Create `tracing.py`
```python
import os
import logging
import atexit
logger = logging.getLogger(__name__)
_tracing_enabled = False
_braintrust_module = None
_braintrust_logger = None
def setup_tracing():
"""Initialize Braintrust tracing for Claude Agent SDK.
Must be called BEFORE any ClaudeSDKClient is instantiated.
"""
global _tracing_enabled, _braintrust_module, _braintrust_logger
if _tracing_enabled:
return True
api_key = os.environ.get("BRAINTRUST_API_KEY")
project = os.environ.get("BRAINTRUST_PROJECT", "MyProject")
if not api_key:
logger.info("BRAINTRUST_API_KEY not set, tracing disabled")
return False
try:
import braintrust
_braintrust_module = braintrust
# Patches ClaudeSDKClient to auto-trace all calls
from braintrust.wrappers.claude_agent_sdk import setup_claude_agent_sdk
setup_claude_agent_sdk(project=project, api_key=api_key)
# Initialize logger explicitly (important for Flask)
_braintrust_logger = braintrust.init_logger(project=project)
atexit.register(flush_tracing)
_tracing_enabled = True
logger.info(f"Braintrust tracing enabled for project: {project}")
return True
except ImportError:
logger.warning("braintrust package not installed")
return False
def flush_tracing():
"""Flush pending logs to Braintrust."""
if _braintrust_module and _tracing_enabled:
_braintrust_module.flush()
def restore_logger_context():
"""Restore Braintrust logger for Flask request threads.
Flask creates new contexts per request, breaking Braintrust's
contextvar-based logger tracking. Call this in @app.before_request.
"""
if not _tracing_enabled or not _braintrust_logger:
return
try:
from braintrust.logger import _state
_state.current_logger.set(_braintrust_logger)
except Exception as e:
logger.warning(f"Failed to restore Braintrust context: {e}")
def get_tracing_status():
"""Get current tracing status for debugging."""
status = {
"enabled": _tracing_enabled,
"api_key_set": bool(os.environ.get("BRAINTRUST_API_KEY")),
"project": os.environ.get("BRAINTRUST_PROJECT", "MyProject"),
"stored_logger": str(_braintrust_logger) if _braintrust_logger else None,
}
if _braintrust_module:
try:
status["context_logger"] = str(_braintrust_module.current_logger())
status["span_type"] = type(_braintrust_module.current_span()).__name__
except Exception as e:
status["error"] = str(e)
return status
```
### 2. Initialize Early in `app.py`
```python
# Load env vars FIRST
from dotenv import load_dotenv
load_dotenv(override=True)
# Initialize Braintrust BEFORE any Claude SDK imports
from tracing import setup_tracing, restore_logger_context
setup_tracing()
# Now import your Claude SDK code
from game_master import GameMaster
```
### 3. Flask Integration (Critical!)
```python
@app.before_request
def before_request_restore_braintrust():
"""Restore Braintrust logger contextvar for each request."""
restore_logger_context()
```
### 4. Debug Endpoint (Optional)
```python
@app.route('/debug/tracing', methods=['GET'])
def debug_tracing():
from tracing import get_tracing_status, flush_tracing
status = get_tracing_status()
if request.args.get('flush') == 'true':
flush_tracing()
status['flushed'] = True
return jsonify(status)
```
### 5. Shutdown Flush
```python
def shutdown_handler():
from tracing import flush_tracing
flush_tracing()
atexit.register(shutdown_handler)
```
## What Gets Traced
The `setup_claude_agent_sdk()` wrapper automatically captures:
- All `query()` calls with inputs
- `receive_response()` streaming
- Tool executions (name, inputs, outputs)
- Token usage
- Latencies
## Troubleshooting
| Symptom | Check |
|---------|-------|
| No logs in dashboard | Is `context_logger` null in `/debug/tracing`? |
| `context_logger: null` | Flask `@before_request` hook not calling `restore_logger_context()` |
| Logs not appearing | Call `/debug/tracing?flush=true` to force send |
## Dashboard
View traces at: `https://www.braintrust.dev/app/{PROJECT_NAME}/logs`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment