Python: fix(claude): propagate usage details and finish_reason from ResultMessage#6927
Open
droideronline wants to merge 2 commits into
Open
Python: fix(claude): propagate usage details and finish_reason from ResultMessage#6927droideronline wants to merge 2 commits into
droideronline wants to merge 2 commits into
Conversation
…sage The Claude Agent SDK's ResultMessage carries token usage statistics (input_tokens, output_tokens, cache tokens) and a stop_reason that were previously discarded. This commit: * Adds _parse_claude_usage_details() to convert the SDK usage dict to the framework's UsageDetails TypedDict. * Emits an AgentResponseUpdate with a Content.from_usage() payload and the stop_reason mapped to finish_reason when ResultMessage arrives, so that AgentResponse.usage_details and AgentResponse.finish_reason are populated by the standard _process_update() aggregation path. * Adds tests covering usage propagation, finish_reason propagation, streaming usage, and the no-metadata case.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the Python Claude agent integration to propagate token usage statistics and the model stop reason from the Claude Agent SDK’s ResultMessage into the Agent Framework’s AgentResponse, so callers can access usage_details and finish_reason when using Claude.
Changes:
- Added
_parse_claude_usage_details()to map Claude usage dict keys into the framework’sUsageDetails. - Emitted an
AgentResponseUpdateatResultMessagetime to flow usage (viaContent.from_usage) andfinish_reasonthrough the standard update processing path. - Added test coverage to validate
usage_detailsandfinish_reasonpropagation for both non-streaming and streaming runs, plus a no-op scenario.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| python/packages/claude/agent_framework_claude/_agent.py | Parses Claude usage into UsageDetails and emits a final update containing usage/finish metadata from ResultMessage. |
| python/packages/claude/tests/test_claude_agent.py | Adds tests ensuring usage_details and finish_reason propagate (and no extra update is emitted when absent). |
…resent Review feedback: total_token_count was only set when the sum was non-zero, so a response with both input_tokens=0 and output_tokens=0 would omit it despite the individual counts being present. Fix the guard to check whether either token count was returned by the SDK rather than whether their sum is truthy.
Contributor
Author
|
@moonbox3 @eavanvalkenburg - kindly take a look when you get a chance. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #6929
Summary
The Claude Agent SDK's
ResultMessagecarries token usage statistics (input_tokens,output_tokens, cache tokens) and astop_reasonthat were previously discarded by the agent framework. As a result,AgentResponse.usage_detailswas alwaysNoneandAgentResponse.finish_reasonwas alwaysNonewhen using the Claude agent.Problem
When calling
agent.run()with the Claude agent,AgentResponse.usage_detailsandAgentResponse.finish_reasonare alwaysNone, even though the underlying Claude Agent SDK'sResultMessagecontains this information.Direct SDK call returns:
Agent Framework before this fix:
Agent Framework after this fix:
Changes
python/packages/claude/agent_framework_claude/_agent.pyUsageDetailsto imports fromagent_framework._parse_claude_usage_details()— converts the Claude API usage dict to the framework'sUsageDetailsTypedDict.ResultMessage— in_get_stream(), whenResultMessagearrives the handler now:message.usage→UsageDetailsand yields anAgentResponseUpdatewithContent.from_usage()so the standard_process_update()path populatesAgentResponse.usage_detailsmessage.stop_reason→finish_reasonon the update soAgentResponse.finish_reasonis setResultMessagehas no usage or stop_reason (backward-compatible no-op)python/packages/claude/tests/test_claude_agent.pyAdds 4 tests:
test_run_propagates_usage_details_from_result_messagetest_run_propagates_finish_reason_from_result_messagetest_run_stream_propagates_usage_detailstest_run_no_usage_no_stop_reason_no_extra_updateTesting
All 65 existing tests pass. 4 new tests added (69 total).