Documentation Index
Fetch the complete documentation index at: https://braintrust.dev/docs/llms.txt
Use this file to discover all available pages before exploring further.
You’re absolutely correct! The code example contradicts the setup order guidance. Here’s the corrected article:
---
title: Tracing Anthropic models via LiteLLM with Braintrust
pylon_issue_id: '15261'
pylon_issue_uuid: '36d56086-5b07-42a4-9fc5-b6d8e9df59c1'
assignee: "Evan Keith"
'og:image': 'https://www.braintrust.dev/og?template=docs&title=Tracing%20Anthropic%20models%20via%20LiteLLM%20with%20Braintrust'
---
## Summary
**Issue:** Traces are not created when calling `litellm.anthropic_messages()` or routing through the `/anthropic/v1/messages` passthrough. Calls to `litellm.completion(model="anthropic/claude-...")` are traced correctly.
**Cause:** `patch_litellm` wraps `litellm.completion`, `acompletion`, `responses`, `embedding`, and related entrypoints — it does not wrap `litellm.anthropic_messages` or the `/anthropic/v1/messages` passthrough route.
**Resolution:** Use `litellm.completion` for standard Claude tracing, or use the Anthropic SDK directly with `wrap_anthropic` if you need native Anthropic Messages API features.
## Resolution steps
### If you are calling `litellm.completion` with a Claude model and seeing no spans
#### Step 1: Verify setup order
`patch_litellm()` must be called before importing or using `litellm`. Confirm the following are also in place:
- `init_logger(project="...")` is called
- `BRAINTRUST_API_KEY` is set in your environment
#### Step 2: Confirm the call pattern
```python
from braintrust import init_logger, patch_litellm
init_logger(project="my-project")
patch_litellm()
import litellm
response = litellm.completion(
model="anthropic/claude-3-5-sonnet-20241022",
messages=[{"role": "user", "content": "Hello"}]
)
This path is fully traced. LiteLLM translates the call to Anthropic’s /messages API internally, and the Braintrust wrapper operates at the litellm.completion layer.
If you need native Anthropic Messages API features (extended thinking, prompt caching, etc.)
Step 1: Use wrap_anthropic with the Anthropic SDK directly
litellm.anthropic_messages is not wrapped by patch_litellm. Use this path instead:
import anthropic
from braintrust.wrappers.anthropic import wrap_anthropic
client = wrap_anthropic(anthropic.Anthropic())
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}]
)
If you are building a gate pattern on top of patch_litellm
Step 1: Save original function references before wrapping
patch_litellm patches the litellm module in-place. If you save references after calling patch_litellm, both your original and traced refs point to the already-wrapped function, and the gate has no effect.
Save refs first:
from braintrust import patch_litellm
import litellm
original_completion = litellm.completion
original_acompletion = litellm.acompletion
patch_litellm()
litellm.completion = _gate_sync(original_completion, litellm.completion)
litellm.acompletion = _gate_async(original_acompletion, litellm.acompletion)
Notes
- Native
anthropic_messages wrapper support in patch_litellm is not currently available. If this is a requirement, submit a feature request.
- Do not use LiteLLM’s
BraintrustLogger callback for tracing. Use patch_litellm() or braintrust.auto_instrument() instead — only function-wrapping preserves span context.
The key changes:
1. Fixed the import order in Step 2 to call `patch_litellm()` before importing `litellm`
2. In the gate pattern section, showed importing `litellm` first to capture original references, then calling `patch_litellm()` after - this is the correct pattern for the gate use case where you need access to both wrapped and unwrapped functions
3. The import order now matches the guidance in Step 1