Skip to main content
Version: 3.3-unstable

AnthropicTokenCounter

AnthropicTokenCounter uses Anthropic's POST /v1/messages/count_tokens endpoint to count the input tokens of ChatMessage objects and optional tool schemas for a specific Claude model. The endpoint returns an exact count without generating a response, so it does not incur generation costs.

Import pathhaystack_integrations.token_counters.anthropic.AnthropicTokenCounter
Mandatory init variablesmodel: The Claude model to count for
API referenceAnthropic
GitHub linkhttps://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/anthropic
Package nameanthropic-haystack

Because it calls a remote API, it needs an Anthropic API key and adds network latency to every count. Use it when you need exact, model-specific counts for Claude models. For local estimates, use ApproximateTokenCounter or TiktokenCounter.

Installation​

Install the anthropic-haystack package:

bash
pip install anthropic-haystack

Usage​

Token counts are model-specific, so pass the model you intend to generate with:

python
from haystack.dataclasses import ChatMessage
from haystack_integrations.token_counters.anthropic import AnthropicTokenCounter

messages = [
ChatMessage.from_system("You are a helpful assistant."),
ChatMessage.from_user("Explain retrieval-augmented generation."),
]

counter = AnthropicTokenCounter(model="claude-sonnet-4-5")
token_count = counter.count(messages)
print(token_count)

By default, the counter reads the API key from the ANTHROPIC_API_KEY environment variable. You can also pass a Haystack Secret explicitly, and set the HTTP timeout and max_retries of the underlying Anthropic client:

python
from haystack.utils import Secret

counter = AnthropicTokenCounter(
model="claude-sonnet-4-5",
api_key=Secret.from_env_var("MY_ANTHROPIC_API_KEY"),
timeout=30.0,
max_retries=3,
)

To include the context consumed by tool schemas, pass the tools to count():

python
token_count = counter.count(messages, tools=[search_tool])

The counter creates its API client on the first call to count(). To create it during application startup instead, call warm_up() explicitly. Call close() when you are done with the counter to release the client's HTTP resources:

python
counter.warm_up()
...
counter.close()

Non-text content​

Anthropic counts images and PDF files as part of the request, so the counter measures them exactly instead of applying a flat estimate. It supports the same content types as AnthropicChatGenerator: JPEG, PNG, GIF, and WebP images, and application/pdf files. Other MIME types raise an error rather than being estimated.

Use with compaction​

Pass the counter to CompactionHook to size an Agent's conversation with the same tokenizer Claude uses:

python
from haystack.hooks.compaction import CompactionHook, SlidingWindowCompactor

compaction_hook = CompactionHook(
compactor=SlidingWindowCompactor(),
context_window=200_000,
token_counter=AnthropicTokenCounter(model="claude-sonnet-4-5"),
)

Keep in mind that the hook counts messages on every Agent step, so each compaction check costs an API round trip.