Last active
December 10, 2025 13:08
-
-
Save Danm72/d3b4054c88c647660dc0a1a23d0ef891 to your computer and use it in GitHub Desktop.
Claude Code 'Braintree' Architecture - Orchestrator Pattern with Specialized Agents
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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