Skip to content

Anthropic integration: missing usage metrics and span metadata (speed, compaction iterations, fallback_credit, compaction/context_management params, stop_details) #791

Description

Surfaced while reviewing the weekly dependency bump (#783), which moved anthropic 1.5.0 → 1.7.0. Everything below is verified against the installed 1.7.0 unless marked otherwise. Nothing here is a regression from the bump — these are gaps the bump made visible, plus a few pre-existing ones in the same code paths.

All six are small, independent changes in py/src/braintrust/integrations/anthropic/.

Cost & accounting correctness

These change numbers Braintrust reports, so they're the ones that actually matter.

1. usage.speed is dropped — fast-mode calls are mis-costed

_ANTHROPIC_USAGE_METADATA_FIELDS (_utils.py:31) is {"service_tier", "inference_geo"}. speed is present on BetaUsage but not in the set, so it never reaches span metadata.

Fast mode on Opus 5 bills $10/$50 per MTok vs $5/$25 standard. A fast-mode span currently looks like it cost half what it did.

Fix: add "speed" to the frozenset.

2. usage.iterations (compaction per-iteration tokens) is never read

BetaUsage.iterations is a list of BetaCompactionIterationUsage, each carrying its own input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens. extract_anthropic_usage (_utils.py:56) never touches it.

⚠️ Needs verification first. I could not determine whether the top-level usage totals already roll these up — the type stubs carry no field descriptions. One recorded compaction call settles it. If they don't roll up, we under-report cost on exactly the long-running workloads people enable compaction for.

This one should be its own PR, gated on that check.

3. usage.fallback_credit is never read

Also on BetaUsage, also unhandled. Relevant to refusal fallbacks: when a fallback model rescues a declined request, billing and cache pricing shift. Same shape of fix as #1.

Span metadata completeness

4. compaction request param not captured

METADATA_PARAMS (tracing.py:62) is an allowlist of request params tracked as span metadata. compaction — added in anthropic 1.6.0 — isn't in it, so a span gives no indication compaction was configured for the call.

5. context_management request param not captured

Same allowlist. This is the context-editing config (clear_tool_uses_20250919, clear_thinking_20251015). It changes what the model actually saw, which makes it meaningful trace context.

6. stop_details not captured

_message_output (tracing.py:1505) records stop_reason and stop_sequence but not the adjacent stop_details, which the API populates when stop_reason == "refusal" with a category ("cyber", "bio", …) and explanation.

That's the difference between a trace showing that a call was refused and one showing why. Guard the read — stop_details is null for every non-refusal stop reason.

Not in scope here

Output-side handling is already correct and needs no change: _message_output passes message.content through wholesale rather than filtering by block type, so BetaCompactionBlock already lands in span output.

Two further items were considered and deliberately left out, as product/scoping calls rather than defects:

  • tool_runner loop structure. Each turn is already traced (the runner calls beta.messages.parse, and we rewrite client.beta in place at tracing.py:1599). What's missing is a parent span grouping the agentic run and child spans for client-side tool executions — our tool spans cover Anthropic's server tools only.
  • anthropic-beta header formatting change in 1.7.0 (values now comma-joined with no spaces). No action needed; playback is green.

Testing

Per CLAUDE.md, each of these should get cassette-backed coverage in test_anthropic.py rather than a mock, since they depend on the real response shape. Session:

cd py && nox -s "test_anthropic(latest)"

Suggested split: #1, #3, #4, #5, #6 are all small allowlist additions and could land as one PR. #2 needs the rollup question answered first.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions