Python: keep agent compaction configuration when HandoffBuilder clones participants - #8329
Open
Manjunath Janardhan (manjunathshiva) wants to merge 1 commit into
Conversation
…s participants `_clone_chat_agent` rebuilds each participant through `Agent(...)` to inject the handoff tools and middleware, listing constructor arguments by hand. `compaction_strategy` and `tokenizer` live outside `default_options` and were not in that list, so the clone silently got `None` for both and the participant ran with no compaction at all. Nothing raises: a long handoff conversation simply grows unbounded until it trips the model's context limit, after showing up as cost and latency first. Both are forwarded by reference rather than deep-copied, matching `context_providers` and `middleware`. They hold immutable configuration the clone never mutates, and a tokenizer can carry a vocabulary that is expensive or unsafe to copy. Rebuilding through the constructor is deliberate and stays: `Agent.__init__` re-separates MCP tools from regular ones, which is why the method recombines `agent.mcp_tools` into the tools list first. Copying the instance instead would skip that. The second test is the one that matters beyond this bug. Every parameter added to `Agent.__init__` has to be added to this call or it is silently dropped, and the `test_handoff_clone_preserves_*` tests above were each written after that already happened. The guard reads the keyword names off the `Agent(...)` call with `ast` and asserts every constructor parameter is either forwarded or named as deliberately handled elsewhere, so the next missing field fails here rather than in a user's workflow. Reading the AST rather than substring-matching the source means a commented-out argument cannot satisfy it.
Manjunath Janardhan (manjunathshiva)
deployed
to
github-app-auth
September 12, 2026 05:48 — with
GitHub Actions
Active
Manjunath Janardhan (manjunathshiva)
deployed
to
github-app-auth
September 12, 2026 05:48 — with
GitHub Actions
Active
Manjunath Janardhan (manjunathshiva)
deployed
to
github-app-auth
September 12, 2026 05:48 — with
GitHub Actions
Active
Manjunath Janardhan (manjunathshiva)
deployed
to
github-app-auth
September 12, 2026 05:48 — with
GitHub Actions
Active
Copilot started reviewing on behalf of
Manjunath Janardhan (manjunathshiva)
September 12, 2026 05:48
View session
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused fix correctly preserves both omitted fields and includes appropriate regression protection.
Pull request overview
Preserves agent-level compaction settings when handoff participants are cloned.
Changes:
- Forwards
compaction_strategyandtokenizerto cloned agents. - Adds regression and constructor-field drift tests.
File summaries
| File | Description |
|---|---|
python/packages/orchestrations/agent_framework_orchestrations/_handoff.py |
Preserves compaction configuration during cloning. |
python/packages/orchestrations/tests/test_handoff.py |
Tests configuration retention and future constructor coverage. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Manjunath Janardhan (manjunathshiva)
marked this pull request as ready for review
September 12, 2026 05:49
Manjunath Janardhan (manjunathshiva)
requested review from
SergeyMenshykh,
Tao Chen (TaoChenOSU),
Eduard van Valkenburg (eavanvalkenburg),
Giles Odigwe (giles17),
Jose Alvarez (jpalvarezl),
Evan Mattson (moonbox3),
Roger Barreto (rogerbarreto) and
westey (westey-m)
as code owners
September 12, 2026 05:49
Manjunath Janardhan (manjunathshiva)
deployed
to
github-app-auth
September 12, 2026 05:50 — with
GitHub Actions
Active
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.
Motivation & Context
HandoffAgentExecutor._clone_chat_agentrebuilds each participant throughAgent(...)to injecthandoff tools and middleware, listing constructor arguments by hand.
compaction_strategyandtokenizerlive outsidedefault_optionsand were missing from that list, so the clone gotNonefor both:
Nothing raises. The participant simply runs with no compaction, so a long handoff conversation grows
unbounded until it trips the model's context limit — surfacing as cost and latency well before it
surfaces as an error.
One note on the issue text: it says "the cloned executor agent gets
Nonefor both" and "forwardboth fields", but only ever names
compaction_strategy. The second field istokenizer. A fixwritten from the title alone would close half the bug.
Description & Review Guide
What are the major changes? Two arguments forwarded in
_clone_chat_agent, plus two tests.No API change, no change to compaction behaviour itself.
Why by reference and not
deepcopy. Both are forwarded as-is, matchingcontext_providersand
middlewareon the lines above. I checked that the strategies hold only immutableconfiguration —
ToolResultCompactionStrategystores one threshold,ContextWindowCompactionStrategyten — and
CharacterEstimatorTokenizeris stateless, so clones cannot interfere through them.additional_propertiesstays deep-copied because it is a mutable mapping the clone does own.Why not replace the hand-rolled constructor with a copy.
Agentinherits__copy__and__deepcopy__fromSerializationMixin, which copy every instance field and would have fixed thisclass of bug permanently — so I checked whether they could be used here. They cannot:
Agent.__init__re-separates MCP tools from regular tools, which is exactly why this methodrecombines
agent.mcp_toolsinto the tools list before calling it. Copying the instance would skipthat separation, and
copywould additionally sharedefault_optionswith the original, somutating
allow_multiple_tool_callson the clone would reach back into the caller's agent.Rebuilding through the constructor is deliberate and stays.
The second test is the point. Every parameter added to
Agent.__init__has to be added to thiscall or it is silently dropped, and the
test_handoff_clone_preserves_*tests directly above wereeach written after that already happened — this is at least the fourth field to go missing.
test_handoff_clone_forwards_every_agent_constructor_fieldreads the keyword names off theAgent(...)call withastand asserts every constructor parameter is either forwarded or named inhandled_elsewherewith a reason. The next new parameter fails there instead of in a user'sworkflow. Reading the AST rather than substring-matching the source is deliberate: I verified that a
commented-out argument still fails the guard, which a substring check would have passed.
What is the impact of these changes? Compaction configured on a handoff participant now takes
effect. That is a behaviour change in the sense that previously-ignored configuration starts
working, so a long-running handoff conversation will begin compacting where it did not before. I
have not marked it a breaking change because it makes documented configuration behave as
documented, but say if you would rather label it.
What do you want reviewers to focus on? Whether by-reference is the sharing you want for these
two, and whether the drift guard is welcome — it is a little unusual for this suite, and I would
rather drop it than have it be a maintenance burden.
_clone_chat_agentis the onlyclone-by-reconstruct site in the repo, so there is no sibling instance to fix.
Validation: orchestrations 197 passing with
poe check -P orchestrationsclean across all fivetype checkers, and core 5136 passing unchanged. Both new tests fail against the unfixed tree.
Related Issue
Fixes #8320
Contribution Checklist