diff --git a/python/packages/a2a/agent_framework_a2a/_agent.py b/python/packages/a2a/agent_framework_a2a/_agent.py index 2bdc5c6198..ba534436d6 100644 --- a/python/packages/a2a/agent_framework_a2a/_agent.py +++ b/python/packages/a2a/agent_framework_a2a/_agent.py @@ -26,8 +26,8 @@ from a2a.types import Message as A2AMessage from a2a.types import Part as A2APart from a2a.types import Role as A2ARole from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, ChatMessage, @@ -193,11 +193,11 @@ class A2AAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Get a response from the agent. This method returns the final result of the agent's execution - as a single AgentRunResponse object. The caller is blocked until + as a single AgentResponse object. The caller is blocked until the final result is available. Args: @@ -212,7 +212,7 @@ class A2AAgent(BaseAgent): """ # Collect all updates and use framework to consolidate updates into response updates = [update async for update in self.run_stream(messages, thread=thread, **kwargs)] - return AgentRunResponse.from_agent_run_response_updates(updates) + return AgentResponse.from_agent_run_response_updates(updates) async def run_stream( self, @@ -220,11 +220,11 @@ class A2AAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Run the agent as a stream. This method will return the intermediate steps and final results of the - agent's execution as a stream of AgentRunResponseUpdate objects to the caller. + agent's execution as a stream of AgentResponseUpdate objects to the caller. Args: messages: The message(s) to send to the agent. @@ -245,7 +245,7 @@ class A2AAgent(BaseAgent): if isinstance(item, Message): # Process A2A Message contents = self._parse_contents_from_a2a(item.parts) - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=contents, role=Role.ASSISTANT if item.role == A2ARole.agent else Role.USER, response_id=str(getattr(item, "message_id", uuid.uuid4())), @@ -260,7 +260,7 @@ class A2AAgent(BaseAgent): for message in task_messages: # Use the artifact's ID from raw_representation as message_id for unique identification artifact_id = getattr(message.raw_representation, "artifact_id", None) - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=message.contents, role=message.role, response_id=task.id, @@ -269,7 +269,7 @@ class A2AAgent(BaseAgent): ) else: # Empty task - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[], role=Role.ASSISTANT, response_id=task.id, diff --git a/python/packages/a2a/tests/test_a2a_agent.py b/python/packages/a2a/tests/test_a2a_agent.py index 58ab18fee4..5d77345b20 100644 --- a/python/packages/a2a/tests/test_a2a_agent.py +++ b/python/packages/a2a/tests/test_a2a_agent.py @@ -21,8 +21,8 @@ from a2a.types import ( ) from a2a.types import Role as A2ARole from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, ChatMessage, DataContent, ErrorContent, @@ -131,7 +131,7 @@ async def test_run_with_message_response(a2a_agent: A2AAgent, mock_a2a_client: M response = await a2a_agent.run("Hello agent") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert len(response.messages) == 1 assert response.messages[0].role == Role.ASSISTANT assert response.messages[0].text == "Hello from agent!" @@ -146,7 +146,7 @@ async def test_run_with_task_response_single_artifact(a2a_agent: A2AAgent, mock_ response = await a2a_agent.run("Generate a report") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert len(response.messages) == 1 assert response.messages[0].role == Role.ASSISTANT assert response.messages[0].text == "Generated report content" @@ -165,7 +165,7 @@ async def test_run_with_task_response_multiple_artifacts(a2a_agent: A2AAgent, mo response = await a2a_agent.run("Generate multiple outputs") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert len(response.messages) == 3 assert response.messages[0].text == "First artifact content" @@ -185,7 +185,7 @@ async def test_run_with_task_response_no_artifacts(a2a_agent: A2AAgent, mock_a2a response = await a2a_agent.run("Do something with no output") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.response_id == "task-empty" @@ -357,13 +357,13 @@ async def test_run_stream_with_message_response(a2a_agent: A2AAgent, mock_a2a_cl mock_a2a_client.add_message_response("msg-stream-123", "Streaming response from agent!", "agent") # Collect streaming updates - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in a2a_agent.run_stream("Hello agent"): updates.append(update) # Verify streaming response assert len(updates) == 1 - assert isinstance(updates[0], AgentRunResponseUpdate) + assert isinstance(updates[0], AgentResponseUpdate) assert updates[0].role == Role.ASSISTANT assert len(updates[0].contents) == 1 diff --git a/python/packages/ag-ui/agent_framework_ag_ui/_events.py b/python/packages/ag-ui/agent_framework_ag_ui/_events.py index 812c99064d..ddf3ebba01 100644 --- a/python/packages/ag-ui/agent_framework_ag_ui/_events.py +++ b/python/packages/ag-ui/agent_framework_ag_ui/_events.py @@ -24,7 +24,7 @@ from ag_ui.core import ( ToolCallStartEvent, ) from agent_framework import ( - AgentRunResponseUpdate, + AgentResponseUpdate, FunctionApprovalRequestContent, FunctionCallContent, FunctionResultContent, @@ -81,9 +81,9 @@ class AgentFrameworkEventBridge: self.should_stop_after_confirm: bool = False # Flag to stop run after confirm_changes self.suppressed_summary: str = "" # Store LLM summary to show after confirmation - async def from_agent_run_update(self, update: AgentRunResponseUpdate) -> list[BaseEvent]: + async def from_agent_run_update(self, update: AgentResponseUpdate) -> list[BaseEvent]: """ - Convert an AgentRunResponseUpdate to AG-UI events. + Convert an AgentResponseUpdate to AG-UI events. Args: update: The agent run update to convert. diff --git a/python/packages/ag-ui/agent_framework_ag_ui/_orchestrators.py b/python/packages/ag-ui/agent_framework_ag_ui/_orchestrators.py index feba6f8a29..b2b1c68222 100644 --- a/python/packages/ag-ui/agent_framework_ag_ui/_orchestrators.py +++ b/python/packages/ag-ui/agent_framework_ag_ui/_orchestrators.py @@ -646,11 +646,11 @@ class DefaultOrchestrator(Orchestrator): yield end_event if response_format and all_updates: - from agent_framework import AgentRunResponse + from agent_framework import AgentResponse from pydantic import BaseModel logger.info(f"Processing structured output, update count: {len(all_updates)}") - final_response = AgentRunResponse.from_agent_run_response_updates( + final_response = AgentResponse.from_agent_run_response_updates( all_updates, output_format_type=response_format ) diff --git a/python/packages/ag-ui/agent_framework_ag_ui_examples/README.md b/python/packages/ag-ui/agent_framework_ag_ui_examples/README.md index 620f18dbbf..e9d6d4ed17 100644 --- a/python/packages/ag-ui/agent_framework_ag_ui_examples/README.md +++ b/python/packages/ag-ui/agent_framework_ag_ui_examples/README.md @@ -169,7 +169,7 @@ The package uses a clean, orchestrator-based architecture: - **AgentFrameworkAgent**: Lightweight wrapper that delegates to orchestrators - **Orchestrators**: Handle different execution flows (default, human-in-the-loop, etc.) - **Confirmation Strategies**: Domain-specific confirmation messages (extensible) -- **AgentFrameworkEventBridge**: Converts AgentRunResponseUpdate to AG-UI events +- **AgentFrameworkEventBridge**: Converts AgentResponseUpdate to AG-UI events - **Message Adapters**: Bidirectional conversion between AG-UI and Agent Framework message formats - **FastAPI Endpoint**: Streaming HTTP endpoint with Server-Sent Events (SSE) @@ -198,10 +198,10 @@ def my_tool(param: str) -> str: def my_custom_agent(chat_client: ChatClientProtocol) -> AgentFrameworkAgent: """Create a custom agent with the specified chat client. - + Args: chat_client: The chat client to use for the agent - + Returns: A configured AgentFrameworkAgent instance """ @@ -211,7 +211,7 @@ def my_custom_agent(chat_client: ChatClientProtocol) -> AgentFrameworkAgent: chat_client=chat_client, tools=[my_tool], ) - + return AgentFrameworkAgent( agent=agent, name="MyCustomAgent", @@ -302,13 +302,13 @@ from agent_framework.ag_ui import AgentFrameworkAgent, ConfirmationStrategy class CustomConfirmationStrategy(ConfirmationStrategy): def on_approval_accepted(self, steps: list[dict[str, Any]]) -> str: return "Your custom approval message!" - + def on_approval_rejected(self, steps: list[dict[str, Any]]) -> str: return "Your custom rejection message!" - + def on_state_confirmed(self) -> str: return "State changes confirmed!" - + def on_state_rejected(self) -> str: return "State changes rejected!" @@ -349,7 +349,7 @@ class MyCustomOrchestrator(Orchestrator): def can_handle(self, context: ExecutionContext) -> bool: # Return True if this orchestrator should handle the request return context.input_data.get("custom_mode") == True - + async def run(self, context: ExecutionContext): # Custom execution logic yield RunStartedEvent(...) diff --git a/python/packages/ag-ui/tests/test_backend_tool_rendering.py b/python/packages/ag-ui/tests/test_backend_tool_rendering.py index 97654182cf..446da23ff2 100644 --- a/python/packages/ag-ui/tests/test_backend_tool_rendering.py +++ b/python/packages/ag-ui/tests/test_backend_tool_rendering.py @@ -12,7 +12,7 @@ from ag_ui.core import ( ToolCallResultEvent, ToolCallStartEvent, ) -from agent_framework import AgentRunResponseUpdate, FunctionCallContent, FunctionResultContent, TextContent +from agent_framework import AgentResponseUpdate, FunctionCallContent, FunctionResultContent, TextContent from agent_framework_ag_ui._events import AgentFrameworkEventBridge @@ -28,7 +28,7 @@ async def test_tool_call_flow(): arguments={"location": "Seattle"}, ) - update1 = AgentRunResponseUpdate(contents=[tool_call]) + update1 = AgentResponseUpdate(contents=[tool_call]) events1 = await bridge.from_agent_run_update(update1) # Should have: ToolCallStartEvent, ToolCallArgsEvent @@ -49,7 +49,7 @@ async def test_tool_call_flow(): result="Weather in Seattle: Rainy, 52°F", ) - update2 = AgentRunResponseUpdate(contents=[tool_result]) + update2 = AgentResponseUpdate(contents=[tool_result]) events2 = await bridge.from_agent_run_update(update2) # Should have: ToolCallEndEvent, ToolCallResultEvent @@ -78,7 +78,7 @@ async def test_text_with_tool_call(): arguments={"location": "San Francisco", "days": 3}, ) - update = AgentRunResponseUpdate(contents=[text_content, tool_call]) + update = AgentResponseUpdate(contents=[text_content, tool_call]) events = await bridge.from_agent_run_update(update) # Should have: TextMessageStart, TextMessageContent, ToolCallStart, ToolCallArgs @@ -107,7 +107,7 @@ async def test_multiple_tool_results(): FunctionResultContent(call_id="tool-3", result="Result 3"), ] - update = AgentRunResponseUpdate(contents=results) + update = AgentResponseUpdate(contents=results) events = await bridge.from_agent_run_update(update) # Should have 3 pairs of ToolCallEndEvent + ToolCallResultEvent = 6 events diff --git a/python/packages/ag-ui/tests/test_document_writer_flow.py b/python/packages/ag-ui/tests/test_document_writer_flow.py index 01ab789c20..2e5cec9f95 100644 --- a/python/packages/ag-ui/tests/test_document_writer_flow.py +++ b/python/packages/ag-ui/tests/test_document_writer_flow.py @@ -3,7 +3,7 @@ """Tests for document writer predictive state flow with confirm_changes.""" from ag_ui.core import EventType, StateDeltaEvent, ToolCallArgsEvent, ToolCallEndEvent, ToolCallStartEvent -from agent_framework import AgentRunResponseUpdate, FunctionCallContent, FunctionResultContent, TextContent +from agent_framework import AgentResponseUpdate, FunctionCallContent, FunctionResultContent, TextContent from agent_framework_ag_ui._events import AgentFrameworkEventBridge @@ -26,7 +26,7 @@ async def test_streaming_document_with_state_deltas(): name="write_document_local", arguments='{"document":"Once', ) - update1 = AgentRunResponseUpdate(contents=[tool_call_start]) + update1 = AgentResponseUpdate(contents=[tool_call_start]) events1 = await bridge.from_agent_run_update(update1) # Should have ToolCallStartEvent and ToolCallArgsEvent @@ -35,7 +35,7 @@ async def test_streaming_document_with_state_deltas(): # Second chunk - incomplete JSON, should try partial extraction tool_call_chunk2 = FunctionCallContent(call_id="call_123", name="write_document_local", arguments=" upon a time") - update2 = AgentRunResponseUpdate(contents=[tool_call_chunk2]) + update2 = AgentResponseUpdate(contents=[tool_call_chunk2]) events2 = await bridge.from_agent_run_update(update2) # Should emit StateDeltaEvent with partial document @@ -76,7 +76,7 @@ async def test_confirm_changes_emission(): result="Document written.", ) - update = AgentRunResponseUpdate(contents=[tool_result]) + update = AgentResponseUpdate(contents=[tool_result]) events = await bridge.from_agent_run_update(update) # Should have: ToolCallEndEvent, ToolCallResultEvent, StateSnapshotEvent, confirm_changes sequence @@ -116,7 +116,7 @@ async def test_text_suppression_before_confirm(): # Text content that should be suppressed text = TextContent(text="I have written a story about pirates.") - update = AgentRunResponseUpdate(contents=[text]) + update = AgentResponseUpdate(contents=[text]) events = await bridge.from_agent_run_update(update) @@ -151,7 +151,7 @@ async def test_no_confirm_for_non_predictive_tools(): result="Sunny, 72°F", ) - update = AgentRunResponseUpdate(contents=[tool_result]) + update = AgentResponseUpdate(contents=[tool_result]) events = await bridge.from_agent_run_update(update) # Should NOT have confirm_changes @@ -180,7 +180,7 @@ async def test_state_delta_deduplication(): name="write_document_local", arguments='{"document":"Same text"}', ) - update1 = AgentRunResponseUpdate(contents=[tool_call1]) + update1 = AgentResponseUpdate(contents=[tool_call1]) events1 = await bridge.from_agent_run_update(update1) # Count state deltas @@ -194,7 +194,7 @@ async def test_state_delta_deduplication(): name="write_document_local", arguments='{"document":"Same text"}', # Identical content ) - update2 = AgentRunResponseUpdate(contents=[tool_call2]) + update2 = AgentResponseUpdate(contents=[tool_call2]) events2 = await bridge.from_agent_run_update(update2) # Should NOT emit state delta (same value) @@ -221,7 +221,7 @@ async def test_predict_state_config_multiple_fields(): name="create_post", arguments='{"title":"My Post","body":"Post content"}', ) - update = AgentRunResponseUpdate(contents=[tool_call]) + update = AgentResponseUpdate(contents=[tool_call]) events = await bridge.from_agent_run_update(update) # Should emit StateDeltaEvent for both fields diff --git a/python/packages/ag-ui/tests/test_events_comprehensive.py b/python/packages/ag-ui/tests/test_events_comprehensive.py index 30d302e7be..295ba00372 100644 --- a/python/packages/ag-ui/tests/test_events_comprehensive.py +++ b/python/packages/ag-ui/tests/test_events_comprehensive.py @@ -5,7 +5,7 @@ import json from agent_framework import ( - AgentRunResponseUpdate, + AgentResponseUpdate, FunctionApprovalRequestContent, FunctionCallContent, FunctionResultContent, @@ -19,7 +19,7 @@ async def test_basic_text_message_conversion(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate(contents=[TextContent(text="Hello")]) + update = AgentResponseUpdate(contents=[TextContent(text="Hello")]) events = await bridge.from_agent_run_update(update) assert len(events) == 2 @@ -35,8 +35,8 @@ async def test_text_message_streaming(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update1 = AgentRunResponseUpdate(contents=[TextContent(text="Hello ")]) - update2 = AgentRunResponseUpdate(contents=[TextContent(text="world")]) + update1 = AgentResponseUpdate(contents=[TextContent(text="Hello ")]) + update2 = AgentResponseUpdate(contents=[TextContent(text="world")]) events1 = await bridge.from_agent_run_update(update1) events2 = await bridge.from_agent_run_update(update2) @@ -61,7 +61,7 @@ async def test_skip_text_content_for_structured_outputs(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread", skip_text_content=True) - update = AgentRunResponseUpdate(contents=[TextContent(text='{"result": "data"}')]) + update = AgentResponseUpdate(contents=[TextContent(text='{"result": "data"}')]) events = await bridge.from_agent_run_update(update) # No events should be emitted @@ -74,9 +74,9 @@ async def test_skip_text_content_for_empty_text(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update1 = AgentRunResponseUpdate(contents=[TextContent(text="Hello ")]) - update2 = AgentRunResponseUpdate(contents=[TextContent(text="")]) # Empty chunk - update3 = AgentRunResponseUpdate(contents=[TextContent(text="world")]) + update1 = AgentResponseUpdate(contents=[TextContent(text="Hello ")]) + update2 = AgentResponseUpdate(contents=[TextContent(text="")]) # Empty chunk + update3 = AgentResponseUpdate(contents=[TextContent(text="world")]) events1 = await bridge.from_agent_run_update(update1) events2 = await bridge.from_agent_run_update(update2) @@ -105,7 +105,7 @@ async def test_tool_call_with_name(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate(contents=[FunctionCallContent(name="search_web", call_id="call_123")]) + update = AgentResponseUpdate(contents=[FunctionCallContent(name="search_web", call_id="call_123")]) events = await bridge.from_agent_run_update(update) assert len(events) == 1 @@ -121,17 +121,15 @@ async def test_tool_call_streaming_args(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") # First chunk: name only - update1 = AgentRunResponseUpdate(contents=[FunctionCallContent(name="search_web", call_id="call_123")]) + update1 = AgentResponseUpdate(contents=[FunctionCallContent(name="search_web", call_id="call_123")]) events1 = await bridge.from_agent_run_update(update1) # Second chunk: arguments chunk 1 (name can be empty string for continuation) - update2 = AgentRunResponseUpdate( - contents=[FunctionCallContent(name="", call_id="call_123", arguments='{"query": "')] - ) + update2 = AgentResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_123", arguments='{"query": "')]) events2 = await bridge.from_agent_run_update(update2) # Third chunk: arguments chunk 2 - update3 = AgentRunResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_123", arguments='AI"}')]) + update3 = AgentResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_123", arguments='AI"}')]) events3 = await bridge.from_agent_run_update(update3) # First update: ToolCallStartEvent @@ -169,9 +167,9 @@ async def test_streaming_tool_call_no_duplicate_start_events(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") # Simulate streaming tool call: first chunk has name, subsequent chunks have name="" - update1 = AgentRunResponseUpdate(contents=[FunctionCallContent(name="get_weather", call_id="call_789")]) - update2 = AgentRunResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_789", arguments='{"loc":')]) - update3 = AgentRunResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_789", arguments='"SF"}')]) + update1 = AgentResponseUpdate(contents=[FunctionCallContent(name="get_weather", call_id="call_789")]) + update2 = AgentResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_789", arguments='{"loc":')]) + update3 = AgentResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_789", arguments='"SF"}')]) events1 = await bridge.from_agent_run_update(update1) events2 = await bridge.from_agent_run_update(update2) @@ -195,7 +193,7 @@ async def test_tool_result_with_dict(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") result_data = {"status": "success", "count": 42} - update = AgentRunResponseUpdate(contents=[FunctionResultContent(call_id="call_123", result=result_data)]) + update = AgentResponseUpdate(contents=[FunctionResultContent(call_id="call_123", result=result_data)]) events = await bridge.from_agent_run_update(update) # Should emit ToolCallEndEvent + ToolCallResultEvent @@ -216,7 +214,7 @@ async def test_tool_result_with_string(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate(contents=[FunctionResultContent(call_id="call_123", result="Search complete")]) + update = AgentResponseUpdate(contents=[FunctionResultContent(call_id="call_123", result="Search complete")]) events = await bridge.from_agent_run_update(update) assert len(events) == 2 @@ -231,7 +229,7 @@ async def test_tool_result_with_none(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate(contents=[FunctionResultContent(call_id="call_123", result=None)]) + update = AgentResponseUpdate(contents=[FunctionResultContent(call_id="call_123", result=None)]) events = await bridge.from_agent_run_update(update) assert len(events) == 2 @@ -247,7 +245,7 @@ async def test_multiple_tool_results_in_sequence(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[ FunctionResultContent(call_id="call_1", result="Result 1"), FunctionResultContent(call_id="call_2", result="Result 2"), @@ -284,7 +282,7 @@ async def test_function_approval_request_basic(): function_call=func_call, ) - update = AgentRunResponseUpdate(contents=[approval]) + update = AgentResponseUpdate(contents=[approval]) events = await bridge.from_agent_run_update(update) # Should emit: ToolCallEndEvent + CustomEvent @@ -312,7 +310,7 @@ async def test_empty_predict_state_config(): ) # Tool call with arguments - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[ FunctionCallContent(name="write_doc", call_id="call_1", arguments='{"content": "test"}'), FunctionResultContent(call_id="call_1", result="Done"), @@ -347,7 +345,7 @@ async def test_tool_not_in_predict_state_config(): ) # Different tool name - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[ FunctionCallContent(name="search_web", call_id="call_1", arguments='{"query": "AI"}'), FunctionResultContent(call_id="call_1", result="Results"), @@ -376,7 +374,7 @@ async def test_state_management_tracking(): ) # Streaming tool call - update1 = AgentRunResponseUpdate( + update1 = AgentResponseUpdate( contents=[ FunctionCallContent(name="write_doc", call_id="call_1"), FunctionCallContent(name="", call_id="call_1", arguments='{"content": "Hello"}'), @@ -389,7 +387,7 @@ async def test_state_management_tracking(): assert bridge.pending_state_updates["document"] == "Hello" # Tool result should update current_state - update2 = AgentRunResponseUpdate(contents=[FunctionResultContent(call_id="call_1", result="Done")]) + update2 = AgentResponseUpdate(contents=[FunctionResultContent(call_id="call_1", result="Done")]) await bridge.from_agent_run_update(update2) # current_state should be updated @@ -413,7 +411,7 @@ async def test_wildcard_tool_argument(): ) # Complete tool call with dict arguments - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[ FunctionCallContent( name="create_recipe", @@ -503,7 +501,7 @@ async def test_state_snapshot_after_tool_result(): ) # Tool call with streaming args - update1 = AgentRunResponseUpdate( + update1 = AgentResponseUpdate( contents=[ FunctionCallContent(name="write_doc", call_id="call_1"), FunctionCallContent(name="", call_id="call_1", arguments='{"content": "Test"}'), @@ -512,7 +510,7 @@ async def test_state_snapshot_after_tool_result(): await bridge.from_agent_run_update(update1) # Tool result should trigger StateSnapshotEvent - update2 = AgentRunResponseUpdate(contents=[FunctionResultContent(call_id="call_1", result="Done")]) + update2 = AgentResponseUpdate(contents=[FunctionResultContent(call_id="call_1", result="Done")]) events = await bridge.from_agent_run_update(update2) # Should have: ToolCallEnd, ToolCallResult, StateSnapshot, ToolCallStart (confirm_changes), ToolCallArgs, ToolCallEnd @@ -528,12 +526,12 @@ async def test_message_id_persistence_across_chunks(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") # First chunk - update1 = AgentRunResponseUpdate(contents=[TextContent(text="Hello ")]) + update1 = AgentResponseUpdate(contents=[TextContent(text="Hello ")]) events1 = await bridge.from_agent_run_update(update1) message_id = events1[0].message_id # Second chunk - update2 = AgentRunResponseUpdate(contents=[TextContent(text="world")]) + update2 = AgentResponseUpdate(contents=[TextContent(text="world")]) events2 = await bridge.from_agent_run_update(update2) # Should use same message_id @@ -548,14 +546,14 @@ async def test_tool_call_id_tracking(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") # First chunk with name - update1 = AgentRunResponseUpdate(contents=[FunctionCallContent(name="search", call_id="call_1")]) + update1 = AgentResponseUpdate(contents=[FunctionCallContent(name="search", call_id="call_1")]) await bridge.from_agent_run_update(update1) assert bridge.current_tool_call_id == "call_1" assert bridge.current_tool_call_name == "search" # Second chunk with args but no name - update2 = AgentRunResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_1", arguments='{"q":"AI"}')]) + update2 = AgentResponseUpdate(contents=[FunctionCallContent(name="", call_id="call_1", arguments='{"q":"AI"}')]) events2 = await bridge.from_agent_run_update(update2) # Should still track same tool call @@ -576,7 +574,7 @@ async def test_tool_name_reset_after_result(): ) # Tool call - update1 = AgentRunResponseUpdate( + update1 = AgentResponseUpdate( contents=[ FunctionCallContent(name="write_doc", call_id="call_1"), FunctionCallContent(name="", call_id="call_1", arguments='{"content": "Test"}'), @@ -587,7 +585,7 @@ async def test_tool_name_reset_after_result(): assert bridge.current_tool_call_name == "write_doc" # Tool result with predictive state (should trigger confirm_changes and reset) - update2 = AgentRunResponseUpdate(contents=[FunctionResultContent(call_id="call_1", result="Done")]) + update2 = AgentResponseUpdate(contents=[FunctionResultContent(call_id="call_1", result="Done")]) await bridge.from_agent_run_update(update2) # Tool name should be reset @@ -613,7 +611,7 @@ async def test_function_approval_with_wildcard_argument(): ), ) - update = AgentRunResponseUpdate(contents=[approval_content]) + update = AgentResponseUpdate(contents=[approval_content]) events = await bridge.from_agent_run_update(update) # Should emit StateSnapshotEvent with entire parsed args as value @@ -639,7 +637,7 @@ async def test_function_approval_missing_argument(): function_call=FunctionCallContent(name="process", call_id="call_1", arguments='{"other_field": "value"}'), ) - update = AgentRunResponseUpdate(contents=[approval_content]) + update = AgentResponseUpdate(contents=[approval_content]) events = await bridge.from_agent_run_update(update) # Should not emit StateSnapshotEvent since argument not found @@ -654,7 +652,7 @@ async def test_empty_predict_state_config_no_deltas(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread", predict_state_config={}) # Tool call with arguments - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[ FunctionCallContent(name="search", call_id="call_1"), FunctionCallContent(name="", call_id="call_1", arguments='{"query": "test"}'), @@ -678,7 +676,7 @@ async def test_tool_with_no_matching_config(): ) # Tool call for different tool - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[ FunctionCallContent(name="search_web", call_id="call_1"), FunctionCallContent(name="", call_id="call_1", arguments='{"query": "test"}'), @@ -698,7 +696,7 @@ async def test_tool_call_without_name_or_id(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") # This should not crash but log an error - update = AgentRunResponseUpdate(contents=[FunctionCallContent(name="", call_id="", arguments='{"arg": "val"}')]) + update = AgentResponseUpdate(contents=[FunctionCallContent(name="", call_id="", arguments='{"arg": "val"}')]) events = await bridge.from_agent_run_update(update) # Should emit ToolCallArgsEvent with generated ID @@ -717,7 +715,7 @@ async def test_state_delta_count_logging(): # Emit multiple state deltas with different content each time for i in range(15): - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[ FunctionCallContent(name="", call_id="call_1", arguments=f'{{"text": "Content variation {i}"}}'), ] @@ -739,7 +737,7 @@ async def test_tool_result_with_empty_list(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate(contents=[FunctionResultContent(call_id="call_123", result=[])]) + update = AgentResponseUpdate(contents=[FunctionResultContent(call_id="call_123", result=[])]) events = await bridge.from_agent_run_update(update) assert len(events) == 2 @@ -761,7 +759,7 @@ async def test_tool_result_with_single_text_content(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[FunctionResultContent(call_id="call_123", result=[MockTextContent("Hello from MCP tool!")])] ) events = await bridge.from_agent_run_update(update) @@ -785,7 +783,7 @@ async def test_tool_result_with_multiple_text_contents(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[ FunctionResultContent( call_id="call_123", @@ -813,7 +811,7 @@ async def test_tool_result_with_model_dump_objects(): bridge = AgentFrameworkEventBridge(run_id="test_run", thread_id="test_thread") - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[FunctionResultContent(call_id="call_123", result=[MockModel(value=1), MockModel(value=2)])] ) events = await bridge.from_agent_run_update(update) diff --git a/python/packages/ag-ui/tests/test_human_in_the_loop.py b/python/packages/ag-ui/tests/test_human_in_the_loop.py index 8e932d4aea..00e64472b6 100644 --- a/python/packages/ag-ui/tests/test_human_in_the_loop.py +++ b/python/packages/ag-ui/tests/test_human_in_the_loop.py @@ -2,7 +2,7 @@ """Tests for human in the loop (function approval requests).""" -from agent_framework import AgentRunResponseUpdate, FunctionApprovalRequestContent, FunctionCallContent +from agent_framework import AgentResponseUpdate, FunctionApprovalRequestContent, FunctionCallContent from agent_framework_ag_ui._events import AgentFrameworkEventBridge @@ -27,7 +27,7 @@ async def test_function_approval_request_emission(): function_call=func_call, ) - update = AgentRunResponseUpdate(contents=[approval_request]) + update = AgentResponseUpdate(contents=[approval_request]) events = await bridge.from_agent_run_update(update) # Should emit ToolCallEndEvent + CustomEvent for approval request @@ -66,7 +66,7 @@ async def test_function_approval_request_with_confirm_changes(): function_call=func_call, ) - update = AgentRunResponseUpdate(contents=[approval_request]) + update = AgentResponseUpdate(contents=[approval_request]) events = await bridge.from_agent_run_update(update) # Should emit: ToolCallEndEvent, CustomEvent, and confirm_changes (Start, Args, End) = 5 events @@ -129,7 +129,7 @@ async def test_multiple_approval_requests(): function_call=func_call_2, ) - update = AgentRunResponseUpdate(contents=[approval_1, approval_2]) + update = AgentResponseUpdate(contents=[approval_1, approval_2]) events = await bridge.from_agent_run_update(update) # Should emit ToolCallEndEvent + CustomEvent for each approval (4 events total) @@ -174,7 +174,7 @@ async def test_function_approval_request_sets_stop_flag(): function_call=func_call, ) - update = AgentRunResponseUpdate(contents=[approval_request]) + update = AgentResponseUpdate(contents=[approval_request]) await bridge.from_agent_run_update(update) assert bridge.should_stop_after_confirm is True diff --git a/python/packages/ag-ui/tests/test_orchestrators.py b/python/packages/ag-ui/tests/test_orchestrators.py index b1d1a21315..dc9420f15a 100644 --- a/python/packages/ag-ui/tests/test_orchestrators.py +++ b/python/packages/ag-ui/tests/test_orchestrators.py @@ -6,7 +6,7 @@ from collections.abc import AsyncGenerator from types import SimpleNamespace from typing import Any -from agent_framework import AgentRunResponseUpdate, FunctionInvocationConfiguration, TextContent, ai_function +from agent_framework import AgentResponseUpdate, FunctionInvocationConfiguration, TextContent, ai_function from agent_framework_ag_ui._agent import AgentConfig from agent_framework_ag_ui._orchestrators import DefaultOrchestrator, ExecutionContext @@ -36,9 +36,9 @@ class DummyAgent: thread: Any, tools: list[Any] | None = None, **kwargs: Any, - ) -> AsyncGenerator[AgentRunResponseUpdate, None]: + ) -> AsyncGenerator[AgentResponseUpdate, None]: self.seen_tools = tools - yield AgentRunResponseUpdate(contents=[TextContent(text="ok")], role="assistant") + yield AgentResponseUpdate(contents=[TextContent(text="ok")], role="assistant") class RecordingAgent: @@ -59,9 +59,9 @@ class RecordingAgent: thread: Any, tools: list[Any] | None = None, **kwargs: Any, - ) -> AsyncGenerator[AgentRunResponseUpdate, None]: + ) -> AsyncGenerator[AgentResponseUpdate, None]: self.seen_messages = messages - yield AgentRunResponseUpdate(contents=[TextContent(text="ok")], role="assistant") + yield AgentResponseUpdate(contents=[TextContent(text="ok")], role="assistant") async def test_default_orchestrator_merges_client_tools() -> None: diff --git a/python/packages/ag-ui/tests/test_orchestrators_coverage.py b/python/packages/ag-ui/tests/test_orchestrators_coverage.py index 1b63d35bfa..6c311d593a 100644 --- a/python/packages/ag-ui/tests/test_orchestrators_coverage.py +++ b/python/packages/ag-ui/tests/test_orchestrators_coverage.py @@ -9,7 +9,7 @@ from types import SimpleNamespace from typing import Any from agent_framework import ( - AgentRunResponseUpdate, + AgentResponseUpdate, ChatMessage, TextContent, ai_function, @@ -55,7 +55,7 @@ async def test_human_in_the_loop_json_decode_error() -> None: agent = StubAgent( default_options={"tools": [approval_tool], "response_format": None}, - updates=[AgentRunResponseUpdate(contents=[TextContent(text="response")], role="assistant")], + updates=[AgentResponseUpdate(contents=[TextContent(text="response")], role="assistant")], ) context = TestExecutionContext( input_data=input_data, @@ -451,7 +451,7 @@ async def test_structured_output_processing() -> None: agent = StubAgent( default_options=DEFAULT_OPTIONS, updates=[ - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[TextContent(text='{"ingredients": ["tomato"], "message": "Added tomato"}')], role="assistant", ) @@ -691,7 +691,7 @@ async def test_confirm_changes_closes_active_message_before_finish() -> None: from agent_framework import FunctionCallContent, FunctionResultContent updates = [ - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[ FunctionCallContent( name="write_document_local", @@ -700,7 +700,7 @@ async def test_confirm_changes_closes_active_message_before_finish() -> None: ) ] ), - AgentRunResponseUpdate(contents=[FunctionResultContent(call_id="call_1", result="Done")]), + AgentResponseUpdate(contents=[FunctionResultContent(call_id="call_1", result="Done")]), ] orchestrator = DefaultOrchestrator() @@ -792,9 +792,9 @@ async def test_agent_protocol_fallback_paths() -> None: thread: Any = None, tools: list[Any] | None = None, **kwargs: Any, - ) -> AsyncGenerator[AgentRunResponseUpdate, None]: + ) -> AsyncGenerator[AgentResponseUpdate, None]: self.messages_received = messages - yield AgentRunResponseUpdate(contents=[TextContent(text="response")], role="assistant") + yield AgentResponseUpdate(contents=[TextContent(text="response")], role="assistant") from agent_framework import ChatMessage, TextContent diff --git a/python/packages/ag-ui/tests/utils_test_ag_ui.py b/python/packages/ag-ui/tests/utils_test_ag_ui.py index b0f70f3dc8..c3fa590cd1 100644 --- a/python/packages/ag-ui/tests/utils_test_ag_ui.py +++ b/python/packages/ag-ui/tests/utils_test_ag_ui.py @@ -9,8 +9,8 @@ from typing import Any, Generic from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseChatClient, ChatMessage, @@ -81,7 +81,7 @@ class StubAgent(AgentProtocol): def __init__( self, - updates: list[AgentRunResponseUpdate] | None = None, + updates: list[AgentResponseUpdate] | None = None, *, agent_id: str = "stub-agent", agent_name: str | None = "stub-agent", @@ -91,7 +91,7 @@ class StubAgent(AgentProtocol): self.id = agent_id self.name = agent_name self.description = "stub agent" - self.updates = updates or [AgentRunResponseUpdate(contents=[TextContent(text="response")], role="assistant")] + self.updates = updates or [AgentResponseUpdate(contents=[TextContent(text="response")], role="assistant")] self.default_options: dict[str, Any] = ( default_options if isinstance(default_options, dict) else {"tools": None, "response_format": None} ) @@ -105,8 +105,8 @@ class StubAgent(AgentProtocol): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: - return AgentRunResponse(messages=[], response_id="stub-response") + ) -> AgentResponse: + return AgentResponse(messages=[], response_id="stub-response") def run_stream( self, @@ -114,8 +114,8 @@ class StubAgent(AgentProtocol): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: - async def _stream() -> AsyncIterator[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: + async def _stream() -> AsyncIterator[AgentResponseUpdate]: self.messages_received = [] if messages is None else list(messages) # type: ignore[arg-type] self.tools_received = kwargs.get("tools") for update in self.updates: diff --git a/python/packages/azure-ai/tests/test_azure_ai_agent_client.py b/python/packages/azure-ai/tests/test_azure_ai_agent_client.py index 87e52e7b32..2df00beae3 100644 --- a/python/packages/azure-ai/tests/test_azure_ai_agent_client.py +++ b/python/packages/azure-ai/tests/test_azure_ai_agent_client.py @@ -8,8 +8,8 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, AIFunction, ChatAgent, @@ -1544,7 +1544,7 @@ async def test_azure_ai_chat_client_agent_basic_run() -> None: response = await agent.run("Hello! Please respond with 'Hello World' exactly.") # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 assert "Hello World" in response.text @@ -1561,7 +1561,7 @@ async def test_azure_ai_chat_client_agent_basic_run_streaming() -> None: full_message: str = "" async for chunk in agent.run_stream("Please respond with exactly: 'This is a streaming response test.'"): assert chunk is not None - assert isinstance(chunk, AgentRunResponseUpdate) + assert isinstance(chunk, AgentResponseUpdate) if chunk.text: full_message += chunk.text @@ -1585,14 +1585,14 @@ async def test_azure_ai_chat_client_agent_thread_persistence() -> None: first_response = await agent.run( "Remember this number: 42. What number did I just tell you to remember?", thread=thread ) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert "42" in first_response.text # Second message - test conversation memory second_response = await agent.run( "What number did I tell you to remember in my previous message?", thread=thread ) - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert "42" in second_response.text @@ -1609,7 +1609,7 @@ async def test_azure_ai_chat_client_agent_existing_thread_id() -> None: first_response = await first_agent.run("My name is Alice. Remember this.", thread=thread) # Validate first response - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # The thread ID is set after the first response @@ -1628,7 +1628,7 @@ async def test_azure_ai_chat_client_agent_existing_thread_id() -> None: response2 = await second_agent.run("What is my name?", thread=thread) # Validate that the agent remembers the previous conversation - assert isinstance(response2, AgentRunResponse) + assert isinstance(response2, AgentResponse) assert response2.text is not None # Should reference Alice from the previous conversation assert "alice" in response2.text.lower() @@ -1648,7 +1648,7 @@ async def test_azure_ai_chat_client_agent_code_interpreter(): response = await agent.run("Write Python code to calculate the factorial of 5 and show the result.") # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None # Factorial of 5 is 120 assert "120" in response.text or "factorial" in response.text.lower() @@ -1683,7 +1683,7 @@ async def test_azure_ai_chat_client_agent_file_search(): response = await agent.run("Who is the youngest employee in the files?") # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None # Should find information about Alice Johnson (age 24) being the youngest assert any(term in response.text.lower() for term in ["alice", "johnson", "24"]) @@ -1723,7 +1723,7 @@ async def test_azure_ai_chat_client_agent_hosted_mcp_tool() -> None: options={"max_tokens": 200}, ) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 @@ -1748,7 +1748,7 @@ async def test_azure_ai_chat_client_agent_level_tool_persistence(): # First run - agent-level tool should be available first_response = await agent.run("What's the weather like in Chicago?") - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Should use the agent-level weather tool assert any(term in first_response.text.lower() for term in ["chicago", "sunny", "25"]) @@ -1756,7 +1756,7 @@ async def test_azure_ai_chat_client_agent_level_tool_persistence(): # Second run - agent-level tool should still be available (persistence test) second_response = await agent.run("What's the weather in Miami?") - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None # Should use the agent-level weather tool again assert any(term in second_response.text.lower() for term in ["miami", "sunny", "25"]) @@ -1781,7 +1781,7 @@ async def test_azure_ai_chat_client_agent_chat_options_run_level() -> None: }, ) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 @@ -1805,7 +1805,7 @@ async def test_azure_ai_chat_client_agent_chat_options_agent_level() -> None: "Provide a brief, helpful response.", ) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 diff --git a/python/packages/azure-ai/tests/test_azure_ai_client.py b/python/packages/azure-ai/tests/test_azure_ai_client.py index 57180715e1..5c6f83adcc 100644 --- a/python/packages/azure-ai/tests/test_azure_ai_client.py +++ b/python/packages/azure-ai/tests/test_azure_ai_client.py @@ -10,7 +10,7 @@ from uuid import uuid4 import pytest from agent_framework import ( - AgentRunResponse, + AgentResponse, ChatAgent, ChatClientProtocol, ChatMessage, @@ -1303,7 +1303,7 @@ async def test_integration_agent_existing_thread(): thread = first_agent.get_new_thread() first_response = await first_agent.run("My hobby is photography. Remember this.", thread=thread, store=True) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Preserve the thread for reuse @@ -1321,6 +1321,6 @@ async def test_integration_agent_existing_thread(): # Reuse the preserved thread second_response = await second_agent.run("What is my hobby?", thread=preserved_thread) - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None assert "photography" in second_response.text.lower() diff --git a/python/packages/azurefunctions/agent_framework_azurefunctions/_callbacks.py b/python/packages/azurefunctions/agent_framework_azurefunctions/_callbacks.py index 3e38cdb6ec..53c4c2d71a 100644 --- a/python/packages/azurefunctions/agent_framework_azurefunctions/_callbacks.py +++ b/python/packages/azurefunctions/agent_framework_azurefunctions/_callbacks.py @@ -9,7 +9,7 @@ invoked during durable entity execution. from dataclasses import dataclass from typing import Protocol -from agent_framework import AgentRunResponse, AgentRunResponseUpdate +from agent_framework import AgentResponse, AgentResponseUpdate @dataclass(frozen=True) @@ -27,14 +27,14 @@ class AgentResponseCallbackProtocol(Protocol): async def on_streaming_response_update( self, - update: AgentRunResponseUpdate, + update: AgentResponseUpdate, context: AgentCallbackContext, ) -> None: """Handle a streaming response update emitted by the agent.""" async def on_agent_response( self, - response: AgentRunResponse, + response: AgentResponse, context: AgentCallbackContext, ) -> None: """Handle the final agent response.""" diff --git a/python/packages/azurefunctions/agent_framework_azurefunctions/_durable_agent_state.py b/python/packages/azurefunctions/agent_framework_azurefunctions/_durable_agent_state.py index 8982e7b4f2..c84a30fbb4 100644 --- a/python/packages/azurefunctions/agent_framework_azurefunctions/_durable_agent_state.py +++ b/python/packages/azurefunctions/agent_framework_azurefunctions/_durable_agent_state.py @@ -35,7 +35,7 @@ from enum import Enum from typing import Any, cast from agent_framework import ( - AgentRunResponse, + AgentResponse, BaseContent, ChatMessage, DataContent, @@ -693,8 +693,8 @@ class DurableAgentStateResponse(DurableAgentStateEntry): ) @staticmethod - def from_run_response(correlation_id: str, response: AgentRunResponse) -> DurableAgentStateResponse: - """Creates a DurableAgentStateResponse from an AgentRunResponse.""" + def from_run_response(correlation_id: str, response: AgentResponse) -> DurableAgentStateResponse: + """Creates a DurableAgentStateResponse from an AgentResponse.""" return DurableAgentStateResponse( correlation_id=correlation_id, created_at=_parse_created_at(response.created_at), diff --git a/python/packages/azurefunctions/agent_framework_azurefunctions/_entities.py b/python/packages/azurefunctions/agent_framework_azurefunctions/_entities.py index 8be9fb8ded..f757004cbb 100644 --- a/python/packages/azurefunctions/agent_framework_azurefunctions/_entities.py +++ b/python/packages/azurefunctions/agent_framework_azurefunctions/_entities.py @@ -15,8 +15,8 @@ from typing import Any, cast import azure.durable_functions as df from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, ChatMessage, ErrorContent, Role, @@ -95,7 +95,7 @@ class AgentEntity: self, context: df.DurableEntityContext, request: RunRequest | dict[str, Any] | str, - ) -> AgentRunResponse: + ) -> AgentResponse: """(Deprecated) Execute the agent with a message directly in the entity. Args: @@ -103,7 +103,7 @@ class AgentEntity: request: RunRequest object, dict, or string message (for backward compatibility) Returns: - AgentRunResponse enriched with execution metadata. + AgentResponse enriched with execution metadata. """ return await self.run(context, request) @@ -111,7 +111,7 @@ class AgentEntity: self, context: df.DurableEntityContext, request: RunRequest | dict[str, Any] | str, - ) -> AgentRunResponse: + ) -> AgentResponse: """Execute the agent with a message directly in the entity. Args: @@ -119,7 +119,7 @@ class AgentEntity: request: RunRequest object, dict, or string message (for backward compatibility) Returns: - AgentRunResponse enriched with execution metadata. + AgentResponse enriched with execution metadata. """ if isinstance(request, str): run_request = RunRequest(message=request, role=Role.USER) @@ -159,7 +159,7 @@ class AgentEntity: if response_format: run_kwargs["options"]["response_format"] = response_format - agent_run_response: AgentRunResponse = await self._invoke_agent( + agent_response: AgentResponse = await self._invoke_agent( run_kwargs=run_kwargs, correlation_id=correlation_id, thread_id=thread_id, @@ -168,11 +168,11 @@ class AgentEntity: logger.debug( "[AgentEntity.run] Agent invocation completed - response type: %s", - type(agent_run_response).__name__, + type(agent_response).__name__, ) try: - response_text = agent_run_response.text if agent_run_response.text else "No response" + response_text = agent_response.text if agent_response.text else "No response" logger.debug(f"Response: {response_text[:100]}...") except Exception as extraction_error: logger.error( @@ -181,12 +181,12 @@ class AgentEntity: exc_info=True, ) - state_response = DurableAgentStateResponse.from_run_response(correlation_id, agent_run_response) + state_response = DurableAgentStateResponse.from_run_response(correlation_id, agent_response) self.state.data.conversation_history.append(state_response) - logger.debug("[AgentEntity.run] AgentRunResponse stored in conversation history") + logger.debug("[AgentEntity.run] AgentResponse stored in conversation history") - return agent_run_response + return agent_response except Exception as exc: logger.exception("[AgentEntity.run] Agent execution failed.") @@ -196,7 +196,7 @@ class AgentEntity: role=Role.ASSISTANT, contents=[ErrorContent(message=str(exc), error_code=type(exc).__name__)] ) - error_response = AgentRunResponse(messages=[error_message]) + error_response = AgentResponse(messages=[error_message]) # Create and store error response in conversation history error_state_response = DurableAgentStateResponse.from_run_response(correlation_id, error_response) @@ -211,7 +211,7 @@ class AgentEntity: correlation_id: str, thread_id: str, request_message: str, - ) -> AgentRunResponse: + ) -> AgentResponse: """Execute the agent, preferring streaming when available.""" callback_context: AgentCallbackContext | None = None if self.callback is not None: @@ -229,7 +229,7 @@ class AgentEntity: stream_candidate = await stream_candidate return await self._consume_stream( - stream=cast(AsyncIterable[AgentRunResponseUpdate], stream_candidate), + stream=cast(AsyncIterable[AgentResponseUpdate], stream_candidate), callback_context=callback_context, ) except TypeError as type_error: @@ -248,32 +248,32 @@ class AgentEntity: else: logger.debug("Agent does not expose run_stream; falling back to run().") - agent_run_response = await self._invoke_non_stream(run_kwargs) - await self._notify_final_response(agent_run_response, callback_context) - return agent_run_response + agent_response = await self._invoke_non_stream(run_kwargs) + await self._notify_final_response(agent_response, callback_context) + return agent_response async def _consume_stream( self, - stream: AsyncIterable[AgentRunResponseUpdate], + stream: AsyncIterable[AgentResponseUpdate], callback_context: AgentCallbackContext | None = None, - ) -> AgentRunResponse: - """Consume streaming responses and build the final AgentRunResponse.""" - updates: list[AgentRunResponseUpdate] = [] + ) -> AgentResponse: + """Consume streaming responses and build the final AgentResponse.""" + updates: list[AgentResponseUpdate] = [] async for update in stream: updates.append(update) await self._notify_stream_update(update, callback_context) if updates: - response = AgentRunResponse.from_agent_run_response_updates(updates) + response = AgentResponse.from_agent_run_response_updates(updates) else: logger.debug("[AgentEntity] No streaming updates received; creating empty response") - response = AgentRunResponse(messages=[]) + response = AgentResponse(messages=[]) await self._notify_final_response(response, callback_context) return response - async def _invoke_non_stream(self, run_kwargs: dict[str, Any]) -> AgentRunResponse: + async def _invoke_non_stream(self, run_kwargs: dict[str, Any]) -> AgentResponse: """Invoke the agent without streaming support.""" run_callable = getattr(self.agent, "run", None) if run_callable is None or not callable(run_callable): @@ -283,14 +283,14 @@ class AgentEntity: if inspect.isawaitable(result): result = await result - if not isinstance(result, AgentRunResponse): - raise TypeError(f"Agent run() must return an AgentRunResponse instance; received {type(result).__name__}") + if not isinstance(result, AgentResponse): + raise TypeError(f"Agent run() must return an AgentResponse instance; received {type(result).__name__}") return result async def _notify_stream_update( self, - update: AgentRunResponseUpdate, + update: AgentResponseUpdate, context: AgentCallbackContext | None, ) -> None: """Invoke the streaming callback if one is registered.""" @@ -310,7 +310,7 @@ class AgentEntity: async def _notify_final_response( self, - response: AgentRunResponse, + response: AgentResponse, context: AgentCallbackContext | None, ) -> None: """Invoke the final response callback if one is registered.""" diff --git a/python/packages/azurefunctions/agent_framework_azurefunctions/_orchestration.py b/python/packages/azurefunctions/agent_framework_azurefunctions/_orchestration.py index bb8afd29ba..da63db4016 100644 --- a/python/packages/azurefunctions/agent_framework_azurefunctions/_orchestration.py +++ b/python/packages/azurefunctions/agent_framework_azurefunctions/_orchestration.py @@ -11,8 +11,8 @@ from typing import TYPE_CHECKING, Any, TypeAlias, cast from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, ChatMessage, get_logger, @@ -46,10 +46,10 @@ else: class AgentTask(_TypedCompoundTask): - """A custom Task that wraps entity calls and provides typed AgentRunResponse results. + """A custom Task that wraps entity calls and provides typed AgentResponse results. This task wraps the underlying entity call task and intercepts its completion - to convert the raw result into a typed AgentRunResponse object. + to convert the raw result into a typed AgentResponse object. """ def __init__( @@ -77,7 +77,7 @@ class AgentTask(_TypedCompoundTask): self.id = entity_task.id def try_set_value(self, child: TaskBase) -> None: - """Transition the AgentTask to a terminal state and set its value to `AgentRunResponse`. + """Transition the AgentTask to a terminal state and set its value to `AgentResponse`. Parameters ---------- @@ -104,7 +104,7 @@ class AgentTask(_TypedCompoundTask): response, ) - # Set the typed AgentRunResponse as this task's result + # Set the typed AgentResponse as this task's result self.set_value(is_error=False, value=response) except Exception as e: logger.exception( @@ -118,18 +118,18 @@ class AgentTask(_TypedCompoundTask): self._first_error = child.result self.set_value(is_error=True, value=self._first_error) - def _load_agent_response(self, agent_response: AgentRunResponse | dict[str, Any] | None) -> AgentRunResponse: - """Convert raw payloads into AgentRunResponse instance.""" + def _load_agent_response(self, agent_response: AgentResponse | dict[str, Any] | None) -> AgentResponse: + """Convert raw payloads into AgentResponse instance.""" if agent_response is None: raise ValueError("agent_response cannot be None") logger.debug("[load_agent_response] Loading agent response of type: %s", type(agent_response)) - if isinstance(agent_response, AgentRunResponse): + if isinstance(agent_response, AgentResponse): return agent_response if isinstance(agent_response, dict): - logger.debug("[load_agent_response] Converting dict payload using AgentRunResponse.from_dict") - return AgentRunResponse.from_dict(agent_response) + logger.debug("[load_agent_response] Converting dict payload using AgentResponse.from_dict") + return AgentResponse.from_dict(agent_response) raise TypeError(f"Unsupported type for agent_response: {type(agent_response)}") @@ -137,14 +137,14 @@ class AgentTask(_TypedCompoundTask): self, response_format: type[BaseModel] | None, correlation_id: str, - response: AgentRunResponse, + response: AgentResponse, ) -> None: - """Ensure the AgentRunResponse value is parsed into the expected response_format.""" + """Ensure the AgentResponse value is parsed into the expected response_format.""" if response_format is not None and not isinstance(response.value, response_format): response.try_parse_value(response_format) logger.debug( - "[DurableAIAgent] Loaded AgentRunResponse.value for correlation_id %s with type: %s", + "[DurableAIAgent] Loaded AgentResponse.value for correlation_id %s with type: %s", correlation_id, type(response.value).__name__, ) @@ -190,7 +190,7 @@ class DurableAIAgent(AgentProtocol): # We return an AgentTask here which is a TaskBase subclass. # This is an intentional deviation from AgentProtocol which defines run() as async. # The AgentTask can be yielded in Durable Functions orchestrations and will provide - # a typed AgentRunResponse result. + # a typed AgentResponse result. def run( # type: ignore[override] self, messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None, @@ -203,7 +203,7 @@ class DurableAIAgent(AgentProtocol): This method implements AgentProtocol and returns an AgentTask (subclass of TaskBase) that can be yielded in Durable Functions orchestrations. The task's result will be - a typed AgentRunResponse. + a typed AgentResponse. Args: messages: The message(s) to send to the agent @@ -212,7 +212,7 @@ class DurableAIAgent(AgentProtocol): **kwargs: Additional arguments (enable_tool_calls) Returns: - An AgentTask that resolves to an AgentRunResponse when yielded + An AgentTask that resolves to an AgentResponse when yielded Example: @app.orchestration_trigger(context_name="context") @@ -220,7 +220,7 @@ class DurableAIAgent(AgentProtocol): agent = app.get_agent(context, "MyAgent") thread = agent.get_new_thread() response = yield agent.run("Hello", thread=thread) - # response is typed as AgentRunResponse + # response is typed as AgentResponse """ message_str = self._normalize_messages(messages) @@ -266,7 +266,7 @@ class DurableAIAgent(AgentProtocol): # Call the entity to get the underlying task entity_task = self.context.call_entity(entity_id, "run", run_request.to_dict()) - # Wrap it in an AgentTask that will convert the result to AgentRunResponse + # Wrap it in an AgentTask that will convert the result to AgentResponse agent_task = AgentTask( entity_task=entity_task, response_format=response_format, @@ -286,7 +286,7 @@ class DurableAIAgent(AgentProtocol): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterator[AgentRunResponseUpdate]: + ) -> AsyncIterator[AgentResponseUpdate]: """Run the agent with streaming (not supported for durable agents). Raises: diff --git a/python/packages/azurefunctions/tests/test_app.py b/python/packages/azurefunctions/tests/test_app.py index 6937b3e0f5..37f70a04e1 100644 --- a/python/packages/azurefunctions/tests/test_app.py +++ b/python/packages/azurefunctions/tests/test_app.py @@ -10,7 +10,7 @@ from unittest.mock import ANY, AsyncMock, Mock, patch import azure.durable_functions as df import azure.functions as func import pytest -from agent_framework import AgentRunResponse, ChatMessage, ErrorContent +from agent_framework import AgentResponse, ChatMessage, ErrorContent from agent_framework_azurefunctions import AgentFunctionApp from agent_framework_azurefunctions._app import WAIT_FOR_RESPONSE_FIELD, WAIT_FOR_RESPONSE_HEADER @@ -332,7 +332,7 @@ class TestAgentEntityOperations: """Test that entity can run agent operation.""" mock_agent = Mock() mock_agent.run = AsyncMock( - return_value=AgentRunResponse(messages=[ChatMessage(role="assistant", text="Test response")]) + return_value=AgentResponse(messages=[ChatMessage(role="assistant", text="Test response")]) ) entity = AgentEntity(mock_agent) @@ -343,7 +343,7 @@ class TestAgentEntityOperations: {"message": "Test message", "thread_id": "test-conv-123", "correlationId": "corr-app-entity-1"}, ) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.text == "Test response" assert entity.state.message_count == 2 @@ -351,7 +351,7 @@ class TestAgentEntityOperations: """Test that the entity stores conversation history.""" mock_agent = Mock() mock_agent.run = AsyncMock( - return_value=AgentRunResponse(messages=[ChatMessage(role="assistant", text="Response 1")]) + return_value=AgentResponse(messages=[ChatMessage(role="assistant", text="Response 1")]) ) entity = AgentEntity(mock_agent) @@ -390,7 +390,7 @@ class TestAgentEntityOperations: """Test that the entity increments the message count.""" mock_agent = Mock() mock_agent.run = AsyncMock( - return_value=AgentRunResponse(messages=[ChatMessage(role="assistant", text="Response")]) + return_value=AgentResponse(messages=[ChatMessage(role="assistant", text="Response")]) ) entity = AgentEntity(mock_agent) @@ -437,7 +437,7 @@ class TestAgentEntityFactory: """Test that the entity function handles the run operation.""" mock_agent = Mock() mock_agent.run = AsyncMock( - return_value=AgentRunResponse(messages=[ChatMessage(role="assistant", text="Response")]) + return_value=AgentResponse(messages=[ChatMessage(role="assistant", text="Response")]) ) entity_function = create_agent_entity(mock_agent) @@ -465,7 +465,7 @@ class TestAgentEntityFactory: """Test that the entity function handles the deprecated run_agent operation for backward compatibility.""" mock_agent = Mock() mock_agent.run = AsyncMock( - return_value=AgentRunResponse(messages=[ChatMessage(role="assistant", text="Response")]) + return_value=AgentResponse(messages=[ChatMessage(role="assistant", text="Response")]) ) entity_function = create_agent_entity(mock_agent) @@ -619,7 +619,7 @@ class TestErrorHandling: mock_context, {"message": "Test message", "thread_id": "conv-1", "correlationId": "corr-app-error-1"} ) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert len(result.messages) == 1 content = result.messages[0].contents[0] assert isinstance(content, ErrorContent) diff --git a/python/packages/azurefunctions/tests/test_entities.py b/python/packages/azurefunctions/tests/test_entities.py index dcea75aa1c..63bc685afb 100644 --- a/python/packages/azurefunctions/tests/test_entities.py +++ b/python/packages/azurefunctions/tests/test_entities.py @@ -12,7 +12,7 @@ from typing import Any, TypeVar from unittest.mock import AsyncMock, Mock, patch import pytest -from agent_framework import AgentRunResponse, AgentRunResponseUpdate, ChatMessage, ErrorContent, Role +from agent_framework import AgentResponse, AgentResponseUpdate, ChatMessage, ErrorContent, Role from pydantic import BaseModel from agent_framework_azurefunctions._durable_agent_state import ( @@ -37,12 +37,12 @@ def _role_value(chat_message: DurableAgentStateMessage) -> str: return str(role_value) -def _agent_response(text: str | None) -> AgentRunResponse: - """Create an AgentRunResponse with a single assistant message.""" +def _agent_response(text: str | None) -> AgentResponse: + """Create an AgentResponse with a single assistant message.""" message = ( ChatMessage(role="assistant", text=text) if text is not None else ChatMessage(role="assistant", contents=[]) ) - return AgentRunResponse(messages=[message]) + return AgentResponse(messages=[message]) class RecordingCallback: @@ -54,12 +54,12 @@ class RecordingCallback: async def on_streaming_response_update( self, - update: AgentRunResponseUpdate, + update: AgentResponseUpdate, context: Any, ) -> None: await self.stream_mock(update, context) - async def on_agent_response(self, response: AgentRunResponse, context: Any) -> None: + async def on_agent_response(self, response: AgentResponse, context: Any) -> None: await self.response_mock(response, context) @@ -132,7 +132,7 @@ class TestAgentEntityRunAgent: assert getattr(sent_message.role, "value", sent_message.role) == "user" # Verify result - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.text == "Test response" async def test_run_agent_executes_agent(self) -> None: @@ -159,18 +159,18 @@ class TestAgentEntityRunAgent: assert getattr(sent_message.role, "value", sent_message.role) == "user" # Verify result - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.text == "Test response" async def test_run_agent_streaming_callbacks_invoked(self) -> None: """Ensure streaming updates trigger callbacks and run() is not used.""" updates = [ - AgentRunResponseUpdate(text="Hello"), - AgentRunResponseUpdate(text=" world"), + AgentResponseUpdate(text="Hello"), + AgentResponseUpdate(text=" world"), ] - async def update_generator() -> AsyncIterator[AgentRunResponseUpdate]: + async def update_generator() -> AsyncIterator[AgentResponseUpdate]: for update in updates: yield update @@ -192,7 +192,7 @@ class TestAgentEntityRunAgent: }, ) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert "Hello" in result.text assert callback.stream_mock.await_count == len(updates) assert callback.response_mock.await_count == 1 @@ -239,7 +239,7 @@ class TestAgentEntityRunAgent: }, ) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.text == "Final response" assert callback.stream_mock.await_count == 0 assert callback.response_mock.await_count == 1 @@ -605,7 +605,7 @@ class TestErrorHandling: mock_context, {"message": "Message", "thread_id": "conv-1", "correlationId": "corr-entity-error-1"} ) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert len(result.messages) == 1 content = result.messages[0].contents[0] assert isinstance(content, ErrorContent) @@ -624,7 +624,7 @@ class TestErrorHandling: mock_context, {"message": "Message", "thread_id": "conv-1", "correlationId": "corr-entity-error-2"} ) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert len(result.messages) == 1 content = result.messages[0].contents[0] assert isinstance(content, ErrorContent) @@ -643,7 +643,7 @@ class TestErrorHandling: mock_context, {"message": "Message", "thread_id": "conv-1", "correlationId": "corr-entity-error-3"} ) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert len(result.messages) == 1 content = result.messages[0].contents[0] assert isinstance(content, ErrorContent) @@ -682,7 +682,7 @@ class TestErrorHandling: ) # Even on error, message info should be preserved - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert len(result.messages) == 1 content = result.messages[0].contents[0] assert isinstance(content, ErrorContent) @@ -793,7 +793,7 @@ class TestRunRequestSupport: result = await entity.run(mock_context, request) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.text == "Response" async def test_run_agent_with_dict_request(self) -> None: @@ -814,7 +814,7 @@ class TestRunRequestSupport: result = await entity.run(mock_context, request_dict) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.text == "Response" async def test_run_agent_with_string_raises_without_correlation(self) -> None: @@ -869,7 +869,7 @@ class TestRunRequestSupport: result = await entity.run(mock_context, request) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.text == '{"answer": 42}' assert result.value is None @@ -887,7 +887,7 @@ class TestRunRequestSupport: result = await entity.run(mock_context, request) - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) # Agent should have been called (tool disabling is framework-dependent) mock_agent.run.assert_called_once() diff --git a/python/packages/azurefunctions/tests/test_orchestration.py b/python/packages/azurefunctions/tests/test_orchestration.py index 0fd774d1cd..e9d4ca1bd7 100644 --- a/python/packages/azurefunctions/tests/test_orchestration.py +++ b/python/packages/azurefunctions/tests/test_orchestration.py @@ -6,7 +6,7 @@ from typing import Any from unittest.mock import Mock import pytest -from agent_framework import AgentRunResponse, AgentThread, ChatMessage +from agent_framework import AgentResponse, AgentThread, ChatMessage from azure.durable_functions.models.Task import TaskBase, TaskState from agent_framework_azurefunctions import AgentFunctionApp, DurableAIAgent @@ -39,7 +39,7 @@ def _create_entity_task(task_id: int = 1) -> TaskBase: class TestAgentResponseHelpers: - """Tests for helper utilities that prepare AgentRunResponse values.""" + """Tests for helper utilities that prepare AgentResponse values.""" @staticmethod def _create_agent_task() -> AgentTask: @@ -48,7 +48,7 @@ class TestAgentResponseHelpers: def test_load_agent_response_from_instance(self) -> None: task = self._create_agent_task() - response = AgentRunResponse(messages=[ChatMessage(role="assistant", text='{"foo": "bar"}')]) + response = AgentResponse(messages=[ChatMessage(role="assistant", text='{"foo": "bar"}')]) loaded = task._load_agent_response(response) @@ -57,7 +57,7 @@ class TestAgentResponseHelpers: def test_load_agent_response_from_serialized(self) -> None: task = self._create_agent_task() - serialized = AgentRunResponse(messages=[ChatMessage(role="assistant", text="structured")]).to_dict() + serialized = AgentResponse(messages=[ChatMessage(role="assistant", text="structured")]).to_dict() serialized["value"] = {"answer": 42} loaded = task._load_agent_response(serialized) @@ -65,7 +65,7 @@ class TestAgentResponseHelpers: assert loaded is not None assert loaded.value == {"answer": 42} loaded_dict = loaded.to_dict() - assert loaded_dict["type"] == "agent_run_response" + assert loaded_dict["type"] == "agent_response" def test_load_agent_response_rejects_none(self) -> None: task = self._create_agent_task() @@ -86,7 +86,7 @@ class TestAgentResponseHelpers: # Simulate successful entity task completion entity_task.state = TaskState.SUCCEEDED - entity_task.result = AgentRunResponse(messages=[ChatMessage(role="assistant", text="Test response")]).to_dict() + entity_task.result = AgentResponse(messages=[ChatMessage(role="assistant", text="Test response")]).to_dict() # Clear pending_tasks to simulate that parent has processed the child task.pending_tasks.clear() @@ -94,9 +94,9 @@ class TestAgentResponseHelpers: # Call try_set_value task.try_set_value(entity_task) - # Verify task completed successfully with AgentRunResponse + # Verify task completed successfully with AgentResponse assert task.state == TaskState.SUCCEEDED - assert isinstance(task.result, AgentRunResponse) + assert isinstance(task.result, AgentResponse) assert task.result.text == "Test response" def test_try_set_value_failure(self) -> None: @@ -128,9 +128,7 @@ class TestAgentResponseHelpers: # Simulate successful entity task with JSON response entity_task.state = TaskState.SUCCEEDED - entity_task.result = AgentRunResponse( - messages=[ChatMessage(role="assistant", text='{"answer": "42"}')] - ).to_dict() + entity_task.result = AgentResponse(messages=[ChatMessage(role="assistant", text='{"answer": "42"}')]).to_dict() # Clear pending_tasks to simulate that parent has processed the child task.pending_tasks.clear() @@ -140,7 +138,7 @@ class TestAgentResponseHelpers: # Verify task completed and value was parsed assert task.state == TaskState.SUCCEEDED - assert isinstance(task.result, AgentRunResponse) + assert isinstance(task.result, AgentResponse) assert isinstance(task.result.value, TestSchema) assert task.result.value.answer == "42" @@ -152,7 +150,7 @@ class TestAgentResponseHelpers: name: str task = self._create_agent_task() - response = AgentRunResponse(messages=[ChatMessage(role="assistant", text='{"name": "test"}')]) + response = AgentResponse(messages=[ChatMessage(role="assistant", text='{"name": "test"}')]) # Value should be None initially assert response.value is None @@ -173,7 +171,7 @@ class TestAgentResponseHelpers: task = self._create_agent_task() existing_value = SampleSchema(name="existing") - response = AgentRunResponse( + response = AgentResponse( messages=[ChatMessage(role="assistant", text='{"name": "new"}')], value=existing_value, ) diff --git a/python/packages/bedrock/samples/bedrock_sample.py b/python/packages/bedrock/samples/bedrock_sample.py index 4b5ca8a9a1..57901f49e8 100644 --- a/python/packages/bedrock/samples/bedrock_sample.py +++ b/python/packages/bedrock/samples/bedrock_sample.py @@ -5,7 +5,7 @@ import logging from collections.abc import Sequence from agent_framework import ( - AgentRunResponse, + AgentResponse, ChatAgent, FunctionCallContent, FunctionResultContent, @@ -39,7 +39,7 @@ async def main() -> None: _log_response(response) -def _log_response(response: AgentRunResponse) -> None: +def _log_response(response: AgentResponse) -> None: logging.info("\nConversation transcript:") for idx, message in enumerate(response.messages, start=1): tag = f"{idx}. {message.role.value if isinstance(message.role, Role) else message.role}" diff --git a/python/packages/chatkit/README.md b/python/packages/chatkit/README.md index afdb6f237f..cd4464d7de 100644 --- a/python/packages/chatkit/README.md +++ b/python/packages/chatkit/README.md @@ -4,7 +4,7 @@ This package provides an integration layer between Microsoft Agent Framework and [OpenAI ChatKit (Python)](https://github.com/openai/chatkit-python/). Specifically, it mirrors the [Agent SDK integration](https://github.com/openai/chatkit-python/blob/main/docs/server.md#agents-sdk-integration), and provides the following helpers: -- `stream_agent_response`: A helper to convert a streamed `AgentRunResponseUpdate` +- `stream_agent_response`: A helper to convert a streamed `AgentResponseUpdate` from a Microsoft Agent Framework agent that implements `AgentProtocol` to ChatKit events. - `ThreadItemConverter`: A extendable helper class to convert ChatKit thread items to `ChatMessage` objects that can be consumed by an Agent Framework agent. diff --git a/python/packages/chatkit/agent_framework_chatkit/_streaming.py b/python/packages/chatkit/agent_framework_chatkit/_streaming.py index daeaa0b4ab..b0273c5944 100644 --- a/python/packages/chatkit/agent_framework_chatkit/_streaming.py +++ b/python/packages/chatkit/agent_framework_chatkit/_streaming.py @@ -6,7 +6,7 @@ import uuid from collections.abc import AsyncIterable, AsyncIterator, Callable from datetime import datetime -from agent_framework import AgentRunResponseUpdate, TextContent +from agent_framework import AgentResponseUpdate, TextContent from chatkit.types import ( AssistantMessageContent, AssistantMessageContentPartTextDelta, @@ -19,13 +19,13 @@ from chatkit.types import ( async def stream_agent_response( - response_stream: AsyncIterable[AgentRunResponseUpdate], + response_stream: AsyncIterable[AgentResponseUpdate], thread_id: str, generate_id: Callable[[str], str] | None = None, ) -> AsyncIterator[ThreadStreamEvent]: - """Convert a streamed AgentRunResponseUpdate from Agent Framework to ChatKit events. + """Convert a streamed AgentResponseUpdate from Agent Framework to ChatKit events. - This helper function takes a stream of AgentRunResponseUpdate objects from + This helper function takes a stream of AgentResponseUpdate objects from a Microsoft Agent Framework agent and converts them to ChatKit ThreadStreamEvent objects that can be consumed by the ChatKit UI. @@ -34,7 +34,7 @@ async def stream_agent_response( text chunk as it arrives from the agent. Args: - response_stream: An async iterable of AgentRunResponseUpdate objects + response_stream: An async iterable of AgentResponseUpdate objects from an Agent Framework agent. thread_id: The ChatKit thread ID for the conversation. generate_id: Optional function to generate IDs for ChatKit items. diff --git a/python/packages/chatkit/tests/test_streaming.py b/python/packages/chatkit/tests/test_streaming.py index 2e5041613a..ead7c5f33e 100644 --- a/python/packages/chatkit/tests/test_streaming.py +++ b/python/packages/chatkit/tests/test_streaming.py @@ -4,7 +4,7 @@ from unittest.mock import Mock -from agent_framework import AgentRunResponseUpdate, Role, TextContent +from agent_framework import AgentResponseUpdate, Role, TextContent from chatkit.types import ( ThreadItemAddedEvent, ThreadItemDoneEvent, @@ -34,7 +34,7 @@ class TestStreamAgentResponse: """Test streaming single text update.""" async def single_update_stream(): - yield AgentRunResponseUpdate(role=Role.ASSISTANT, contents=[TextContent(text="Hello world")]) + yield AgentResponseUpdate(role=Role.ASSISTANT, contents=[TextContent(text="Hello world")]) events = [] async for event in stream_agent_response(single_update_stream(), thread_id="test_thread"): @@ -59,8 +59,8 @@ class TestStreamAgentResponse: """Test streaming multiple text updates.""" async def multiple_updates_stream(): - yield AgentRunResponseUpdate(role=Role.ASSISTANT, contents=[TextContent(text="Hello ")]) - yield AgentRunResponseUpdate(role=Role.ASSISTANT, contents=[TextContent(text="world!")]) + yield AgentResponseUpdate(role=Role.ASSISTANT, contents=[TextContent(text="Hello ")]) + yield AgentResponseUpdate(role=Role.ASSISTANT, contents=[TextContent(text="world!")]) events = [] async for event in stream_agent_response(multiple_updates_stream(), thread_id="test_thread"): @@ -91,7 +91,7 @@ class TestStreamAgentResponse: return f"custom_{item_type}_123" async def single_update_stream(): - yield AgentRunResponseUpdate(role=Role.ASSISTANT, contents=[TextContent(text="Test")]) + yield AgentResponseUpdate(role=Role.ASSISTANT, contents=[TextContent(text="Test")]) events = [] async for event in stream_agent_response( @@ -107,8 +107,8 @@ class TestStreamAgentResponse: """Test streaming updates with empty content.""" async def empty_content_stream(): - yield AgentRunResponseUpdate(role=Role.ASSISTANT, contents=[]) - yield AgentRunResponseUpdate(role=Role.ASSISTANT, contents=None) + yield AgentResponseUpdate(role=Role.ASSISTANT, contents=[]) + yield AgentResponseUpdate(role=Role.ASSISTANT, contents=None) events = [] async for event in stream_agent_response(empty_content_stream(), thread_id="test_thread"): @@ -130,7 +130,7 @@ class TestStreamAgentResponse: del non_text_content.text async def non_text_stream(): - yield AgentRunResponseUpdate(role=Role.ASSISTANT, contents=[non_text_content]) + yield AgentResponseUpdate(role=Role.ASSISTANT, contents=[non_text_content]) events = [] async for event in stream_agent_response(non_text_stream(), thread_id="test_thread"): diff --git a/python/packages/copilotstudio/agent_framework_copilotstudio/_agent.py b/python/packages/copilotstudio/agent_framework_copilotstudio/_agent.py index a80fb7221a..606e1e83b6 100644 --- a/python/packages/copilotstudio/agent_framework_copilotstudio/_agent.py +++ b/python/packages/copilotstudio/agent_framework_copilotstudio/_agent.py @@ -5,8 +5,8 @@ from typing import Any, ClassVar from agent_framework import ( AgentMiddlewareTypes, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, ChatMessage, @@ -210,15 +210,15 @@ class CopilotStudioAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Get a response from the agent. This method returns the final result of the agent's execution - as a single AgentRunResponse object. The caller is blocked until + as a single AgentResponse object. The caller is blocked until the final result is available. Note: For streaming responses, use the run_stream method, which returns - intermediate steps and the final result as a stream of AgentRunResponseUpdate + intermediate steps and the final result as a stream of AgentResponseUpdate objects. Streaming only the final result is not feasible because the timing of the final result's availability is unknown, and blocking the caller until then is undesirable in streaming scenarios. @@ -248,7 +248,7 @@ class CopilotStudioAgent(BaseAgent): response_messages = [message async for message in self._process_activities(activities, streaming=False)] response_id = response_messages[0].message_id if response_messages else None - return AgentRunResponse(messages=response_messages, response_id=response_id) + return AgentResponse(messages=response_messages, response_id=response_id) async def run_stream( self, @@ -256,13 +256,13 @@ class CopilotStudioAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Run the agent as a stream. This method will return the intermediate steps and final results of the - agent's execution as a stream of AgentRunResponseUpdate objects to the caller. + agent's execution as a stream of AgentResponseUpdate objects to the caller. - Note: An AgentRunResponseUpdate object contains a chunk of a message. + Note: An AgentResponseUpdate object contains a chunk of a message. Args: messages: The message(s) to send to the agent. @@ -285,7 +285,7 @@ class CopilotStudioAgent(BaseAgent): activities = self.client.ask_question(question, thread.service_thread_id) async for message in self._process_activities(activities, streaming=True): - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( role=message.role, contents=message.contents, author_name=message.author_name, diff --git a/python/packages/copilotstudio/tests/test_copilot_agent.py b/python/packages/copilotstudio/tests/test_copilot_agent.py index 2a2e36263a..4777557d32 100644 --- a/python/packages/copilotstudio/tests/test_copilot_agent.py +++ b/python/packages/copilotstudio/tests/test_copilot_agent.py @@ -5,8 +5,8 @@ from unittest.mock import MagicMock, patch import pytest from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, ChatMessage, Role, @@ -133,7 +133,7 @@ class TestCopilotStudioAgent: response = await agent.run("test message") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert len(response.messages) == 1 content = response.messages[0].contents[0] assert isinstance(content, TextContent) @@ -153,7 +153,7 @@ class TestCopilotStudioAgent: chat_message = ChatMessage(role=Role.USER, contents=[TextContent("test message")]) response = await agent.run(chat_message) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert len(response.messages) == 1 content = response.messages[0].contents[0] assert isinstance(content, TextContent) @@ -173,7 +173,7 @@ class TestCopilotStudioAgent: response = await agent.run("test message", thread=thread) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert len(response.messages) == 1 assert thread.service_thread_id == "test-conversation-id" @@ -204,7 +204,7 @@ class TestCopilotStudioAgent: response_count = 0 async for response in agent.run_stream("test message"): - assert isinstance(response, AgentRunResponseUpdate) + assert isinstance(response, AgentResponseUpdate) content = response.contents[0] assert isinstance(content, TextContent) assert content.text == "Streaming response" @@ -231,7 +231,7 @@ class TestCopilotStudioAgent: response_count = 0 async for response in agent.run_stream("test message", thread=thread): - assert isinstance(response, AgentRunResponseUpdate) + assert isinstance(response, AgentResponseUpdate) content = response.contents[0] assert isinstance(content, TextContent) assert content.text == "Streaming response" @@ -285,7 +285,7 @@ class TestCopilotStudioAgent: response = await agent.run("test message") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert len(response.messages) == 2 async def test_run_list_of_messages(self, mock_copilot_client: MagicMock, mock_activity: MagicMock) -> None: @@ -301,7 +301,7 @@ class TestCopilotStudioAgent: messages = ["Hello", "How are you?"] response = await agent.run(messages) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert len(response.messages) == 1 async def test_run_stream_start_conversation_failure(self, mock_copilot_client: MagicMock) -> None: diff --git a/python/packages/core/agent_framework/_agents.py b/python/packages/core/agent_framework/_agents.py index ddd7c06b4b..a2a7e71a64 100644 --- a/python/packages/core/agent_framework/_agents.py +++ b/python/packages/core/agent_framework/_agents.py @@ -33,8 +33,8 @@ from ._serialization import SerializationMixin from ._threads import AgentThread, ChatMessageStoreProtocol from ._tools import FUNCTION_INVOKING_CHAT_CLIENT_MARKER, AIFunction, ToolProtocol from ._types import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, ChatMessage, ChatResponse, ChatResponseUpdate, @@ -177,16 +177,16 @@ class AgentProtocol(Protocol): async def run(self, messages=None, *, thread=None, **kwargs): # Your custom implementation - from agent_framework import AgentRunResponse + from agent_framework import AgentResponse - return AgentRunResponse(messages=[], response_id="custom-response") + return AgentResponse(messages=[], response_id="custom-response") def run_stream(self, messages=None, *, thread=None, **kwargs): # Your custom streaming implementation async def _stream(): - from agent_framework import AgentRunResponseUpdate + from agent_framework import AgentResponseUpdate - yield AgentRunResponseUpdate() + yield AgentResponseUpdate() return _stream() @@ -210,15 +210,15 @@ class AgentProtocol(Protocol): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Get a response from the agent. This method returns the final result of the agent's execution - as a single AgentRunResponse object. The caller is blocked until + as a single AgentResponse object. The caller is blocked until the final result is available. Note: For streaming responses, use the run_stream method, which returns - intermediate steps and the final result as a stream of AgentRunResponseUpdate + intermediate steps and the final result as a stream of AgentResponseUpdate objects. Streaming only the final result is not feasible because the timing of the final result's availability is unknown, and blocking the caller until then is undesirable in streaming scenarios. @@ -241,13 +241,13 @@ class AgentProtocol(Protocol): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Run the agent as a stream. This method will return the intermediate steps and final results of the - agent's execution as a stream of AgentRunResponseUpdate objects to the caller. + agent's execution as a stream of AgentResponseUpdate objects to the caller. - Note: An AgentRunResponseUpdate object contains a chunk of a message. + Note: An AgentResponseUpdate object contains a chunk of a message. Args: messages: The message(s) to send to the agent. @@ -283,19 +283,19 @@ class BaseAgent(SerializationMixin): Examples: .. code-block:: python - from agent_framework import BaseAgent, AgentThread, AgentRunResponse + from agent_framework import BaseAgent, AgentThread, AgentResponse # Create a concrete subclass that implements the protocol class SimpleAgent(BaseAgent): async def run(self, messages=None, *, thread=None, **kwargs): # Custom implementation - return AgentRunResponse(messages=[], response_id="simple-response") + return AgentResponse(messages=[], response_id="simple-response") def run_stream(self, messages=None, *, thread=None, **kwargs): async def _stream(): # Custom streaming implementation - yield AgentRunResponseUpdate() + yield AgentResponseUpdate() return _stream() @@ -412,8 +412,8 @@ class BaseAgent(SerializationMixin): description: str | None = None, arg_name: str = "task", arg_description: str | None = None, - stream_callback: Callable[[AgentRunResponseUpdate], None] - | Callable[[AgentRunResponseUpdate], Awaitable[None]] + stream_callback: Callable[[AgentResponseUpdate], None] + | Callable[[AgentResponseUpdate], Awaitable[None]] | None = None, ) -> AIFunction[BaseModel, str]: """Create an AIFunction tool that wraps this agent. @@ -478,7 +478,7 @@ class BaseAgent(SerializationMixin): return (await self.run(input_text, **forwarded_kwargs)).text # Use streaming mode - accumulate updates and create final response - response_updates: list[AgentRunResponseUpdate] = [] + response_updates: list[AgentResponseUpdate] = [] async for update in self.run_stream(input_text, **forwarded_kwargs): response_updates.append(update) if is_async_callback: @@ -487,7 +487,7 @@ class BaseAgent(SerializationMixin): stream_callback(update) # Create final text from accumulated updates - return AgentRunResponse.from_agent_run_response_updates(response_updates).text + return AgentResponse.from_agent_run_response_updates(response_updates).text agent_tool: AIFunction[BaseModel, str] = AIFunction( name=tool_name, @@ -766,7 +766,7 @@ class ChatAgent(BaseAgent, Generic[TOptions_co]): # type: ignore[misc] | None = None, options: TOptions_co | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Run the agent with the given messages and options. Note: @@ -789,7 +789,7 @@ class ChatAgent(BaseAgent, Generic[TOptions_co]): # type: ignore[misc] Will only be passed to functions that are called. Returns: - An AgentRunResponse containing the agent's response. + An AgentResponse containing the agent's response. """ # Build options dict from provided options opts = dict(options) if options else {} @@ -872,7 +872,7 @@ class ChatAgent(BaseAgent, Generic[TOptions_co]): # type: ignore[misc] response.messages, **{k: v for k, v in kwargs.items() if k != "thread"}, ) - return AgentRunResponse( + return AgentResponse( messages=response.messages, response_id=response.response_id, created_at=response.created_at, @@ -894,7 +894,7 @@ class ChatAgent(BaseAgent, Generic[TOptions_co]): # type: ignore[misc] | None = None, options: TOptions_co | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Stream the agent with the given messages and options. Note: @@ -917,7 +917,7 @@ class ChatAgent(BaseAgent, Generic[TOptions_co]): # type: ignore[misc] Will only be passed to functions that are called. Yields: - AgentRunResponseUpdate objects containing chunks of the agent's response. + AgentResponseUpdate objects containing chunks of the agent's response. """ # Build options dict from provided options opts = dict(options) if options else {} @@ -989,7 +989,7 @@ class ChatAgent(BaseAgent, Generic[TOptions_co]): # type: ignore[misc] if update.author_name is None: update.author_name = agent_name - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=update.contents, role=update.role, author_name=update.author_name, diff --git a/python/packages/core/agent_framework/_middleware.py b/python/packages/core/agent_framework/_middleware.py index 6c19347e2c..0e26565c5a 100644 --- a/python/packages/core/agent_framework/_middleware.py +++ b/python/packages/core/agent_framework/_middleware.py @@ -8,7 +8,7 @@ from functools import update_wrapper from typing import TYPE_CHECKING, Any, ClassVar, Generic, TypeAlias, TypedDict, TypeVar from ._serialization import SerializationMixin -from ._types import AgentRunResponse, AgentRunResponseUpdate, ChatMessage, prepare_messages +from ._types import AgentResponse, AgentResponseUpdate, ChatMessage, prepare_messages from .exceptions import MiddlewareException if TYPE_CHECKING: @@ -67,8 +67,8 @@ class AgentRunContext(SerializationMixin): metadata: Metadata dictionary for sharing data between agent middleware. result: Agent execution result. Can be observed after calling ``next()`` to see the actual execution result or can be set to override the execution result. - For non-streaming: should be AgentRunResponse. - For streaming: should be AsyncIterable[AgentRunResponseUpdate]. + For non-streaming: should be AgentResponse. + For streaming: should be AsyncIterable[AgentResponseUpdate]. terminate: A flag indicating whether to terminate execution after current middleware. When set to True, execution will stop as soon as control returns to framework. kwargs: Additional keyword arguments passed to the agent run method. @@ -105,7 +105,7 @@ class AgentRunContext(SerializationMixin): thread: "AgentThread | None" = None, is_streaming: bool = False, metadata: dict[str, Any] | None = None, - result: AgentRunResponse | AsyncIterable[AgentRunResponseUpdate] | None = None, + result: AgentResponse | AsyncIterable[AgentResponseUpdate] | None = None, terminate: bool = False, kwargs: dict[str, Any] | None = None, ) -> None: @@ -321,8 +321,8 @@ class AgentMiddleware(ABC): Use context.is_streaming to determine if this is a streaming call. Middleware can set context.result to override execution, or observe the actual execution result after calling next(). - For non-streaming: AgentRunResponse - For streaming: AsyncIterable[AgentRunResponseUpdate] + For non-streaming: AgentResponse + For streaming: AsyncIterable[AgentResponseUpdate] next: Function to call the next middleware or final agent execution. Does not return anything - all data flows through the context. @@ -773,8 +773,8 @@ class AgentMiddlewarePipeline(BaseMiddlewarePipeline): agent: "AgentProtocol", messages: list[ChatMessage], context: AgentRunContext, - final_handler: Callable[[AgentRunContext], Awaitable[AgentRunResponse]], - ) -> AgentRunResponse | None: + final_handler: Callable[[AgentRunContext], Awaitable[AgentResponse]], + ) -> AgentResponse | None: """Execute the agent middleware pipeline for non-streaming. Args: @@ -795,15 +795,15 @@ class AgentMiddlewarePipeline(BaseMiddlewarePipeline): return await final_handler(context) # Store the final result - result_container: dict[str, AgentRunResponse | None] = {"result": None} + result_container: dict[str, AgentResponse | None] = {"result": None} # Custom final handler that handles termination and result override - async def agent_final_handler(c: AgentRunContext) -> AgentRunResponse: + async def agent_final_handler(c: AgentRunContext) -> AgentResponse: # If terminate was set, return the result (which might be None) if c.terminate: - if c.result is not None and isinstance(c.result, AgentRunResponse): + if c.result is not None and isinstance(c.result, AgentResponse): return c.result - return AgentRunResponse() + return AgentResponse() # Execute actual handler and populate context for observability return await final_handler(c) @@ -811,13 +811,13 @@ class AgentMiddlewarePipeline(BaseMiddlewarePipeline): await first_handler(context) # Return the result from result container or overridden result - if context.result is not None and isinstance(context.result, AgentRunResponse): + if context.result is not None and isinstance(context.result, AgentResponse): return context.result - # If no result was set (next() not called), return empty AgentRunResponse + # If no result was set (next() not called), return empty AgentResponse response = result_container.get("result") if response is None: - return AgentRunResponse() + return AgentResponse() return response async def execute_stream( @@ -825,8 +825,8 @@ class AgentMiddlewarePipeline(BaseMiddlewarePipeline): agent: "AgentProtocol", messages: list[ChatMessage], context: AgentRunContext, - final_handler: Callable[[AgentRunContext], AsyncIterable[AgentRunResponseUpdate]], - ) -> AsyncIterable[AgentRunResponseUpdate]: + final_handler: Callable[[AgentRunContext], AsyncIterable[AgentResponseUpdate]], + ) -> AsyncIterable[AgentResponseUpdate]: """Execute the agent middleware pipeline for streaming. Args: @@ -849,7 +849,7 @@ class AgentMiddlewarePipeline(BaseMiddlewarePipeline): return # Store the final result - result_container: dict[str, AsyncIterable[AgentRunResponseUpdate] | None] = {"result_stream": None} + result_container: dict[str, AsyncIterable[AgentResponseUpdate] | None] = {"result_stream": None} first_handler = self._create_streaming_handler_chain(final_handler, result_container, "result_stream") await first_handler(context) @@ -1210,7 +1210,7 @@ def use_agent_middleware(agent_class: type[TAgent]) -> type[TAgent]: thread: Any = None, middleware: Sequence[Middleware] | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Middleware-enabled run method.""" # Build fresh middleware pipelines from current middleware collection and run-level middleware agent_middleware = getattr(self, "middleware", None) @@ -1237,7 +1237,7 @@ def use_agent_middleware(agent_class: type[TAgent]) -> type[TAgent]: kwargs=kwargs, ) - async def _execute_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def _execute_handler(ctx: AgentRunContext) -> AgentResponse: return await original_run(self, ctx.messages, thread=thread, **ctx.kwargs) # type: ignore result = await agent_pipeline.execute( @@ -1247,7 +1247,7 @@ def use_agent_middleware(agent_class: type[TAgent]) -> type[TAgent]: _execute_handler, ) - return result if result else AgentRunResponse() + return result if result else AgentResponse() # No middleware, execute directly return await original_run(self, normalized_messages, thread=thread, **kwargs) # type: ignore[return-value] @@ -1259,7 +1259,7 @@ def use_agent_middleware(agent_class: type[TAgent]) -> type[TAgent]: thread: Any = None, middleware: Sequence[Middleware] | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Middleware-enabled run_stream method.""" # Build fresh middleware pipelines from current middleware collection and run-level middleware agent_middleware = getattr(self, "middleware", None) @@ -1285,11 +1285,11 @@ def use_agent_middleware(agent_class: type[TAgent]) -> type[TAgent]: kwargs=kwargs, ) - async def _execute_stream_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: + async def _execute_stream_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: async for update in original_run_stream(self, ctx.messages, thread=thread, **ctx.kwargs): # type: ignore[misc] yield update - async def _stream_generator() -> AsyncIterable[AgentRunResponseUpdate]: + async def _stream_generator() -> AsyncIterable[AgentResponseUpdate]: async for update in agent_pipeline.execute_stream( self, # type: ignore[arg-type] normalized_messages, diff --git a/python/packages/core/agent_framework/_types.py b/python/packages/core/agent_framework/_types.py index 3df5280e0f..54711a1e5a 100644 --- a/python/packages/core/agent_framework/_types.py +++ b/python/packages/core/agent_framework/_types.py @@ -29,8 +29,8 @@ else: __all__ = [ - "AgentRunResponse", - "AgentRunResponseUpdate", + "AgentResponse", + "AgentResponseUpdate", "AnnotatedRegions", "Annotations", "BaseAnnotation", @@ -188,7 +188,7 @@ _T = TypeVar("_T") TEmbedding = TypeVar("TEmbedding") TChatResponse = TypeVar("TChatResponse", bound="ChatResponse") TToolMode = TypeVar("TToolMode", bound="ToolMode") -TAgentRunResponse = TypeVar("TAgentRunResponse", bound="AgentRunResponse") +TAgentRunResponse = TypeVar("TAgentRunResponse", bound="AgentResponse") CreatedAtT = str # Use a datetimeoffset type? Or a more specific type like datetime.datetime? @@ -2541,7 +2541,7 @@ def prepend_instructions_to_messages( def _process_update( - response: "ChatResponse | AgentRunResponse", update: "ChatResponseUpdate | AgentRunResponseUpdate" + response: "ChatResponse | AgentResponse", update: "ChatResponseUpdate | AgentResponseUpdate" ) -> None: """Processes a single update and modifies the response in place.""" is_new_message = False @@ -2645,7 +2645,7 @@ def _coalesce_text_content( contents.extend(coalesced_contents) -def _finalize_response(response: "ChatResponse | AgentRunResponse") -> None: +def _finalize_response(response: "ChatResponse | AgentResponse") -> None: """Finalizes the response by performing any necessary post-processing.""" for msg in response.messages: _coalesce_text_content(msg.contents, TextContent) @@ -3067,10 +3067,10 @@ class ChatResponseUpdate(SerializationMixin): return self.text -# region AgentRunResponse +# region AgentResponse -class AgentRunResponse(SerializationMixin): +class AgentResponse(SerializationMixin): """Represents the response to an Agent run request. Provides one or more response messages and metadata about the response. @@ -3080,11 +3080,11 @@ class AgentRunResponse(SerializationMixin): Examples: .. code-block:: python - from agent_framework import AgentRunResponse, ChatMessage + from agent_framework import AgentResponse, ChatMessage # Create agent response msg = ChatMessage(role="assistant", text="Task completed successfully.") - response = AgentRunResponse(messages=[msg], response_id="run_123") + response = AgentResponse(messages=[msg], response_id="run_123") print(response.text) # "Task completed successfully." # Access user input requests @@ -3092,20 +3092,20 @@ class AgentRunResponse(SerializationMixin): print(len(user_requests)) # 0 # Combine streaming updates - updates = [...] # List of AgentRunResponseUpdate objects - response = AgentRunResponse.from_agent_run_response_updates(updates) + updates = [...] # List of AgentResponseUpdate objects + response = AgentResponse.from_agent_run_response_updates(updates) # Serialization - to_dict and from_dict response_dict = response.to_dict() - # {'type': 'agent_run_response', 'messages': [...], 'response_id': 'run_123', + # {'type': 'agent_response', 'messages': [...], 'response_id': 'run_123', # 'additional_properties': {}} - restored_response = AgentRunResponse.from_dict(response_dict) + restored_response = AgentResponse.from_dict(response_dict) print(restored_response.response_id) # "run_123" # Serialization - to_json and from_json response_json = response.to_json() - # '{"type": "agent_run_response", "messages": [...], "response_id": "run_123", ...}' - restored_from_json = AgentRunResponse.from_json(response_json) + # '{"type": "agent_response", "messages": [...], "response_id": "run_123", ...}' + restored_from_json = AgentResponse.from_json(response_json) print(restored_from_json.text) # "Task completed successfully." """ @@ -3127,7 +3127,7 @@ class AgentRunResponse(SerializationMixin): additional_properties: dict[str, Any] | None = None, **kwargs: Any, ) -> None: - """Initialize an AgentRunResponse. + """Initialize an AgentResponse. Keyword Args: messages: The list of chat messages in the response. @@ -3185,14 +3185,14 @@ class AgentRunResponse(SerializationMixin): @classmethod def from_agent_run_response_updates( cls: type[TAgentRunResponse], - updates: Sequence["AgentRunResponseUpdate"], + updates: Sequence["AgentResponseUpdate"], *, output_format_type: type[BaseModel] | None = None, ) -> TAgentRunResponse: - """Joins multiple updates into a single AgentRunResponse. + """Joins multiple updates into a single AgentResponse. Args: - updates: A sequence of AgentRunResponseUpdate objects to combine. + updates: A sequence of AgentResponseUpdate objects to combine. Keyword Args: output_format_type: Optional Pydantic model type to parse the response text into structured data. @@ -3208,14 +3208,14 @@ class AgentRunResponse(SerializationMixin): @classmethod async def from_agent_response_generator( cls: type[TAgentRunResponse], - updates: AsyncIterable["AgentRunResponseUpdate"], + updates: AsyncIterable["AgentResponseUpdate"], *, output_format_type: type[BaseModel] | None = None, ) -> TAgentRunResponse: - """Joins multiple updates into a single AgentRunResponse. + """Joins multiple updates into a single AgentResponse. Args: - updates: An async iterable of AgentRunResponseUpdate objects to combine. + updates: An async iterable of AgentResponseUpdate objects to combine. Keyword Args: output_format_type: Optional Pydantic model type to parse the response text into structured data @@ -3240,19 +3240,19 @@ class AgentRunResponse(SerializationMixin): logger.debug("Failed to parse value from agent run response text: %s", ex) -# region AgentRunResponseUpdate +# region AgentResponseUpdate -class AgentRunResponseUpdate(SerializationMixin): +class AgentResponseUpdate(SerializationMixin): """Represents a single streaming response chunk from an Agent. Examples: .. code-block:: python - from agent_framework import AgentRunResponseUpdate, TextContent + from agent_framework import AgentResponseUpdate, TextContent # Create an agent run update - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[TextContent(text="Processing...")], role="assistant", response_id="run_123", @@ -3264,15 +3264,15 @@ class AgentRunResponseUpdate(SerializationMixin): # Serialization - to_dict and from_dict update_dict = update.to_dict() - # {'type': 'agent_run_response_update', 'contents': [{'type': 'text', 'text': 'Processing...'}], + # {'type': 'agent_response_update', 'contents': [{'type': 'text', 'text': 'Processing...'}], # 'role': {'type': 'role', 'value': 'assistant'}, 'response_id': 'run_123'} - restored_update = AgentRunResponseUpdate.from_dict(update_dict) + restored_update = AgentResponseUpdate.from_dict(update_dict) print(restored_update.response_id) # "run_123" # Serialization - to_json and from_json update_json = update.to_json() - # '{"type": "agent_run_response_update", "contents": [{"type": "text", "text": "Processing..."}], ...}' - restored_from_json = AgentRunResponseUpdate.from_json(update_json) + # '{"type": "agent_response_update", "contents": [{"type": "text", "text": "Processing..."}], ...}' + restored_from_json = AgentResponseUpdate.from_json(update_json) print(restored_from_json.text) # "Processing..." """ @@ -3292,7 +3292,7 @@ class AgentRunResponseUpdate(SerializationMixin): raw_representation: Any | None = None, **kwargs: Any, ) -> None: - """Initialize an AgentRunResponseUpdate. + """Initialize an AgentResponseUpdate. Keyword Args: contents: Optional list of BaseContent items or dicts to include in the update. diff --git a/python/packages/core/agent_framework/_workflows/_agent.py b/python/packages/core/agent_framework/_workflows/_agent.py index 7eec2472f0..b5c723d405 100644 --- a/python/packages/core/agent_framework/_workflows/_agent.py +++ b/python/packages/core/agent_framework/_workflows/_agent.py @@ -9,8 +9,8 @@ from datetime import datetime, timezone from typing import TYPE_CHECKING, Any, ClassVar, TypedDict, cast from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, BaseContent, @@ -126,7 +126,7 @@ class WorkflowAgent(BaseAgent): checkpoint_id: str | None = None, checkpoint_storage: CheckpointStorage | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Get a response from the workflow agent (non-streaming). This method collects all streaming updates and merges them into a single response. @@ -146,10 +146,10 @@ class WorkflowAgent(BaseAgent): and ai_function tools. Returns: - The final workflow response as an AgentRunResponse. + The final workflow response as an AgentResponse. """ # Collect all streaming updates - response_updates: list[AgentRunResponseUpdate] = [] + response_updates: list[AgentResponseUpdate] = [] input_messages = normalize_messages_input(messages) thread = thread or self.get_new_thread() response_id = str(uuid.uuid4()) @@ -175,7 +175,7 @@ class WorkflowAgent(BaseAgent): checkpoint_id: str | None = None, checkpoint_storage: CheckpointStorage | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Stream response updates from the workflow agent. Args: @@ -193,11 +193,11 @@ class WorkflowAgent(BaseAgent): and ai_function tools. Yields: - AgentRunResponseUpdate objects representing the workflow execution progress. + AgentResponseUpdate objects representing the workflow execution progress. """ input_messages = normalize_messages_input(messages) thread = thread or self.get_new_thread() - response_updates: list[AgentRunResponseUpdate] = [] + response_updates: list[AgentResponseUpdate] = [] response_id = str(uuid.uuid4()) async for update in self._run_stream_impl( @@ -220,7 +220,7 @@ class WorkflowAgent(BaseAgent): checkpoint_id: str | None = None, checkpoint_storage: CheckpointStorage | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Internal implementation of streaming execution. Args: @@ -233,7 +233,7 @@ class WorkflowAgent(BaseAgent): workflow and ai_function tools. Yields: - AgentRunResponseUpdate objects representing the workflow execution progress. + AgentResponseUpdate objects representing the workflow execution progress. """ # Determine the event stream based on whether we have function responses if bool(self.pending_requests): @@ -289,8 +289,8 @@ class WorkflowAgent(BaseAgent): self, response_id: str, event: WorkflowEvent, - ) -> AgentRunResponseUpdate | None: - """Convert a workflow event to an AgentRunResponseUpdate. + ) -> AgentResponseUpdate | None: + """Convert a workflow event to an AgentResponseUpdate. AgentRunUpdateEvent, RequestInfoEvent, and WorkflowOutputEvent are processed. Other workflow events are ignored as they are workflow-internal. @@ -319,17 +319,17 @@ class WorkflowAgent(BaseAgent): # Convert workflow output to an agent response update. # Handle different data types appropriately. - # Skip AgentRunResponse from AgentExecutor with output_response=True + # Skip AgentResponse from AgentExecutor with output_response=True # since streaming events already surfaced the content. - if isinstance(data, AgentRunResponse): + if isinstance(data, AgentResponse): executor = self.workflow.executors.get(source_executor_id) if isinstance(executor, AgentExecutor) and executor.output_response: return None - if isinstance(data, AgentRunResponseUpdate): + if isinstance(data, AgentResponseUpdate): return data if isinstance(data, ChatMessage): - return AgentRunResponseUpdate( + return AgentResponseUpdate( contents=list(data.contents), role=data.role, author_name=data.author_name or source_executor_id, @@ -341,7 +341,7 @@ class WorkflowAgent(BaseAgent): contents = self._extract_contents(data) if not contents: return None - return AgentRunResponseUpdate( + return AgentResponseUpdate( contents=contents, role=Role.ASSISTANT, author_name=source_executor_id, @@ -367,7 +367,7 @@ class WorkflowAgent(BaseAgent): function_call=function_call, additional_properties={"request_id": request_id}, ) - return AgentRunResponseUpdate( + return AgentResponseUpdate( contents=[function_call, approval_request], role=Role.ASSISTANT, author_name=self.name, @@ -441,30 +441,30 @@ class WorkflowAgent(BaseAgent): class _ResponseState(TypedDict): """State for grouping response updates by message_id.""" - by_msg: dict[str, list[AgentRunResponseUpdate]] - dangling: list[AgentRunResponseUpdate] + by_msg: dict[str, list[AgentResponseUpdate]] + dangling: list[AgentResponseUpdate] @staticmethod - def merge_updates(updates: list[AgentRunResponseUpdate], response_id: str) -> AgentRunResponse: - """Merge streaming updates into a single AgentRunResponse. + def merge_updates(updates: list[AgentResponseUpdate], response_id: str) -> AgentResponse: + """Merge streaming updates into a single AgentResponse. Behavior: - Group updates by response_id; within each response_id, group by message_id and keep a dangling bucket for updates without message_id. - - Convert each group (per message and dangling) into an intermediate AgentRunResponse via - AgentRunResponse.from_agent_run_response_updates, then sort by created_at and merge. + - Convert each group (per message and dangling) into an intermediate AgentResponse via + AgentResponse.from_agent_run_response_updates, then sort by created_at and merge. - Append messages from updates without any response_id at the end (global dangling), while aggregating metadata. Args: - updates: The list of AgentRunResponseUpdate objects to merge. - response_id: The response identifier to set on the returned AgentRunResponse. + updates: The list of AgentResponseUpdate objects to merge. + response_id: The response identifier to set on the returned AgentResponse. Returns: - An AgentRunResponse with messages in processing order and aggregated metadata. + An AgentResponse with messages in processing order and aggregated metadata. """ # PHASE 1: GROUP UPDATES BY RESPONSE_ID AND MESSAGE_ID states: dict[str, WorkflowAgent._ResponseState] = {} - global_dangling: list[AgentRunResponseUpdate] = [] + global_dangling: list[AgentResponseUpdate] = [] for u in updates: if u.response_id: @@ -497,7 +497,7 @@ class WorkflowAgent(BaseAgent): return a return a + b - def _merge_responses(current: AgentRunResponse | None, incoming: AgentRunResponse) -> AgentRunResponse: + def _merge_responses(current: AgentResponse | None, incoming: AgentResponse) -> AgentResponse: if current is None: return incoming raw_list: list[object] = [] @@ -512,7 +512,7 @@ class WorkflowAgent(BaseAgent): _add_raw(current.raw_representation) if incoming.raw_representation is not None: _add_raw(incoming.raw_representation) - return AgentRunResponse( + return AgentResponse( messages=(current.messages or []) + (incoming.messages or []), response_id=current.response_id or incoming.response_id, created_at=incoming.created_at or current.created_at, @@ -533,16 +533,16 @@ class WorkflowAgent(BaseAgent): by_msg = state["by_msg"] dangling = state["dangling"] - per_message_responses: list[AgentRunResponse] = [] + per_message_responses: list[AgentResponse] = [] for _, msg_updates in by_msg.items(): if msg_updates: - per_message_responses.append(AgentRunResponse.from_agent_run_response_updates(msg_updates)) + per_message_responses.append(AgentResponse.from_agent_run_response_updates(msg_updates)) if dangling: - per_message_responses.append(AgentRunResponse.from_agent_run_response_updates(dangling)) + per_message_responses.append(AgentResponse.from_agent_run_response_updates(dangling)) per_message_responses.sort(key=lambda r: _parse_dt(r.created_at)) - aggregated: AgentRunResponse | None = None + aggregated: AgentResponse | None = None for resp in per_message_responses: if resp.response_id and grouped_response_id and resp.response_id != grouped_response_id: resp.response_id = grouped_response_id @@ -570,7 +570,7 @@ class WorkflowAgent(BaseAgent): # PHASE 3: HANDLE GLOBAL DANGLING UPDATES (NO RESPONSE_ID) if global_dangling: - flattened = AgentRunResponse.from_agent_run_response_updates(global_dangling) + flattened = AgentResponse.from_agent_run_response_updates(global_dangling) final_messages.extend(flattened.messages) if flattened.usage_details: merged_usage = _sum_usage(merged_usage, flattened.usage_details) @@ -591,7 +591,7 @@ class WorkflowAgent(BaseAgent): raw_representations.append(cast_flat) # PHASE 4: CONSTRUCT FINAL RESPONSE WITH INPUT RESPONSE_ID - return AgentRunResponse( + return AgentResponse( messages=final_messages, response_id=response_id, created_at=latest_created_at, diff --git a/python/packages/core/agent_framework/_workflows/_agent_executor.py b/python/packages/core/agent_framework/_workflows/_agent_executor.py index 52e3f76536..bcd47caca2 100644 --- a/python/packages/core/agent_framework/_workflows/_agent_executor.py +++ b/python/packages/core/agent_framework/_workflows/_agent_executor.py @@ -9,7 +9,7 @@ from agent_framework import FunctionApprovalRequestContent, FunctionApprovalResp from .._agents import AgentProtocol, ChatAgent from .._threads import AgentThread -from .._types import AgentRunResponse, AgentRunResponseUpdate, ChatMessage +from .._types import AgentResponse, AgentResponseUpdate, ChatMessage from ._agent_utils import resolve_agent_id from ._checkpoint_encoding import decode_checkpoint_value, encode_checkpoint_value from ._const import WORKFLOW_RUN_KWARGS_KEY @@ -51,14 +51,14 @@ class AgentExecutorResponse: Attributes: executor_id: The ID of the executor that generated the response. - agent_run_response: The underlying agent run response (unaltered from client). + agent_response: The underlying agent run response (unaltered from client). full_conversation: The full conversation context (prior inputs + all assistant/tool outputs) that should be used when chaining to another AgentExecutor. This prevents downstream agents losing user prompts while keeping the emitted AgentRunEvent text faithful to the raw agent output. """ executor_id: str - agent_run_response: AgentRunResponse + agent_response: AgentResponse full_conversation: list[ChatMessage] | None = None @@ -85,7 +85,7 @@ class AgentExecutor(Executor): Args: agent: The agent to be wrapped by this executor. agent_thread: The thread to use for running the agent. If None, a new thread will be created. - output_response: Whether to yield an AgentRunResponse as a workflow output when the agent completes. + output_response: Whether to yield an AgentResponse as a workflow output when the agent completes. id: A unique identifier for the executor. If None, the agent's name will be used if available. """ # Prefer provided id; else use agent.name if present; else generate deterministic prefix @@ -106,14 +106,14 @@ class AgentExecutor(Executor): @property def output_response(self) -> bool: - """Whether this executor yields AgentRunResponse as workflow output when complete.""" + """Whether this executor yields AgentResponse as workflow output when complete.""" return self._output_response @property def workflow_output_types(self) -> list[type[Any]]: - # Override to declare AgentRunResponse as a possible output type only if enabled. + # Override to declare AgentResponse as a possible output type only if enabled. if self._output_response: - return [AgentRunResponse] + return [AgentResponse] return [] @property @@ -123,7 +123,7 @@ class AgentExecutor(Executor): @handler async def run( - self, request: AgentExecutorRequest, ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse] + self, request: AgentExecutorRequest, ctx: WorkflowContext[AgentExecutorResponse, AgentResponse] ) -> None: """Handle an AgentExecutorRequest (canonical input). @@ -136,22 +136,22 @@ class AgentExecutor(Executor): @handler async def from_response( - self, prior: AgentExecutorResponse, ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse] + self, prior: AgentExecutorResponse, ctx: WorkflowContext[AgentExecutorResponse, AgentResponse] ) -> None: """Enable seamless chaining: accept a prior AgentExecutorResponse as input. Strategy: treat the prior response's messages as the conversation state and immediately run the agent to produce a new response. """ - # Replace cache with full conversation if available, else fall back to agent_run_response messages. + # Replace cache with full conversation if available, else fall back to agent_response messages. if prior.full_conversation is not None: self._cache = list(prior.full_conversation) else: - self._cache = list(prior.agent_run_response.messages) + self._cache = list(prior.agent_response.messages) await self._run_agent_and_emit(ctx) @handler - async def from_str(self, text: str, ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse]) -> None: + async def from_str(self, text: str, ctx: WorkflowContext[AgentExecutorResponse, AgentResponse]) -> None: """Accept a raw user prompt string and run the agent (one-shot).""" self._cache = normalize_messages_input(text) await self._run_agent_and_emit(ctx) @@ -160,7 +160,7 @@ class AgentExecutor(Executor): async def from_message( self, message: ChatMessage, - ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse], + ctx: WorkflowContext[AgentExecutorResponse, AgentResponse], ) -> None: """Accept a single ChatMessage as input.""" self._cache = normalize_messages_input(message) @@ -170,7 +170,7 @@ class AgentExecutor(Executor): async def from_messages( self, messages: list[str | ChatMessage], - ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse], + ctx: WorkflowContext[AgentExecutorResponse, AgentResponse], ) -> None: """Accept a list of chat inputs (strings or ChatMessage) as conversation context.""" self._cache = normalize_messages_input(messages) @@ -181,7 +181,7 @@ class AgentExecutor(Executor): self, original_request: FunctionApprovalRequestContent, response: FunctionApprovalResponseContent, - ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse], + ctx: WorkflowContext[AgentExecutorResponse, AgentResponse], ) -> None: """Handle user input responses for function approvals during agent execution. @@ -292,7 +292,7 @@ class AgentExecutor(Executor): logger.debug("AgentExecutor %s: Resetting cache", self.id) self._cache.clear() - async def _run_agent_and_emit(self, ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse]) -> None: + async def _run_agent_and_emit(self, ctx: WorkflowContext[AgentExecutorResponse, AgentResponse]) -> None: """Execute the underlying agent, emit events, and enqueue response. Checks ctx.is_streaming() to determine whether to emit incremental AgentRunUpdateEvent @@ -306,7 +306,7 @@ class AgentExecutor(Executor): response = await self._run_agent(cast(WorkflowContext, ctx)) # Always extend full conversation with cached messages plus agent outputs - # (agent_run_response.messages) after each run. This is to avoid losing context + # (agent_response.messages) after each run. This is to avoid losing context # when agent did not complete and the cache is cleared when responses come back. # Do not mutate response.messages so AgentRunEvent remains faithful to the raw output. self._full_conversation.extend(list(self._cache) + (list(response.messages) if response else [])) @@ -323,14 +323,14 @@ class AgentExecutor(Executor): await ctx.send_message(agent_response) self._cache.clear() - async def _run_agent(self, ctx: WorkflowContext) -> AgentRunResponse | None: + async def _run_agent(self, ctx: WorkflowContext) -> AgentResponse | None: """Execute the underlying agent in non-streaming mode. Args: ctx: The workflow context for emitting events. Returns: - The complete AgentRunResponse, or None if waiting for user input. + The complete AgentResponse, or None if waiting for user input. """ run_kwargs: dict[str, Any] = await ctx.get_shared_state(WORKFLOW_RUN_KWARGS_KEY) @@ -350,18 +350,18 @@ class AgentExecutor(Executor): return response - async def _run_agent_streaming(self, ctx: WorkflowContext) -> AgentRunResponse | None: + async def _run_agent_streaming(self, ctx: WorkflowContext) -> AgentResponse | None: """Execute the underlying agent in streaming mode and collect the full response. Args: ctx: The workflow context for emitting events. Returns: - The complete AgentRunResponse, or None if waiting for user input. + The complete AgentResponse, or None if waiting for user input. """ run_kwargs: dict[str, Any] = await ctx.get_shared_state(WORKFLOW_RUN_KWARGS_KEY) - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] user_input_requests: list[FunctionApprovalRequestContent] = [] async for update in self._agent.run_stream( self._cache, @@ -374,15 +374,15 @@ class AgentExecutor(Executor): if update.user_input_requests: user_input_requests.extend(update.user_input_requests) - # Build the final AgentRunResponse from the collected updates + # Build the final AgentResponse from the collected updates if isinstance(self._agent, ChatAgent): response_format = self._agent.default_options.get("response_format") - response = AgentRunResponse.from_agent_run_response_updates( + response = AgentResponse.from_agent_run_response_updates( updates, output_format_type=response_format, ) else: - response = AgentRunResponse.from_agent_run_response_updates(updates) + response = AgentResponse.from_agent_run_response_updates(updates) # Handle any user input requests after the streaming completes if user_input_requests: diff --git a/python/packages/core/agent_framework/_workflows/_base_group_chat_orchestrator.py b/python/packages/core/agent_framework/_workflows/_base_group_chat_orchestrator.py index 6e03d9e5c3..026933d777 100644 --- a/python/packages/core/agent_framework/_workflows/_base_group_chat_orchestrator.py +++ b/python/packages/core/agent_framework/_workflows/_base_group_chat_orchestrator.py @@ -346,7 +346,7 @@ class BaseGroupChatOrchestrator(Executor, ABC): List of ChatMessages extracted from the response """ if isinstance(response, AgentExecutorResponse): - return response.agent_run_response.messages + return response.agent_response.messages if isinstance(response, GroupChatResponseMessage): return [response.message] raise TypeError(f"Unsupported response type: {type(response)}") diff --git a/python/packages/core/agent_framework/_workflows/_concurrent.py b/python/packages/core/agent_framework/_workflows/_concurrent.py index dbbccccee2..033946afff 100644 --- a/python/packages/core/agent_framework/_workflows/_concurrent.py +++ b/python/packages/core/agent_framework/_workflows/_concurrent.py @@ -79,7 +79,7 @@ class _AggregateAgentConversations(Executor): [ single_user_prompt?, agent1_final_assistant, agent2_final_assistant, ... ] - Extracts a single user prompt (first user message seen across results). - - For each result, selects the final assistant message (prefers agent_run_response.messages). + - For each result, selects the final assistant message (prefers agent_response.messages). - Avoids duplicating the same user message per agent. """ @@ -107,7 +107,7 @@ class _AggregateAgentConversations(Executor): assistant_replies: list[ChatMessage] = [] for r in results: - resp_messages = list(getattr(r.agent_run_response, "messages", []) or []) + resp_messages = list(getattr(r.agent_response, "messages", []) or []) conv = r.full_conversation if r.full_conversation is not None else resp_messages logger.debug( @@ -213,7 +213,7 @@ class ConcurrentBuilder: # Custom aggregator via callback (sync or async). The callback receives # list[AgentExecutorResponse] and its return value becomes the workflow's output. def summarize(results: list[AgentExecutorResponse]) -> str: - return " | ".join(r.agent_run_response.messages[-1].text for r in results) + return " | ".join(r.agent_response.messages[-1].text for r in results) workflow = ConcurrentBuilder().participants([agent1, agent2, agent3]).with_aggregator(summarize).build() @@ -223,7 +223,7 @@ class ConcurrentBuilder: class MyAggregator(Executor): @handler async def aggregate(self, results: list[AgentExecutorResponse], ctx: WorkflowContext[Never, str]) -> None: - await ctx.yield_output(" | ".join(r.agent_run_response.messages[-1].text for r in results)) + await ctx.yield_output(" | ".join(r.agent_response.messages[-1].text for r in results)) workflow = ( @@ -416,7 +416,7 @@ class ConcurrentBuilder: class CustomAggregator(Executor): @handler async def aggregate(self, results: list[AgentExecutorResponse], ctx: WorkflowContext) -> None: - await ctx.yield_output(" | ".join(r.agent_run_response.messages[-1].text for r in results)) + await ctx.yield_output(" | ".join(r.agent_response.messages[-1].text for r in results)) wf = ConcurrentBuilder().participants([a1, a2, a3]).with_aggregator(CustomAggregator()).build() @@ -424,7 +424,7 @@ class ConcurrentBuilder: # Callback-based aggregator (string result) async def summarize(results: list[AgentExecutorResponse]) -> str: - return " | ".join(r.agent_run_response.messages[-1].text for r in results) + return " | ".join(r.agent_response.messages[-1].text for r in results) wf = ConcurrentBuilder().participants([a1, a2, a3]).with_aggregator(summarize).build() @@ -432,7 +432,7 @@ class ConcurrentBuilder: # Callback-based aggregator (yield result) async def summarize(results: list[AgentExecutorResponse], ctx: WorkflowContext[Never, str]) -> None: - await ctx.yield_output(" | ".join(r.agent_run_response.messages[-1].text for r in results)) + await ctx.yield_output(" | ".join(r.agent_response.messages[-1].text for r in results)) wf = ConcurrentBuilder().participants([a1, a2, a3]).with_aggregator(summarize).build() diff --git a/python/packages/core/agent_framework/_workflows/_events.py b/python/packages/core/agent_framework/_workflows/_events.py index 27709ad3a9..2eff8f04a3 100644 --- a/python/packages/core/agent_framework/_workflows/_events.py +++ b/python/packages/core/agent_framework/_workflows/_events.py @@ -8,7 +8,7 @@ from dataclasses import dataclass from enum import Enum from typing import Any, TypeAlias -from agent_framework import AgentRunResponse, AgentRunResponseUpdate +from agent_framework import AgentResponse, AgentResponseUpdate from ._checkpoint_encoding import decode_checkpoint_value, encode_checkpoint_value from ._typing_utils import deserialize_type, serialize_type @@ -367,9 +367,9 @@ class ExecutorFailedEvent(ExecutorEvent): class AgentRunUpdateEvent(ExecutorEvent): """Event triggered when an agent is streaming messages.""" - data: AgentRunResponseUpdate + data: AgentResponseUpdate - def __init__(self, executor_id: str, data: AgentRunResponseUpdate): + def __init__(self, executor_id: str, data: AgentResponseUpdate): """Initialize the agent streaming event.""" super().__init__(executor_id, data) @@ -381,9 +381,9 @@ class AgentRunUpdateEvent(ExecutorEvent): class AgentRunEvent(ExecutorEvent): """Event triggered when an agent run is completed.""" - data: AgentRunResponse + data: AgentResponse - def __init__(self, executor_id: str, data: AgentRunResponse): + def __init__(self, executor_id: str, data: AgentResponse): """Initialize the agent run event.""" super().__init__(executor_id, data) diff --git a/python/packages/core/agent_framework/_workflows/_handoff.py b/python/packages/core/agent_framework/_workflows/_handoff.py index e2ef233ee4..9e9e115bd4 100644 --- a/python/packages/core/agent_framework/_workflows/_handoff.py +++ b/python/packages/core/agent_framework/_workflows/_handoff.py @@ -42,7 +42,7 @@ from .._agents import AgentProtocol, ChatAgent from .._middleware import FunctionInvocationContext, FunctionMiddleware from .._threads import AgentThread from .._tools import AIFunction, ai_function -from .._types import AgentRunResponse, ChatMessage, Role +from .._types import AgentResponse, ChatMessage, Role from ._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse from ._agent_utils import resolve_agent_id from ._base_group_chat_orchestrator import TerminationCondition @@ -155,7 +155,7 @@ class HandoffAgentUserRequest: agent_response: The response generated by the agent at the most recent turn """ - agent_response: AgentRunResponse + agent_response: AgentResponse @staticmethod def create_response(response: str | list[str] | ChatMessage | list[ChatMessage]) -> list[ChatMessage]: @@ -361,7 +361,7 @@ class HandoffAgentExecutor(AgentExecutor): return _handoff_tool @override - async def _run_agent_and_emit(self, ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse]) -> None: + async def _run_agent_and_emit(self, ctx: WorkflowContext[AgentExecutorResponse, AgentResponse]) -> None: """Override to support handoff.""" # When the full conversation is empty, it means this is the first run. # Broadcast the initial cache to all other agents. Subsequent runs won't @@ -436,7 +436,7 @@ class HandoffAgentExecutor(AgentExecutor): self, original_request: HandoffAgentUserRequest, response: list[ChatMessage], - ctx: WorkflowContext[AgentExecutorResponse, AgentRunResponse], + ctx: WorkflowContext[AgentExecutorResponse, AgentResponse], ) -> None: """Handle user response for a request that is issued after agent runs. @@ -477,7 +477,7 @@ class HandoffAgentExecutor(AgentExecutor): # Since all agents are connected via fan-out, we can directly send the message await ctx.send_message(agent_executor_request) - def _is_handoff_requested(self, response: AgentRunResponse) -> str | None: + def _is_handoff_requested(self, response: AgentResponse) -> str | None: """Determine if the agent response includes a handoff request. If a handoff tool is invoked, the middleware will short-circuit execution diff --git a/python/packages/core/agent_framework/_workflows/_magentic.py b/python/packages/core/agent_framework/_workflows/_magentic.py index 03171e795c..052a59766f 100644 --- a/python/packages/core/agent_framework/_workflows/_magentic.py +++ b/python/packages/core/agent_framework/_workflows/_magentic.py @@ -16,7 +16,7 @@ from typing_extensions import Never from agent_framework import ( AgentProtocol, - AgentRunResponse, + AgentResponse, ChatMessage, Role, ) @@ -594,7 +594,7 @@ class StandardMagenticManager(MagenticManagerBase): The agent's run method is called which applies the agent's configured options (temperature, seed, instructions, etc.). """ - response: AgentRunResponse = await self._agent.run(messages) + response: AgentResponse = await self._agent.run(messages) if not response.messages: raise RuntimeError("Agent returned no messages in response.") if len(response.messages) > 1: diff --git a/python/packages/core/agent_framework/_workflows/_workflow_builder.py b/python/packages/core/agent_framework/_workflows/_workflow_builder.py index 0f1933b0c9..8cc31e2cc9 100644 --- a/python/packages/core/agent_framework/_workflows/_workflow_builder.py +++ b/python/packages/core/agent_framework/_workflows/_workflow_builder.py @@ -223,7 +223,7 @@ class WorkflowBuilder: Args: candidate: The executor or agent to wrap. agent_thread: The thread to use for running the agent. If None, a new thread will be created. - output_response: Whether to yield an AgentRunResponse as a workflow output when the agent completes. + output_response: Whether to yield an AgentResponse as a workflow output when the agent completes. executor_id: A unique identifier for the executor. If None, the agent's name will be used if available. """ try: # Local import to avoid hard dependency at import time @@ -352,7 +352,7 @@ class WorkflowBuilder: the agent's internal name. But it must be unique within the workflow. agent_thread: The thread to use for running the agent. If None, a new thread will be created when the agent is instantiated. - output_response: Whether to yield an AgentRunResponse as a workflow output when the agent completes. + output_response: Whether to yield an AgentResponse as a workflow output when the agent completes. Example: .. code-block:: python @@ -411,7 +411,7 @@ class WorkflowBuilder: Args: agent: The agent to add to the workflow. agent_thread: The thread to use for running the agent. If None, a new thread will be created. - output_response: Whether to yield an AgentRunResponse as a workflow output when the agent completes. + output_response: Whether to yield an AgentResponse as a workflow output when the agent completes. id: A unique identifier for the executor. If None, the agent's name will be used if available. Returns: diff --git a/python/packages/core/agent_framework/observability.py b/python/packages/core/agent_framework/observability.py index 33f1dac830..70564c9354 100644 --- a/python/packages/core/agent_framework/observability.py +++ b/python/packages/core/agent_framework/observability.py @@ -35,8 +35,8 @@ if TYPE_CHECKING: # pragma: no cover from ._threads import AgentThread from ._tools import AIFunction from ._types import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, ChatMessage, ChatResponse, ChatResponseUpdate, @@ -1315,10 +1315,10 @@ def use_instrumentation( def _trace_agent_run( - run_func: Callable[..., Awaitable["AgentRunResponse"]], + run_func: Callable[..., Awaitable["AgentResponse"]], provider_name: str, capture_usage: bool = True, -) -> Callable[..., Awaitable["AgentRunResponse"]]: +) -> Callable[..., Awaitable["AgentResponse"]]: """Decorator to trace chat completion activities. Args: @@ -1334,7 +1334,7 @@ def _trace_agent_run( *, thread: "AgentThread | None" = None, **kwargs: Any, - ) -> "AgentRunResponse": + ) -> "AgentResponse": global OBSERVABILITY_SETTINGS if not OBSERVABILITY_SETTINGS.ENABLED: @@ -1384,10 +1384,10 @@ def _trace_agent_run( def _trace_agent_run_stream( - run_streaming_func: Callable[..., AsyncIterable["AgentRunResponseUpdate"]], + run_streaming_func: Callable[..., AsyncIterable["AgentResponseUpdate"]], provider_name: str, capture_usage: bool, -) -> Callable[..., AsyncIterable["AgentRunResponseUpdate"]]: +) -> Callable[..., AsyncIterable["AgentResponseUpdate"]]: """Decorator to trace streaming agent run activities. Args: @@ -1403,7 +1403,7 @@ def _trace_agent_run_stream( *, thread: "AgentThread | None" = None, **kwargs: Any, - ) -> AsyncIterable["AgentRunResponseUpdate"]: + ) -> AsyncIterable["AgentResponseUpdate"]: global OBSERVABILITY_SETTINGS if not OBSERVABILITY_SETTINGS.ENABLED: @@ -1412,9 +1412,9 @@ def _trace_agent_run_stream( yield streaming_agent_response return - from ._types import AgentRunResponse, merge_chat_options + from ._types import AgentResponse, merge_chat_options - all_updates: list["AgentRunResponseUpdate"] = [] + all_updates: list["AgentResponseUpdate"] = [] default_options = getattr(self, "default_options", {}) options = merge_chat_options(default_options, kwargs.get("options", {})) @@ -1444,7 +1444,7 @@ def _trace_agent_run_stream( capture_exception(span=span, exception=exception, timestamp=time_ns()) raise else: - response = AgentRunResponse.from_agent_run_response_updates(all_updates) + response = AgentResponse.from_agent_run_response_updates(all_updates) attributes = _get_response_attributes(attributes, response, capture_usage=capture_usage) _capture_response(span=span, attributes=attributes) if OBSERVABILITY_SETTINGS.SENSITIVE_DATA_ENABLED and response.messages: @@ -1784,7 +1784,7 @@ def _to_otel_part(content: "Contents") -> dict[str, Any] | None: def _get_response_attributes( attributes: dict[str, Any], - response: "ChatResponse | AgentRunResponse", + response: "ChatResponse | AgentResponse", duration: float | None = None, *, capture_usage: bool = True, diff --git a/python/packages/core/tests/azure/test_azure_assistants_client.py b/python/packages/core/tests/azure/test_azure_assistants_client.py index ae4ad0e89b..6c65dac7c1 100644 --- a/python/packages/core/tests/azure/test_azure_assistants_client.py +++ b/python/packages/core/tests/azure/test_azure_assistants_client.py @@ -9,8 +9,8 @@ from azure.identity import AzureCliCredential from pydantic import Field from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, ChatAgent, ChatClientProtocol, @@ -403,7 +403,7 @@ async def test_azure_assistants_agent_basic_run(): response = await agent.run("Hello! Please respond with 'Hello World' exactly.") # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 assert "Hello World" in response.text @@ -420,7 +420,7 @@ async def test_azure_assistants_agent_basic_run_streaming(): full_message: str = "" async for chunk in agent.run_stream("Please respond with exactly: 'This is a streaming response test.'"): assert chunk is not None - assert isinstance(chunk, AgentRunResponseUpdate) + assert isinstance(chunk, AgentResponseUpdate) if chunk.text: full_message += chunk.text @@ -444,14 +444,14 @@ async def test_azure_assistants_agent_thread_persistence(): first_response = await agent.run( "Remember this number: 42. What number did I just tell you to remember?", thread=thread ) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert "42" in first_response.text # Second message - test conversation memory second_response = await agent.run( "What number did I tell you to remember in my previous message?", thread=thread ) - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert "42" in second_response.text # Verify thread has been populated with conversation ID @@ -475,7 +475,7 @@ async def test_azure_assistants_agent_existing_thread_id(): response1 = await agent.run("What's the weather in Paris?", thread=thread) # Validate first response - assert isinstance(response1, AgentRunResponse) + assert isinstance(response1, AgentResponse) assert response1.text is not None assert any(word in response1.text.lower() for word in ["weather", "paris"]) @@ -497,7 +497,7 @@ async def test_azure_assistants_agent_existing_thread_id(): response2 = await agent.run("What was the last city I asked about?", thread=thread) # Validate that the agent remembers the previous conversation - assert isinstance(response2, AgentRunResponse) + assert isinstance(response2, AgentResponse) assert response2.text is not None # Should reference Paris from the previous conversation assert "paris" in response2.text.lower() @@ -517,7 +517,7 @@ async def test_azure_assistants_agent_code_interpreter(): response = await agent.run("Write Python code to calculate the factorial of 5 and show the result.") # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None # Factorial of 5 is 120 assert "120" in response.text or "factorial" in response.text.lower() @@ -536,7 +536,7 @@ async def test_azure_assistants_client_agent_level_tool_persistence(): # First run - agent-level tool should be available first_response = await agent.run("What's the weather like in Chicago?") - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Should use the agent-level weather tool assert any(term in first_response.text.lower() for term in ["chicago", "sunny", "72"]) @@ -544,7 +544,7 @@ async def test_azure_assistants_client_agent_level_tool_persistence(): # Second run - agent-level tool should still be available (persistence test) second_response = await agent.run("What's the weather in Miami?") - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None # Should use the agent-level weather tool again assert any(term in second_response.text.lower() for term in ["miami", "sunny", "72"]) diff --git a/python/packages/core/tests/azure/test_azure_chat_client.py b/python/packages/core/tests/azure/test_azure_chat_client.py index df9c52943a..fe8e066bf9 100644 --- a/python/packages/core/tests/azure/test_azure_chat_client.py +++ b/python/packages/core/tests/azure/test_azure_chat_client.py @@ -17,8 +17,8 @@ from openai.types.chat.chat_completion_chunk import ChoiceDelta as ChunkChoiceDe from openai.types.chat.chat_completion_message import ChatCompletionMessage from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, BaseChatClient, ChatAgent, ChatClientProtocol, @@ -731,7 +731,7 @@ async def test_azure_openai_chat_client_agent_basic_run(): # Test basic run response = await agent.run("Please respond with exactly: 'This is a response test.'") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 assert "response test" in response.text.lower() @@ -747,7 +747,7 @@ async def test_azure_openai_chat_client_agent_basic_run_streaming(): # Test streaming run full_text = "" async for chunk in agent.run_stream("Please respond with exactly: 'This is a streaming response test.'"): - assert isinstance(chunk, AgentRunResponseUpdate) + assert isinstance(chunk, AgentResponseUpdate) if chunk.text: full_text += chunk.text @@ -769,13 +769,13 @@ async def test_azure_openai_chat_client_agent_thread_persistence(): # First interaction response1 = await agent.run("My name is Alice. Remember this.", thread=thread) - assert isinstance(response1, AgentRunResponse) + assert isinstance(response1, AgentResponse) assert response1.text is not None # Second interaction - test memory response2 = await agent.run("What is my name?", thread=thread) - assert isinstance(response2, AgentRunResponse) + assert isinstance(response2, AgentResponse) assert response2.text is not None assert "alice" in response2.text.lower() @@ -795,7 +795,7 @@ async def test_azure_openai_chat_client_agent_existing_thread(): thread = first_agent.get_new_thread() first_response = await first_agent.run("My name is Alice. Remember this.", thread=thread) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Preserve the thread for reuse @@ -810,7 +810,7 @@ async def test_azure_openai_chat_client_agent_existing_thread(): # Reuse the preserved thread second_response = await second_agent.run("What is my name?", thread=preserved_thread) - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None assert "alice" in second_response.text.lower() @@ -828,7 +828,7 @@ async def test_azure_chat_client_agent_level_tool_persistence(): # First run - agent-level tool should be available first_response = await agent.run("What's the weather like in Chicago?") - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Should use the agent-level weather tool assert any(term in first_response.text.lower() for term in ["chicago", "sunny", "72"]) @@ -836,7 +836,7 @@ async def test_azure_chat_client_agent_level_tool_persistence(): # Second run - agent-level tool should still be available (persistence test) second_response = await agent.run("What's the weather in Miami?") - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None # Should use the agent-level weather tool again assert any(term in second_response.text.lower() for term in ["miami", "sunny", "72"]) diff --git a/python/packages/core/tests/azure/test_azure_responses_client.py b/python/packages/core/tests/azure/test_azure_responses_client.py index 352b7798d3..0e1c17f9a8 100644 --- a/python/packages/core/tests/azure/test_azure_responses_client.py +++ b/python/packages/core/tests/azure/test_azure_responses_client.py @@ -10,7 +10,7 @@ from pydantic import BaseModel from pytest import param from agent_framework import ( - AgentRunResponse, + AgentResponse, ChatAgent, ChatClientProtocol, ChatMessage, @@ -432,7 +432,7 @@ async def test_integration_client_agent_existing_thread(): thread = first_agent.get_new_thread() first_response = await first_agent.run("My hobby is photography. Remember this.", thread=thread, store=True) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Preserve the thread for reuse @@ -447,6 +447,6 @@ async def test_integration_client_agent_existing_thread(): # Reuse the preserved thread second_response = await second_agent.run("What is my hobby?", thread=preserved_thread) - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None assert "photography" in second_response.text.lower() diff --git a/python/packages/core/tests/core/conftest.py b/python/packages/core/tests/core/conftest.py index d8a09505af..1561392214 100644 --- a/python/packages/core/tests/core/conftest.py +++ b/python/packages/core/tests/core/conftest.py @@ -13,8 +13,8 @@ from pytest import fixture from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseChatClient, ChatMessage, @@ -231,9 +231,9 @@ class MockAgent(AgentProtocol): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: logger.debug(f"Running mock agent, with: {messages=}, {thread=}, {kwargs=}") - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, contents=[TextContent("Response")])]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, contents=[TextContent("Response")])]) async def run_stream( self, @@ -241,9 +241,9 @@ class MockAgent(AgentProtocol): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: logger.debug(f"Running mock agent stream, with: {messages=}, {thread=}, {kwargs=}") - yield AgentRunResponseUpdate(contents=[TextContent("Response")]) + yield AgentResponseUpdate(contents=[TextContent("Response")]) def get_new_thread(self) -> AgentThread: return MockAgentThread() diff --git a/python/packages/core/tests/core/test_agents.py b/python/packages/core/tests/core/test_agents.py index a1147f6db8..ee9054c143 100644 --- a/python/packages/core/tests/core/test_agents.py +++ b/python/packages/core/tests/core/test_agents.py @@ -10,8 +10,8 @@ from pytest import raises from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, ChatAgent, ChatClientProtocol, @@ -45,7 +45,7 @@ async def test_agent_run(agent: AgentProtocol) -> None: async def test_agent_run_streaming(agent: AgentProtocol) -> None: - async def collect_updates(updates: AsyncIterable[AgentRunResponseUpdate]) -> list[AgentRunResponseUpdate]: + async def collect_updates(updates: AsyncIterable[AgentResponseUpdate]) -> list[AgentResponseUpdate]: return [u async for u in updates] updates = await collect_updates(agent.run_stream(messages="test")) @@ -87,7 +87,7 @@ async def test_chat_client_agent_run(chat_client: ChatClientProtocol) -> None: async def test_chat_client_agent_run_streaming(chat_client: ChatClientProtocol) -> None: agent = ChatAgent(chat_client=chat_client) - result = await AgentRunResponse.from_agent_response_generator(agent.run_stream("Hello")) + result = await AgentResponse.from_agent_response_generator(agent.run_stream("Hello")) assert result.text == "test streaming response another update" @@ -329,7 +329,7 @@ async def test_chat_agent_run_stream_context_providers(chat_client: ChatClientPr agent = ChatAgent(chat_client=chat_client, context_provider=mock_provider) # Collect all stream updates - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("Hello"): updates.append(update) @@ -440,9 +440,9 @@ async def test_chat_agent_as_tool_with_stream_callback(chat_client: ChatClientPr agent = ChatAgent(chat_client=chat_client, name="StreamingAgent") # Collect streaming updates - collected_updates: list[AgentRunResponseUpdate] = [] + collected_updates: list[AgentResponseUpdate] = [] - def stream_callback(update: AgentRunResponseUpdate) -> None: + def stream_callback(update: AgentResponseUpdate) -> None: collected_updates.append(update) tool = agent.as_tool(stream_callback=stream_callback) @@ -474,9 +474,9 @@ async def test_chat_agent_as_tool_with_async_stream_callback(chat_client: ChatCl agent = ChatAgent(chat_client=chat_client, name="AsyncStreamingAgent") # Collect streaming updates using an async callback - collected_updates: list[AgentRunResponseUpdate] = [] + collected_updates: list[AgentResponseUpdate] = [] - async def async_stream_callback(update: AgentRunResponseUpdate) -> None: + async def async_stream_callback(update: AgentResponseUpdate) -> None: collected_updates.append(update) tool = agent.as_tool(stream_callback=async_stream_callback) diff --git a/python/packages/core/tests/core/test_chat_agent_integration.py b/python/packages/core/tests/core/test_chat_agent_integration.py index 331d599aba..574c02fd61 100644 --- a/python/packages/core/tests/core/test_chat_agent_integration.py +++ b/python/packages/core/tests/core/test_chat_agent_integration.py @@ -8,8 +8,8 @@ import pytest from pydantic import BaseModel from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, ChatAgent, HostedCodeInterpreterTool, @@ -46,7 +46,7 @@ async def test_openai_responses_client_agent_basic_run_streaming(): # Test streaming run full_text = "" async for chunk in agent.run_stream("Please respond with exactly: 'This is a streaming response test.'"): - assert isinstance(chunk, AgentRunResponseUpdate) + assert isinstance(chunk, AgentResponseUpdate) if chunk.text: full_text += chunk.text @@ -68,13 +68,13 @@ async def test_openai_responses_client_agent_thread_persistence(): # First interaction first_response = await agent.run("My favorite programming language is Python. Remember this.", thread=thread) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Second interaction - test memory second_response = await agent.run("What is my favorite programming language?", thread=thread) - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None @@ -100,7 +100,7 @@ async def test_openai_responses_client_agent_thread_storage_with_store_true(): ) # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 @@ -125,7 +125,7 @@ async def test_openai_responses_client_agent_existing_thread(): thread = first_agent.get_new_thread() first_response = await first_agent.run("My hobby is photography. Remember this.", thread=thread) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Preserve the thread for reuse @@ -140,7 +140,7 @@ async def test_openai_responses_client_agent_existing_thread(): # Reuse the preserved thread second_response = await second_agent.run("What is my hobby?", thread=preserved_thread) - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None assert "photography" in second_response.text.lower() @@ -157,7 +157,7 @@ async def test_openai_responses_client_agent_hosted_code_interpreter_tool(): # Test code interpreter functionality response = await agent.run("Calculate the sum of numbers from 1 to 10 using Python code.") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 # Should contain calculation result (sum of 1-10 = 55) or code execution content @@ -179,7 +179,7 @@ async def test_openai_responses_client_agent_image_generation_tool(): # Test image generation functionality response = await agent.run("Generate an image of a cute red panda sitting on a tree branch in a forest.") - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.messages # Verify we got image content - look for ImageGenerationToolResultContent @@ -209,7 +209,7 @@ async def test_openai_responses_client_agent_level_tool_persistence(): # First run - agent-level tool should be available first_response = await agent.run("What's the weather like in Chicago?") - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Should use the agent-level weather tool assert any(term in first_response.text.lower() for term in ["chicago", "sunny", "72"]) @@ -217,7 +217,7 @@ async def test_openai_responses_client_agent_level_tool_persistence(): # Second run - agent-level tool should still be available (persistence test) second_response = await agent.run("What's the weather in Miami?") - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None # Should use the agent-level weather tool again assert any(term in second_response.text.lower() for term in ["miami", "sunny", "72"]) @@ -249,7 +249,7 @@ async def test_openai_responses_client_run_level_tool_isolation(): tools=[get_weather_with_counter], # Run-level tool ) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Should use the run-level weather tool (call count should be 1) assert call_count == 1 @@ -258,7 +258,7 @@ async def test_openai_responses_client_run_level_tool_isolation(): # Second run - run-level tool should NOT persist (key isolation test) second_response = await agent.run("What's the weather like in Miami?") - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None # Should NOT use the weather tool since it was only run-level in previous call # Call count should still be 1 (no additional calls) @@ -286,7 +286,7 @@ async def test_openai_responses_client_agent_chat_options_agent_level() -> None: "Provide a brief, helpful response.", ) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 @@ -312,7 +312,7 @@ async def test_openai_responses_client_agent_hosted_mcp_tool() -> None: options={"max_tokens": 5000}, ) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text # Should contain Azure-related content since it's asking about Azure CLI assert any(term in response.text.lower() for term in ["azure", "storage", "account", "cli"]) @@ -338,7 +338,7 @@ async def test_openai_responses_client_agent_local_mcp_tool() -> None: options={"max_tokens": 200}, ) - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 # Should contain Azure-related content since it's asking about Azure CLI @@ -375,7 +375,7 @@ async def test_openai_responses_client_agent_with_response_format_pydantic() -> ) # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.value is not None assert isinstance(response.value, ReleaseBrief) @@ -422,7 +422,7 @@ async def test_openai_responses_client_agent_with_runtime_json_schema() -> None: ) # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None # Parse JSON and validate structure diff --git a/python/packages/core/tests/core/test_middleware.py b/python/packages/core/tests/core/test_middleware.py index 2ec11e9be9..ebb833f2b4 100644 --- a/python/packages/core/tests/core/test_middleware.py +++ b/python/packages/core/tests/core/test_middleware.py @@ -9,8 +9,8 @@ from pydantic import BaseModel, Field from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, ChatMessage, ChatResponse, ChatResponseUpdate, @@ -172,9 +172,9 @@ class TestAgentMiddlewarePipeline: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - expected_response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + expected_response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: return expected_response result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -200,9 +200,9 @@ class TestAgentMiddlewarePipeline: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - expected_response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + expected_response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: execution_order.append("handler") return expected_response @@ -216,11 +216,11 @@ class TestAgentMiddlewarePipeline: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk1")]) - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk2")]) + async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate(contents=[TextContent(text="chunk1")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk2")]) - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in pipeline.execute_stream(mock_agent, messages, context, final_handler): updates.append(update) @@ -248,13 +248,13 @@ class TestAgentMiddlewarePipeline: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: + async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: execution_order.append("handler_start") - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk1")]) - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk2")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk1")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk2")]) execution_order.append("handler_end") - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in pipeline.execute_stream(mock_agent, messages, context, final_handler): updates.append(update) @@ -271,10 +271,10 @@ class TestAgentMiddlewarePipeline: context = AgentRunContext(agent=mock_agent, messages=messages) execution_order: list[str] = [] - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: # Handler should not be executed when terminated before next() execution_order.append("handler") - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) response = await pipeline.execute(mock_agent, messages, context, final_handler) assert response is not None @@ -291,9 +291,9 @@ class TestAgentMiddlewarePipeline: context = AgentRunContext(agent=mock_agent, messages=messages) execution_order: list[str] = [] - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: execution_order.append("handler") - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) response = await pipeline.execute(mock_agent, messages, context, final_handler) assert response is not None @@ -310,14 +310,14 @@ class TestAgentMiddlewarePipeline: context = AgentRunContext(agent=mock_agent, messages=messages) execution_order: list[str] = [] - async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: + async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: # Handler should not be executed when terminated before next() execution_order.append("handler_start") - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk1")]) - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk2")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk1")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk2")]) execution_order.append("handler_end") - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in pipeline.execute_stream(mock_agent, messages, context, final_handler): updates.append(update) @@ -334,13 +334,13 @@ class TestAgentMiddlewarePipeline: context = AgentRunContext(agent=mock_agent, messages=messages) execution_order: list[str] = [] - async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: + async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: execution_order.append("handler_start") - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk1")]) - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk2")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk1")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk2")]) execution_order.append("handler_end") - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in pipeline.execute_stream(mock_agent, messages, context, final_handler): updates.append(update) @@ -370,9 +370,9 @@ class TestAgentMiddlewarePipeline: thread = AgentThread() context = AgentRunContext(agent=mock_agent, messages=messages, thread=thread) - expected_response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + expected_response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: return expected_response result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -396,9 +396,9 @@ class TestAgentMiddlewarePipeline: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages, thread=None) - expected_response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + expected_response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: return expected_response result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -767,9 +767,9 @@ class TestClassBasedMiddleware: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: metadata_updates.append("handler") - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -830,9 +830,9 @@ class TestFunctionBasedMiddleware: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: execution_order.append("handler") - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -893,9 +893,9 @@ class TestMixedMiddleware: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: execution_order.append("handler") - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -1004,9 +1004,9 @@ class TestMultipleMiddlewareOrdering: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: execution_order.append("handler") - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -1142,10 +1142,10 @@ class TestContextContentValidation: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: # Verify metadata was set by middleware assert ctx.metadata.get("validated") is True - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) assert result is not None @@ -1253,20 +1253,20 @@ class TestStreamingScenarios: # Test non-streaming context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: streaming_flags.append(ctx.is_streaming) - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response")]) await pipeline.execute(mock_agent, messages, context, final_handler) # Test streaming context_stream = AgentRunContext(agent=mock_agent, messages=messages) - async def final_stream_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: + async def final_stream_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: streaming_flags.append(ctx.is_streaming) - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk")]) - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in pipeline.execute_stream(mock_agent, messages, context_stream, final_stream_handler): updates.append(update) @@ -1290,11 +1290,11 @@ class TestStreamingScenarios: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_stream_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: + async def final_stream_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: chunks_processed.append("stream_start") - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk1")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk1")]) chunks_processed.append("chunk1_yielded") - yield AgentRunResponseUpdate(contents=[TextContent(text="chunk2")]) + yield AgentResponseUpdate(contents=[TextContent(text="chunk2")]) chunks_processed.append("chunk2_yielded") chunks_processed.append("stream_end") @@ -1452,16 +1452,16 @@ class TestMiddlewareExecutionControl: handler_called = False - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: nonlocal handler_called handler_called = True - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="should not execute")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="should not execute")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) - # Verify no execution happened - should return empty AgentRunResponse + # Verify no execution happened - should return empty AgentResponse assert result is not None - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.messages == [] # Empty response assert not handler_called assert context.result is None @@ -1483,13 +1483,13 @@ class TestMiddlewareExecutionControl: handler_called = False - async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: + async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: nonlocal handler_called handler_called = True - yield AgentRunResponseUpdate(contents=[TextContent(text="should not execute")]) + yield AgentResponseUpdate(contents=[TextContent(text="should not execute")]) # When middleware doesn't call next(), streaming should yield no updates - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in pipeline.execute_stream(mock_agent, messages, context, final_handler): updates.append(update) @@ -1556,17 +1556,17 @@ class TestMiddlewareExecutionControl: handler_called = False - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: nonlocal handler_called handler_called = True - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="should not execute")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="should not execute")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) # Verify only first middleware was called and empty response returned assert execution_order == ["first"] assert result is not None - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert result.messages == [] # Empty response assert not handler_called diff --git a/python/packages/core/tests/core/test_middleware_context_result.py b/python/packages/core/tests/core/test_middleware_context_result.py index 447ba0d4b9..bfcfb48e5f 100644 --- a/python/packages/core/tests/core/test_middleware_context_result.py +++ b/python/packages/core/tests/core/test_middleware_context_result.py @@ -9,8 +9,8 @@ from pydantic import BaseModel, Field from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, ChatAgent, ChatMessage, Role, @@ -40,7 +40,7 @@ class TestResultOverrideMiddleware: async def test_agent_middleware_response_override_non_streaming(self, mock_agent: AgentProtocol) -> None: """Test that agent middleware can override response for non-streaming execution.""" - override_response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="overridden response")]) + override_response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="overridden response")]) class ResponseOverrideMiddleware(AgentMiddleware): async def process( @@ -57,10 +57,10 @@ class TestResultOverrideMiddleware: handler_called = False - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: nonlocal handler_called handler_called = True - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="original response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="original response")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -74,9 +74,9 @@ class TestResultOverrideMiddleware: async def test_agent_middleware_response_override_streaming(self, mock_agent: AgentProtocol) -> None: """Test that agent middleware can override response for streaming execution.""" - async def override_stream() -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate(contents=[TextContent(text="overridden")]) - yield AgentRunResponseUpdate(contents=[TextContent(text=" stream")]) + async def override_stream() -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate(contents=[TextContent(text="overridden")]) + yield AgentResponseUpdate(contents=[TextContent(text=" stream")]) class StreamResponseOverrideMiddleware(AgentMiddleware): async def process( @@ -91,10 +91,10 @@ class TestResultOverrideMiddleware: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate(contents=[TextContent(text="original")]) + async def final_handler(ctx: AgentRunContext) -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate(contents=[TextContent(text="original")]) - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in pipeline.execute_stream(mock_agent, messages, context, final_handler): updates.append(update) @@ -148,7 +148,7 @@ class TestResultOverrideMiddleware: await next(context) # Then conditionally override based on content if any("special" in msg.text for msg in context.messages if msg.text): - context.result = AgentRunResponse( + context.result = AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text="Special response from middleware!")] ) @@ -174,10 +174,10 @@ class TestResultOverrideMiddleware: """Test streaming result override functionality with ChatAgent integration.""" mock_chat_client = MockChatClient() - async def custom_stream() -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate(contents=[TextContent(text="Custom")]) - yield AgentRunResponseUpdate(contents=[TextContent(text=" streaming")]) - yield AgentRunResponseUpdate(contents=[TextContent(text=" response!")]) + async def custom_stream() -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate(contents=[TextContent(text="Custom")]) + yield AgentResponseUpdate(contents=[TextContent(text=" streaming")]) + yield AgentResponseUpdate(contents=[TextContent(text=" response!")]) class ChatAgentStreamOverrideMiddleware(AgentMiddleware): async def process( @@ -195,7 +195,7 @@ class TestResultOverrideMiddleware: # Test streaming override case override_messages = [ChatMessage(role=Role.USER, text="Give me a custom stream")] - override_updates: list[AgentRunResponseUpdate] = [] + override_updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream(override_messages): override_updates.append(update) @@ -206,7 +206,7 @@ class TestResultOverrideMiddleware: # Test normal streaming case normal_messages = [ChatMessage(role=Role.USER, text="Normal streaming request")] - normal_updates: list[AgentRunResponseUpdate] = [] + normal_updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream(normal_messages): normal_updates.append(update) @@ -231,19 +231,19 @@ class TestResultOverrideMiddleware: handler_called = False - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: + async def final_handler(ctx: AgentRunContext) -> AgentResponse: nonlocal handler_called handler_called = True - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="executed response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="executed response")]) # Test case where next() is NOT called no_execute_messages = [ChatMessage(role=Role.USER, text="Don't run this")] no_execute_context = AgentRunContext(agent=mock_agent, messages=no_execute_messages) no_execute_result = await pipeline.execute(mock_agent, no_execute_messages, no_execute_context, final_handler) - # When middleware doesn't call next(), result should be empty AgentRunResponse + # When middleware doesn't call next(), result should be empty AgentResponse assert no_execute_result is not None - assert isinstance(no_execute_result, AgentRunResponse) + assert isinstance(no_execute_result, AgentResponse) assert no_execute_result.messages == [] # Empty response assert not handler_called assert no_execute_context.result is None @@ -313,7 +313,7 @@ class TestResultObservability: async def test_agent_middleware_response_observability(self, mock_agent: AgentProtocol) -> None: """Test that middleware can observe response after execution.""" - observed_responses: list[AgentRunResponse] = [] + observed_responses: list[AgentResponse] = [] class ObservabilityMiddleware(AgentMiddleware): async def process( @@ -327,7 +327,7 @@ class TestResultObservability: # Context should now contain the response for observability assert context.result is not None - assert isinstance(context.result, AgentRunResponse) + assert isinstance(context.result, AgentResponse) observed_responses.append(context.result) middleware = ObservabilityMiddleware() @@ -335,8 +335,8 @@ class TestResultObservability: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="executed response")]) + async def final_handler(ctx: AgentRunContext) -> AgentResponse: + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="executed response")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) @@ -392,11 +392,11 @@ class TestResultObservability: # Now observe and conditionally override assert context.result is not None - assert isinstance(context.result, AgentRunResponse) + assert isinstance(context.result, AgentResponse) if "modify" in context.result.messages[0].text: # Override after observing - context.result = AgentRunResponse( + context.result = AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text="modified after execution")] ) @@ -405,8 +405,8 @@ class TestResultObservability: messages = [ChatMessage(role=Role.USER, text="test")] context = AgentRunContext(agent=mock_agent, messages=messages) - async def final_handler(ctx: AgentRunContext) -> AgentRunResponse: - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response to modify")]) + async def final_handler(ctx: AgentRunContext) -> AgentResponse: + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="response to modify")]) result = await pipeline.execute(mock_agent, messages, context, final_handler) diff --git a/python/packages/core/tests/core/test_middleware_with_agent.py b/python/packages/core/tests/core/test_middleware_with_agent.py index 38625db168..5cfea39287 100644 --- a/python/packages/core/tests/core/test_middleware_with_agent.py +++ b/python/packages/core/tests/core/test_middleware_with_agent.py @@ -6,7 +6,7 @@ from typing import Any import pytest from agent_framework import ( - AgentRunResponseUpdate, + AgentResponseUpdate, ChatAgent, ChatContext, ChatMessage, @@ -372,7 +372,7 @@ class TestChatAgentStreamingMiddleware: # Execute streaming messages = [ChatMessage(role=Role.USER, text="test message")] - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream(messages): updates.append(update) @@ -878,7 +878,7 @@ class TestMiddlewareDynamicRebuild: agent = ChatAgent(chat_client=chat_client, middleware=[middleware1]) # First streaming execution - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("Test stream message 1"): updates.append(update) @@ -1085,7 +1085,7 @@ class TestRunLevelMiddleware: run_middleware = StreamingTrackingMiddleware("run_stream") # Execute streaming with run middleware - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("Test streaming", middleware=[run_middleware]): updates.append(update) @@ -1711,7 +1711,7 @@ class TestChatAgentChatMiddleware: # Execute streaming messages = [ChatMessage(role=Role.USER, text="test message")] - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream(messages): updates.append(update) diff --git a/python/packages/core/tests/core/test_observability.py b/python/packages/core/tests/core/test_observability.py index 5b9704abb0..95f234efd4 100644 --- a/python/packages/core/tests/core/test_observability.py +++ b/python/packages/core/tests/core/test_observability.py @@ -13,7 +13,7 @@ from opentelemetry.trace import StatusCode from agent_framework import ( AGENT_FRAMEWORK_USER_AGENT, AgentProtocol, - AgentRunResponse, + AgentResponse, AgentThread, BaseChatClient, ChatMessage, @@ -407,7 +407,7 @@ def mock_chat_agent(): self.default_options: dict[str, Any] = {"model_id": "TestModel"} async def run(self, messages=None, *, thread=None, **kwargs): - return AgentRunResponse( + return AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text="Agent response")], usage_details=UsageDetails(input_token_count=15, output_token_count=25), response_id="test_response_id", @@ -415,10 +415,10 @@ def mock_chat_agent(): ) async def run_stream(self, messages=None, *, thread=None, **kwargs): - from agent_framework import AgentRunResponseUpdate + from agent_framework import AgentResponseUpdate - yield AgentRunResponseUpdate(text="Hello", role=Role.ASSISTANT) - yield AgentRunResponseUpdate(text=" from agent", role=Role.ASSISTANT) + yield AgentResponseUpdate(text="Hello", role=Role.ASSISTANT) + yield AgentResponseUpdate(text=" from agent", role=Role.ASSISTANT) return MockChatClientAgent diff --git a/python/packages/core/tests/core/test_types.py b/python/packages/core/tests/core/test_types.py index 5376f72754..c5187fd960 100644 --- a/python/packages/core/tests/core/test_types.py +++ b/python/packages/core/tests/core/test_types.py @@ -10,8 +10,8 @@ from pydantic import BaseModel from pytest import fixture, mark, raises from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, BaseContent, ChatMessage, ChatOptions, @@ -1026,90 +1026,90 @@ def text_content() -> TextContent: @fixture -def agent_run_response(chat_message: ChatMessage) -> AgentRunResponse: - return AgentRunResponse(messages=chat_message) +def agent_response(chat_message: ChatMessage) -> AgentResponse: + return AgentResponse(messages=chat_message) @fixture -def agent_run_response_update(text_content: TextContent) -> AgentRunResponseUpdate: - return AgentRunResponseUpdate(role=Role.ASSISTANT, contents=[text_content]) +def agent_response_update(text_content: TextContent) -> AgentResponseUpdate: + return AgentResponseUpdate(role=Role.ASSISTANT, contents=[text_content]) -# region AgentRunResponse +# region AgentResponse def test_agent_run_response_init_single_message(chat_message: ChatMessage) -> None: - response = AgentRunResponse(messages=chat_message) + response = AgentResponse(messages=chat_message) assert response.messages == [chat_message] def test_agent_run_response_init_list_messages(chat_message: ChatMessage) -> None: - response = AgentRunResponse(messages=[chat_message, chat_message]) + response = AgentResponse(messages=[chat_message, chat_message]) assert len(response.messages) == 2 assert response.messages[0] == chat_message def test_agent_run_response_init_none_messages() -> None: - response = AgentRunResponse() + response = AgentResponse() assert response.messages == [] def test_agent_run_response_text_property(chat_message: ChatMessage) -> None: - response = AgentRunResponse(messages=[chat_message, chat_message]) + response = AgentResponse(messages=[chat_message, chat_message]) assert response.text == "HelloHello" def test_agent_run_response_text_property_empty() -> None: - response = AgentRunResponse() + response = AgentResponse() assert response.text == "" -def test_agent_run_response_from_updates(agent_run_response_update: AgentRunResponseUpdate) -> None: - updates = [agent_run_response_update, agent_run_response_update] - response = AgentRunResponse.from_agent_run_response_updates(updates) +def test_agent_run_response_from_updates(agent_response_update: AgentResponseUpdate) -> None: + updates = [agent_response_update, agent_response_update] + response = AgentResponse.from_agent_run_response_updates(updates) assert len(response.messages) > 0 assert response.text == "Test contentTest content" def test_agent_run_response_str_method(chat_message: ChatMessage) -> None: - response = AgentRunResponse(messages=chat_message) + response = AgentResponse(messages=chat_message) assert str(response) == "Hello" -# region AgentRunResponseUpdate +# region AgentResponseUpdate def test_agent_run_response_update_init_content_list(text_content: TextContent) -> None: - update = AgentRunResponseUpdate(contents=[text_content, text_content]) + update = AgentResponseUpdate(contents=[text_content, text_content]) assert len(update.contents) == 2 assert update.contents[0] == text_content def test_agent_run_response_update_init_none_content() -> None: - update = AgentRunResponseUpdate() + update = AgentResponseUpdate() assert update.contents == [] def test_agent_run_response_update_text_property(text_content: TextContent) -> None: - update = AgentRunResponseUpdate(contents=[text_content, text_content]) + update = AgentResponseUpdate(contents=[text_content, text_content]) assert update.text == "Test contentTest content" def test_agent_run_response_update_text_property_empty() -> None: - update = AgentRunResponseUpdate() + update = AgentResponseUpdate() assert update.text == "" def test_agent_run_response_update_str_method(text_content: TextContent) -> None: - update = AgentRunResponseUpdate(contents=[text_content]) + update = AgentResponseUpdate(contents=[text_content]) assert str(update) == "Test content" def test_agent_run_response_update_created_at() -> None: - """Test that AgentRunResponseUpdate properly handles created_at timestamps.""" + """Test that AgentResponseUpdate properly handles created_at timestamps.""" # Test with a properly formatted UTC timestamp utc_timestamp = "2024-12-01T00:31:30.000000Z" - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[TextContent(text="test")], role=Role.ASSISTANT, created_at=utc_timestamp, @@ -1120,7 +1120,7 @@ def test_agent_run_response_update_created_at() -> None: # Verify that we can generate a proper UTC timestamp now_utc = datetime.now(tz=timezone.utc) formatted_utc = now_utc.strftime("%Y-%m-%dT%H:%M:%S.%fZ") - update_with_now = AgentRunResponseUpdate( + update_with_now = AgentResponseUpdate( contents=[TextContent(text="test")], role=Role.ASSISTANT, created_at=formatted_utc, @@ -1130,10 +1130,10 @@ def test_agent_run_response_update_created_at() -> None: def test_agent_run_response_created_at() -> None: - """Test that AgentRunResponse properly handles created_at timestamps.""" + """Test that AgentResponse properly handles created_at timestamps.""" # Test with a properly formatted UTC timestamp utc_timestamp = "2024-12-01T00:31:30.000000Z" - response = AgentRunResponse( + response = AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text="Hello")], created_at=utc_timestamp, ) @@ -1143,7 +1143,7 @@ def test_agent_run_response_created_at() -> None: # Verify that we can generate a proper UTC timestamp now_utc = datetime.now(tz=timezone.utc) formatted_utc = now_utc.strftime("%Y-%m-%dT%H:%M:%S.%fZ") - response_with_now = AgentRunResponse( + response_with_now = AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text="Hello")], created_at=formatted_utc, ) @@ -1285,20 +1285,20 @@ def test_chat_tool_mode_eq_with_string(): assert {"mode": "auto"} == {"mode": "auto"} -# region AgentRunResponse +# region AgentResponse @fixture -def agent_run_response_async() -> AgentRunResponse: - return AgentRunResponse(messages=[ChatMessage(role="user", text="Hello")]) +def agent_run_response_async() -> AgentResponse: + return AgentResponse(messages=[ChatMessage(role="user", text="Hello")]) async def test_agent_run_response_from_async_generator(): async def gen(): - yield AgentRunResponseUpdate(contents=[TextContent("A")]) - yield AgentRunResponseUpdate(contents=[TextContent("B")]) + yield AgentResponseUpdate(contents=[TextContent("A")]) + yield AgentResponseUpdate(contents=[TextContent("B")]) - r = await AgentRunResponse.from_agent_response_generator(gen()) + r = await AgentResponse.from_agent_response_generator(gen()) assert r.text == "AB" @@ -1668,7 +1668,7 @@ def test_chat_response_update_all_content_types(): def test_agent_run_response_complex_serialization(): - """Test AgentRunResponse from_dict and to_dict with messages and usage_details.""" + """Test AgentResponse from_dict and to_dict with messages and usage_details.""" response_data = { "messages": [ @@ -1683,7 +1683,7 @@ def test_agent_run_response_complex_serialization(): }, } - response = AgentRunResponse.from_dict(response_data) + response = AgentResponse.from_dict(response_data) assert len(response.messages) == 2 assert isinstance(response.messages[0], ChatMessage) assert isinstance(response.usage_details, UsageDetails) @@ -1696,7 +1696,7 @@ def test_agent_run_response_complex_serialization(): def test_agent_run_response_update_all_content_types(): - """Test AgentRunResponseUpdate from_dict with all content types and role handling.""" + """Test AgentResponseUpdate from_dict with all content types and role handling.""" update_data = { "contents": [ @@ -1725,7 +1725,7 @@ def test_agent_run_response_update_all_content_types(): "role": {"value": "assistant"}, # Test role as dict } - update = AgentRunResponseUpdate.from_dict(update_data) + update = AgentResponseUpdate.from_dict(update_data) assert len(update.contents) == 12 # unknown_type is logged and ignored assert isinstance(update.role, Role) assert update.role.value == "assistant" @@ -1738,7 +1738,7 @@ def test_agent_run_response_update_all_content_types(): # Test role as string conversion update_data_str_role = update_data.copy() update_data_str_role["role"] = "user" - update_str = AgentRunResponseUpdate.from_dict(update_data_str_role) + update_str = AgentResponseUpdate.from_dict(update_data_str_role) assert isinstance(update_str.role, Role) assert update_str.role.value == "user" @@ -1922,7 +1922,7 @@ def test_agent_run_response_update_all_content_types(): id="chat_response_update", ), pytest.param( - AgentRunResponse, + AgentResponse, { "messages": [ { @@ -1942,10 +1942,10 @@ def test_agent_run_response_update_all_content_types(): "total_token_count": 8, }, }, - id="agent_run_response", + id="agent_response", ), pytest.param( - AgentRunResponseUpdate, + AgentResponseUpdate, { "contents": [ {"type": "text", "text": "Streaming"}, @@ -1956,7 +1956,7 @@ def test_agent_run_response_update_all_content_types(): "response_id": "run-123", "author_name": "Agent", }, - id="agent_run_response_update", + id="agent_response_update", ), ], ) diff --git a/python/packages/core/tests/openai/test_openai_assistants_client.py b/python/packages/core/tests/openai/test_openai_assistants_client.py index 77605432ff..27fae35af9 100644 --- a/python/packages/core/tests/openai/test_openai_assistants_client.py +++ b/python/packages/core/tests/openai/test_openai_assistants_client.py @@ -11,8 +11,8 @@ from openai.types.beta.threads.runs import RunStep from pydantic import Field from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, ChatAgent, ChatClientProtocol, @@ -1118,7 +1118,7 @@ async def test_openai_assistants_agent_basic_run(): response = await agent.run("Hello! Please respond with 'Hello World' exactly.") # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None assert len(response.text) > 0 assert "Hello World" in response.text @@ -1135,7 +1135,7 @@ async def test_openai_assistants_agent_basic_run_streaming(): full_message: str = "" async for chunk in agent.run_stream("Please respond with exactly: 'This is a streaming response test.'"): assert chunk is not None - assert isinstance(chunk, AgentRunResponseUpdate) + assert isinstance(chunk, AgentResponseUpdate) if chunk.text: full_message += chunk.text @@ -1159,14 +1159,14 @@ async def test_openai_assistants_agent_thread_persistence(): first_response = await agent.run( "Remember this number: 42. What number did I just tell you to remember?", thread=thread ) - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert "42" in first_response.text # Second message - test conversation memory second_response = await agent.run( "What number did I tell you to remember in my previous message?", thread=thread ) - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert "42" in second_response.text # Verify thread has been populated with conversation ID @@ -1190,7 +1190,7 @@ async def test_openai_assistants_agent_existing_thread_id(): response1 = await agent.run("What's the weather in Paris?", thread=thread) # Validate first response - assert isinstance(response1, AgentRunResponse) + assert isinstance(response1, AgentResponse) assert response1.text is not None assert any(word in response1.text.lower() for word in ["weather", "paris"]) @@ -1212,7 +1212,7 @@ async def test_openai_assistants_agent_existing_thread_id(): response2 = await agent.run("What was the last city I asked about?", thread=thread) # Validate that the agent remembers the previous conversation - assert isinstance(response2, AgentRunResponse) + assert isinstance(response2, AgentResponse) assert response2.text is not None # Should reference Paris from the previous conversation assert "paris" in response2.text.lower() @@ -1232,7 +1232,7 @@ async def test_openai_assistants_agent_code_interpreter(): response = await agent.run("Write Python code to calculate the factorial of 5 and show the result.") # Validate response - assert isinstance(response, AgentRunResponse) + assert isinstance(response, AgentResponse) assert response.text is not None # Factorial of 5 is 120 assert "120" in response.text or "factorial" in response.text.lower() @@ -1251,7 +1251,7 @@ async def test_agent_level_tool_persistence(): # First run - agent-level tool should be available first_response = await agent.run("What's the weather like in Chicago?") - assert isinstance(first_response, AgentRunResponse) + assert isinstance(first_response, AgentResponse) assert first_response.text is not None # Should use the agent-level weather tool assert any(term in first_response.text.lower() for term in ["chicago", "sunny", "72"]) @@ -1259,7 +1259,7 @@ async def test_agent_level_tool_persistence(): # Second run - agent-level tool should still be available (persistence test) second_response = await agent.run("What's the weather in Miami?") - assert isinstance(second_response, AgentRunResponse) + assert isinstance(second_response, AgentResponse) assert second_response.text is not None # Should use the agent-level weather tool again assert any(term in second_response.text.lower() for term in ["miami", "sunny", "72"]) diff --git a/python/packages/core/tests/workflow/test_agent_executor.py b/python/packages/core/tests/workflow/test_agent_executor.py index 1485c9f523..95225cb4a3 100644 --- a/python/packages/core/tests/workflow/test_agent_executor.py +++ b/python/packages/core/tests/workflow/test_agent_executor.py @@ -5,8 +5,8 @@ from typing import Any from agent_framework import ( AgentExecutor, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, ChatMessage, @@ -35,9 +35,9 @@ class _CountingAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: self.call_count += 1 - return AgentRunResponse( + return AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text=f"Response #{self.call_count}: {self.name}")] ) @@ -47,9 +47,9 @@ class _CountingAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: self.call_count += 1 - yield AgentRunResponseUpdate(contents=[TextContent(text=f"Response #{self.call_count}: {self.name}")]) + yield AgentResponseUpdate(contents=[TextContent(text=f"Response #{self.call_count}: {self.name}")]) async def test_agent_executor_checkpoint_stores_and_restores_state() -> None: diff --git a/python/packages/core/tests/workflow/test_agent_executor_tool_calls.py b/python/packages/core/tests/workflow/test_agent_executor_tool_calls.py index a7849120b0..ecf8b3d635 100644 --- a/python/packages/core/tests/workflow/test_agent_executor_tool_calls.py +++ b/python/packages/core/tests/workflow/test_agent_executor_tool_calls.py @@ -10,8 +10,8 @@ from typing_extensions import Never from agent_framework import ( AgentExecutor, AgentExecutorResponse, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentRunUpdateEvent, AgentThread, BaseAgent, @@ -46,9 +46,9 @@ class _ToolCallingAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Non-streaming run - not used in this test.""" - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="done")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="done")]) async def run_stream( self, @@ -56,16 +56,16 @@ class _ToolCallingAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Simulate streaming with tool calls and results.""" # First update: some text - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[TextContent(text="Let me search for that...")], role=Role.ASSISTANT, ) # Second update: tool call (no text!) - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[ FunctionCallContent( call_id="call_123", @@ -77,7 +77,7 @@ class _ToolCallingAgent(BaseAgent): ) # Third update: tool result (no text!) - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[ FunctionResultContent( call_id="call_123", @@ -88,7 +88,7 @@ class _ToolCallingAgent(BaseAgent): ) # Fourth update: final text response - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[TextContent(text="The weather is sunny, 72°F.")], role=Role.ASSISTANT, ) @@ -223,7 +223,7 @@ class MockChatClient: @executor(id="test_executor") async def test_executor(agent_executor_response: AgentExecutorResponse, ctx: WorkflowContext[Never, str]) -> None: - await ctx.yield_output(agent_executor_response.agent_run_response.text) + await ctx.yield_output(agent_executor_response.agent_response.text) async def test_agent_executor_tool_call_with_approval() -> None: diff --git a/python/packages/core/tests/workflow/test_agent_run_event_typing.py b/python/packages/core/tests/workflow/test_agent_run_event_typing.py index 271a9bbe2f..e5071a7c96 100644 --- a/python/packages/core/tests/workflow/test_agent_run_event_typing.py +++ b/python/packages/core/tests/workflow/test_agent_run_event_typing.py @@ -2,26 +2,26 @@ """Tests for AgentRunEvent and AgentRunUpdateEvent type annotations.""" -from agent_framework import AgentRunResponse, AgentRunResponseUpdate, ChatMessage, Role +from agent_framework import AgentResponse, AgentResponseUpdate, ChatMessage, Role from agent_framework._workflows._events import AgentRunEvent, AgentRunUpdateEvent def test_agent_run_event_data_type() -> None: - """Verify AgentRunEvent.data is typed as AgentRunResponse | None.""" - response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Hello")]) + """Verify AgentRunEvent.data is typed as AgentResponse | None.""" + response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Hello")]) event = AgentRunEvent(executor_id="test", data=response) # This assignment should pass type checking without a cast - data: AgentRunResponse | None = event.data + data: AgentResponse | None = event.data assert data is not None assert data.text == "Hello" def test_agent_run_update_event_data_type() -> None: - """Verify AgentRunUpdateEvent.data is typed as AgentRunResponseUpdate | None.""" - update = AgentRunResponseUpdate() + """Verify AgentRunUpdateEvent.data is typed as AgentResponseUpdate | None.""" + update = AgentResponseUpdate() event = AgentRunUpdateEvent(executor_id="test", data=update) # This assignment should pass type checking without a cast - data: AgentRunResponseUpdate | None = event.data + data: AgentResponseUpdate | None = event.data assert data is not None diff --git a/python/packages/core/tests/workflow/test_agent_utils.py b/python/packages/core/tests/workflow/test_agent_utils.py index 7f80658a09..9207846791 100644 --- a/python/packages/core/tests/workflow/test_agent_utils.py +++ b/python/packages/core/tests/workflow/test_agent_utils.py @@ -3,7 +3,7 @@ from collections.abc import AsyncIterable from typing import Any -from agent_framework import AgentRunResponse, AgentRunResponseUpdate, AgentThread, ChatMessage +from agent_framework import AgentResponse, AgentResponseUpdate, AgentThread, ChatMessage from agent_framework._workflows._agent_utils import resolve_agent_id @@ -38,7 +38,7 @@ class MockAgent: *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: ... + ) -> AgentResponse: ... def run_stream( self, @@ -46,7 +46,7 @@ class MockAgent: *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: ... + ) -> AsyncIterable[AgentResponseUpdate]: ... def get_new_thread(self, **kwargs: Any) -> AgentThread: """Creates a new conversation thread for the agent.""" diff --git a/python/packages/core/tests/workflow/test_concurrent.py b/python/packages/core/tests/workflow/test_concurrent.py index 57810b8f59..a0c03c7720 100644 --- a/python/packages/core/tests/workflow/test_concurrent.py +++ b/python/packages/core/tests/workflow/test_concurrent.py @@ -8,7 +8,7 @@ from typing_extensions import Never from agent_framework import ( AgentExecutorRequest, AgentExecutorResponse, - AgentRunResponse, + AgentResponse, ChatMessage, ConcurrentBuilder, Executor, @@ -36,7 +36,7 @@ class _FakeAgentExec(Executor): @handler async def run(self, request: AgentExecutorRequest, ctx: WorkflowContext[AgentExecutorResponse]) -> None: - response = AgentRunResponse(messages=ChatMessage(Role.ASSISTANT, text=self._reply_text)) + response = AgentResponse(messages=ChatMessage(Role.ASSISTANT, text=self._reply_text)) full_conversation = list(request.messages) + list(response.messages) await ctx.send_message(AgentExecutorResponse(self.id, response, full_conversation=full_conversation)) @@ -142,7 +142,7 @@ async def test_concurrent_custom_aggregator_callback_is_used() -> None: async def summarize(results: list[AgentExecutorResponse]) -> str: texts: list[str] = [] for r in results: - msgs: list[ChatMessage] = r.agent_run_response.messages + msgs: list[ChatMessage] = r.agent_response.messages texts.append(msgs[-1].text if msgs else "") return " | ".join(sorted(texts)) @@ -173,7 +173,7 @@ async def test_concurrent_custom_aggregator_sync_callback_is_used() -> None: def summarize_sync(results: list[AgentExecutorResponse], _ctx: WorkflowContext[Any]) -> str: # type: ignore[unused-argument] texts: list[str] = [] for r in results: - msgs: list[ChatMessage] = r.agent_run_response.messages + msgs: list[ChatMessage] = r.agent_response.messages texts.append(msgs[-1].text if msgs else "") return " | ".join(sorted(texts)) @@ -217,7 +217,7 @@ async def test_concurrent_with_aggregator_executor_instance() -> None: async def aggregate(self, results: list[AgentExecutorResponse], ctx: WorkflowContext[Never, str]) -> None: texts: list[str] = [] for r in results: - msgs: list[ChatMessage] = r.agent_run_response.messages + msgs: list[ChatMessage] = r.agent_response.messages texts.append(msgs[-1].text if msgs else "") await ctx.yield_output(" & ".join(sorted(texts))) @@ -251,7 +251,7 @@ async def test_concurrent_with_aggregator_executor_factory() -> None: async def aggregate(self, results: list[AgentExecutorResponse], ctx: WorkflowContext[Never, str]) -> None: texts: list[str] = [] for r in results: - msgs: list[ChatMessage] = r.agent_run_response.messages + msgs: list[ChatMessage] = r.agent_response.messages texts.append(msgs[-1].text if msgs else "") await ctx.yield_output(" | ".join(sorted(texts))) @@ -292,7 +292,7 @@ async def test_concurrent_with_aggregator_executor_factory_with_default_id() -> async def aggregate(self, results: list[AgentExecutorResponse], ctx: WorkflowContext[Never, str]) -> None: texts: list[str] = [] for r in results: - msgs: list[ChatMessage] = r.agent_run_response.messages + msgs: list[ChatMessage] = r.agent_response.messages texts.append(msgs[-1].text if msgs else "") await ctx.yield_output(" | ".join(sorted(texts))) diff --git a/python/packages/core/tests/workflow/test_full_conversation.py b/python/packages/core/tests/workflow/test_full_conversation.py index af24c3e17b..b1a3194468 100644 --- a/python/packages/core/tests/workflow/test_full_conversation.py +++ b/python/packages/core/tests/workflow/test_full_conversation.py @@ -9,8 +9,8 @@ from typing_extensions import Never from agent_framework import ( AgentExecutor, AgentExecutorResponse, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, ChatMessage, @@ -39,8 +39,8 @@ class _SimpleAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=self._reply_text)]) + ) -> AgentResponse: + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=self._reply_text)]) async def run_stream( # type: ignore[override] self, @@ -48,9 +48,9 @@ class _SimpleAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: # This agent does not support streaming; yield a single complete response - yield AgentRunResponseUpdate(contents=[TextContent(text=self._reply_text)]) + yield AgentResponseUpdate(contents=[TextContent(text=self._reply_text)]) class _CaptureFullConversation(Executor): @@ -108,7 +108,7 @@ class _CaptureAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: # Normalize and record messages for verification when running non-streaming norm: list[ChatMessage] = [] if messages: @@ -118,7 +118,7 @@ class _CaptureAgent(BaseAgent): elif isinstance(m, str): norm.append(ChatMessage(role=Role.USER, text=m)) self._last_messages = norm - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=self._reply_text)]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=self._reply_text)]) async def run_stream( # type: ignore[override] self, @@ -126,7 +126,7 @@ class _CaptureAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: # Normalize and record messages for verification when running streaming norm: list[ChatMessage] = [] if messages: @@ -136,7 +136,7 @@ class _CaptureAgent(BaseAgent): elif isinstance(m, str): norm.append(ChatMessage(role=Role.USER, text=m)) self._last_messages = norm - yield AgentRunResponseUpdate(contents=[TextContent(text=self._reply_text)]) + yield AgentResponseUpdate(contents=[TextContent(text=self._reply_text)]) async def test_sequential_adapter_uses_full_conversation() -> None: diff --git a/python/packages/core/tests/workflow/test_group_chat.py b/python/packages/core/tests/workflow/test_group_chat.py index b575fdd684..c65f19d599 100644 --- a/python/packages/core/tests/workflow/test_group_chat.py +++ b/python/packages/core/tests/workflow/test_group_chat.py @@ -8,8 +8,8 @@ import pytest from agent_framework import ( AgentExecutorResponse, AgentRequestInfoResponse, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, BaseGroupChatOrchestrator, @@ -44,9 +44,9 @@ class StubAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: response = ChatMessage(role=Role.ASSISTANT, text=self._reply_text, author_name=self.name) - return AgentRunResponse(messages=[response]) + return AgentResponse(messages=[response]) def run_stream( # type: ignore[override] self, @@ -54,9 +54,9 @@ class StubAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: - async def _stream() -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate( + ) -> AsyncIterable[AgentResponseUpdate]: + async def _stream() -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate( contents=[TextContent(text=self._reply_text)], role=Role.ASSISTANT, author_name=self.name ) @@ -88,12 +88,12 @@ class StubManagerAgent(ChatAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: if self._call_count == 0: self._call_count += 1 # First call: select the agent (using AgentOrchestrationOutput format) payload = {"terminate": False, "reason": "Selecting agent", "next_speaker": "agent", "final_message": None} - return AgentRunResponse( + return AgentResponse( messages=[ ChatMessage( role=Role.ASSISTANT, @@ -114,7 +114,7 @@ class StubManagerAgent(ChatAgent): "next_speaker": None, "final_message": "agent manager final", } - return AgentRunResponse( + return AgentResponse( messages=[ ChatMessage( role=Role.ASSISTANT, @@ -134,12 +134,12 @@ class StubManagerAgent(ChatAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: if self._call_count == 0: self._call_count += 1 - async def _stream_initial() -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate( + async def _stream_initial() -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate( contents=[ TextContent( text=( @@ -154,8 +154,8 @@ class StubManagerAgent(ChatAgent): return _stream_initial() - async def _stream_final() -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate( + async def _stream_final() -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate( contents=[ TextContent( text=( @@ -341,14 +341,14 @@ class TestGroupChatBuilder: def __init__(self) -> None: super().__init__(name="", description="test") - async def run(self, messages: Any = None, *, thread: Any = None, **kwargs: Any) -> AgentRunResponse: - return AgentRunResponse(messages=[]) + async def run(self, messages: Any = None, *, thread: Any = None, **kwargs: Any) -> AgentResponse: + return AgentResponse(messages=[]) def run_stream( self, messages: Any = None, *, thread: Any = None, **kwargs: Any - ) -> AsyncIterable[AgentRunResponseUpdate]: - async def _stream() -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate(contents=[]) + ) -> AsyncIterable[AgentResponseUpdate]: + async def _stream() -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate(contents=[]) return _stream() diff --git a/python/packages/core/tests/workflow/test_magentic.py b/python/packages/core/tests/workflow/test_magentic.py index 8cfa8d0bea..b999ca54bb 100644 --- a/python/packages/core/tests/workflow/test_magentic.py +++ b/python/packages/core/tests/workflow/test_magentic.py @@ -9,8 +9,8 @@ import pytest from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentRunUpdateEvent, AgentThread, BaseAgent, @@ -158,9 +158,9 @@ class StubAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: response = ChatMessage(role=Role.ASSISTANT, text=self._reply_text, author_name=self.name) - return AgentRunResponse(messages=[response]) + return AgentResponse(messages=[response]) def run_stream( # type: ignore[override] self, @@ -168,9 +168,9 @@ class StubAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: - async def _stream() -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate( + ) -> AsyncIterable[AgentResponseUpdate]: + async def _stream() -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate( contents=[TextContent(text=self._reply_text)], role=Role.ASSISTANT, author_name=self.name ) @@ -424,8 +424,8 @@ class StubManagerAgent(BaseAgent): *, thread: Any = None, **kwargs: Any, - ) -> AgentRunResponse: - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="ok")]) + ) -> AgentResponse: + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="ok")]) def run_stream( self, @@ -433,9 +433,9 @@ class StubManagerAgent(BaseAgent): *, thread: Any = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: - async def _gen() -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate(message_deltas=[ChatMessage(role=Role.ASSISTANT, text="ok")]) + ) -> AsyncIterable[AgentResponseUpdate]: + async def _gen() -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate(message_deltas=[ChatMessage(role=Role.ASSISTANT, text="ok")]) return _gen() @@ -538,14 +538,14 @@ class StubThreadAgent(BaseAgent): super().__init__(name=name or "agentA") async def run_stream(self, messages=None, *, thread=None, **kwargs): # type: ignore[override] - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[TextContent(text="thread-ok")], author_name=self.name, role=Role.ASSISTANT, ) async def run(self, messages=None, *, thread=None, **kwargs): # type: ignore[override] - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="thread-ok", author_name=self.name)]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="thread-ok", author_name=self.name)]) class StubAssistantsClient: @@ -560,16 +560,14 @@ class StubAssistantsAgent(BaseAgent): self.chat_client = StubAssistantsClient() # type name contains 'AssistantsClient' async def run_stream(self, messages=None, *, thread=None, **kwargs): # type: ignore[override] - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[TextContent(text="assistants-ok")], author_name=self.name, role=Role.ASSISTANT, ) async def run(self, messages=None, *, thread=None, **kwargs): # type: ignore[override] - return AgentRunResponse( - messages=[ChatMessage(role=Role.ASSISTANT, text="assistants-ok", author_name=self.name)] - ) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="assistants-ok", author_name=self.name)]) async def _collect_agent_responses_setup(participant: AgentProtocol) -> list[ChatMessage]: diff --git a/python/packages/core/tests/workflow/test_orchestration_request_info.py b/python/packages/core/tests/workflow/test_orchestration_request_info.py index a47a666ddf..24b2239757 100644 --- a/python/packages/core/tests/workflow/test_orchestration_request_info.py +++ b/python/packages/core/tests/workflow/test_orchestration_request_info.py @@ -10,8 +10,8 @@ import pytest from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, ChatMessage, Role, @@ -114,10 +114,10 @@ class TestAgentRequestInfoExecutor: """Test that request_info handler calls ctx.request_info.""" executor = AgentRequestInfoExecutor(id="test_executor") - agent_run_response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Agent response")]) + agent_response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Agent response")]) agent_response = AgentExecutorResponse( executor_id="test_agent", - agent_run_response=agent_run_response, + agent_response=agent_response, ) ctx = MagicMock(spec=WorkflowContext) @@ -132,10 +132,10 @@ class TestAgentRequestInfoExecutor: """Test response handler when user provides additional messages.""" executor = AgentRequestInfoExecutor(id="test_executor") - agent_run_response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Original")]) + agent_response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Original")]) original_request = AgentExecutorResponse( executor_id="test_agent", - agent_run_response=agent_run_response, + agent_response=agent_response, ) response = AgentRequestInfoResponse.from_strings(["Additional input"]) @@ -158,10 +158,10 @@ class TestAgentRequestInfoExecutor: """Test response handler when user approves (no additional messages).""" executor = AgentRequestInfoExecutor(id="test_executor") - agent_run_response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Original")]) + agent_response = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Original")]) original_request = AgentExecutorResponse( executor_id="test_agent", - agent_run_response=agent_run_response, + agent_response=agent_response, ) response = AgentRequestInfoResponse.approve() @@ -205,9 +205,9 @@ class _TestAgent: *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Dummy run method.""" - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Test response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Test response")]) def run_stream( self, @@ -215,11 +215,11 @@ class _TestAgent: *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Dummy run_stream method.""" async def generator(): - yield AgentRunResponseUpdate(messages=[ChatMessage(role=Role.ASSISTANT, text="Test response stream")]) + yield AgentResponseUpdate(messages=[ChatMessage(role=Role.ASSISTANT, text="Test response stream")]) return generator() diff --git a/python/packages/core/tests/workflow/test_runner.py b/python/packages/core/tests/workflow/test_runner.py index 73fe20d834..6e436cde01 100644 --- a/python/packages/core/tests/workflow/test_runner.py +++ b/python/packages/core/tests/workflow/test_runner.py @@ -7,7 +7,7 @@ import pytest from agent_framework import ( AgentExecutorResponse, - AgentRunResponse, + AgentResponse, Executor, WorkflowContext, WorkflowEvent, @@ -158,7 +158,7 @@ async def test_runner_emits_runner_completion_for_agent_response_without_targets await ctx.send_message( Message( - data=AgentExecutorResponse("agent", AgentRunResponse()), + data=AgentExecutorResponse("agent", AgentResponse()), source_id="agent", ) ) diff --git a/python/packages/core/tests/workflow/test_sequential.py b/python/packages/core/tests/workflow/test_sequential.py index 4a3076188c..d104eb8a02 100644 --- a/python/packages/core/tests/workflow/test_sequential.py +++ b/python/packages/core/tests/workflow/test_sequential.py @@ -7,8 +7,8 @@ import pytest from agent_framework import ( AgentExecutorResponse, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, ChatMessage, @@ -35,8 +35,8 @@ class _EchoAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=f"{self.name} reply")]) + ) -> AgentResponse: + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=f"{self.name} reply")]) async def run_stream( # type: ignore[override] self, @@ -44,9 +44,9 @@ class _EchoAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: # Minimal async generator with one assistant update - yield AgentRunResponseUpdate(contents=[TextContent(text=f"{self.name} reply")]) + yield AgentResponseUpdate(contents=[TextContent(text=f"{self.name} reply")]) class _SummarizerExec(Executor): diff --git a/python/packages/core/tests/workflow/test_workflow.py b/python/packages/core/tests/workflow/test_workflow.py index 059c94803e..ee67c4e35f 100644 --- a/python/packages/core/tests/workflow/test_workflow.py +++ b/python/packages/core/tests/workflow/test_workflow.py @@ -11,9 +11,9 @@ import pytest from agent_framework import ( AgentExecutor, + AgentResponse, + AgentResponseUpdate, AgentRunEvent, - AgentRunResponse, - AgentRunResponseUpdate, AgentRunUpdateEvent, AgentThread, BaseAgent, @@ -831,9 +831,9 @@ class _StreamingTestAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Non-streaming run - returns complete response.""" - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=self._reply_text)]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=self._reply_text)]) async def run_stream( self, @@ -841,11 +841,11 @@ class _StreamingTestAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Streaming run - yields incremental updates.""" # Simulate streaming by yielding character by character for char in self._reply_text: - yield AgentRunResponseUpdate(contents=[TextContent(text=char)]) + yield AgentResponseUpdate(contents=[TextContent(text=char)]) async def test_agent_streaming_vs_non_streaming() -> None: diff --git a/python/packages/core/tests/workflow/test_workflow_agent.py b/python/packages/core/tests/workflow/test_workflow_agent.py index d2ed8d1394..d415b146cc 100644 --- a/python/packages/core/tests/workflow/test_workflow_agent.py +++ b/python/packages/core/tests/workflow/test_workflow_agent.py @@ -8,8 +8,8 @@ import pytest from agent_framework import ( AgentProtocol, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentRunUpdateEvent, AgentThread, ChatMessage, @@ -52,7 +52,7 @@ class SimpleExecutor(Executor): response_message = ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=response_text)]) # Emit update event. - streaming_update = AgentRunResponseUpdate( + streaming_update = AgentResponseUpdate( contents=[TextContent(text=response_text)], role=Role.ASSISTANT, message_id=str(uuid.uuid4()) ) await ctx.add_event(AgentRunUpdateEvent(executor_id=self.id, data=streaming_update)) @@ -74,7 +74,7 @@ class RequestingExecutor(Executor): self, original_request: str, response: str, ctx: WorkflowContext[ChatMessage] ) -> None: # Handle the response and emit completion response - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[TextContent(text="Request completed successfully")], role=Role.ASSISTANT, message_id=str(uuid.uuid4()), @@ -100,7 +100,7 @@ class ConversationHistoryCapturingExecutor(Executor): response_message = ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=response_text)]) - streaming_update = AgentRunResponseUpdate( + streaming_update = AgentResponseUpdate( contents=[TextContent(text=response_text)], role=Role.ASSISTANT, message_id=str(uuid.uuid4()) ) await ctx.add_event(AgentRunUpdateEvent(executor_id=self.id, data=streaming_update)) @@ -124,7 +124,7 @@ class TestWorkflowAgent: result = await agent.run("Hello World") # Verify we got responses from both executors - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert len(result.messages) >= 2, f"Expected at least 2 messages, got {len(result.messages)}" # Find messages from each executor @@ -162,7 +162,7 @@ class TestWorkflowAgent: agent = WorkflowAgent(workflow=workflow, name="Streaming Test Agent") # Execute workflow streaming to capture streaming events - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("Test input"): updates.append(update) @@ -191,13 +191,13 @@ class TestWorkflowAgent: agent = WorkflowAgent(workflow=workflow, name="Request Test Agent") # Execute workflow streaming to get request info event - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("Start request"): updates.append(update) # Should have received an approval request for the request info assert len(updates) > 0 - approval_update: AgentRunResponseUpdate | None = None + approval_update: AgentResponseUpdate | None = None for update in updates: if any(isinstance(content, FunctionApprovalRequestContent) for content in update.contents): approval_update = update @@ -248,7 +248,7 @@ class TestWorkflowAgent: continuation_result = await agent.run(response_message) # Should complete successfully - assert isinstance(continuation_result, AgentRunResponse) + assert isinstance(continuation_result, AgentResponse) # Verify cleanup - pending requests should be cleared after function response handling assert len(agent.pending_requests) == 0 @@ -293,7 +293,7 @@ class TestWorkflowAgent: """Test that ctx.yield_output() in a workflow executor surfaces as agent output when using .as_agent(). This validates the fix for issue #2813: WorkflowOutputEvent should be converted to - AgentRunResponseUpdate when the workflow is wrapped via .as_agent(). + AgentResponseUpdate when the workflow is wrapped via .as_agent(). """ @executor @@ -314,12 +314,12 @@ class TestWorkflowAgent: agent = workflow.as_agent("test-agent") agent_result = await agent.run("hello") - assert isinstance(agent_result, AgentRunResponse) + assert isinstance(agent_result, AgentResponse) assert len(agent_result.messages) == 1 assert agent_result.messages[0].text == "processed: hello" async def test_workflow_as_agent_yield_output_surfaces_in_run_stream(self) -> None: - """Test that ctx.yield_output() surfaces as AgentRunResponseUpdate when streaming.""" + """Test that ctx.yield_output() surfaces as AgentResponseUpdate when streaming.""" @executor async def yielding_executor(messages: list[ChatMessage], ctx: WorkflowContext) -> None: @@ -329,7 +329,7 @@ class TestWorkflowAgent: workflow = WorkflowBuilder().set_start_executor(yielding_executor).build() agent = workflow.as_agent("test-agent") - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("hello"): updates.append(update) @@ -353,7 +353,7 @@ class TestWorkflowAgent: result = await agent.run("test") - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert len(result.messages) == 3 # Verify each content type is preserved @@ -410,7 +410,7 @@ class TestWorkflowAgent: workflow = WorkflowBuilder().set_start_executor(raw_yielding_executor).build() agent = workflow.as_agent("raw-test-agent") - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("test"): updates.append(update) @@ -448,7 +448,7 @@ class TestWorkflowAgent: agent = workflow.as_agent("list-msg-agent") # Verify streaming returns the update with all 4 contents before coalescing - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("test"): updates.append(update) @@ -460,7 +460,7 @@ class TestWorkflowAgent: # Verify run() coalesces text contents (expected behavior) result = await agent.run("test") - assert isinstance(result, AgentRunResponse) + assert isinstance(result, AgentResponse) assert len(result.messages) == 1 # TextContent items are coalesced into one assert len(result.messages[0].contents) == 1 @@ -587,17 +587,17 @@ class TestWorkflowAgent: def get_new_thread(self) -> AgentThread: return AgentThread() - async def run(self, messages: Any, *, thread: AgentThread | None = None, **kwargs: Any) -> AgentRunResponse: - return AgentRunResponse( + async def run(self, messages: Any, *, thread: AgentThread | None = None, **kwargs: Any) -> AgentResponse: + return AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text=self._response_text)], text=self._response_text, ) async def run_stream( self, messages: Any, *, thread: AgentThread | None = None, **kwargs: Any - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: for word in self._response_text.split(): - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[TextContent(text=word + " ")], role=Role.ASSISTANT, author_name=self._name, @@ -661,16 +661,16 @@ class TestWorkflowAgent: def get_new_thread(self) -> AgentThread: return AgentThread() - async def run(self, messages: Any, *, thread: AgentThread | None = None, **kwargs: Any) -> AgentRunResponse: - return AgentRunResponse( + async def run(self, messages: Any, *, thread: AgentThread | None = None, **kwargs: Any) -> AgentResponse: + return AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text=self._response_text)], text=self._response_text, ) async def run_stream( self, messages: Any, *, thread: AgentThread | None = None, **kwargs: Any - ) -> AsyncIterable[AgentRunResponseUpdate]: - yield AgentRunResponseUpdate( + ) -> AsyncIterable[AgentResponseUpdate]: + yield AgentResponseUpdate( contents=[TextContent(text=self._response_text)], role=Role.ASSISTANT, author_name=self._name, @@ -717,7 +717,7 @@ class TestWorkflowAgentAuthorName: agent = WorkflowAgent(workflow=workflow, name="Test Agent") # Collect streaming updates - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("Hello"): updates.append(update) @@ -736,7 +736,7 @@ class TestWorkflowAgentAuthorName: @handler async def handle_message(self, message: list[ChatMessage], ctx: WorkflowContext[list[ChatMessage]]) -> None: # Emit update with explicit author_name - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[TextContent(text="Response with author")], role=Role.ASSISTANT, author_name="custom_author_name", # Explicitly set @@ -749,7 +749,7 @@ class TestWorkflowAgentAuthorName: agent = WorkflowAgent(workflow=workflow, name="Test Agent") # Collect streaming updates - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("Hello"): updates.append(update) @@ -767,7 +767,7 @@ class TestWorkflowAgentAuthorName: agent = WorkflowAgent(workflow=workflow, name="Multi-Executor Agent") # Collect streaming updates - updates: list[AgentRunResponseUpdate] = [] + updates: list[AgentResponseUpdate] = [] async for update in agent.run_stream("Hello"): updates.append(update) @@ -788,7 +788,7 @@ class TestWorkflowAgentMergeUpdates: # Create updates with different response_ids and message_ids in non-chronological order updates = [ # Response B, Message 2 (latest in resp B) - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[TextContent(text="RespB-Msg2")], role=Role.ASSISTANT, response_id="resp-b", @@ -796,7 +796,7 @@ class TestWorkflowAgentMergeUpdates: created_at="2024-01-01T12:02:00Z", ), # Response A, Message 1 (earliest overall) - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[TextContent(text="RespA-Msg1")], role=Role.ASSISTANT, response_id="resp-a", @@ -804,7 +804,7 @@ class TestWorkflowAgentMergeUpdates: created_at="2024-01-01T12:00:00Z", ), # Response B, Message 1 (earlier in resp B) - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[TextContent(text="RespB-Msg1")], role=Role.ASSISTANT, response_id="resp-b", @@ -812,7 +812,7 @@ class TestWorkflowAgentMergeUpdates: created_at="2024-01-01T12:01:00Z", ), # Response A, Message 2 (later in resp A) - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[TextContent(text="RespA-Msg2")], role=Role.ASSISTANT, response_id="resp-a", @@ -820,7 +820,7 @@ class TestWorkflowAgentMergeUpdates: created_at="2024-01-01T12:00:30Z", ), # Global dangling update (no response_id) - should go at end - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[TextContent(text="Global-Dangling")], role=Role.ASSISTANT, response_id=None, @@ -891,7 +891,7 @@ class TestWorkflowAgentMergeUpdates: """Test that merge_updates correctly aggregates usage details, timestamps, and additional properties.""" # Create updates with various metadata including usage details updates = [ - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[ TextContent(text="First"), UsageContent( @@ -904,7 +904,7 @@ class TestWorkflowAgentMergeUpdates: created_at="2024-01-01T12:00:00Z", additional_properties={"source": "executor1", "priority": "high"}, ), - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[ TextContent(text="Second"), UsageContent( @@ -917,7 +917,7 @@ class TestWorkflowAgentMergeUpdates: created_at="2024-01-01T12:01:00Z", # Later timestamp additional_properties={"source": "executor2", "category": "analysis"}, ), - AgentRunResponseUpdate( + AgentResponseUpdate( contents=[ TextContent(text="Third"), UsageContent(details=UsageDetails(input_token_count=5, output_token_count=3, total_token_count=8)), diff --git a/python/packages/core/tests/workflow/test_workflow_builder.py b/python/packages/core/tests/workflow/test_workflow_builder.py index 91a213e3c2..ef572ba82b 100644 --- a/python/packages/core/tests/workflow/test_workflow_builder.py +++ b/python/packages/core/tests/workflow/test_workflow_builder.py @@ -7,8 +7,8 @@ import pytest from agent_framework import ( AgentExecutor, - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, ChatMessage, @@ -29,11 +29,11 @@ class DummyAgent(BaseAgent): norm.append(m) elif isinstance(m, str): norm.append(ChatMessage(role=Role.USER, text=m)) - return AgentRunResponse(messages=norm) + return AgentResponse(messages=norm) async def run_stream(self, messages=None, *, thread: AgentThread | None = None, **kwargs): # type: ignore[override] # Minimal async generator - yield AgentRunResponseUpdate() + yield AgentResponseUpdate() def test_builder_accepts_agents_directly(): diff --git a/python/packages/core/tests/workflow/test_workflow_kwargs.py b/python/packages/core/tests/workflow/test_workflow_kwargs.py index 27638f8fe1..75c34f9d95 100644 --- a/python/packages/core/tests/workflow/test_workflow_kwargs.py +++ b/python/packages/core/tests/workflow/test_workflow_kwargs.py @@ -6,8 +6,8 @@ from typing import Annotated, Any import pytest from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, ChatMessage, @@ -55,9 +55,9 @@ class _KwargsCapturingAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: self.captured_kwargs.append(dict(kwargs)) - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=f"{self.name} response")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=f"{self.name} response")]) async def run_stream( self, @@ -65,9 +65,9 @@ class _KwargsCapturingAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: self.captured_kwargs.append(dict(kwargs)) - yield AgentRunResponseUpdate(contents=[TextContent(text=f"{self.name} response")]) + yield AgentResponseUpdate(contents=[TextContent(text=f"{self.name} response")]) # region Sequential Builder Tests diff --git a/python/packages/declarative/agent_framework_declarative/_workflows/_actions_agents.py b/python/packages/declarative/agent_framework_declarative/_workflows/_actions_agents.py index d8b58c3a44..9d610d057d 100644 --- a/python/packages/declarative/agent_framework_declarative/_workflows/_actions_agents.py +++ b/python/packages/declarative/agent_framework_declarative/_workflows/_actions_agents.py @@ -12,7 +12,7 @@ from collections.abc import AsyncGenerator from typing import Any, cast from agent_framework import get_logger -from agent_framework._types import AgentRunResponse, ChatMessage +from agent_framework._types import AgentResponse, ChatMessage from ._handlers import ( ActionContext, @@ -348,7 +348,7 @@ async def handle_invoke_azure_agent(ctx: ActionContext) -> AsyncGenerator[Workfl tool_calls.extend(chunk.tool_calls) # Build consolidated response from updates - response = AgentRunResponse.from_agent_run_response_updates(updates) + response = AgentResponse.from_agent_run_response_updates(updates) text = response.text response_messages = response.messages @@ -581,7 +581,7 @@ async def handle_invoke_prompt_agent(ctx: ActionContext) -> AsyncGenerator[Workf ) # Build consolidated response from updates - response = AgentRunResponse.from_agent_run_response_updates(updates) + response = AgentResponse.from_agent_run_response_updates(updates) text = response.text response_messages = response.messages diff --git a/python/packages/devui/agent_framework_devui/_mapper.py b/python/packages/devui/agent_framework_devui/_mapper.py index 021a4a4549..e86eeac18d 100644 --- a/python/packages/devui/agent_framework_devui/_mapper.py +++ b/python/packages/devui/agent_framework_devui/_mapper.py @@ -145,7 +145,7 @@ class MessageMapper: """Convert a single Agent Framework event to OpenAI events. Args: - raw_event: Agent Framework event (AgentRunResponseUpdate, WorkflowEvent, etc.) + raw_event: Agent Framework event (AgentResponseUpdate, WorkflowEvent, etc.) request: Original request for context Returns: @@ -178,26 +178,26 @@ class MessageMapper: # Import Agent Framework types for proper isinstance checks try: - from agent_framework import AgentRunResponse, AgentRunResponseUpdate, WorkflowEvent + from agent_framework import AgentResponse, AgentResponseUpdate, WorkflowEvent from agent_framework._workflows._events import AgentRunUpdateEvent - # Handle AgentRunUpdateEvent - workflow event wrapping AgentRunResponseUpdate + # Handle AgentRunUpdateEvent - workflow event wrapping AgentResponseUpdate # This must be checked BEFORE generic WorkflowEvent check if isinstance(raw_event, AgentRunUpdateEvent): - # Extract the AgentRunResponseUpdate from the event's data attribute - if raw_event.data and isinstance(raw_event.data, AgentRunResponseUpdate): + # Extract the AgentResponseUpdate from the event's data attribute + if raw_event.data and isinstance(raw_event.data, AgentResponseUpdate): # Preserve executor_id in context for proper output routing context["current_executor_id"] = raw_event.executor_id return await self._convert_agent_update(raw_event.data, context) # If no data, treat as generic workflow event return await self._convert_workflow_event(raw_event, context) - # Handle complete agent response (AgentRunResponse) - for non-streaming agent execution - if isinstance(raw_event, AgentRunResponse): + # Handle complete agent response (AgentResponse) - for non-streaming agent execution + if isinstance(raw_event, AgentResponse): return await self._convert_agent_response(raw_event, context) - # Handle agent updates (AgentRunResponseUpdate) - for direct agent execution - if isinstance(raw_event, AgentRunResponseUpdate): + # Handle agent updates (AgentResponseUpdate) - for direct agent execution + if isinstance(raw_event, AgentResponseUpdate): return await self._convert_agent_update(raw_event, context) # Handle workflow events (any class that inherits from WorkflowEvent) @@ -686,13 +686,13 @@ class MessageMapper: return events async def _convert_agent_response(self, response: Any, context: dict[str, Any]) -> Sequence[Any]: - """Convert complete AgentRunResponse to OpenAI events. + """Convert complete AgentResponse to OpenAI events. This handles non-streaming agent execution where agent.run() returns - a complete AgentRunResponse instead of streaming AgentRunResponseUpdate objects. + a complete AgentResponse instead of streaming AgentResponseUpdate objects. Args: - response: Agent run response (AgentRunResponse) + response: Agent run response (AgentResponse) context: Conversion context Returns: @@ -1047,7 +1047,7 @@ class MessageMapper: # Create ExecutorActionItem with completed status # ExecutorCompletedEvent uses 'data' field, not 'result' # Serialize the result data to ensure it's JSON-serializable - # (AgentExecutorResponse contains AgentRunResponse/ChatMessage which are SerializationMixin) + # (AgentExecutorResponse contains AgentResponse/ChatMessage which are SerializationMixin) raw_result = getattr(event, "data", None) serialized_result = self._serialize_value(raw_result) if raw_result is not None else None executor_item = ExecutorActionItem( diff --git a/python/packages/devui/frontend/src/types/agent-framework.ts b/python/packages/devui/frontend/src/types/agent-framework.ts index 6d12a4cc8a..98f73c1841 100644 --- a/python/packages/devui/frontend/src/types/agent-framework.ts +++ b/python/packages/devui/frontend/src/types/agent-framework.ts @@ -208,7 +208,7 @@ export interface UsageDetails { } // Agent run response update (streaming) -export interface AgentRunResponseUpdate { +export interface AgentResponseUpdate { contents: Contents[]; role?: Role; author_name?: string; @@ -222,7 +222,7 @@ export interface AgentRunResponseUpdate { } // Agent run response (final) -export interface AgentRunResponse { +export interface AgentResponse { messages: ChatMessage[]; response_id?: string; created_at?: CreatedAtT; @@ -302,11 +302,11 @@ export interface ExecutorEvent extends WorkflowEvent { } export interface AgentRunUpdateEvent extends ExecutorEvent { - data?: AgentRunResponseUpdate; + data?: AgentResponseUpdate; } export interface AgentRunEvent extends ExecutorEvent { - data?: AgentRunResponse; + data?: AgentResponse; } // Span event structure (from OpenTelemetry) diff --git a/python/packages/devui/tests/test_cleanup_hooks.py b/python/packages/devui/tests/test_cleanup_hooks.py index f065c1e0c6..2d6fd7b614 100644 --- a/python/packages/devui/tests/test_cleanup_hooks.py +++ b/python/packages/devui/tests/test_cleanup_hooks.py @@ -7,7 +7,7 @@ import tempfile from pathlib import Path import pytest -from agent_framework import AgentRunResponse, ChatMessage, Role, TextContent +from agent_framework import AgentResponse, ChatMessage, Role, TextContent from agent_framework_devui import register_cleanup from agent_framework_devui._discovery import EntityDiscovery @@ -35,7 +35,7 @@ class MockAgent: async def run_stream(self, messages=None, *, thread=None, **kwargs): """Mock streaming run method.""" - yield AgentRunResponse( + yield AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Test response")])], ) @@ -259,7 +259,7 @@ async def test_cleanup_with_file_based_discovery(): # Write agent module with cleanup registration agent_file = agent_dir / "__init__.py" agent_file.write_text(""" -from agent_framework import AgentRunResponse, ChatMessage, Role, TextContent +from agent_framework import AgentResponse, ChatMessage, Role, TextContent from agent_framework_devui import register_cleanup class MockCredential: @@ -278,7 +278,7 @@ class TestAgent: description = "Test agent with cleanup" async def run_stream(self, messages=None, *, thread=None, **kwargs): - yield AgentRunResponse( + yield AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, content=[TextContent(text="Test")])], inner_messages=[], ) diff --git a/python/packages/devui/tests/test_discovery.py b/python/packages/devui/tests/test_discovery.py index 1f0baf90fc..72e534b012 100644 --- a/python/packages/devui/tests/test_discovery.py +++ b/python/packages/devui/tests/test_discovery.py @@ -84,7 +84,7 @@ async def test_discovery_accepts_agents_with_only_run(): init_file = agent_dir / "__init__.py" init_file.write_text(""" -from agent_framework import AgentRunResponse, AgentThread, ChatMessage, Role, TextContent +from agent_framework import AgentResponse, AgentThread, ChatMessage, Role, TextContent class NonStreamingAgent: id = "non_streaming" @@ -92,7 +92,7 @@ class NonStreamingAgent: description = "Agent without run_stream" async def run(self, messages=None, *, thread=None, **kwargs): - return AgentRunResponse( + return AgentResponse( messages=[ChatMessage( role=Role.ASSISTANT, contents=[TextContent(text="response")] @@ -203,13 +203,13 @@ workflow = builder.build() agent_dir = temp_path / "my_agent" agent_dir.mkdir() (agent_dir / "agent.py").write_text(""" -from agent_framework import AgentRunResponse, AgentThread, ChatMessage, Role, TextContent +from agent_framework import AgentResponse, AgentThread, ChatMessage, Role, TextContent class TestAgent: name = "Test Agent" async def run(self, messages=None, *, thread=None, **kwargs): - return AgentRunResponse( + return AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="test")])], response_id="test" ) diff --git a/python/packages/devui/tests/test_execution.py b/python/packages/devui/tests/test_execution.py index 2e599f2b31..15cb9bf4df 100644 --- a/python/packages/devui/tests/test_execution.py +++ b/python/packages/devui/tests/test_execution.py @@ -287,7 +287,7 @@ async def test_full_pipeline_agent_events_are_json_serializable(executor_with_re 2. Each event is converted by the mapper 3. Server calls model_dump_json() on each event for SSE - If any event contains non-serializable objects (like AgentRunResponse), + If any event contains non-serializable objects (like AgentResponse), this test will fail - catching the bug before it hits production. """ executor, entity_id, mock_client = executor_with_real_agent @@ -327,7 +327,7 @@ async def test_full_pipeline_workflow_events_are_json_serializable(): This is particularly important for workflows with AgentExecutor because: - AgentExecutor produces ExecutorCompletedEvent with AgentExecutorResponse - - AgentExecutorResponse contains AgentRunResponse and ChatMessage objects + - AgentExecutorResponse contains AgentResponse and ChatMessage objects - These are SerializationMixin objects, not Pydantic, which caused the original bug This test ensures the ENTIRE streaming pipeline works end-to-end. @@ -566,7 +566,7 @@ def test_extract_workflow_hil_responses_handles_stringified_json(): async def test_executor_handles_non_streaming_agent(): """Test executor can handle agents with only run() method (no run_stream).""" - from agent_framework import AgentRunResponse, AgentThread, ChatMessage, Role, TextContent + from agent_framework import AgentResponse, AgentThread, ChatMessage, Role, TextContent class NonStreamingAgent: """Agent with only run() method - does NOT satisfy full AgentProtocol.""" @@ -576,7 +576,7 @@ async def test_executor_handles_non_streaming_agent(): description = "Test agent without run_stream()" async def run(self, messages=None, *, thread=None, **kwargs): - return AgentRunResponse( + return AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=f"Processed: {messages}")])], response_id="test_123", ) diff --git a/python/packages/devui/tests/test_helpers.py b/python/packages/devui/tests/test_helpers.py index 49ae59bf11..1385dc867d 100644 --- a/python/packages/devui/tests/test_helpers.py +++ b/python/packages/devui/tests/test_helpers.py @@ -18,8 +18,8 @@ from collections.abc import AsyncIterable, MutableSequence from typing import Any, Generic from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, BaseChatClient, @@ -172,9 +172,9 @@ class MockAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: self.call_count += 1 - return AgentRunResponse( + return AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=self.response_text)])] ) @@ -184,10 +184,10 @@ class MockAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: self.call_count += 1 for chunk in self.streaming_chunks: - yield AgentRunResponseUpdate(contents=[TextContent(text=chunk)], role=Role.ASSISTANT) + yield AgentResponseUpdate(contents=[TextContent(text=chunk)], role=Role.ASSISTANT) class MockToolCallingAgent(BaseAgent): @@ -203,9 +203,9 @@ class MockToolCallingAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: self.call_count += 1 - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="done")]) + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="done")]) async def run_stream( self, @@ -213,15 +213,15 @@ class MockToolCallingAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: self.call_count += 1 # First: text - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[TextContent(text="Let me search for that...")], role=Role.ASSISTANT, ) # Second: tool call - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[ FunctionCallContent( call_id="call_123", @@ -232,7 +232,7 @@ class MockToolCallingAgent(BaseAgent): role=Role.ASSISTANT, ) # Third: tool result - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[ FunctionResultContent( call_id="call_123", @@ -242,7 +242,7 @@ class MockToolCallingAgent(BaseAgent): role=Role.TOOL, ) # Fourth: final text - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[TextContent(text="The weather is sunny, 72°F.")], role=Role.ASSISTANT, ) @@ -295,9 +295,9 @@ def create_mock_tool_agent(id: str = "tool_agent", name: str = "ToolAgent") -> M return MockToolCallingAgent(id=id, name=name) -def create_agent_run_response(text: str = "Test response") -> AgentRunResponse: - """Create an AgentRunResponse with the given text.""" - return AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=text)])]) +def create_agent_run_response(text: str = "Test response") -> AgentResponse: + """Create an AgentResponse with the given text.""" + return AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=text)])]) def create_agent_executor_response( @@ -308,7 +308,7 @@ def create_agent_executor_response( agent_response = create_agent_run_response(response_text) return AgentExecutorResponse( executor_id=executor_id, - agent_run_response=agent_response, + agent_response=agent_response, full_conversation=[ ChatMessage(role=Role.USER, contents=[TextContent(text="User input")]), ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=response_text)]), @@ -324,7 +324,7 @@ def create_executor_completed_event( This creates the exact data structure that caused the serialization bug: ExecutorCompletedEvent.data contains AgentExecutorResponse which contains - AgentRunResponse and ChatMessage objects (SerializationMixin, not Pydantic). + AgentResponse and ChatMessage objects (SerializationMixin, not Pydantic). """ data = create_agent_executor_response(executor_id) if with_agent_response else {"simple": "dict"} return ExecutorCompletedEvent(executor_id=executor_id, data=data) diff --git a/python/packages/devui/tests/test_mapper.py b/python/packages/devui/tests/test_mapper.py index 2de788257b..b1762f79b9 100644 --- a/python/packages/devui/tests/test_mapper.py +++ b/python/packages/devui/tests/test_mapper.py @@ -13,7 +13,7 @@ import pytest # Import Agent Framework types from agent_framework._types import ( - AgentRunResponseUpdate, + AgentResponseUpdate, ErrorContent, FunctionCallContent, FunctionResultContent, @@ -83,11 +83,9 @@ def create_test_content(content_type: str, **kwargs: Any) -> Any: raise ValueError(f"Unknown content type: {content_type}") -def create_test_agent_update(contents: list[Any]) -> AgentRunResponseUpdate: - """Create test AgentRunResponseUpdate.""" - return AgentRunResponseUpdate( - contents=contents, role=Role.ASSISTANT, message_id="test_msg", response_id="test_resp" - ) +def create_test_agent_update(contents: list[Any]) -> AgentResponseUpdate: + """Create test AgentResponseUpdate.""" + return AgentResponseUpdate(contents=contents, role=Role.ASSISTANT, message_id="test_msg", response_id="test_resp") # ============================================================================= @@ -105,7 +103,7 @@ async def test_critical_isinstance_bug_detection(mapper: MessageMapper, test_req assert not hasattr(update, "response") # Fake attribute should not exist # Test isinstance works with real types - assert isinstance(update, AgentRunResponseUpdate) + assert isinstance(update, AgentResponseUpdate) # Test mapper conversion - should NOT produce "Unknown event" events = await mapper.convert_event(update, test_request) @@ -264,7 +262,7 @@ async def test_agent_lifecycle_events(mapper: MessageMapper, test_request: Agent async def test_agent_run_response_mapping(mapper: MessageMapper, test_request: AgentFrameworkRequest) -> None: - """Test that mapper handles complete AgentRunResponse (non-streaming).""" + """Test that mapper handles complete AgentResponse (non-streaming).""" response = create_agent_run_response("Complete response from run()") events = await mapper.convert_event(response, test_request) @@ -325,14 +323,14 @@ async def test_executor_completed_event_with_agent_response( This is a REGRESSION TEST for the serialization bug where ExecutorCompletedEvent.data contained AgentExecutorResponse with nested - AgentRunResponse and ChatMessage objects (SerializationMixin) that + AgentResponse and ChatMessage objects (SerializationMixin) that Pydantic couldn't serialize. """ # Create event with realistic nested data - the exact structure that caused the bug event = create_executor_completed_event(executor_id="exec_agent", with_agent_response=True) # Verify the data has the problematic structure - assert hasattr(event.data, "agent_run_response") + assert hasattr(event.data, "agent_response") assert hasattr(event.data, "full_conversation") # First invoke the executor @@ -380,7 +378,7 @@ async def test_executor_completed_event_serialization_to_json( done_event = events[0] # This is the critical test - model_dump_json() should NOT raise - # "Unable to serialize unknown type: " + # "Unable to serialize unknown type: " try: json_str = done_event.model_dump_json() assert json_str is not None @@ -453,11 +451,11 @@ async def test_magentic_agent_run_update_event_with_agent_delta_metadata( This tests the ACTUAL event format Magentic emits - not a fake MagenticAgentDeltaEvent class. Magentic uses AgentRunUpdateEvent with additional_properties containing magentic_event_type. """ - from agent_framework._types import AgentRunResponseUpdate, Role, TextContent + from agent_framework._types import AgentResponseUpdate, Role, TextContent from agent_framework._workflows._events import AgentRunUpdateEvent # Create the REAL event format that Magentic emits - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[TextContent(text="Hello from agent")], role=Role.ASSISTANT, author_name="Writer", @@ -484,11 +482,11 @@ async def test_magentic_orchestrator_message_event(mapper: MessageMapper, test_r Magentic emits orchestrator planning/instruction messages using AgentRunUpdateEvent with additional_properties containing magentic_event_type='orchestrator_message'. """ - from agent_framework._types import AgentRunResponseUpdate, Role, TextContent + from agent_framework._types import AgentResponseUpdate, Role, TextContent from agent_framework._workflows._events import AgentRunUpdateEvent # Create orchestrator message event (REAL format from Magentic) - update = AgentRunResponseUpdate( + update = AgentResponseUpdate( contents=[TextContent(text="Planning: First, the writer will create content...")], role=Role.ASSISTANT, author_name="Orchestrator", @@ -520,19 +518,19 @@ async def test_magentic_events_use_same_event_class_as_other_workflows( additional_properties. Any mapper code checking for 'MagenticAgentDeltaEvent' class names is dead code. """ - from agent_framework._types import AgentRunResponseUpdate, Role, TextContent + from agent_framework._types import AgentResponseUpdate, Role, TextContent from agent_framework._workflows._events import AgentRunUpdateEvent # Create events the way different workflows do it # 1. Regular workflow (no additional_properties) - regular_update = AgentRunResponseUpdate( + regular_update = AgentResponseUpdate( contents=[TextContent(text="Regular workflow response")], role=Role.ASSISTANT, ) regular_event = AgentRunUpdateEvent(executor_id="regular_executor", data=regular_update) # 2. Magentic workflow (with additional_properties) - magentic_update = AgentRunResponseUpdate( + magentic_update = AgentResponseUpdate( contents=[TextContent(text="Magentic workflow response")], role=Role.ASSISTANT, additional_properties={"magentic_event_type": "agent_delta"}, diff --git a/python/packages/lab/lightning/samples/train_math_agent.py b/python/packages/lab/lightning/samples/train_math_agent.py index 7cb4947e88..2c6937446e 100644 --- a/python/packages/lab/lightning/samples/train_math_agent.py +++ b/python/packages/lab/lightning/samples/train_math_agent.py @@ -18,7 +18,7 @@ import string from typing import TypedDict, cast import sympy # type: ignore[import-untyped,reportMissingImports] -from agent_framework import AgentRunResponse, ChatAgent, MCPStdioTool +from agent_framework import AgentResponse, ChatAgent, MCPStdioTool from agent_framework.lab.lightning import AgentFrameworkTracer from agent_framework.openai import OpenAIChatClient from agentlightning import LLM, Dataset, Trainer, rollout @@ -102,7 +102,7 @@ def _is_result_correct(prediction: str, ground_truth: str) -> float: return float(_scalar_are_results_same(prediction, ground_truth, 1e-2)) -def evaluate(result: AgentRunResponse, ground_truth: str) -> float: +def evaluate(result: AgentResponse, ground_truth: str) -> float: """Main evaluation function that extracts the agent's answer and compares with ground truth. This function: diff --git a/python/packages/lab/tau2/agent_framework_lab_tau2/runner.py b/python/packages/lab/tau2/agent_framework_lab_tau2/runner.py index ad5b3416fe..b514ebd60c 100644 --- a/python/packages/lab/tau2/agent_framework_lab_tau2/runner.py +++ b/python/packages/lab/tau2/agent_framework_lab_tau2/runner.py @@ -7,7 +7,7 @@ from agent_framework import ( AgentExecutor, AgentExecutorRequest, AgentExecutorResponse, - AgentRunResponse, + AgentResponse, ChatAgent, ChatClientProtocol, ChatMessage, @@ -124,7 +124,7 @@ class TaskRunner: f"{'assistant' if is_from_agent else 'user'}, " f"routing to {'user' if is_from_agent else 'assistant'}:" ) - log_messages(response.agent_run_response.messages) + log_messages(response.agent_response.messages) if self.step_count >= self.max_steps: logger.info(f"Max steps ({self.max_steps}) reached - terminating conversation") @@ -132,7 +132,7 @@ class TaskRunner: # Terminate the workflow return False - response_text = response.agent_run_response.text + response_text = response.agent_response.text if is_from_agent and self._is_agent_stop(response_text): logger.info("Agent requested stop - terminating conversation") self.termination_reason = TerminationReason.AGENT_STOP @@ -144,7 +144,7 @@ class TaskRunner: # The final user message won't appear in the assistant's message store, # because it will never arrive there. # We need to store it because it's needed for evaluation. - self._final_user_message = flip_messages(response.agent_run_response.messages) + self._final_user_message = flip_messages(response.agent_response.messages) return False return True @@ -255,7 +255,7 @@ class TaskRunner: """ # Flip message roles for proper conversation flow # Assistant messages become user messages and vice versa - flipped = flip_messages(response.agent_run_response.messages) + flipped = flip_messages(response.agent_response.messages) # Determine source to route to correct target is_from_agent = response.executor_id == ASSISTANT_AGENT_ID @@ -342,7 +342,7 @@ class TaskRunner: first_message = ChatMessage(Role.ASSISTANT, text=DEFAULT_FIRST_AGENT_MESSAGE) initial_greeting = AgentExecutorResponse( executor_id=ASSISTANT_AGENT_ID, - agent_run_response=AgentRunResponse(messages=[first_message]), + agent_response=AgentResponse(messages=[first_message]), full_conversation=[ChatMessage(Role.ASSISTANT, text=DEFAULT_FIRST_AGENT_MESSAGE)], ) diff --git a/python/packages/purview/agent_framework_purview/_middleware.py b/python/packages/purview/agent_framework_purview/_middleware.py index 108cf40410..7839f2f968 100644 --- a/python/packages/purview/agent_framework_purview/_middleware.py +++ b/python/packages/purview/agent_framework_purview/_middleware.py @@ -57,9 +57,9 @@ class PurviewPolicyMiddleware(AgentMiddleware): context.messages, Activity.UPLOAD_TEXT ) if should_block_prompt: - from agent_framework import AgentRunResponse, ChatMessage, Role + from agent_framework import AgentResponse, ChatMessage, Role - context.result = AgentRunResponse( + context.result = AgentResponse( messages=[ChatMessage(role=Role.SYSTEM, text=self._settings.blocked_prompt_message)] ) context.terminate = True @@ -76,7 +76,7 @@ class PurviewPolicyMiddleware(AgentMiddleware): await next(context) try: - # Post (response) check only if we have a normal AgentRunResponse + # Post (response) check only if we have a normal AgentResponse # Use the same user_id from the request for the response evaluation if context.result and not context.is_streaming: should_block_response, _ = await self._processor.process_messages( @@ -85,9 +85,9 @@ class PurviewPolicyMiddleware(AgentMiddleware): user_id=resolved_user_id, ) if should_block_response: - from agent_framework import AgentRunResponse, ChatMessage, Role + from agent_framework import AgentResponse, ChatMessage, Role - context.result = AgentRunResponse( + context.result = AgentResponse( messages=[ChatMessage(role=Role.SYSTEM, text=self._settings.blocked_response_message)] ) else: diff --git a/python/packages/purview/tests/test_middleware.py b/python/packages/purview/tests/test_middleware.py index 0769efab27..9426bc66af 100644 --- a/python/packages/purview/tests/test_middleware.py +++ b/python/packages/purview/tests/test_middleware.py @@ -5,7 +5,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -from agent_framework import AgentRunContext, AgentRunResponse, ChatMessage, Role +from agent_framework import AgentResponse, AgentRunContext, ChatMessage, Role from azure.core.credentials import AccessToken from agent_framework_purview import PurviewPolicyMiddleware, PurviewSettings @@ -57,7 +57,7 @@ class TestPurviewPolicyMiddleware: async def mock_next(ctx: AgentRunContext) -> None: nonlocal next_called next_called = True - ctx.result = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="I'm good, thanks!")]) + ctx.result = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="I'm good, thanks!")]) await middleware.process(context, mock_next) @@ -104,7 +104,7 @@ class TestPurviewPolicyMiddleware: with patch.object(middleware._processor, "process_messages", side_effect=mock_process_messages): async def mock_next(ctx: AgentRunContext) -> None: - ctx.result = AgentRunResponse( + ctx.result = AgentResponse( messages=[ChatMessage(role=Role.ASSISTANT, text="Here's some sensitive information")] ) @@ -145,7 +145,7 @@ class TestPurviewPolicyMiddleware: with patch.object(middleware._processor, "process_messages", return_value=(False, "user-123")) as mock_process: async def mock_next(ctx: AgentRunContext) -> None: - ctx.result = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Response")]) + ctx.result = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Response")]) await middleware.process(context, mock_next) @@ -167,7 +167,7 @@ class TestPurviewPolicyMiddleware: ) as mock_process: async def mock_next(ctx: AgentRunContext) -> None: - ctx.result = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Response")]) + ctx.result = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Response")]) await middleware.process(context, mock_next) @@ -199,7 +199,7 @@ class TestPurviewPolicyMiddleware: with patch.object(middleware._processor, "process_messages", side_effect=mock_process_messages): async def mock_next(ctx: AgentRunContext) -> None: - ctx.result = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Response")]) + ctx.result = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Response")]) await middleware.process(context, mock_next) @@ -225,7 +225,7 @@ class TestPurviewPolicyMiddleware: with patch.object(middleware._processor, "process_messages", side_effect=mock_process_messages): async def mock_next(ctx): - ctx.result = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Response")]) + ctx.result = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Response")]) # Should not raise, just log await middleware.process(context, mock_next) diff --git a/python/samples/demos/chatkit-integration/README.md b/python/samples/demos/chatkit-integration/README.md index 3d47925bdd..688d24aebf 100644 --- a/python/samples/demos/chatkit-integration/README.md +++ b/python/samples/demos/chatkit-integration/README.md @@ -62,7 +62,7 @@ graph TB AttStore -.->|save metadata| SQLite Converter -->|ChatMessage array| Agent - Agent -->|AgentRunResponseUpdate| Streamer + Agent -->|AgentResponseUpdate| Streamer Streamer -->|ThreadStreamEvent| ChatKit ChatKit --> Widgets diff --git a/python/samples/demos/chatkit-integration/app.py b/python/samples/demos/chatkit-integration/app.py index 148a084bae..c215b64290 100644 --- a/python/samples/demos/chatkit-integration/app.py +++ b/python/samples/demos/chatkit-integration/app.py @@ -18,7 +18,7 @@ from typing import Annotated, Any import uvicorn # Agent Framework imports -from agent_framework import AgentRunResponseUpdate, ChatAgent, ChatMessage, FunctionResultContent, Role +from agent_framework import AgentResponseUpdate, ChatAgent, ChatMessage, FunctionResultContent, Role from agent_framework.azure import AzureOpenAIChatClient # Agent Framework ChatKit integration @@ -365,7 +365,7 @@ class WeatherChatKitServer(ChatKitServer[dict[str, Any]]): agent_stream = self.weather_agent.run_stream(agent_messages) # Create an intercepting stream that extracts function results while passing through updates - async def intercept_stream() -> AsyncIterator[AgentRunResponseUpdate]: + async def intercept_stream() -> AsyncIterator[AgentResponseUpdate]: nonlocal weather_data, show_city_selector async for update in agent_stream: # Check for function results in the update @@ -462,7 +462,7 @@ class WeatherChatKitServer(ChatKitServer[dict[str, Any]]): agent_stream = self.weather_agent.run_stream(agent_messages) # Create an intercepting stream that extracts function results while passing through updates - async def intercept_stream() -> AsyncIterator[AgentRunResponseUpdate]: + async def intercept_stream() -> AsyncIterator[AgentResponseUpdate]: nonlocal weather_data async for update in agent_stream: # Check for function results in the update diff --git a/python/samples/demos/workflow_evaluation/create_workflow.py b/python/samples/demos/workflow_evaluation/create_workflow.py index a150b7274f..6fb4b874c6 100644 --- a/python/samples/demos/workflow_evaluation/create_workflow.py +++ b/python/samples/demos/workflow_evaluation/create_workflow.py @@ -47,7 +47,7 @@ from _tools import ( ) from agent_framework import ( AgentExecutorResponse, - AgentRunResponseUpdate, + AgentResponseUpdate, AgentRunUpdateEvent, ChatMessage, Executor, @@ -133,8 +133,8 @@ class ResearchLead(Executor): for response in responses: findings = [] - if response.agent_run_response and response.agent_run_response.messages: - for msg in response.agent_run_response.messages: + if response.agent_response and response.agent_response.messages: + for msg in response.agent_response.messages: if msg.role == Role.ASSISTANT and msg.text and msg.text.strip(): findings.append(msg.text.strip()) @@ -373,7 +373,7 @@ async def _process_workflow_events(events, conversation_ids, response_ids): def _track_agent_ids(event, agent, response_ids, conversation_ids): """Track agent response and conversation IDs - supporting multiple responses per agent.""" - if isinstance(event.data, AgentRunResponseUpdate): + if isinstance(event.data, AgentResponseUpdate): # Check for conversation_id and response_id from raw_representation # V2 API stores conversation_id directly on raw_representation (ChatResponseUpdate) if hasattr(event.data, "raw_representation") and event.data.raw_representation: diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_code_interpreter_file_generation.py b/python/samples/getting_started/agents/azure_ai/azure_ai_with_code_interpreter_file_generation.py index 76758d1b61..22fbb16c46 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_with_code_interpreter_file_generation.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_with_code_interpreter_file_generation.py @@ -8,7 +8,7 @@ from agent_framework import ( HostedFileContent, TextContent, ) -from agent_framework._agents import AgentRunResponseUpdate +from agent_framework._agents import AgentResponseUpdate from agent_framework.azure import AzureAIClient from azure.identity.aio import AzureCliCredential @@ -45,7 +45,7 @@ async def test_non_streaming() -> None: # Check for annotations in the response annotations_found: list[str] = [] - # AgentRunResponse has messages property, which contains ChatMessage objects + # AgentResponse has messages property, which contains ChatMessage objects for message in result.messages: for content in message.contents: if isinstance(content, TextContent) and content.annotations: @@ -78,7 +78,7 @@ async def test_streaming() -> None: file_ids_found: list[str] = [] async for update in agent.run_stream(QUERY): - if isinstance(update, AgentRunResponseUpdate): + if isinstance(update, AgentResponseUpdate): for content in update.contents: if isinstance(content, TextContent): if content.text: diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_hosted_mcp.py b/python/samples/getting_started/agents/azure_ai/azure_ai_with_hosted_mcp.py index dd72108c05..d4672d965a 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_with_hosted_mcp.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_with_hosted_mcp.py @@ -3,7 +3,7 @@ import asyncio from typing import Any -from agent_framework import AgentProtocol, AgentRunResponse, AgentThread, ChatMessage, HostedMCPTool +from agent_framework import AgentProtocol, AgentResponse, AgentThread, ChatMessage, HostedMCPTool from agent_framework.azure import AzureAIClient from azure.identity.aio import AzureCliCredential @@ -14,7 +14,7 @@ This sample demonstrates integrating hosted Model Context Protocol (MCP) tools w """ -async def handle_approvals_without_thread(query: str, agent: "AgentProtocol") -> AgentRunResponse: +async def handle_approvals_without_thread(query: str, agent: "AgentProtocol") -> AgentResponse: """When we don't have a thread, we need to ensure we return with the input, approval request and approval.""" result = await agent.run(query, store=False) @@ -35,7 +35,7 @@ async def handle_approvals_without_thread(query: str, agent: "AgentProtocol") -> return result -async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", thread: "AgentThread") -> AgentRunResponse: +async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", thread: "AgentThread") -> AgentResponse: """Here we let the thread deal with the previous responses, and we just rerun with the approval.""" result = await agent.run(query, thread=thread) diff --git a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter.py index 0136512373..a42cfd04e8 100644 --- a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter.py +++ b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter.py @@ -2,7 +2,7 @@ import asyncio -from agent_framework import AgentRunResponse, ChatResponseUpdate, HostedCodeInterpreterTool +from agent_framework import AgentResponse, ChatResponseUpdate, HostedCodeInterpreterTool from agent_framework.azure import AzureAIAgentClient from azure.ai.agents.models import ( RunStepDeltaCodeInterpreterDetailItemObject, @@ -17,7 +17,7 @@ for Python code execution and mathematical problem solving. """ -def print_code_interpreter_inputs(response: AgentRunResponse) -> None: +def print_code_interpreter_inputs(response: AgentResponse) -> None: """Helper method to access code interpreter data.""" print("\nCode Interpreter Inputs during the run:") @@ -48,7 +48,7 @@ async def main() -> None: ) query = "Generate the factorial of 100 using python code, show the code and execute it." print(f"User: {query}") - response = await AgentRunResponse.from_agent_response_generator(agent.run_stream(query)) + response = await AgentResponse.from_agent_response_generator(agent.run_stream(query)) print(f"Agent: {response}") # To review the code interpreter outputs, you can access # them from the response raw_representations, just uncomment the next line: diff --git a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter_file_generation.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter_file_generation.py index cbd64bc5a7..0096645cc9 100644 --- a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter_file_generation.py +++ b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter_file_generation.py @@ -2,7 +2,7 @@ import asyncio -from agent_framework import AgentRunResponseUpdate, ChatAgent, HostedCodeInterpreterTool, HostedFileContent +from agent_framework import AgentResponseUpdate, ChatAgent, HostedCodeInterpreterTool, HostedFileContent from agent_framework.azure import AzureAIAgentClient from azure.identity.aio import AzureCliCredential @@ -53,7 +53,7 @@ async def main() -> None: file_ids: list[str] = [] async for chunk in agent.run_stream(query): - if not isinstance(chunk, AgentRunResponseUpdate): + if not isinstance(chunk, AgentResponseUpdate): continue for content in chunk.contents: diff --git a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_hosted_mcp.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_hosted_mcp.py index 10a5a68031..493bfaa374 100644 --- a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_hosted_mcp.py +++ b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_hosted_mcp.py @@ -3,7 +3,7 @@ import asyncio from typing import Any -from agent_framework import AgentProtocol, AgentRunResponse, AgentThread, HostedMCPTool +from agent_framework import AgentProtocol, AgentResponse, AgentThread, HostedMCPTool from agent_framework.azure import AzureAIAgentClient from azure.identity.aio import AzureCliCredential @@ -15,7 +15,7 @@ servers, including user approval workflows for function call security. """ -async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", thread: "AgentThread") -> AgentRunResponse: +async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", thread: "AgentThread") -> AgentResponse: """Here we let the thread deal with the previous responses, and we just rerun with the approval.""" from agent_framework import ChatMessage diff --git a/python/samples/getting_started/agents/azure_openai/azure_assistants_with_code_interpreter.py b/python/samples/getting_started/agents/azure_openai/azure_assistants_with_code_interpreter.py index af07cabd75..b37af8f8de 100644 --- a/python/samples/getting_started/agents/azure_openai/azure_assistants_with_code_interpreter.py +++ b/python/samples/getting_started/agents/azure_openai/azure_assistants_with_code_interpreter.py @@ -2,7 +2,7 @@ import asyncio -from agent_framework import AgentRunResponseUpdate, ChatAgent, ChatResponseUpdate, HostedCodeInterpreterTool +from agent_framework import AgentResponseUpdate, ChatAgent, ChatResponseUpdate, HostedCodeInterpreterTool from agent_framework.azure import AzureOpenAIAssistantsClient from azure.identity import AzureCliCredential from openai.types.beta.threads.runs import ( @@ -21,7 +21,7 @@ for Python code execution and mathematical problem solving. """ -def get_code_interpreter_chunk(chunk: AgentRunResponseUpdate) -> str | None: +def get_code_interpreter_chunk(chunk: AgentResponseUpdate) -> str | None: """Helper method to access code interpreter data.""" if ( isinstance(chunk.raw_representation, ChatResponseUpdate) diff --git a/python/samples/getting_started/agents/custom/custom_agent.py b/python/samples/getting_started/agents/custom/custom_agent.py index 82c630bcc2..5dc050a1b5 100644 --- a/python/samples/getting_started/agents/custom/custom_agent.py +++ b/python/samples/getting_started/agents/custom/custom_agent.py @@ -5,8 +5,8 @@ from collections.abc import AsyncIterable from typing import Any from agent_framework import ( - AgentRunResponse, - AgentRunResponseUpdate, + AgentResponse, + AgentResponseUpdate, AgentThread, BaseAgent, ChatMessage, @@ -60,7 +60,7 @@ class EchoAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AgentRunResponse: + ) -> AgentResponse: """Execute the agent and return a complete response. Args: @@ -69,7 +69,7 @@ class EchoAgent(BaseAgent): **kwargs: Additional keyword arguments. Returns: - An AgentRunResponse containing the agent's reply. + An AgentResponse containing the agent's reply. """ # Normalize input messages to a list normalized_messages = self._normalize_messages(messages) @@ -93,7 +93,7 @@ class EchoAgent(BaseAgent): if thread is not None: await self._notify_thread_of_new_messages(thread, normalized_messages, response_message) - return AgentRunResponse(messages=[response_message]) + return AgentResponse(messages=[response_message]) async def run_stream( self, @@ -101,7 +101,7 @@ class EchoAgent(BaseAgent): *, thread: AgentThread | None = None, **kwargs: Any, - ) -> AsyncIterable[AgentRunResponseUpdate]: + ) -> AsyncIterable[AgentResponseUpdate]: """Execute the agent and yield streaming response updates. Args: @@ -110,7 +110,7 @@ class EchoAgent(BaseAgent): **kwargs: Additional keyword arguments. Yields: - AgentRunResponseUpdate objects containing chunks of the response. + AgentResponseUpdate objects containing chunks of the response. """ # Normalize input messages to a list normalized_messages = self._normalize_messages(messages) @@ -131,7 +131,7 @@ class EchoAgent(BaseAgent): # Add space before word except for the first one chunk_text = f" {word}" if i > 0 else word - yield AgentRunResponseUpdate( + yield AgentResponseUpdate( contents=[TextContent(text=chunk_text)], role=Role.ASSISTANT, ) diff --git a/python/samples/getting_started/agents/openai/openai_assistants_with_code_interpreter.py b/python/samples/getting_started/agents/openai/openai_assistants_with_code_interpreter.py index b5e9ed3d69..05bb96acc2 100644 --- a/python/samples/getting_started/agents/openai/openai_assistants_with_code_interpreter.py +++ b/python/samples/getting_started/agents/openai/openai_assistants_with_code_interpreter.py @@ -2,7 +2,7 @@ import asyncio -from agent_framework import AgentRunResponseUpdate, ChatAgent, ChatResponseUpdate, HostedCodeInterpreterTool +from agent_framework import AgentResponseUpdate, ChatAgent, ChatResponseUpdate, HostedCodeInterpreterTool from agent_framework.openai import OpenAIAssistantsClient from openai.types.beta.threads.runs import ( CodeInterpreterToolCallDelta, @@ -20,7 +20,7 @@ for Python code execution and mathematical problem solving. """ -def get_code_interpreter_chunk(chunk: AgentRunResponseUpdate) -> str | None: +def get_code_interpreter_chunk(chunk: AgentResponseUpdate) -> str | None: """Helper method to access code interpreter data.""" if ( isinstance(chunk.raw_representation, ChatResponseUpdate) diff --git a/python/samples/getting_started/agents/openai/openai_responses_client_with_structured_output.py b/python/samples/getting_started/agents/openai/openai_responses_client_with_structured_output.py index 88e36236ca..b84a7b5d97 100644 --- a/python/samples/getting_started/agents/openai/openai_responses_client_with_structured_output.py +++ b/python/samples/getting_started/agents/openai/openai_responses_client_with_structured_output.py @@ -2,7 +2,7 @@ import asyncio -from agent_framework import AgentRunResponse +from agent_framework import AgentResponse from agent_framework.openai import OpenAIResponsesClient from pydantic import BaseModel @@ -60,9 +60,9 @@ async def streaming_example() -> None: query = "Tell me about Tokyo, Japan" print(f"User: {query}") - # Get structured response from streaming agent using AgentRunResponse.from_agent_response_generator - # This method collects all streaming updates and combines them into a single AgentRunResponse - result = await AgentRunResponse.from_agent_response_generator( + # Get structured response from streaming agent using AgentResponse.from_agent_response_generator + # This method collects all streaming updates and combines them into a single AgentResponse + result = await AgentResponse.from_agent_response_generator( agent.run_stream(query, response_format=OutputStruct), output_format_type=OutputStruct, ) @@ -70,7 +70,7 @@ async def streaming_example() -> None: # Access the structured output directly from the response value if result.value: structured_data: OutputStruct = result.value # type: ignore - print("Structured Output (from streaming with AgentRunResponse.from_agent_response_generator):") + print("Structured Output (from streaming with AgentResponse.from_agent_response_generator):") print(f"City: {structured_data.city}") print(f"Description: {structured_data.description}") else: diff --git a/python/samples/getting_started/azure_functions/03_reliable_streaming/function_app.py b/python/samples/getting_started/azure_functions/03_reliable_streaming/function_app.py index 31db10a9df..b1f9509a66 100644 --- a/python/samples/getting_started/azure_functions/03_reliable_streaming/function_app.py +++ b/python/samples/getting_started/azure_functions/03_reliable_streaming/function_app.py @@ -19,9 +19,9 @@ import logging import os from datetime import timedelta -import redis.asyncio as aioredis -from agent_framework import AgentRunResponseUpdate import azure.functions as func +import redis.asyncio as aioredis +from agent_framework import AgentResponseUpdate from agent_framework.azure import ( AgentCallbackContext, AgentFunctionApp, @@ -29,7 +29,6 @@ from agent_framework.azure import ( AzureOpenAIChatClient, ) from azure.identity import AzureCliCredential - from redis_stream_response_handler import RedisStreamResponseHandler, StreamChunk from tools import get_local_events, get_weather_forecast @@ -39,6 +38,7 @@ logger = logging.getLogger(__name__) REDIS_CONNECTION_STRING = os.environ.get("REDIS_CONNECTION_STRING", "redis://localhost:6379") REDIS_STREAM_TTL_MINUTES = int(os.environ.get("REDIS_STREAM_TTL_MINUTES", "10")) + async def get_stream_handler() -> RedisStreamResponseHandler: """Create a new Redis stream handler for each request. @@ -70,7 +70,7 @@ class RedisStreamCallback(AgentResponseCallbackProtocol): async def on_streaming_response_update( self, - update: AgentRunResponseUpdate, + update: AgentResponseUpdate, context: AgentCallbackContext, ) -> None: """Write streaming update to Redis Stream. @@ -291,24 +291,21 @@ def _format_chunk(chunk: StreamChunk, use_sse_format: bool) -> str: """Format a text chunk.""" if use_sse_format: return _format_sse_event("message", chunk.text, chunk.entry_id) - else: - return chunk.text + return chunk.text def _format_end_of_stream(entry_id: str, use_sse_format: bool) -> str: """Format end-of-stream marker.""" if use_sse_format: return _format_sse_event("done", "[DONE]", entry_id) - else: - return "\n" + return "\n" def _format_error(error: str, use_sse_format: bool) -> str: """Format error message.""" if use_sse_format: return _format_sse_event("error", error, None) - else: - return f"\n[Error: {error}]\n" + return f"\n[Error: {error}]\n" def _format_sse_event(event_type: str, data: str, event_id: str | None = None) -> str: diff --git a/python/samples/getting_started/azure_functions/05_multi_agent_orchestration_concurrency/function_app.py b/python/samples/getting_started/azure_functions/05_multi_agent_orchestration_concurrency/function_app.py index 69ea8816b2..e67fe53345 100644 --- a/python/samples/getting_started/azure_functions/05_multi_agent_orchestration_concurrency/function_app.py +++ b/python/samples/getting_started/azure_functions/05_multi_agent_orchestration_concurrency/function_app.py @@ -12,8 +12,8 @@ import json import logging from typing import Any, cast -from agent_framework import AgentRunResponse import azure.functions as func +from agent_framework import AgentResponse from agent_framework.azure import AgentFunctionApp, AzureOpenAIChatClient from azure.durable_functions import DurableOrchestrationClient, DurableOrchestrationContext from azure.identity import AzureCliCredential @@ -71,8 +71,8 @@ def multi_agent_concurrent_orchestration(context: DurableOrchestrationContext): # Execute both tasks concurrently using task_all task_results = yield context.task_all([physicist_task, chemist_task]) - physicist_result = cast(AgentRunResponse, task_results[0]) - chemist_result = cast(AgentRunResponse, task_results[1]) + physicist_result = cast(AgentResponse, task_results[0]) + chemist_result = cast(AgentResponse, task_results[1]) return { "physicist": physicist_result.text, diff --git a/python/samples/getting_started/devui/workflow_agents/workflow.py b/python/samples/getting_started/devui/workflow_agents/workflow.py index 3c6307aef8..3b304fd690 100644 --- a/python/samples/getting_started/devui/workflow_agents/workflow.py +++ b/python/samples/getting_started/devui/workflow_agents/workflow.py @@ -40,7 +40,7 @@ def needs_editing(message: Any) -> bool: if not isinstance(message, AgentExecutorResponse): return False try: - review = ReviewResult.model_validate_json(message.agent_run_response.text) + review = ReviewResult.model_validate_json(message.agent_response.text) return review.score < 80 except Exception: return False @@ -52,7 +52,7 @@ def is_approved(message: Any) -> bool: if not isinstance(message, AgentExecutorResponse): return True try: - review = ReviewResult.model_validate_json(message.agent_run_response.text) + review = ReviewResult.model_validate_json(message.agent_response.text) return review.score >= 80 except Exception: return True diff --git a/python/samples/getting_started/middleware/agent_and_run_level_middleware.py b/python/samples/getting_started/middleware/agent_and_run_level_middleware.py index 6589b5a57b..b421454163 100644 --- a/python/samples/getting_started/middleware/agent_and_run_level_middleware.py +++ b/python/samples/getting_started/middleware/agent_and_run_level_middleware.py @@ -8,8 +8,8 @@ from typing import Annotated from agent_framework import ( AgentMiddleware, + AgentResponse, AgentRunContext, - AgentRunResponse, FunctionInvocationContext, ) from agent_framework.azure import AzureAIAgentClient @@ -121,7 +121,7 @@ class CachingMiddleware(AgentMiddleware): """Run-level caching middleware for expensive operations.""" def __init__(self) -> None: - self.cache: dict[str, AgentRunResponse] = {} + self.cache: dict[str, AgentResponse] = {} async def process(self, context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]) -> None: # Create a simple cache key from the last message diff --git a/python/samples/getting_started/middleware/class_based_middleware.py b/python/samples/getting_started/middleware/class_based_middleware.py index 0bf990a1f4..52d783c0d0 100644 --- a/python/samples/getting_started/middleware/class_based_middleware.py +++ b/python/samples/getting_started/middleware/class_based_middleware.py @@ -8,8 +8,8 @@ from typing import Annotated from agent_framework import ( AgentMiddleware, + AgentResponse, AgentRunContext, - AgentRunResponse, ChatMessage, FunctionInvocationContext, FunctionMiddleware, @@ -58,7 +58,7 @@ class SecurityAgentMiddleware(AgentMiddleware): if "password" in query.lower() or "secret" in query.lower(): print("[SecurityAgentMiddleware] Security Warning: Detected sensitive information, blocking request.") # Override the result with warning message - context.result = AgentRunResponse( + context.result = AgentResponse( messages=[ ChatMessage(role=Role.ASSISTANT, text="Detected sensitive information, the request is blocked.") ] diff --git a/python/samples/getting_started/middleware/middleware_termination.py b/python/samples/getting_started/middleware/middleware_termination.py index 0f1ca72c7c..1eff584721 100644 --- a/python/samples/getting_started/middleware/middleware_termination.py +++ b/python/samples/getting_started/middleware/middleware_termination.py @@ -7,8 +7,8 @@ from typing import Annotated from agent_framework import ( AgentMiddleware, + AgentResponse, AgentRunContext, - AgentRunResponse, ChatMessage, Role, ) @@ -57,7 +57,7 @@ class PreTerminationMiddleware(AgentMiddleware): print(f"[PreTerminationMiddleware] Blocked word '{blocked_word}' detected. Terminating request.") # Set a custom response - context.result = AgentRunResponse( + context.result = AgentResponse( messages=[ ChatMessage( role=Role.ASSISTANT, diff --git a/python/samples/getting_started/middleware/override_result_with_middleware.py b/python/samples/getting_started/middleware/override_result_with_middleware.py index 1dec35855b..5455ebe7b6 100644 --- a/python/samples/getting_started/middleware/override_result_with_middleware.py +++ b/python/samples/getting_started/middleware/override_result_with_middleware.py @@ -6,9 +6,9 @@ from random import randint from typing import Annotated from agent_framework import ( + AgentResponse, + AgentResponseUpdate, AgentRunContext, - AgentRunResponse, - AgentRunResponseUpdate, ChatMessage, Role, TextContent, @@ -64,15 +64,15 @@ async def weather_override_middleware( if context.is_streaming: # For streaming: create an async generator that yields chunks - async def override_stream() -> AsyncIterable[AgentRunResponseUpdate]: + async def override_stream() -> AsyncIterable[AgentResponseUpdate]: for chunk in chunks: - yield AgentRunResponseUpdate(contents=[TextContent(text=chunk)]) + yield AgentResponseUpdate(contents=[TextContent(text=chunk)]) context.result = override_stream() else: # For non-streaming: just replace with the string message custom_message = "".join(chunks) - context.result = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=custom_message)]) + context.result = AgentResponse(messages=[ChatMessage(role=Role.ASSISTANT, text=custom_message)]) async def main() -> None: diff --git a/python/samples/getting_started/purview_agent/sample_purview_agent.py b/python/samples/getting_started/purview_agent/sample_purview_agent.py index 2ce38339c1..223eed55e3 100644 --- a/python/samples/getting_started/purview_agent/sample_purview_agent.py +++ b/python/samples/getting_started/purview_agent/sample_purview_agent.py @@ -25,7 +25,7 @@ import asyncio import os from typing import Any -from agent_framework import AgentRunResponse, ChatAgent, ChatMessage, Role +from agent_framework import AgentResponse, ChatAgent, ChatMessage, Role from agent_framework.azure import AzureOpenAIChatClient from agent_framework.microsoft import ( PurviewChatPolicyMiddleware, @@ -158,10 +158,16 @@ async def run_with_agent_middleware() -> None: ) print("-- Agent Middleware Path --") - first: AgentRunResponse = await agent.run(ChatMessage(role=Role.USER, text="Tell me a joke about a pirate.", additional_properties={"user_id": user_id})) + first: AgentResponse = await agent.run( + ChatMessage(role=Role.USER, text="Tell me a joke about a pirate.", additional_properties={"user_id": user_id}) + ) print("First response (agent middleware):\n", first) - second: AgentRunResponse = await agent.run(ChatMessage(role=Role.USER, text="That was funny. Tell me another one.", additional_properties={"user_id": user_id})) + second: AgentResponse = await agent.run( + ChatMessage( + role=Role.USER, text="That was funny. Tell me another one.", additional_properties={"user_id": user_id} + ) + ) print("Second response (agent middleware):\n", second) @@ -195,7 +201,7 @@ async def run_with_chat_middleware() -> None: ) print("-- Chat Middleware Path --") - first: AgentRunResponse = await agent.run( + first: AgentResponse = await agent.run( ChatMessage( role=Role.USER, text="Give me a short clean joke.", @@ -204,7 +210,7 @@ async def run_with_chat_middleware() -> None: ) print("First response (chat middleware):\n", first) - second: AgentRunResponse = await agent.run( + second: AgentResponse = await agent.run( ChatMessage( role=Role.USER, text="One more please.", @@ -245,12 +251,14 @@ async def run_with_custom_cache_provider() -> None: print("-- Custom Cache Provider Path --") print("Using SimpleDictCacheProvider") - first: AgentRunResponse = await agent.run( - ChatMessage(role=Role.USER, text="Tell me a joke about a programmer.", additional_properties={"user_id": user_id}) + first: AgentResponse = await agent.run( + ChatMessage( + role=Role.USER, text="Tell me a joke about a programmer.", additional_properties={"user_id": user_id} + ) ) print("First response (custom provider):\n", first) - second: AgentRunResponse = await agent.run( + second: AgentResponse = await agent.run( ChatMessage(role=Role.USER, text="That's hilarious! One more?", additional_properties={"user_id": user_id}) ) print("Second response (custom provider):\n", second) @@ -285,12 +293,12 @@ async def run_with_custom_cache_provider() -> None: print("-- Default Cache Path --") print("Using default InMemoryCacheProvider with settings-based configuration") - first: AgentRunResponse = await agent.run( + first: AgentResponse = await agent.run( ChatMessage(role=Role.USER, text="Tell me a joke about AI.", additional_properties={"user_id": user_id}) ) print("First response (default cache):\n", first) - second: AgentRunResponse = await agent.run( + second: AgentResponse = await agent.run( ChatMessage(role=Role.USER, text="Nice! Another AI joke please.", additional_properties={"user_id": user_id}) ) print("Second response (default cache):\n", second) diff --git a/python/samples/getting_started/tools/ai_function_declaration_only.py b/python/samples/getting_started/tools/ai_function_declaration_only.py index 03a2e8f8ed..32ba7cdbc8 100644 --- a/python/samples/getting_started/tools/ai_function_declaration_only.py +++ b/python/samples/getting_started/tools/ai_function_declaration_only.py @@ -34,7 +34,7 @@ async def main(): Expected result: User: What is the current time? Result: { - "type": "agent_run_response", + "type": "agent_response", "messages": [ { "type": "chat_message", diff --git a/python/samples/getting_started/tools/ai_function_with_approval.py b/python/samples/getting_started/tools/ai_function_with_approval.py index bdc673bb2c..a74e1aed3f 100644 --- a/python/samples/getting_started/tools/ai_function_with_approval.py +++ b/python/samples/getting_started/tools/ai_function_with_approval.py @@ -4,7 +4,7 @@ import asyncio from random import randrange from typing import TYPE_CHECKING, Annotated, Any -from agent_framework import AgentRunResponse, ChatAgent, ChatMessage, ai_function +from agent_framework import AgentResponse, ChatAgent, ChatMessage, ai_function from agent_framework.openai import OpenAIResponsesClient if TYPE_CHECKING: @@ -39,7 +39,7 @@ def get_weather_detail(location: Annotated[str, "The city and state, e.g. San Fr ) -async def handle_approvals(query: str, agent: "AgentProtocol") -> AgentRunResponse: +async def handle_approvals(query: str, agent: "AgentProtocol") -> AgentResponse: """Handle function call approvals. When we don't have a thread, we need to ensure we include the original query, diff --git a/python/samples/getting_started/workflows/_start-here/step4_using_factories.py b/python/samples/getting_started/workflows/_start-here/step4_using_factories.py index 1c9dd5b1e6..77ece0128c 100644 --- a/python/samples/getting_started/workflows/_start-here/step4_using_factories.py +++ b/python/samples/getting_started/workflows/_start-here/step4_using_factories.py @@ -3,7 +3,7 @@ import asyncio from agent_framework import ( - AgentRunResponse, + AgentResponse, ChatAgent, Executor, WorkflowBuilder, @@ -83,9 +83,9 @@ async def main(): .build() ) - output: AgentRunResponse | None = None + output: AgentResponse | None = None async for event in workflow.run_stream("hello world"): - if isinstance(event, WorkflowOutputEvent) and isinstance(event.data, AgentRunResponse): + if isinstance(event, WorkflowOutputEvent) and isinstance(event.data, AgentResponse): output = event.data if output: diff --git a/python/samples/getting_started/workflows/agents/azure_chat_agents_function_bridge.py b/python/samples/getting_started/workflows/agents/azure_chat_agents_function_bridge.py index 90b1919b08..587938f2ca 100644 --- a/python/samples/getting_started/workflows/agents/azure_chat_agents_function_bridge.py +++ b/python/samples/getting_started/workflows/agents/azure_chat_agents_function_bridge.py @@ -6,7 +6,7 @@ from typing import Final from agent_framework import ( AgentExecutorRequest, AgentExecutorResponse, - AgentRunResponse, + AgentResponse, AgentRunUpdateEvent, ChatMessage, Role, @@ -70,7 +70,7 @@ async def enrich_with_references( ctx: WorkflowContext[AgentExecutorRequest], ) -> None: """Inject a follow-up user instruction that adds an external note for the next agent.""" - conversation = list(draft.full_conversation or draft.agent_run_response.messages) + conversation = list(draft.full_conversation or draft.agent_response.messages) original_prompt = next((message.text for message in conversation if message.role == Role.USER), "") external_note = _lookup_external_note(original_prompt) or ( "No additional references were found. Please refine the previous assistant response for clarity." @@ -134,7 +134,7 @@ async def main() -> None: elif isinstance(event, WorkflowOutputEvent): print("\n\n===== Final Output =====") response = event.data - if isinstance(response, AgentRunResponse): + if isinstance(response, AgentResponse): print(response.text or "(empty response)") else: print(response if response is not None else "No response generated.") diff --git a/python/samples/getting_started/workflows/agents/azure_chat_agents_tool_calls_with_feedback.py b/python/samples/getting_started/workflows/agents/azure_chat_agents_tool_calls_with_feedback.py index aab84478ce..53abdcb604 100644 --- a/python/samples/getting_started/workflows/agents/azure_chat_agents_tool_calls_with_feedback.py +++ b/python/samples/getting_started/workflows/agents/azure_chat_agents_tool_calls_with_feedback.py @@ -8,7 +8,7 @@ from typing import Annotated from agent_framework import ( AgentExecutorRequest, AgentExecutorResponse, - AgentRunResponse, + AgentResponse, AgentRunUpdateEvent, ChatAgent, ChatMessage, @@ -102,12 +102,12 @@ class Coordinator(Executor): async def on_writer_response( self, draft: AgentExecutorResponse, - ctx: WorkflowContext[Never, AgentRunResponse], + ctx: WorkflowContext[Never, AgentResponse], ) -> None: """Handle responses from the other two agents in the workflow.""" if draft.executor_id == self.final_editor_id: # Final editor response; yield output directly. - await ctx.yield_output(draft.agent_run_response) + await ctx.yield_output(draft.agent_response) return # Writer agent response; request human feedback. @@ -117,8 +117,8 @@ class Coordinator(Executor): if draft.full_conversation is not None: conversation = list(draft.full_conversation) else: - conversation = list(draft.agent_run_response.messages) - draft_text = draft.agent_run_response.text.strip() + conversation = list(draft.agent_response.messages) + draft_text = draft.agent_response.text.strip() if not draft_text: draft_text = "No draft text was produced." diff --git a/python/samples/getting_started/workflows/agents/handoff_workflow_as_agent.py b/python/samples/getting_started/workflows/agents/handoff_workflow_as_agent.py index e4f1c1e6cb..d9da8eb4ec 100644 --- a/python/samples/getting_started/workflows/agents/handoff_workflow_as_agent.py +++ b/python/samples/getting_started/workflows/agents/handoff_workflow_as_agent.py @@ -4,7 +4,7 @@ import asyncio from typing import Annotated from agent_framework import ( - AgentRunResponse, + AgentResponse, ChatAgent, ChatMessage, FunctionCallContent, @@ -101,7 +101,7 @@ def create_agents(chat_client: AzureOpenAIChatClient) -> tuple[ChatAgent, ChatAg return triage_agent, refund_agent, order_agent, return_agent -def handle_response_and_requests(response: AgentRunResponse) -> dict[str, HandoffAgentUserRequest]: +def handle_response_and_requests(response: AgentResponse) -> dict[str, HandoffAgentUserRequest]: """Process agent response messages and extract any user requests. This function inspects the agent response and: @@ -109,7 +109,7 @@ def handle_response_and_requests(response: AgentRunResponse) -> dict[str, Handof - Collects HandoffAgentUserRequest instances for response handling Args: - response: The AgentRunResponse from the agent run call. + response: The AgentResponse from the agent run call. Returns: A dictionary mapping request IDs to HandoffAgentUserRequest instances. diff --git a/python/samples/getting_started/workflows/agents/mixed_agents_and_executors.py b/python/samples/getting_started/workflows/agents/mixed_agents_and_executors.py index 70b7110fb0..28064ab1e1 100644 --- a/python/samples/getting_started/workflows/agents/mixed_agents_and_executors.py +++ b/python/samples/getting_started/workflows/agents/mixed_agents_and_executors.py @@ -66,8 +66,8 @@ class Evaluator(Executor): ctx: Workflow context for yielding the final output string """ target_text = "1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89" - correctness = target_text in message.agent_run_response.text - consumption = message.agent_run_response.usage_details + correctness = target_text in message.agent_response.text + consumption = message.agent_response.usage_details await ctx.yield_output(f"Correctness: {correctness}, Consumption: {consumption}") diff --git a/python/samples/getting_started/workflows/agents/workflow_as_agent_reflection_pattern.py b/python/samples/getting_started/workflows/agents/workflow_as_agent_reflection_pattern.py index 85003239db..aa9da00201 100644 --- a/python/samples/getting_started/workflows/agents/workflow_as_agent_reflection_pattern.py +++ b/python/samples/getting_started/workflows/agents/workflow_as_agent_reflection_pattern.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from uuid import uuid4 from agent_framework import ( - AgentRunResponseUpdate, + AgentResponseUpdate, AgentRunUpdateEvent, ChatClientProtocol, ChatMessage, @@ -161,7 +161,7 @@ class Worker(Executor): # Emit approved result to external consumer via AgentRunUpdateEvent. await ctx.add_event( - AgentRunUpdateEvent(self.id, data=AgentRunResponseUpdate(contents=contents, role=Role.ASSISTANT)) + AgentRunUpdateEvent(self.id, data=AgentResponseUpdate(contents=contents, role=Role.ASSISTANT)) ) return diff --git a/python/samples/getting_started/workflows/checkpoint/checkpoint_with_human_in_the_loop.py b/python/samples/getting_started/workflows/checkpoint/checkpoint_with_human_in_the_loop.py index 7b8d08a1af..d4f1d58133 100644 --- a/python/samples/getting_started/workflows/checkpoint/checkpoint_with_human_in_the_loop.py +++ b/python/samples/getting_started/workflows/checkpoint/checkpoint_with_human_in_the_loop.py @@ -127,7 +127,7 @@ class ReviewGateway(Executor): await ctx.request_info( request_data=HumanApprovalRequest( prompt="Review the draft. Reply 'approve' or provide edit instructions.", - draft=response.agent_run_response.text, + draft=response.agent_response.text, iteration=self._iteration, ), response_type=str, diff --git a/python/samples/getting_started/workflows/control-flow/edge_condition.py b/python/samples/getting_started/workflows/control-flow/edge_condition.py index 0dff43a58a..b8459480cd 100644 --- a/python/samples/getting_started/workflows/control-flow/edge_condition.py +++ b/python/samples/getting_started/workflows/control-flow/edge_condition.py @@ -85,7 +85,7 @@ def get_condition(expected_result: bool): try: # Prefer parsing a structured DetectionResult from the agent JSON text. # Using model_validate_json ensures type safety and raises if the shape is wrong. - detection = DetectionResult.model_validate_json(message.agent_run_response.text) + detection = DetectionResult.model_validate_json(message.agent_response.text) # Route only when the spam flag matches the expected path. return detection.is_spam == expected_result except Exception: @@ -99,14 +99,14 @@ def get_condition(expected_result: bool): @executor(id="send_email") async def handle_email_response(response: AgentExecutorResponse, ctx: WorkflowContext[Never, str]) -> None: # Downstream of the email assistant. Parse a validated EmailResponse and yield the workflow output. - email_response = EmailResponse.model_validate_json(response.agent_run_response.text) + email_response = EmailResponse.model_validate_json(response.agent_response.text) await ctx.yield_output(f"Email sent:\n{email_response.response}") @executor(id="handle_spam") async def handle_spam_classifier_response(response: AgentExecutorResponse, ctx: WorkflowContext[Never, str]) -> None: # Spam path. Confirm the DetectionResult and yield the workflow output. Guard against accidental non spam input. - detection = DetectionResult.model_validate_json(response.agent_run_response.text) + detection = DetectionResult.model_validate_json(response.agent_response.text) if detection.is_spam: await ctx.yield_output(f"Email marked as spam: {detection.reason}") else: @@ -123,7 +123,7 @@ async def to_email_assistant_request( Extracts DetectionResult.email_content and forwards it as a user message. """ # Bridge executor. Converts a structured DetectionResult into a ChatMessage and forwards it as a new request. - detection = DetectionResult.model_validate_json(response.agent_run_response.text) + detection = DetectionResult.model_validate_json(response.agent_response.text) user_msg = ChatMessage(Role.USER, text=detection.email_content) await ctx.send_message(AgentExecutorRequest(messages=[user_msg], should_respond=True)) diff --git a/python/samples/getting_started/workflows/control-flow/multi_selection_edge_group.py b/python/samples/getting_started/workflows/control-flow/multi_selection_edge_group.py index b7935a5e75..bd60cf449d 100644 --- a/python/samples/getting_started/workflows/control-flow/multi_selection_edge_group.py +++ b/python/samples/getting_started/workflows/control-flow/multi_selection_edge_group.py @@ -98,7 +98,7 @@ async def store_email(email_text: str, ctx: WorkflowContext[AgentExecutorRequest @executor(id="to_analysis_result") async def to_analysis_result(response: AgentExecutorResponse, ctx: WorkflowContext[AnalysisResult]) -> None: - parsed = AnalysisResultAgent.model_validate_json(response.agent_run_response.text) + parsed = AnalysisResultAgent.model_validate_json(response.agent_response.text) email_id: str = await ctx.get_shared_state(CURRENT_EMAIL_ID_KEY) email: Email = await ctx.get_shared_state(f"{EMAIL_STATE_PREFIX}{email_id}") await ctx.send_message( @@ -125,7 +125,7 @@ async def submit_to_email_assistant(analysis: AnalysisResult, ctx: WorkflowConte @executor(id="finalize_and_send") async def finalize_and_send(response: AgentExecutorResponse, ctx: WorkflowContext[Never, str]) -> None: - parsed = EmailResponse.model_validate_json(response.agent_run_response.text) + parsed = EmailResponse.model_validate_json(response.agent_response.text) await ctx.yield_output(f"Email sent: {parsed.response}") @@ -140,7 +140,7 @@ async def summarize_email(analysis: AnalysisResult, ctx: WorkflowContext[AgentEx @executor(id="merge_summary") async def merge_summary(response: AgentExecutorResponse, ctx: WorkflowContext[AnalysisResult]) -> None: - summary = EmailSummaryModel.model_validate_json(response.agent_run_response.text) + summary = EmailSummaryModel.model_validate_json(response.agent_response.text) email_id: str = await ctx.get_shared_state(CURRENT_EMAIL_ID_KEY) email: Email = await ctx.get_shared_state(f"{EMAIL_STATE_PREFIX}{email_id}") # Build an AnalysisResult mirroring to_analysis_result but with summary diff --git a/python/samples/getting_started/workflows/control-flow/simple_loop.py b/python/samples/getting_started/workflows/control-flow/simple_loop.py index 7bb3389a08..02e672b012 100644 --- a/python/samples/getting_started/workflows/control-flow/simple_loop.py +++ b/python/samples/getting_started/workflows/control-flow/simple_loop.py @@ -106,7 +106,7 @@ class ParseJudgeResponse(Executor): @handler async def parse(self, response: AgentExecutorResponse, ctx: WorkflowContext[NumberSignal]) -> None: - text = response.agent_run_response.text.strip().upper() + text = response.agent_response.text.strip().upper() if "MATCHED" in text: await ctx.send_message(NumberSignal.MATCHED) elif "ABOVE" in text and "BELOW" not in text: diff --git a/python/samples/getting_started/workflows/control-flow/switch_case_edge_group.py b/python/samples/getting_started/workflows/control-flow/switch_case_edge_group.py index c325d74d7f..63ea8796cd 100644 --- a/python/samples/getting_started/workflows/control-flow/switch_case_edge_group.py +++ b/python/samples/getting_started/workflows/control-flow/switch_case_edge_group.py @@ -106,7 +106,7 @@ async def store_email(email_text: str, ctx: WorkflowContext[AgentExecutorRequest @executor(id="to_detection_result") async def to_detection_result(response: AgentExecutorResponse, ctx: WorkflowContext[DetectionResult]) -> None: # Parse the detector JSON into a typed model. Attach the current email id for downstream lookups. - parsed = DetectionResultAgent.model_validate_json(response.agent_run_response.text) + parsed = DetectionResultAgent.model_validate_json(response.agent_response.text) email_id: str = await ctx.get_shared_state(CURRENT_EMAIL_ID_KEY) await ctx.send_message(DetectionResult(spam_decision=parsed.spam_decision, reason=parsed.reason, email_id=email_id)) @@ -127,7 +127,7 @@ async def submit_to_email_assistant(detection: DetectionResult, ctx: WorkflowCon @executor(id="finalize_and_send") async def finalize_and_send(response: AgentExecutorResponse, ctx: WorkflowContext[Never, str]) -> None: # Terminal step for the drafting branch. Yield the email response as output. - parsed = EmailResponse.model_validate_json(response.agent_run_response.text) + parsed = EmailResponse.model_validate_json(response.agent_response.text) await ctx.yield_output(f"Email sent: {parsed.response}") diff --git a/python/samples/getting_started/workflows/human-in-the-loop/agents_with_approval_requests.py b/python/samples/getting_started/workflows/human-in-the-loop/agents_with_approval_requests.py index 6f5370edf8..a082bd6b01 100644 --- a/python/samples/getting_started/workflows/human-in-the-loop/agents_with_approval_requests.py +++ b/python/samples/getting_started/workflows/human-in-the-loop/agents_with_approval_requests.py @@ -208,7 +208,7 @@ async def conclude_workflow( ctx: WorkflowContext[Never, str], ) -> None: """Conclude the workflow by yielding the final email response.""" - await ctx.yield_output(email_response.agent_run_response.text) + await ctx.yield_output(email_response.agent_response.text) def create_email_writer_agent() -> ChatAgent: diff --git a/python/samples/getting_started/workflows/human-in-the-loop/concurrent_request_info.py b/python/samples/getting_started/workflows/human-in-the-loop/concurrent_request_info.py index 4d8ee96d06..3dfd02e6ec 100644 --- a/python/samples/getting_started/workflows/human-in-the-loop/concurrent_request_info.py +++ b/python/samples/getting_started/workflows/human-in-the-loop/concurrent_request_info.py @@ -64,7 +64,7 @@ async def aggregate_with_synthesis(results: list[AgentExecutorResponse]) -> Any: for r in results: try: - messages = getattr(r.agent_run_response, "messages", []) + messages = getattr(r.agent_response, "messages", []) final_text = messages[-1].text if messages and hasattr(messages[-1], "text") else "(no content)" expert_sections.append(f"{getattr(r, 'executor_id', 'analyst')}:\n{final_text}") @@ -161,7 +161,7 @@ async def main() -> None: print("\n" + "-" * 40) print("INPUT REQUESTED") print( - f"Agent {event.source_executor_id} just responded with: '{event.data.agent_run_response.text}'. " + f"Agent {event.source_executor_id} just responded with: '{event.data.agent_response.text}'. " "Please provide your feedback." ) print("-" * 40) diff --git a/python/samples/getting_started/workflows/human-in-the-loop/group_chat_request_info.py b/python/samples/getting_started/workflows/human-in-the-loop/group_chat_request_info.py index d76308c657..e3ed0ab5ff 100644 --- a/python/samples/getting_started/workflows/human-in-the-loop/group_chat_request_info.py +++ b/python/samples/getting_started/workflows/human-in-the-loop/group_chat_request_info.py @@ -27,7 +27,7 @@ import asyncio from agent_framework import ( AgentExecutorResponse, AgentRequestInfoResponse, - AgentRunResponse, + AgentResponse, AgentRunUpdateEvent, ChatMessage, GroupChatBuilder, @@ -138,8 +138,8 @@ async def main() -> None: print(f"About to call agent: {event.source_executor_id}") print("-" * 40) print("Conversation context:") - agent_run_response: AgentRunResponse = event.data.agent_run_response - messages: list[ChatMessage] = agent_run_response.messages + agent_response: AgentResponse = event.data.agent_response + messages: list[ChatMessage] = agent_response.messages recent: list[ChatMessage] = messages[-3:] if len(messages) > 3 else messages # type: ignore for msg in recent: name = msg.author_name or "unknown" diff --git a/python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py b/python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py index d711861502..1afb1223af 100644 --- a/python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py +++ b/python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py @@ -103,7 +103,7 @@ class TurnManager(Executor): 2) Request info with a HumanFeedbackRequest as the payload. """ # Parse structured model output - text = result.agent_run_response.text + text = result.agent_response.text last_guess = GuessOutput.model_validate_json(text).guess # Craft a precise human prompt that defines higher and lower relative to the agent's guess. diff --git a/python/samples/getting_started/workflows/human-in-the-loop/sequential_request_info.py b/python/samples/getting_started/workflows/human-in-the-loop/sequential_request_info.py index 8e735bfb1a..f8a3e7ff85 100644 --- a/python/samples/getting_started/workflows/human-in-the-loop/sequential_request_info.py +++ b/python/samples/getting_started/workflows/human-in-the-loop/sequential_request_info.py @@ -96,7 +96,7 @@ async def main() -> None: print("\n" + "-" * 40) print("REQUEST INFO: INPUT REQUESTED") print( - f"Agent {event.source_executor_id} just responded with: '{event.data.agent_run_response.text}'. " + f"Agent {event.source_executor_id} just responded with: '{event.data.agent_response.text}'. " "Please provide your feedback." ) print("-" * 40) diff --git a/python/samples/getting_started/workflows/orchestration/concurrent_custom_aggregator.py b/python/samples/getting_started/workflows/orchestration/concurrent_custom_aggregator.py index 44f71ba7bc..e45eb0c11f 100644 --- a/python/samples/getting_started/workflows/orchestration/concurrent_custom_aggregator.py +++ b/python/samples/getting_started/workflows/orchestration/concurrent_custom_aggregator.py @@ -58,7 +58,7 @@ async def main() -> None: expert_sections: list[str] = [] for r in results: try: - messages = getattr(r.agent_run_response, "messages", []) + messages = getattr(r.agent_response, "messages", []) final_text = messages[-1].text if messages and hasattr(messages[-1], "text") else "(no content)" expert_sections.append(f"{getattr(r, 'executor_id', 'expert')}:\n{final_text}") except Exception as e: diff --git a/python/samples/getting_started/workflows/orchestration/concurrent_participant_factory.py b/python/samples/getting_started/workflows/orchestration/concurrent_participant_factory.py index 435e59b2ba..01e343a2aa 100644 --- a/python/samples/getting_started/workflows/orchestration/concurrent_participant_factory.py +++ b/python/samples/getting_started/workflows/orchestration/concurrent_participant_factory.py @@ -89,7 +89,7 @@ class SummarizationExecutor(Executor): expert_sections: list[str] = [] for r in results: try: - messages = getattr(r.agent_run_response, "messages", []) + messages = getattr(r.agent_response, "messages", []) final_text = messages[-1].text if messages and hasattr(messages[-1], "text") else "(no content)" expert_sections.append(f"{getattr(r, 'executor_id', 'expert')}:\n{final_text}") except Exception as e: diff --git a/python/samples/getting_started/workflows/orchestration/handoff_autonomous.py b/python/samples/getting_started/workflows/orchestration/handoff_autonomous.py index 2ea327751d..2d0542a0fb 100644 --- a/python/samples/getting_started/workflows/orchestration/handoff_autonomous.py +++ b/python/samples/getting_started/workflows/orchestration/handoff_autonomous.py @@ -5,7 +5,7 @@ import logging from typing import cast from agent_framework import ( - AgentRunResponseUpdate, + AgentResponseUpdate, AgentRunUpdateEvent, ChatAgent, ChatMessage, @@ -82,7 +82,7 @@ last_response_id: str | None = None def _display_event(event: WorkflowEvent) -> None: """Print the final conversation snapshot from workflow output events.""" if isinstance(event, AgentRunUpdateEvent) and event.data: - update: AgentRunResponseUpdate = event.data + update: AgentResponseUpdate = event.data if not update.text: return global last_response_id diff --git a/python/samples/getting_started/workflows/orchestration/handoff_participant_factory.py b/python/samples/getting_started/workflows/orchestration/handoff_participant_factory.py index 58a562c4cf..4330cc1ace 100644 --- a/python/samples/getting_started/workflows/orchestration/handoff_participant_factory.py +++ b/python/samples/getting_started/workflows/orchestration/handoff_participant_factory.py @@ -5,8 +5,8 @@ import logging from typing import Annotated, cast from agent_framework import ( + AgentResponse, AgentRunEvent, - AgentRunResponse, ChatAgent, ChatMessage, HandoffAgentUserRequest, @@ -163,14 +163,14 @@ def _handle_events(events: list[WorkflowEvent]) -> list[RequestInfoEvent]: return requests -def _print_handoff_agent_user_request(response: AgentRunResponse) -> None: +def _print_handoff_agent_user_request(response: AgentResponse) -> None: """Display the agent's response messages when requesting user input. This will happen when an agent generates a response that doesn't trigger a handoff, i.e., the agent is asking the user for more information. Args: - response: The AgentRunResponse from the agent requesting user input + response: The AgentResponse from the agent requesting user input """ if not response.messages: raise RuntimeError("Cannot print agent responses: response has no messages.") diff --git a/python/samples/getting_started/workflows/orchestration/handoff_simple.py b/python/samples/getting_started/workflows/orchestration/handoff_simple.py index 32fd3ba441..e2e4aa7f1c 100644 --- a/python/samples/getting_started/workflows/orchestration/handoff_simple.py +++ b/python/samples/getting_started/workflows/orchestration/handoff_simple.py @@ -4,8 +4,8 @@ import asyncio from typing import Annotated, cast from agent_framework import ( + AgentResponse, AgentRunEvent, - AgentRunResponse, ChatAgent, ChatMessage, HandoffAgentUserRequest, @@ -158,14 +158,14 @@ def _handle_events(events: list[WorkflowEvent]) -> list[RequestInfoEvent]: return requests -def _print_handoff_agent_user_request(response: AgentRunResponse) -> None: +def _print_handoff_agent_user_request(response: AgentResponse) -> None: """Display the agent's response messages when requesting user input. This will happen when an agent generates a response that doesn't trigger a handoff, i.e., the agent is asking the user for more information. Args: - response: The AgentRunResponse from the agent requesting user input + response: The AgentResponse from the agent requesting user input """ if not response.messages: raise RuntimeError("Cannot print agent responses: response has no messages.") diff --git a/python/samples/getting_started/workflows/parallelism/fan_out_fan_in_edges.py b/python/samples/getting_started/workflows/parallelism/fan_out_fan_in_edges.py index fbec7ca303..09287dc62f 100644 --- a/python/samples/getting_started/workflows/parallelism/fan_out_fan_in_edges.py +++ b/python/samples/getting_started/workflows/parallelism/fan_out_fan_in_edges.py @@ -36,7 +36,7 @@ Show how to construct a parallel branch pattern in workflows. Demonstrate: Prerequisites: - Familiarity with WorkflowBuilder, executors, edges, events, and streaming runs. - Azure OpenAI access configured for AzureOpenAIChatClient. Log in with Azure CLI and set any required environment variables. -- Comfort reading AgentExecutorResponse.agent_run_response.text for assistant output aggregation. +- Comfort reading AgentExecutorResponse.agent_response.text for assistant output aggregation. """ @@ -67,8 +67,8 @@ class AggregateInsights(Executor): # Map responses to text by executor id for a simple, predictable demo. by_id: dict[str, str] = {} for r in results: - # AgentExecutorResponse.agent_run_response.text is the assistant text produced by the agent. - by_id[r.executor_id] = r.agent_run_response.text + # AgentExecutorResponse.agent_response.text is the assistant text produced by the agent. + by_id[r.executor_id] = r.agent_response.text research_text = by_id.get("researcher", "") marketing_text = by_id.get("marketer", "") diff --git a/python/samples/getting_started/workflows/state-management/shared_states_with_agents.py b/python/samples/getting_started/workflows/state-management/shared_states_with_agents.py index e9098f996e..0ab5b9a9dd 100644 --- a/python/samples/getting_started/workflows/state-management/shared_states_with_agents.py +++ b/python/samples/getting_started/workflows/state-management/shared_states_with_agents.py @@ -117,7 +117,7 @@ async def to_detection_result(response: AgentExecutorResponse, ctx: WorkflowCont 2) Retrieve the current email_id from shared state. 3) Send a typed DetectionResult for conditional routing. """ - parsed = DetectionResultAgent.model_validate_json(response.agent_run_response.text) + parsed = DetectionResultAgent.model_validate_json(response.agent_response.text) email_id: str = await ctx.get_shared_state(CURRENT_EMAIL_ID_KEY) await ctx.send_message(DetectionResult(is_spam=parsed.is_spam, reason=parsed.reason, email_id=email_id)) @@ -142,7 +142,7 @@ async def submit_to_email_assistant(detection: DetectionResult, ctx: WorkflowCon @executor(id="finalize_and_send") async def finalize_and_send(response: AgentExecutorResponse, ctx: WorkflowContext[Never, str]) -> None: """Validate the drafted reply and yield the final output.""" - parsed = EmailResponse.model_validate_json(response.agent_run_response.text) + parsed = EmailResponse.model_validate_json(response.agent_response.text) await ctx.yield_output(f"Email sent: {parsed.response}") diff --git a/python/samples/getting_started/workflows/visualization/concurrent_with_visualization.py b/python/samples/getting_started/workflows/visualization/concurrent_with_visualization.py index 81545b75c7..a0555dab4b 100644 --- a/python/samples/getting_started/workflows/visualization/concurrent_with_visualization.py +++ b/python/samples/getting_started/workflows/visualization/concurrent_with_visualization.py @@ -61,8 +61,8 @@ class AggregateInsights(Executor): # Map responses to text by executor id for a simple, predictable demo. by_id: dict[str, str] = {} for r in results: - # AgentExecutorResponse.agent_run_response.text contains concatenated assistant text - by_id[r.executor_id] = r.agent_run_response.text + # AgentExecutorResponse.agent_response.text contains concatenated assistant text + by_id[r.executor_id] = r.agent_response.text research_text = by_id.get("researcher", "") marketing_text = by_id.get("marketer", "") diff --git a/python/samples/semantic-kernel-migration/copilot_studio/02_copilot_studio_streaming.py b/python/samples/semantic-kernel-migration/copilot_studio/02_copilot_studio_streaming.py index 186d093495..d437ff807e 100644 --- a/python/samples/semantic-kernel-migration/copilot_studio/02_copilot_studio_streaming.py +++ b/python/samples/semantic-kernel-migration/copilot_studio/02_copilot_studio_streaming.py @@ -26,7 +26,7 @@ async def run_agent_framework() -> None: name="TourGuide", instructions="Provide travel recommendations in short bursts.", ) - # AF streaming provides incremental AgentRunResponseUpdate objects. + # AF streaming provides incremental AgentResponseUpdate objects. print("[AF][stream]", end=" ") async for update in agent.run_stream("Plan a day in Copenhagen for foodies."): if update.text: