Skip to content

Account for Anthropic thinking tokens in usage details - #554

Open
PratikDhanave (PratikDhanave) wants to merge 6 commits into
microsoft:mainfrom
PratikDhanaveFork:fix-anthropic-reasoning-token-count
Open

Account for Anthropic thinking tokens in usage details#554
PratikDhanave (PratikDhanave) wants to merge 6 commits into
microsoft:mainfrom
PratikDhanaveFork:fix-anthropic-reasoning-token-count

Conversation

@PratikDhanave

Copy link
Copy Markdown
Contributor

The Anthropic SDK exposes Usage.OutputTokensDetails.ThinkingTokens"the number of output tokens the model generated as internal reasoning." toUsageDetails mapped input, output, total, and both cache fields but never read it:

details := message.UsageDetails{
    InputTokenCount:       usage.InputTokens,
    OutputTokenCount:      usage.OutputTokens,
    TotalTokenCount:       usage.InputTokens + usage.OutputTokens,
    CachedInputTokenCount: usage.CacheReadInputTokens,
}

For any extended-thinking request (this provider explicitly supports it — it emits ThinkingBlock/ThinkingDelta as TextReasoningContent), those tokens were silently dropped: the framework’s dedicated UsageDetails.ReasoningTokenCount (populated by the OpenAI, Gemini, and Copilot providers, and surfaced as an OTel telemetry attribute) stayed 0. toUsageDetailsDelta additionally rebuilt the Usage from only four scalar fields, omitting OutputTokensDetails, so the streaming path could never recover it.

Fix

  • toUsageDetails: ReasoningTokenCount: usage.OutputTokensDetails.ThinkingTokens.
  • toUsageDetailsDelta: carry OutputTokensDetails through when reconstructing the Usage.

Thinking tokens are a subset of output tokens, so TotalTokenCount is unchanged — only the missing breakdown field is added, matching the OpenAI providers.

Test

TestUsageReasoningTokens returns a non-streaming response with output_tokens_details.thinking_tokens: 35 and asserts ReasoningTokenCount == 35. It fails on the old code (0) and passes with the fix.

Copilot AI review requested due to automatic review settings July 19, 2026 11:13
@PratikDhanave
PratikDhanave (PratikDhanave) requested a review from a team as a code owner July 19, 2026 11:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves token-usage accounting by ensuring “reasoning/thinking” tokens emitted by providers are surfaced via UsageDetails.ReasoningTokenCount, including in Anthropic streaming deltas, so telemetry/OTel breakdowns are accurate.

Changes:

  • Anthropic: map Usage.OutputTokensDetails.ThinkingTokens into UsageDetails.ReasoningTokenCount.
  • Anthropic streaming: preserve OutputTokensDetails when reconstructing anthropic.Usage from MessageDeltaUsage.
  • Copilot: surface reasoning tokens from assistant.usage events and add a regression test; add an Anthropic non-streaming regression test.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
provider/copilotprovider/copilot.go Adds ReasoningTokenCount mapping in Copilot usage updates.
provider/copilotprovider/copilot_test.go Adds coverage asserting Copilot usage events expose reasoning tokens.
provider/anthropicprovider/agent.go Maps Anthropic thinking tokens into ReasoningTokenCount and carries details through streaming delta reconstruction.
provider/anthropicprovider/agent_test.go Adds a non-streaming Anthropic regression test for thinking tokens.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread provider/anthropicprovider/agent.go
@PratikDhanave
PratikDhanave (PratikDhanave) force-pushed the fix-anthropic-reasoning-token-count branch 2 times, most recently from fb35d43 to 1753be4 Compare July 23, 2026 15:44
@github-actions

This comment has been minimized.

@github-actions github-actions Bot added the parity-approved Go API consistency review found no parity issues label Jul 23, 2026
@PratikDhanave
PratikDhanave (PratikDhanave) force-pushed the fix-anthropic-reasoning-token-count branch from 1753be4 to 0e1eb69 Compare July 24, 2026 01:42
@github-actions

