Skip to main content

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.

Applies to:
  • Plan -
  • Deployment -
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