Providers · 01 macOS only

Anthropic

Halton Meter's Anthropic adapter intercepts traffic to api.anthropic.com and meters /v1/messages calls — including extended thinking, prompt caching, and streaming.

macOS 12+ · Python 3.11+ Reading time 2 min Updated May 11, 2026

The Anthropic adapter (daemon/halton_meter/adapters/anthropic.py) is the most mature surface in Halton Meter. It owns the host api.anthropic.com and meters every call to the /v1/messages family of endpoints — request and streaming-response bodies parsed, input/output/thinking/cache tokens captured, latency recorded, cost computed against the active rate card.

What’s metered

PathModes
/v1/messagesStandard, streaming, extended-thinking, batch
/v1/messages?... (query variants)Same

Non-/v1/messages* paths (model list, account metadata, OAuth control-plane) are observed but not metered. They pass through unchanged.

Captured fields

For every metered request, the adapter writes one row into requests:

  • provider = "anthropic"
  • model — from the response (not the request) so model-mapping redirects are honoured
  • modestandard, streaming, thinking, batch
  • input_tokensusage.input_tokens
  • output_tokensusage.output_tokens
  • thinking_tokensusage.thinking_tokens, when extended thinking is on
  • cache_read_tokensusage.cache_read_input_tokens
  • cache_write_tokensusage.cache_creation_input_tokens
  • cost_usd_minor_units — computed against the active row in pricing_rates

The cache columns are intentionally separate. Renamed from cached_tokens on 2026-04-30 once cache-write became billable on a different schedule from cache-read.

Streaming

Streaming responses (text/event-stream) are buffered through the adapter, parsed event by event, and the final message_stop event’s usage block becomes the row. If the stream is truncated mid-flight, the row is still written with tokens_complete = false so partial captures don’t silently inflate totals.

Tools that route through this adapter

ToolPath
Claude Code (Node)NODE_EXTRA_CA_CERTS + HTTPS_PROXY
Anthropic Python SDKcertifi bundle (patched by init)
curl against api.anthropic.comsystem keychain (curl) or CURL_CA_BUNDLE
Cursor / Windsurf with Claude back-endNode, same as Claude Code

For the per-tool TLS-trust matrix, see How clients see your CA.

Verifying capture

~ — verify Anthropic capture
$ halton-meter run -- curl -sS https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{"model":"claude-haiku-4-5","max_tokens":8,...}'

$ halton-meter report --since 5m --by model

Expect one row in the report against claude-haiku-4-5. If nothing appears, walk No captures in halton-meter report.

Error classification

When an Anthropic call returns an error, the adapter classifies it into one of the seven canonical buckets — see Error classification. Shipped in v0.3.0.

HTTPProvider error.typeerror_classretryable
400invalid_request_errorbad_requestfalse
401authentication_errorauthfalse
403permission_errorauthfalse
404not_found_errorbad_requestfalse
408request timeouttimeouttrue
413request_too_largebad_requestfalse
429rate_limit_errorrate_limittrue
500api_errorserver_errortrue
529overloaded_errorserver_errortrue
network / connect failurenetworktrue

HTTP 529 is a provider-overload signal, not a per-key throttle, so it buckets as server_error (not rate_limit) and stays retryable=true. See the judgement-call note on the concept page.

Host matching

The adapter declares its host as api.anthropic.com exactly. Host matching is exact-equality (with optional :port suffix) — never prefix or suffix matching — to defend against api.anthropic.com.evil.com and evil.api.anthropic.com.