Python: Fix HandoffBuilder silently dropping context_provider during agent cloning (#3721)

* Initial plan

* Fix context_provider parameter name bug and add test

Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>

* Improve context_provider test to directly check cloned agent

Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>

* Improve test based on code review feedback

Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>

* Remove unused events variable in test_context_provider_preserved_during_handoff

Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>

* Fix formatting: remove trailing whitespace from test_handoff.py

Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
This commit is contained in:
Copilot
2026-02-07 08:23:45 +09:00
committed by GitHub
Unverified
parent a17f13598b
commit 5d355ac507
2 changed files with 45 additions and 1 deletions
@@ -309,7 +309,7 @@ class HandoffAgentExecutor(AgentExecutor):
name=agent.name,
description=agent.description,
chat_message_store_factory=agent.chat_message_store_factory,
context_providers=agent.context_provider,
context_provider=agent.context_provider,
middleware=middleware,
default_options=cloned_options, # type: ignore[arg-type]
)
@@ -11,6 +11,8 @@ from agent_framework import (
ChatResponse,
ChatResponseUpdate,
Content,
Context,
ContextProvider,
ResponseStream,
WorkflowEvent,
resolve_agent_id,
@@ -303,6 +305,48 @@ async def test_tool_choice_preserved_from_agent_config():
assert last_tool_choice == {"mode": "required"}, f"Expected 'required', got {last_tool_choice}"
async def test_context_provider_preserved_during_handoff():
"""Verify that context_provider is preserved when cloning agents in handoff workflows."""
# Track whether context provider methods were called
provider_calls: list[str] = []
class TestContextProvider(ContextProvider):
"""A test context provider that tracks its invocations."""
async def invoking(self, messages: Sequence[ChatMessage], **kwargs: Any) -> Context:
provider_calls.append("invoking")
return Context(instructions="Test context from provider.")
# Create context provider
context_provider = TestContextProvider()
# Create a mock chat client
mock_client = MockChatClient(name="test_agent")
# Create agent with context provider using proper constructor
agent = ChatAgent(
chat_client=mock_client,
name="test_agent",
id="test_agent",
context_provider=context_provider,
)
# Verify the original agent has the context provider
assert agent.context_provider is context_provider, "Original agent should have context provider"
# Build handoff workflow - this should clone the agent and preserve context_provider
workflow = HandoffBuilder(participants=[agent]).with_start_agent(agent).build()
# Run workflow with a simple message to trigger context provider
await _drain(workflow.run("Test message", stream=True))
# Verify context provider was invoked during the workflow execution
assert len(provider_calls) > 0, (
"Context provider should be called during workflow execution, "
"indicating it was properly preserved during agent cloning"
)
# region Participant Factory Tests