Repository navigation
Python: Honor replace usage snapshots in Foundry hosting - #10205
Mehedi Hasan (Mahdi-Hasan) wants to merge 3 commits into
Conversation
_OutputItemTracker added every usage update with add_usage_details, even when the update had merge_mode="replace". Two cumulative snapshots of 100/10 and 250/25 were reported as 350/35. Replace the tracked usage for replace updates and keep adding append updates, the same rule as Content._add_usage_content and AgentResponse.from_updates. Fixes microsoft#10189 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Add agent-framework #10205; bump OSS count to 61 PRs - Foundry hosting fix for replace usage snapshots (microsoft/agent-framework#10205) - Projects stay at 19: agent-framework is already listed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add Nov 9 PRs; bump OSS counts to 70 PRs / 21 projects - quran.com-frontend-next #3368-#3370 - New projects: quranic-universal-library #1021-#1023, hadith-api #144-#146 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The merge-mode test only checked totals, so it would still pass if the tracker kept the update's usage_details by reference. Mutate the update after handle() and check the tracker's usage is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| self._usage_details = add_usage_details(self._usage_details, content.usage_details) | ||
| # A "replace" update is a cumulative snapshot, so it supersedes earlier usage instead of adding to it. | ||
| if content.merge_mode == "replace": | ||
| self._usage_details = deepcopy(content.usage_details) |
There was a problem hiding this comment.
Mehedi Hasan (@Mahdi-Hasan), this replaces the tracker-wide usage slot, so a later executor's snapshot erases usage already accumulated from earlier agents in a hosted workflow. For example, agent A reporting 1000/100 followed by agent B reporting 50/5 produces 50/5 instead of 1050/105. Can we scope replacement to the same logical agent/response stream and add a multi-executor regression?
There was a problem hiding this comment.
Fixed in d68981f. The tracker now keeps usage per (author_name, response_id) stream. A replace snapshot overwrites only its own stream, and the reported usage is the sum over all streams. A re-run of the same agent gets a new response_id, so both runs count.
Added TestWorkflowAgentHosting::test_replace_usage_from_each_executor_is_summed: two chained agents report 1000/100 and 50/5, and the response reports 1050/105. Before the fix it reported 50/5. There is also a tracker-level test, test_output_item_tracker_scopes_replace_usage_to_its_stream.
A hosted workflow sends every executor's updates through one _OutputItemTracker. A replace snapshot from a later agent erased usage already tracked for earlier agents: 1000/100 then 50/5 gave 50/5 instead of 1050/105. Track usage per (author_name, response_id) stream. A replace update overwrites only its own stream and the reported usage is the sum over all streams. Add a tracker test and a two-executor workflow regression. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Motivation & Context
Foundry hosting reports the wrong token usage when an agent streams cumulative usage snapshots.
_OutputItemTrackeradded every usage update, even ones withmerge_mode="replace". Two snapshots of 100/10 and 250/25 were reported as 350/35 instead of 250/25.Description & Review Guide
_OutputItemTracker.handle, areplaceusage update now replaces the tracked usage.appendupdates are still added.Content._add_usage_contentandAgentResponse.from_updates.usagein the finalresponse.completedevent changes, and only when the agent sendsreplaceupdates.appendupdates get the same totals as before.deepcopy, so the tracker never holds a reference to the update'susage_details.Related Issue
Fixes #10189
AI Assistance
AI assistance details: implementation, tests, and this description.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.🤖 Generated with Claude Code