Anthropic

Full coverage of sync, async, streaming, and errors, with prompt-cache token accounting. Includes the one streaming shape that is not recorded.

Fully covered, and verified against the live API on every release.

pip install anthropic capsera
import anthropic
import capsera

capsera.init(api_key=os.environ["CAPSERA_API_KEY"])
client = anthropic.Anthropic()

init() patches Messages and AsyncMessages on the class, so a client constructed before or after is recorded either way.

Coverage

CallRecorded
client.messages.create(...)Yes
await async_client.messages.create(...)Yes
with client.messages.stream(...)Yes
async with async_client.messages.stream(...)Yes
provider errors on any of the aboveYes

Streaming

Use the context manager. Token counts only exist once the stream finishes, and the proxy reads them on context exit:

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Explain agent cost attribution."}],
) as stream:
    for chunk in stream.text_stream:
        print(chunk, end="")

Async uses async with and async for.

Iterating the stream without the context manager is not recorded:

# Not recorded
for event in client.messages.stream(model=..., messages=[...]):
    ...

This is a known gap, tracked as a failing test in the SDK.

Prompt caching

Anthropic bills cached tokens at three rates, and all three are recorded separately: input_tokens, cache_write_tokens (typically 1.25x input), and cache_read_tokens (typically 0.1x input). Cost sums all of them, so a cached workload reports the saving.

client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": LONG_PREAMBLE,
            "cache_control": {"type": "ephemeral"},
        }
    ],
    messages=[{"role": "user", "content": question}],
)

Capsera's cache-hit-rate reporting is computed from these fields. See Prompt analysis.

Errors

A provider error is recorded as a zero-cost event carrying the exception type, such as RateLimitError, BadRequestError, or APIConnectionError, and is then re-raised unchanged. Your except clauses behave as they did before instrumentation.

The message is not recorded, because Anthropic errors often quote the prompt.

Claude through Bedrock or Vertex

Claude on AWS Bedrock or Google Vertex uses a different client and is documented separately. See Bedrock and Mistral, Cohere and Vertex AI.

Pricing differs by platform, and the catalog keys them separately. anthropic.claude-3-5-sonnet-20241022-v2:0 on Bedrock is a different entry from claude-3-5-sonnet-20241022 direct.

Models

The catalog covers the current Claude line across Opus, Sonnet, and Haiku, and prefix matching means dated snapshots such as claude-sonnet-4-6-20260101 inherit the price of claude-sonnet-4-6.