From 5d355ac507c70db4472881bdde31f6bf04a3eb60 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 08:23:45 +0900 Subject: [PATCH] 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> --- .../_handoff.py | 2 +- .../orchestrations/tests/test_handoff.py | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/python/packages/orchestrations/agent_framework_orchestrations/_handoff.py b/python/packages/orchestrations/agent_framework_orchestrations/_handoff.py index 3bbfccba8a..a969a1ac93 100644 --- a/python/packages/orchestrations/agent_framework_orchestrations/_handoff.py +++ b/python/packages/orchestrations/agent_framework_orchestrations/_handoff.py @@ -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] ) diff --git a/python/packages/orchestrations/tests/test_handoff.py b/python/packages/orchestrations/tests/test_handoff.py index 18e3b6e06c..d6dbcc9282 100644 --- a/python/packages/orchestrations/tests/test_handoff.py +++ b/python/packages/orchestrations/tests/test_handoff.py @@ -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