From 9f221d0d0f043117490fd02c4d60d7d3ca358d78 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 11:06:08 +0000 Subject: [PATCH 1/6] Initial plan From 205ef4a8b18fece71c4f5a2206f90b61a061c8ed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 11:08:22 +0000 Subject: [PATCH 2/6] Fix context_provider parameter name bug and add test Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com> --- .../_handoff.py | 2 +- .../orchestrations/tests/test_handoff.py | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/python/packages/orchestrations/agent_framework_orchestrations/_handoff.py b/python/packages/orchestrations/agent_framework_orchestrations/_handoff.py index a2f9a4eea8..b0ff5001fa 100644 --- a/python/packages/orchestrations/agent_framework_orchestrations/_handoff.py +++ b/python/packages/orchestrations/agent_framework_orchestrations/_handoff.py @@ -309,7 +309,7 @@ def _clone_chat_agent(self, agent: ChatAgent) -> ChatAgent: 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 ab9f6e45cb..5273e98561 100644 --- a/python/packages/orchestrations/tests/test_handoff.py +++ b/python/packages/orchestrations/tests/test_handoff.py @@ -11,6 +11,8 @@ ChatResponse, ChatResponseUpdate, Content, + Context, + ContextProvider, ResponseStream, WorkflowEvent, resolve_agent_id, @@ -303,6 +305,53 @@ async def mock_get_response(messages: Any, options: dict[str, Any] | None = None 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.""" + from agent_framework import Context, ContextProvider + + # 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 a mock chat client that validates context_provider is present + async def mock_get_response_with_context_check( + messages: Sequence[ChatMessage], options: dict[str, Any] | None = None, **kwargs: Any + ) -> ChatResponse: + return ChatResponse( + messages=[ChatMessage(role="assistant", text="Response with context")], + response_id="test_response", + ) + + mock_client = MagicMock() + mock_client.get_response = AsyncMock(side_effect=mock_get_response_with_context_check) + + # Create context provider + context_provider = TestContextProvider() + + # Create agent with context provider + agent = ChatAgent( + chat_client=mock_client, + name="test_agent", + context_provider=context_provider, + ) + + # Build handoff workflow + workflow = HandoffBuilder(participants=[agent]).with_start_agent(agent).build() + + # Run the workflow + await agent.run("Test message") + + # Verify context provider was invoked + assert len(provider_calls) > 0, "Context provider should be called during agent execution" + assert provider_calls[0] == "invoking", "Context provider invoking method should be called" + + # region Participant Factory Tests From 7c2250b12af6cdfb552e286ccf5ab987aa46f78d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 11:10:01 +0000 Subject: [PATCH 3/6] Improve context_provider test to directly check cloned agent Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com> --- .../orchestrations/tests/test_handoff.py | 47 ++++++++----------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/python/packages/orchestrations/tests/test_handoff.py b/python/packages/orchestrations/tests/test_handoff.py index 5273e98561..0d6a277724 100644 --- a/python/packages/orchestrations/tests/test_handoff.py +++ b/python/packages/orchestrations/tests/test_handoff.py @@ -307,8 +307,6 @@ async def mock_get_response(messages: Any, options: dict[str, Any] | None = None async def test_context_provider_preserved_during_handoff(): """Verify that context_provider is preserved when cloning agents in handoff workflows.""" - from agent_framework import Context, ContextProvider - # Track whether context provider methods were called provider_calls: list[str] = [] @@ -319,37 +317,32 @@ async def invoking(self, messages: Sequence[ChatMessage], **kwargs: Any) -> Cont provider_calls.append("invoking") return Context(instructions="Test context from provider.") - # Create a mock chat client that validates context_provider is present - async def mock_get_response_with_context_check( - messages: Sequence[ChatMessage], options: dict[str, Any] | None = None, **kwargs: Any - ) -> ChatResponse: - return ChatResponse( - messages=[ChatMessage(role="assistant", text="Response with context")], - response_id="test_response", - ) - - mock_client = MagicMock() - mock_client.get_response = AsyncMock(side_effect=mock_get_response_with_context_check) - # Create context provider context_provider = TestContextProvider() - # Create agent with context provider - agent = ChatAgent( - chat_client=mock_client, - name="test_agent", - context_provider=context_provider, - ) + # Create agent with context provider using the MockHandoffAgent pattern + agent = MockHandoffAgent(name="test_agent") + + # Manually set the context_provider on the agent + agent.context_provider = context_provider - # Build handoff workflow - workflow = HandoffBuilder(participants=[agent]).with_start_agent(agent).build() + # Verify the original agent has the context provider + assert agent.context_provider is context_provider, "Original agent should have context provider" - # Run the workflow - await agent.run("Test message") + # Build handoff workflow - this should clone the agent and preserve context_provider + workflow = HandoffBuilder(participants=[agent]).with_start_agent(agent).build() - # Verify context provider was invoked - assert len(provider_calls) > 0, "Context provider should be called during agent execution" - assert provider_calls[0] == "invoking", "Context provider invoking method should be called" + # Get the cloned agent from the workflow executor + cloned_executor = workflow.executors.get("test_agent") + assert cloned_executor is not None, "Agent executor should exist in workflow" + + # Verify the context_provider is preserved in the cloned agent + # The executor wraps the agent in the _agent property + assert hasattr(cloned_executor, '_agent'), "Executor should have _agent property" + cloned_agent = cloned_executor._agent + assert cloned_agent.context_provider is context_provider, ( + "Context provider should be preserved when cloning agent for handoff workflow" + ) # region Participant Factory Tests From cc8f127d4c63a013d4763d057b44ca5f2f154064 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 11:11:33 +0000 Subject: [PATCH 4/6] Improve test based on code review feedback Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com> --- .../orchestrations/tests/test_handoff.py | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/python/packages/orchestrations/tests/test_handoff.py b/python/packages/orchestrations/tests/test_handoff.py index 0d6a277724..c000f559c8 100644 --- a/python/packages/orchestrations/tests/test_handoff.py +++ b/python/packages/orchestrations/tests/test_handoff.py @@ -320,11 +320,16 @@ async def invoking(self, messages: Sequence[ChatMessage], **kwargs: Any) -> Cont # Create context provider context_provider = TestContextProvider() - # Create agent with context provider using the MockHandoffAgent pattern - agent = MockHandoffAgent(name="test_agent") + # Create a mock chat client + mock_client = MockChatClient(name="test_agent") - # Manually set the context_provider on the agent - agent.context_provider = context_provider + # 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" @@ -332,16 +337,13 @@ async def invoking(self, messages: Sequence[ChatMessage], **kwargs: Any) -> Cont # Build handoff workflow - this should clone the agent and preserve context_provider workflow = HandoffBuilder(participants=[agent]).with_start_agent(agent).build() - # Get the cloned agent from the workflow executor - cloned_executor = workflow.executors.get("test_agent") - assert cloned_executor is not None, "Agent executor should exist in workflow" + # Run workflow with a simple message to trigger context provider + events = await _drain(workflow.run("Test message", stream=True)) - # Verify the context_provider is preserved in the cloned agent - # The executor wraps the agent in the _agent property - assert hasattr(cloned_executor, '_agent'), "Executor should have _agent property" - cloned_agent = cloned_executor._agent - assert cloned_agent.context_provider is context_provider, ( - "Context provider should be preserved when cloning agent for handoff workflow" + # 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" ) From f825c35e850042b6a5ce3573160c47e855dd1d95 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 14:49:59 +0000 Subject: [PATCH 5/6] Remove unused events variable in test_context_provider_preserved_during_handoff Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com> --- python/packages/orchestrations/tests/test_handoff.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/packages/orchestrations/tests/test_handoff.py b/python/packages/orchestrations/tests/test_handoff.py index c000f559c8..1106be879a 100644 --- a/python/packages/orchestrations/tests/test_handoff.py +++ b/python/packages/orchestrations/tests/test_handoff.py @@ -338,7 +338,7 @@ async def invoking(self, messages: Sequence[ChatMessage], **kwargs: Any) -> Cont workflow = HandoffBuilder(participants=[agent]).with_start_agent(agent).build() # Run workflow with a simple message to trigger context provider - events = await _drain(workflow.run("Test message", stream=True)) + await _drain(workflow.run("Test message", stream=True)) # Verify context provider was invoked during the workflow execution assert len(provider_calls) > 0, ( From bbeba1b7d4a1e28aa61cf6cc628a61774b1b7016 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:18:47 +0000 Subject: [PATCH 6/6] Fix formatting: remove trailing whitespace from test_handoff.py Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com> --- python/packages/orchestrations/tests/test_handoff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/packages/orchestrations/tests/test_handoff.py b/python/packages/orchestrations/tests/test_handoff.py index 1106be879a..67a65007f9 100644 --- a/python/packages/orchestrations/tests/test_handoff.py +++ b/python/packages/orchestrations/tests/test_handoff.py @@ -322,7 +322,7 @@ async def invoking(self, messages: Sequence[ChatMessage], **kwargs: Any) -> Cont # 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, @@ -339,7 +339,7 @@ async def invoking(self, messages: Sequence[ChatMessage], **kwargs: Any) -> Cont # 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, "