This comment has been minimized.

toUsageDetails mapped input, output, total, and cache tokens but dropped
Usage.OutputTokensDetails.ThinkingTokens (the tokens the model generated
as internal reasoning), so the framework's dedicated ReasoningTokenCount
field stayed zero for extended-thinking requests. toUsageDetailsDelta
also reconstructed the Usage without OutputTokensDetails, so the
streaming path could not recover it either.

Map ThinkingTokens to UsageDetails.ReasoningTokenCount and carry
OutputTokensDetails through the delta path, matching the OpenAI, Gemini,
and Copilot providers. Thinking tokens are a subset of output tokens, so
TotalTokenCount is unchanged.
Covers the toUsageDetailsDelta path: thinking tokens arriving on the
streamed message_delta usage must surface as ReasoningTokenCount.
@PratikDhanave
PratikDhanave (PratikDhanave) force-pushed the fix-anthropic-reasoning-token-count branch from 0e1eb69 to 51f6d56 Compare July 24, 2026 09:37
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

# Conflicts:
#	provider/anthropicprovider/agent_test.go
auto-merge was automatically disabled August 20, 2026 11:49

Head branch was pushed to by a user without write access

@github-actions github-actions Bot added area:provider Changes files in the provider area area:provider/anthropic Changes files in the provider / anthropic area size:large At most 300 changed lines across at most 10 files pending-auto-risk Automatic risk classification is in progress labels Aug 20, 2026
@github-actions

This comment has been minimized.

@github-actions github-actions Bot added failed-auto-risk Automatic risk classification was inconclusive or failed and removed pending-auto-risk Automatic risk classification is in progress labels Aug 20, 2026
@github-actions

This comment has been minimized.

@github-actions github-actions Bot added pending-auto-risk Automatic risk classification is in progress risk:medium Contained production impact requiring normal review depth and removed failed-auto-risk Automatic risk classification was inconclusive or failed pending-auto-risk Automatic risk classification is in progress labels Aug 21, 2026
@github-actions github-actions Bot added pending-auto-risk Automatic risk classification is in progress risk:medium Contained production impact requiring normal review depth and removed risk:medium Contained production impact requiring normal review depth pending-auto-risk Automatic risk classification is in progress labels Aug 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

API Consistency Review — PR #554

Scope: provider/anthropicprovider/agent.go (unexported helpers only), agent_test.go

Public API change: None. UsageDetails.ReasoningTokenCount is an existing exported field; this PR only fixes the mapping inside the unexported toUsageDetails / toUsageDetailsDelta functions.

Cross-repo parity

SDK reasoning_token_count from Anthropic thinking_tokens
Go (other providers) ✅ OpenAI, Gemini, and Copilot providers already populate ReasoningTokenCount
Go Anthropic (before this PR) ❌ Always 0 — the field was silently dropped
Go Anthropic (after this PR) ✅ Correctly mapped from OutputTokensDetails.ThinkingTokens
Python upstream (_parse_usage_from_anthropic) ⚠️ Also missing — thinking_tokens is not yet mapped in the Python provider; that is a gap in the Python SDK, not a reason to hold back this Go fix
.NET Anthropic Delegates to IChatClient adapter; usage mapping is handled at a different abstraction layer

Conclusion

This is a targeted bug fix that brings the Anthropic provider into alignment with the Go framework's own usage-reporting convention (the same ReasoningTokenCount already surfaced as an OTel attribute from other providers). No new exported API surface is introduced and no behavioral default changes. The Python upstream has a parallel gap, but that does not make the Go fix incorrect.

Parity approved. No cross-repo consistency issues found.

Generated by Go API Consistency Review Agent · sonnet46 · 27.5 AIC · ⌖ 5.81 AIC · ⊞ 6K ·

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

Labels

area:provider/anthropic Changes files in the provider / anthropic area area:provider Changes files in the provider area parity-approved Go API consistency review found no parity issues risk:medium Contained production impact requiring normal review depth size:large At most 300 changed lines across at most 10 files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants