Skip to content

AnthropicLlm usage_metadata is missing thinking token count #5397

Closed

Description

@sebastienc

AnthropicLlm only maps basic input/output token counts into usage_metadata. When extended thinking is enabled, thinking block tokens are included in output_tokens but never broken out separately.

Current behaviour

message_to_generate_content_response and the streaming final response both produce:

usage_metadata=types.GenerateContentResponseUsageMetadata(
    prompt_token_count=message.usage.input_tokens,
    candidates_token_count=message.usage.output_tokens,
    total_token_count=(input_tokens + output_tokens),
)

Cache token counts (cache_creation_input_tokens, cache_read_input_tokens) are also missing but are tracked separately in #5395.

Expected behaviour

When extended thinking is enabled, populate usage_metadata.thoughts_token_count with the token count of thinking blocks. This is derivable from the thinking block content (supplemental API call to tokenizer) or from a future dedicated API field (ref: anthropic-python-sdk ).

Reference

This is particularly relevant now that extended thinking is supported via PR #5392.

Activity

  1. added
    models[Component] This issue is related to model support
    on Apr 19, 2026
  2. added theissue type on Apr 19, 2026
  3. llalitkumarrr commented on Apr 20, 2026

    @llalitkumarrr
    Collaborator

    Hello @sebastienc ,

    Thank you for bringing this to our attention. If you have a solution in mind for this issue, would you be willing to contribute a fix?

  4. added
    request clarification[Status] The maintainer need clarification or more information from the author
    on Apr 20, 2026
  5. sebastienc commented on Apr 20, 2026

    @sebastienc
    ContributorAuthor

    I see three options.

    1. Do nothing since it's not pre-computed by the anthropic sdk right now. We could wait and see.
    2. Use the thinking blocks to locally calculate the number of tokens with a formula we could decide on. Less precision but we could have a value.
    3. Call the token count API with the content of the thinking blocks and use that result.

    Which one would you prefer?

    I'd be happy to implement.

  6. sasha-gitg commented on May 1, 2026

    @sasha-gitg
    Collaborator

    Since this isn't available through the Anthropic API we will not support this feature.

  7. lmandrelli commented on Aug 7, 2026

    @lmandrelli

    The premise for closing this issue has changed: the current Anthropic Messages
    API now provides an exact thinking-token breakdown through
    usage.output_tokens_details.thinking_tokens.

    Anthropic documents the field here:
    https://platform.claude.com/docs/en/build-with-claude/extended-thinking#pricing

    The current Python SDK models it in both response paths:

    • anthropic.types.Usage.output_tokens_details
    • anthropic.types.MessageDeltaUsage.output_tokens_details

    with OutputTokensDetails.thinking_tokens: int. I verified these types with
    anthropic==0.120.2.

    The breakdown is still discarded by google-adk==2.6.2:

    1. In the non-streaming path, message_to_generate_content_response() maps
      the inclusive message.usage.output_tokens directly to
      candidates_token_count without reading output_tokens_details.
    2. In the streaming path, _generate_content_streaming() reads only
      event.usage.output_tokens from the final message_delta, so it also loses
      output_tokens_details.thinking_tokens.

    To preserve GenerateContentResponseUsageMetadata semantics without
    double-counting, I believe the mapping should be:

    prompt_token_count     = input_tokens
    thoughts_token_count   = output_tokens_details.thinking_tokens
    candidates_token_count = output_tokens - thoughts_token_count
    total_token_count      = input_tokens + output_tokens
    

    Anthropic's output_tokens remains the inclusive, authoritative billed-output
    total.

    If output_tokens_details is absent, a cost-safe fallback would retain the
    current mapping:

    candidates_token_count = output_tokens
    thoughts_token_count   = unset
    

    BQ Agent Analytics already exposes
    usage_metadata.thoughts_token_count, so preserving the value in
    LlmResponse.usage_metadata would also complete the existing analytics path
    for Claude without provider-specific BigQuery logic.

    Could this issue be reopened now that Anthropic provides the exact field? I
    would be happy to help validate the streaming and non-streaming behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

models[Component] This issue is related to model supportrequest clarification[Status] The maintainer need clarification or more information from the author

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions