Skip to content

[bot] Anthropic: messages.count_tokens() not instrumented #554

Description

@braintrust-bot

Summary

client.messages.count_tokens() (and its async counterpart await client.messages.count_tokens()) makes a real API call to POST /v1/messages/count_tokens but produces zero Braintrust spans. This method was added to the anthropic Python SDK in v0.84.0 (2026-02-25). The current version pinned as latest in this repo is anthropic==0.116.0.

Braintrust docs status: not_found — The Anthropic integration docs mention Anthropic as a supported provider but do not document count_tokens instrumentation.

Root cause

The AnthropicIntegration wraps Anthropic.__init__ and AsyncAnthropic.__init__ to return proxy objects (TracedAnthropic / TracedAsyncAnthropic). The messages property on these proxies returns a Messages (or AsyncMessages) wrapper class that only defines create(), stream(), and a batches property.

Messages extends Wrapper, whose __getattr__ delegates unknown attribute access to the underlying (unwrapped) self.__messages object. So when a caller invokes client.messages.count_tokens(...), Python finds no count_tokens method on the proxy class and silently falls through to the real, uninstrumented anthropic.resources.messages.Messages.count_tokens. No span is created.

The same applies to AsyncMessages.

What needs to be instrumented

Method SDK class Already traced?
client.messages.count_tokens(model, messages, ...) Messages No
await client.messages.count_tokens(model, messages, ...) AsyncMessages No

The response is a MessageTokensCount object with an input_tokens field. A useful span would record:

  • input: messages, system, tools, tool_choice
  • output: input_tokens count
  • metadata: model, provider: "anthropic"
  • metrics: wall-clock latency

Upstream sources

Local repo files inspected

  • py/src/braintrust/integrations/anthropic/tracing.pyMessages class defines create() and stream() only; no count_tokens; __getattr__ from Wrapper delegates all other attribute access to the unwrapped object
  • py/src/braintrust/integrations/anthropic/_utils.pyWrapper.__getattr__ confirmed as the delegation mechanism
  • py/src/braintrust/integrations/anthropic/patchers.py — only patches Anthropic.__init__ and AsyncAnthropic.__init__
  • py/src/braintrust/integrations/anthropic/integration.pymin_version = "0.48.0", latest pin resolves to anthropic==0.116.0 (from py/pyproject.toml line 327)
  • Full repo grep for count_tokens across py/src/braintrust/ — zero matches

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions