SOLWYN
Providers

Anthropic

Use Solwyn with Anthropic — sync and async examples, cache normalization, model support

import os
from anthropic import Anthropic
from solwyn import Solwyn

client = Solwyn(
    Anthropic(),
    api_key=os.environ["SOLWYN_API_KEY"],
)

response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Explain how a CPU works in two sentences."}],
)

print(response.content[0].text)
client.close()

Sync usage

Pass an anthropic.Anthropic client to Solwyn(). Calls use client.messages.create(), exactly like the standard Anthropic SDK:

import os
from anthropic import Anthropic
from solwyn import Solwyn

with Solwyn(
    Anthropic(),
    api_key=os.environ["SOLWYN_API_KEY"],
) as client:
    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        messages=[
            {"role": "user", "content": "Explain how a CPU works in two sentences."},
        ],
        system="You are a helpful assistant.",
    )
    print(response.content[0].text)

Async usage

Pass an anthropic.AsyncAnthropic client to AsyncSolwyn():

import asyncio
import os
from anthropic import AsyncAnthropic
from solwyn import AsyncSolwyn

async def main():
    async with AsyncSolwyn(
        AsyncAnthropic(),
        api_key=os.environ["SOLWYN_API_KEY"],
    ) as client:
        response = await client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=1024,
            messages=[
                {"role": "user", "content": "Explain how a CPU works in two sentences."},
            ],
            system="You are a helpful assistant.",
        )
        print(response.content[0].text)

asyncio.run(main())

Supported models

The SDK recognizes Anthropic models by the claude-* prefix:

PrefixExamples
claude-*claude-sonnet-4-5, claude-opus-4-5, claude-haiku-4-5

Anthropic is priced for text only — chat through messages.create and, since 0.9.0, beta.messages.create. A media surface requested from a wrapped Anthropic client (embeddings, for instance) fails loud with UnsupportedSurfaceError rather than running untracked. See the provider × modality matrix.

Beta Messages

SDK v0.9.0+. client.beta.messages.create(...) is metered the same way as messages.create — budget-checked and settled on sync and async clients, streaming or not, including the Bedrock, Vertex, and Foundry platform clients. Beta features such as server-side compaction are therefore budget-checked and settled.

response = client.beta.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
  • Beta request fields (betas, context_management, compaction, ...) pass through untouched and are never recorded.
  • A beta call fails over only to other Anthropic entries in your fallback= chain, never to a different provider: beta-only fields have no equivalent elsewhere. Cross-provider entries are skipped for these calls.
  • The other beta Messages helpers — beta.messages.stream, .parse, .tool_runner, .count_tokens, beta.messages.thread, batches, and the raw/streaming response mirrors — stay unmetered and follow your on_unmetered posture, like their non-beta counterparts.
  • Upgrading from 0.8.0: remove beta.messages.create from acknowledge_untracked. A stale token for a now-metered leaf raises ConfigurationError.

Cache normalization

Anthropic reports prompt cache tokens as separate additive fields -- the base input_tokens does not include cache tokens. Solwyn normalizes these into a single input_tokens total:

normalized input_tokens = base input_tokens
                        + cache_read_input_tokens
                        + cache_creation_input_tokens
Normalized fieldAnthropic API source
input_tokensusage.input_tokens + usage.cache_read_input_tokens + usage.cache_creation_input_tokens
output_tokensusage.output_tokens
cached_input_tokensusage.cache_read_input_tokens
cache_creation_5m_tokensusage.cache_creation.ephemeral_5m_input_tokens
cache_creation_1h_tokensusage.cache_creation.ephemeral_1h_input_tokens

Cache-creation TTL split

Anthropic prices cache writes differently by time-to-live: the 5-minute TTL is billed at 1.25× the base input rate, the 1-hour TTL at 2×. Solwyn captures the two separately so the Cloud API can price each correctly:

  • cache_creation_5m_tokens — written with 5-minute TTL (1.25× rate)
  • cache_creation_1h_tokens — written with 1-hour TTL (2× rate)

Older or non-beta responses expose only an aggregate usage.cache_creation_input_tokens without the per-TTL cache_creation sub-object. When only the aggregate is present, Solwyn attributes it to cache_creation_5m_tokens. All cache fields may be absent on older API responses and default to 0.

Server-side compaction

SDK v0.9.0+. Anthropic reports server-side compaction usage only in usage.iterations, and excludes it from the top-level usage fields. Solwyn sums every type == "compaction" entry and adds it to the settled input, output, and cache counts, using the same normalization as the top level, for streaming and non-streaming calls. Other iteration types are already covered by the top-level fields.

token_details also carries the compaction share as subsets of those totals. Each key is omitted when zero, so a call without compaction sends the same payload as before:

FieldCompaction share of
compaction_input_tokensinput_tokens
compaction_cached_input_tokenscached_input_tokens
compaction_cache_creation_5m_tokenscache_creation_5m_tokens
compaction_cache_creation_1h_tokenscache_creation_1h_tokens
compaction_output_tokensoutput_tokens

For streams, see What gets reported.

Supported anthropic SDK versions

solwyn[anthropic] declares anthropic>=0.50. Coverage is exercised against the 0.50.0 floor, the 0.80.0 (parse), 1.0.0 (stable files / skills), and 1.14.0 (native OpenTelemetry) breakpoints, and the current release — 2.3.0 as of SDK 0.9.0. Anthropic versions below 1.14 remain fully supported with no behavior change.

SDK v0.9.0+: Anthropic 2.x is supported with no wrapper change; beta Messages metering and compaction settlement work unchanged on 2.x.

SDK v0.6.0+: Anthropic 1.x is supported on its httpx2 HTTP stack. Solwyn never imports httpx2; it recognizes the stack by identity from the client you pass in. Two things follow:

  • The per-hop bound from failover tuning is delivered as a native httpx2.Timeout when the SDK can prove the client's own timeout class, and as a granular (connect, read, write, pool) tuple otherwise. The transport bound is correct either way; in the fallback only Anthropic's informational x-stainless-read-timeout header degrades.
  • httpx2 transport errors are classified at the same position as their httpx twins: connect and pool timeouts and connection errors fail over; read and write timeouts and protocol errors are post-send ambiguous and re-raise under the default failover_idempotency="safe".

Anthropic 1.0 promoted files and skills to stable. Solwyn classifies every leaf under them — files.upload, files.list, files.download, skills.create, skills.versions.create, and the rest — as unmetered spend, so they follow your ordinary on_unmetered posture (warn once by default) and are acknowledgeable by exact token, rather than resolving as unknown-surface drift.

SDK v0.7.0+: the surface ledger is audited against Anthropic 1.4. Its beta.organization.* admin tree — api_keys, invites, users, workspaces, service_accounts, federation, rate_limits, compliance_settings, external_keys, and their sub-resources — is guarded as namespaces whose leaf operations are unmetered spend, as are beta.webhooks.parse_unverified and the with_raw_response / with_streaming_response variants of messages.batches.results. Nothing previously classified moved, and no Anthropic rule changed in SDK 0.8.0.

SDK v0.9.0+: the ledger is audited through Anthropic 2.3. Newly guarded administration surfaces — the top-level organization and user_profiles trees, beta.user_profiles.action_urls and beta.user_profiles.delete, workspaces.rate_limits.update under both organization and beta.organization, and beta.organization.analytics (including cost / usage), plugins, plugin_marketplaces, rbac_groups, rbac_roles, spend_limits, telemetry_destinations, webhooks, and claude_tag — are unmetered spend, follow on_unmetered, and need exact acknowledgment tokens in strict mode. beta.messages.thread, whose server-held thread turns Solwyn cannot budget or settle, is unmetered too. The client's open_telemetry option is silent configuration.

SDK v0.9.0+: wrapped AnthropicBedrock and AnthropicBedrockMantle clients (sync and async) keep the caller's http_client on every provider call, and AnthropicBedrock also keeps its aws_profile. Previously a client configured with a named AWS profile could fail to resolve credentials, and a custom transport or proxy was bypassed.

To tag Anthropic's native OpenTelemetry spans with the active run ID, see Anthropic conversation IDs.

Reasoning tokens limitation

Anthropic folds extended thinking tokens into output_tokens and does not report them as a separate field. As a result, reasoning_tokens is always 0 for Anthropic responses. This is a known limitation of the Anthropic API, not the Solwyn SDK.

The Solwyn Cloud API accounts for this when computing costs -- extended thinking output tokens are priced correctly using the total output_tokens count.

Passthrough attributes

Any attribute not intercepted by Solwyn is resolved against the underlying anthropic.Anthropic client through the coverage guard. SDK v0.6.0+: unmetered capabilities — messages.count_tokens, models.list, completions.create (pre-1.0 clients only), files.*, skills.*, the beta.* tree (except beta.messages.create, metered since 0.9.0) — warn once per process by default and are then forwarded; on_unmetered="raise" refuses them, "allow" silences them, and acknowledge_untracked exempts exact leaves.

On this page