Skip to main content
The SDK wraps an Anthropic or AsyncAnthropic client in place and instruments the messages surface:
  • client.messages.create(...), non-streaming and stream=True
  • client.messages.stream(...), the context-manager helper
  • the async equivalents on AsyncAnthropic
Anthropic is the provider with the richest cache reporting, so it is the one where the cache-specific metrics matter most.

Install

Wrap and call

Streaming

Both streaming styles are instrumented. Usage is captured from the final message_delta event, which is where Anthropic reports the completed token counts.

Async

Wrap AsyncAnthropic the same way. The SDK detects the async client and instruments create and stream with async wrappers.
Python

Per-call override

The wrapper strips extra_lago / lago before forwarding, so Anthropic’s strict request validation never sees it.

What gets captured

Reasoning tokens are not exposed. Anthropic folds extended-thinking tokens into output_tokens. Billing on llm_output_tokens already captures thinking. llm_reasoning_tokens stays at zero and no event is emitted for it.
Anthropic’s cache tokens are additive, not a subset. input_tokens counts only the tokens that were not served from cache or written to it. Your true prompt total is llm_input_tokens + llm_cached_input_tokens + llm_cache_creation_tokens.A real cached response makes this unmistakable: input_tokens: 13 alongside cache_read_input_tokens: 2803. Billing llm_input_tokens alone would charge that call for 13 tokens instead of 2,816.This is the opposite of OpenAI, Gemini and Mistral, where the cached tokens are already inside the prompt count. See Bill in tokens for a setup that keeps the two rules apart.
Cache writes are the interesting part. Anthropic prices cache creation above normal input and cache reads well below it, and the SDK gives you all three counts separately. That lets you mirror Anthropic’s own rate structure directly: charge llm_cache_creation_tokens at a premium, llm_cached_input_tokens at a discount, and llm_input_tokens at the standard rate — each on its own count, no subtraction needed.The 5-minute and 1-hour TTL splits are reported separately because Anthropic prices them differently.
Unrecognized usage fields (service_tier, inference_geo, server_tool_use) land in CanonicalUsage.extras so provider drift is visible instead of silently dropped.

Pricing

In price mode, native Anthropic clients are priced from OpenRouter’s public model list, per token, refreshed hourly on the background thread.
Claude models accessed through Bedrock are priced from AWS’s bulk price list instead, which currently omits the newest Claude models. If you need dollar-cost billing for Claude and you are on Bedrock, see the Bedrock page.

What is and isn’t instrumented

wrap() patches exactly two methods — messages.create and messages.stream — on both the sync Anthropic and async AsyncAnthropic clients. Everything else on the client passes through unmetered, and each of these is billable:
messages.parse is the easy one to miss. It looks like a create variant and returns the same usage, but it is not instrumented — a workload built on structured outputs would bill nothing.
If you use any of these, build a CanonicalUsage yourself and pass it to sdk.emit().

Next steps

Configuration reference

Every config knob, in both SDKs.

Charges with filters

Price cache reads and cache writes at different rates.