From 6900b6b83011f9bdfc29d7df30ba69491a00f434 Mon Sep 17 00:00:00 2001 From: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com> Date: Fri, 30 Jan 2026 13:05:48 -0800 Subject: [PATCH 1/2] Replaced obsolete create_response method in samples --- .../azure_ai/azure_ai_with_hosted_mcp.py | 4 ++-- .../azure_ai_with_hosted_mcp.py | 2 +- .../azure_ai_with_multiple_tools.py | 2 +- .../azure_responses_client_with_hosted_mcp.py | 6 +++--- ...openai_responses_client_with_hosted_mcp.py | 6 +++--- .../tools/function_tool_with_approval.py | 4 ++-- ...function_tool_with_approval_and_threads.py | 4 ++-- ...ff_with_tool_approval_checkpoint_resume.py | 20 +++++++++---------- .../agents_with_approval_requests.py | 13 ++++++------ .../concurrent_builder_tool_approval.py | 11 +++++----- .../group_chat_builder_tool_approval.py | 8 ++++---- .../sequential_builder_tool_approval.py | 12 +++++------ 12 files changed, 45 insertions(+), 47 deletions(-) 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 8b120f703d..76394a8aac 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 @@ -28,7 +28,7 @@ async def handle_approvals_without_thread(query: str, agent: "AgentProtocol") -> new_inputs.append(ChatMessage(role="assistant", contents=[user_input_needed])) user_approval = input("Approve function call? (y/n): ") new_inputs.append( - ChatMessage(role="user", contents=[user_input_needed.create_response(user_approval.lower() == "y")]) + ChatMessage(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")]) ) result = await agent.run(new_inputs, store=False) @@ -50,7 +50,7 @@ async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", threa new_input.append( ChatMessage( role="user", - contents=[user_input_needed.create_response(user_approval.lower() == "y")], + contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")], ) ) result = await agent.run(new_input, thread=thread) 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 71ab02b279..a16a6f7a92 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 @@ -31,7 +31,7 @@ async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", threa new_input.append( ChatMessage( role="user", - contents=[user_input_needed.create_response(user_approval.lower() == "y")], + contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")], ) ) result = await agent.run(new_input, thread=thread, store=True) diff --git a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_multiple_tools.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_multiple_tools.py index 244c57aa50..4539696bc6 100644 --- a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_multiple_tools.py +++ b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_multiple_tools.py @@ -59,7 +59,7 @@ async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", threa new_input.append( ChatMessage( role="user", - contents=[user_input_needed.create_response(user_approval.lower() == "y")], + contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")], ) ) result = await agent.run(new_input, thread=thread, store=True) diff --git a/python/samples/getting_started/agents/azure_openai/azure_responses_client_with_hosted_mcp.py b/python/samples/getting_started/agents/azure_openai/azure_responses_client_with_hosted_mcp.py index 9ed1d74e16..0833065742 100644 --- a/python/samples/getting_started/agents/azure_openai/azure_responses_client_with_hosted_mcp.py +++ b/python/samples/getting_started/agents/azure_openai/azure_responses_client_with_hosted_mcp.py @@ -33,7 +33,7 @@ async def handle_approvals_without_thread(query: str, agent: "AgentProtocol"): new_inputs.append(ChatMessage(role="assistant", contents=[user_input_needed])) user_approval = input("Approve function call? (y/n): ") new_inputs.append( - ChatMessage(role="user", contents=[user_input_needed.create_response(user_approval.lower() == "y")]) + ChatMessage(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")]) ) result = await agent.run(new_inputs) @@ -56,7 +56,7 @@ async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", threa new_input.append( ChatMessage( role="user", - contents=[user_input_needed.create_response(user_approval.lower() == "y")], + contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")], ) ) result = await agent.run(new_input, thread=thread, store=True) @@ -82,7 +82,7 @@ async def handle_approvals_with_thread_streaming(query: str, agent: "AgentProtoc user_approval = input("Approve function call? (y/n): ") new_input.append( ChatMessage( - role="user", contents=[user_input_needed.create_response(user_approval.lower() == "y")] + role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")] ) ) new_input_added = True diff --git a/python/samples/getting_started/agents/openai/openai_responses_client_with_hosted_mcp.py b/python/samples/getting_started/agents/openai/openai_responses_client_with_hosted_mcp.py index e86d113b75..e5fa62f040 100644 --- a/python/samples/getting_started/agents/openai/openai_responses_client_with_hosted_mcp.py +++ b/python/samples/getting_started/agents/openai/openai_responses_client_with_hosted_mcp.py @@ -32,7 +32,7 @@ async def handle_approvals_without_thread(query: str, agent: "AgentProtocol"): new_inputs.append(ChatMessage(role="assistant", contents=[user_input_needed])) user_approval = input("Approve function call? (y/n): ") new_inputs.append( - ChatMessage(role="user", contents=[user_input_needed.create_response(user_approval.lower() == "y")]) + ChatMessage(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")]) ) result = await agent.run(new_inputs) @@ -55,7 +55,7 @@ async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", threa new_input.append( ChatMessage( role="user", - contents=[user_input_needed.create_response(user_approval.lower() == "y")], + contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")], ) ) result = await agent.run(new_input, thread=thread, store=True) @@ -81,7 +81,7 @@ async def handle_approvals_with_thread_streaming(query: str, agent: "AgentProtoc user_approval = input("Approve function call? (y/n): ") new_input.append( ChatMessage( - role="user", contents=[user_input_needed.create_response(user_approval.lower() == "y")] + role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")] ) ) new_input_added = True diff --git a/python/samples/getting_started/tools/function_tool_with_approval.py b/python/samples/getting_started/tools/function_tool_with_approval.py index 9c026b8bc6..813bbb61ea 100644 --- a/python/samples/getting_started/tools/function_tool_with_approval.py +++ b/python/samples/getting_started/tools/function_tool_with_approval.py @@ -66,7 +66,7 @@ async def handle_approvals(query: str, agent: "AgentProtocol") -> AgentResponse: # Add the user's approval response new_inputs.append( - ChatMessage(role="user", contents=[user_input_needed.create_response(user_approval.lower() == "y")]) + ChatMessage(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")]) ) # Run again with all the context @@ -116,7 +116,7 @@ async def handle_approvals_streaming(query: str, agent: "AgentProtocol") -> None # Add the user's approval response new_inputs.append( - ChatMessage(role="user", contents=[user_input_needed.create_response(user_approval.lower() == "y")]) + ChatMessage(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")]) ) # Update input with all the context for next iteration diff --git a/python/samples/getting_started/tools/function_tool_with_approval_and_threads.py b/python/samples/getting_started/tools/function_tool_with_approval_and_threads.py index 80940efc1f..9b9c06837a 100644 --- a/python/samples/getting_started/tools/function_tool_with_approval_and_threads.py +++ b/python/samples/getting_started/tools/function_tool_with_approval_and_threads.py @@ -54,7 +54,7 @@ async def approval_example() -> None: print(f" Decision: {'Approved' if approved else 'Rejected'}") # Step 2: Send approval response - approval_response = request.create_response(approved=approved) + approval_response = request.to_function_approval_response(approved=approved) result = await agent.run(ChatMessage(role="user", contents=[approval_response]), thread=thread) print(f"Agent: {result}\n") @@ -87,7 +87,7 @@ async def rejection_example() -> None: print(" Decision: Rejected") # Send rejection response - rejection_response = request.create_response(approved=False) + rejection_response = request.to_function_approval_response(approved=False) result = await agent.run(ChatMessage(role="user", contents=[rejection_response]), thread=thread) print(f"Agent: {result}\n") diff --git a/python/samples/getting_started/workflows/checkpoint/handoff_with_tool_approval_checkpoint_resume.py b/python/samples/getting_started/workflows/checkpoint/handoff_with_tool_approval_checkpoint_resume.py index 0d60f6ca22..694fd868cf 100644 --- a/python/samples/getting_started/workflows/checkpoint/handoff_with_tool_approval_checkpoint_resume.py +++ b/python/samples/getting_started/workflows/checkpoint/handoff_with_tool_approval_checkpoint_resume.py @@ -9,8 +9,8 @@ from agent_framework import ( ChatAgent, ChatMessage, + Content, FileCheckpointStorage, - FunctionApprovalRequestContent, HandoffBuilder, HandoffUserInputRequest, RequestInfoEvent, @@ -26,7 +26,7 @@ Sample: Handoff Workflow with Tool Approvals + Checkpoint Resume Demonstrates the two-step pattern for resuming a handoff workflow from a checkpoint -while handling both HandoffUserInputRequest prompts and FunctionApprovalRequestContent +while handling both HandoffUserInputRequest prompts and function approval request Content for tool calls (e.g., submit_refund). Scenario: @@ -137,7 +137,7 @@ def _print_handoff_request(request: HandoffUserInputRequest, request_id: str) -> print(f"{'=' * 60}\n") -def _print_function_approval_request(request: FunctionApprovalRequestContent, request_id: str) -> None: +def _print_function_approval_request(request: Content, request_id: str) -> None: """Log pending tool approval details for debugging.""" args = request.function_call.parse_arguments() or {} print(f"\n{'=' * 60}") @@ -161,10 +161,10 @@ def _build_responses_for_requests( if user_response is None: raise ValueError("User response is required for HandoffUserInputRequest") responses[request.request_id] = user_response - elif isinstance(request.data, FunctionApprovalRequestContent): + elif isinstance(request.data, Content) and request.data.type == "function_approval_request": if approve_tools is None: - raise ValueError("Approval decision is required for FunctionApprovalRequestContent") - responses[request.request_id] = request.data.create_response(approved=approve_tools) + raise ValueError("Approval decision is required for function approval request") + responses[request.request_id] = request.data.to_function_approval_response(approved=approve_tools) else: raise ValueError(f"Unsupported request type: {type(request.data)}") return responses @@ -201,7 +201,7 @@ async def run_until_user_input_needed( pending_requests.append(event) if isinstance(event.data, HandoffUserInputRequest): _print_handoff_request(event.data, event.request_id) - elif isinstance(event.data, FunctionApprovalRequestContent): + elif isinstance(event.data, Content) and event.data.type == "function_approval_request": _print_function_approval_request(event.data, event.request_id) elif isinstance(event, WorkflowOutputEvent): @@ -258,7 +258,7 @@ async def resume_with_responses( restored_requests.append(event) if isinstance(event.data, HandoffUserInputRequest): _print_handoff_request(event.data, event.request_id) - elif isinstance(event.data, FunctionApprovalRequestContent): + elif isinstance(event.data, Content) and event.data.type == "function_approval_request": _print_function_approval_request(event.data, event.request_id) if not restored_requests: @@ -291,7 +291,7 @@ async def resume_with_responses( new_pending_requests.append(event) if isinstance(event.data, HandoffUserInputRequest): _print_handoff_request(event.data, event.request_id) - elif isinstance(event.data, FunctionApprovalRequestContent): + elif isinstance(event.data, Content) and event.data.type == "function_approval_request": _print_function_approval_request(event.data, event.request_id) return new_pending_requests, latest_checkpoint.checkpoint_id @@ -362,7 +362,7 @@ async def main() -> None: workflow_step, _, _, _ = create_workflow(checkpoint_storage=storage) needs_user_input = any(isinstance(req.data, HandoffUserInputRequest) for req in pending_requests) - needs_tool_approval = any(isinstance(req.data, FunctionApprovalRequestContent) for req in pending_requests) + needs_tool_approval = any(isinstance(req.data, Content) and req.data.type == "function_approval_request" for req in pending_requests) user_response = None if needs_user_input: 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 b724f2876c..491b140a28 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 @@ -9,9 +9,8 @@ AgentExecutorResponse, ChatAgent, ChatMessage, + Content, Executor, - FunctionApprovalRequestContent, - FunctionApprovalResponseContent, WorkflowBuilder, WorkflowContext, tool, @@ -251,7 +250,7 @@ async def main() -> None: body="Please provide your team's status update on the project since last week.", ) - responses: dict[str, FunctionApprovalResponseContent] = {} + responses: dict[str, Content] = {} output: list[ChatMessage] | None = None while True: if responses: @@ -262,8 +261,8 @@ async def main() -> None: request_info_events = events.get_request_info_events() for request_info_event in request_info_events: - # We should only expect FunctionApprovalRequestContent in this sample - if not isinstance(request_info_event.data, FunctionApprovalRequestContent): + # We should only expect function_approval_request Content in this sample + if not isinstance(request_info_event.data, Content) and request_info_event.data.type == "function_approval_request": raise ValueError(f"Unexpected request info content type: {type(request_info_event.data)}") # Pretty print the function call details @@ -274,10 +273,10 @@ async def main() -> None: ) # For demo purposes, we automatically approve the request - # The expected response type of the request is `FunctionApprovalResponseContent`, + # The expected response type of the request is `function_approval_response Content`, # which can be created via `create_response` method on the request content print("Performing automatic approval for demo purposes...") - responses[request_info_event.request_id] = request_info_event.data.create_response(approved=True) + responses[request_info_event.request_id] = request_info_event.data.to_function_approval_response(approved=True) # Once we get an output event, we can conclude the workflow # Outputs can only be produced by the conclude_workflow_executor in this sample diff --git a/python/samples/getting_started/workflows/tool-approval/concurrent_builder_tool_approval.py b/python/samples/getting_started/workflows/tool-approval/concurrent_builder_tool_approval.py index 83e6175a72..b43e01916f 100644 --- a/python/samples/getting_started/workflows/tool-approval/concurrent_builder_tool_approval.py +++ b/python/samples/getting_started/workflows/tool-approval/concurrent_builder_tool_approval.py @@ -6,8 +6,7 @@ from agent_framework import ( ChatMessage, ConcurrentBuilder, - FunctionApprovalRequestContent, - FunctionApprovalResponseContent, + Content, RequestInfoEvent, WorkflowOutputEvent, tool, @@ -139,7 +138,7 @@ async def main() -> None: ): if isinstance(event, RequestInfoEvent): request_info_events.append(event) - if isinstance(event.data, FunctionApprovalRequestContent): + if isinstance(event.data, Content) and event.data.type == "function_approval_request": print(f"\nApproval requested for tool: {event.data.function_call.name}") print(f" Arguments: {event.data.function_call.arguments}") elif isinstance(event, WorkflowOutputEvent): @@ -147,12 +146,12 @@ async def main() -> None: # 6. Handle approval requests (if any) if request_info_events: - responses: dict[str, FunctionApprovalResponseContent] = {} + responses: dict[str, Content] = {} for request_event in request_info_events: - if isinstance(request_event.data, FunctionApprovalRequestContent): + if isinstance(request_event.data, Content) and request_event.data.type == "function_approval_request": print(f"\nSimulating human approval for: {request_event.data.function_call.name}") # Create approval response - responses[request_event.request_id] = request_event.data.create_response(approved=True) + responses[request_event.request_id] = request_event.data.to_function_approval_response(approved=True) if responses: # Phase 2: Send all approvals and continue workflow diff --git a/python/samples/getting_started/workflows/tool-approval/group_chat_builder_tool_approval.py b/python/samples/getting_started/workflows/tool-approval/group_chat_builder_tool_approval.py index 3db5f32d1f..b4bc773eba 100644 --- a/python/samples/getting_started/workflows/tool-approval/group_chat_builder_tool_approval.py +++ b/python/samples/getting_started/workflows/tool-approval/group_chat_builder_tool_approval.py @@ -5,7 +5,7 @@ from agent_framework import ( AgentRunUpdateEvent, - FunctionApprovalRequestContent, + Content, GroupChatBuilder, GroupChatRequestSentEvent, GroupChatState, @@ -144,7 +144,7 @@ async def main() -> None: ): if isinstance(event, RequestInfoEvent): request_info_events.append(event) - if isinstance(event.data, FunctionApprovalRequestContent): + if isinstance(event.data, Content) and event.data.type == "function_approval_request": print("\n[APPROVAL REQUIRED] From agent:", event.source_executor_id) print(f" Tool: {event.data.function_call.name}") print(f" Arguments: {event.data.function_call.arguments}") @@ -164,7 +164,7 @@ async def main() -> None: # 6. Handle approval requests if request_info_events: for request_event in request_info_events: - if isinstance(request_event.data, FunctionApprovalRequestContent): + if isinstance(request_event.data, Content) and request_event.data.type == "function_approval_request": print("\n" + "=" * 60) print("Human review required for production deployment!") print("In a real scenario, you would review the deployment details here.") @@ -172,7 +172,7 @@ async def main() -> None: print("=" * 60) # Create approval response - approval_response = request_event.data.create_response(approved=True) + approval_response = request_event.data.to_function_approval_response(approved=True) # Phase 2: Send approval and continue workflow # Keep track of the response to format output nicely in streaming mode diff --git a/python/samples/getting_started/workflows/tool-approval/sequential_builder_tool_approval.py b/python/samples/getting_started/workflows/tool-approval/sequential_builder_tool_approval.py index 1397ce31a1..7712873943 100644 --- a/python/samples/getting_started/workflows/tool-approval/sequential_builder_tool_approval.py +++ b/python/samples/getting_started/workflows/tool-approval/sequential_builder_tool_approval.py @@ -5,7 +5,7 @@ from agent_framework import ( ChatMessage, - FunctionApprovalRequestContent, + Content, RequestInfoEvent, SequentialBuilder, WorkflowOutputEvent, @@ -23,7 +23,7 @@ This sample works as follows: 1. A SequentialBuilder workflow is created with a single agent that has tools requiring approval. 2. The agent receives a user task and determines it needs to call a sensitive tool. -3. The tool call triggers a FunctionApprovalRequestContent, pausing the workflow. +3. The tool call triggers a function_approval_request Content, pausing the workflow. 4. The sample simulates human approval by responding to the RequestInfoEvent. 5. Once approved, the tool executes and the agent completes its response. 6. The workflow outputs the final conversation with all messages. @@ -34,7 +34,7 @@ Demonstrate: - Using @tool(approval_mode="always_require") for sensitive operations. -- Handling RequestInfoEvent with FunctionApprovalRequestContent in sequential workflows. +- Handling RequestInfoEvent with function_approval_request Content in sequential workflows. - Resuming workflow execution after approval via send_responses_streaming. Prerequisites: @@ -92,19 +92,19 @@ async def main() -> None: ): if isinstance(event, RequestInfoEvent): request_info_events.append(event) - if isinstance(event.data, FunctionApprovalRequestContent): + if isinstance(event.data, Content) and event.data.type == "function_approval_request": print(f"\nApproval requested for tool: {event.data.function_call.name}") print(f" Arguments: {event.data.function_call.arguments}") # 5. Handle approval requests if request_info_events: for request_event in request_info_events: - if isinstance(request_event.data, FunctionApprovalRequestContent): + if isinstance(request_event.data, Content) and request_event.data.type == "function_approval_request": # In a real application, you would prompt the user here print("\nSimulating human approval (auto-approving for demo)...") # Create approval response - approval_response = request_event.data.create_response(approved=True) + approval_response = request_event.data.to_function_approval_response(approved=True) # Phase 2: Send approval and continue workflow output: list[ChatMessage] | None = None From 53fdd19accb255ddb201388549cc8a961edee7b5 Mon Sep 17 00:00:00 2001 From: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com> Date: Fri, 30 Jan 2026 14:15:50 -0800 Subject: [PATCH 2/2] Addressed PR comments --- .../human-in-the-loop/agents_with_approval_requests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 491b140a28..c49d2c1308 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 @@ -262,7 +262,7 @@ async def main() -> None: request_info_events = events.get_request_info_events() for request_info_event in request_info_events: # We should only expect function_approval_request Content in this sample - if not isinstance(request_info_event.data, Content) and request_info_event.data.type == "function_approval_request": + if not isinstance(request_info_event.data, Content) or request_info_event.data.type != "function_approval_request": raise ValueError(f"Unexpected request info content type: {type(request_info_event.data)}") # Pretty print the function call details @@ -274,7 +274,7 @@ async def main() -> None: # For demo purposes, we automatically approve the request # The expected response type of the request is `function_approval_response Content`, - # which can be created via `create_response` method on the request content + # which can be created via `to_function_approval_response` method on the request content print("Performing automatic approval for demo purposes...") responses[request_info_event.request_id] = request_info_event.data.to_function_approval_response(approved=True)