Python: Added function approval example with streaming (#1365)

* Added function approval example with streaming

* Update python/samples/getting_started/tools/ai_tool_with_approval.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Dmytro Struk
2025-10-09 10:31:36 -07:00
committed by GitHub
Unverified
parent a02b82f022
commit 9fe4a61dd0
@@ -4,7 +4,7 @@ import asyncio
from random import randrange
from typing import TYPE_CHECKING, Annotated, Any
from agent_framework import ChatAgent, ai_function
from agent_framework import AgentRunResponse, ChatAgent, ChatMessage, ai_function
from agent_framework.openai import OpenAIResponsesClient
if TYPE_CHECKING:
@@ -39,14 +39,12 @@ def get_weather_detail(location: Annotated[str, "The city and state, e.g. San Fr
)
async def handle_approvals(query: str, agent: "AgentProtocol"):
async def handle_approvals(query: str, agent: "AgentProtocol") -> AgentRunResponse:
"""Handle function call approvals.
When we don't have a thread, we need to ensure we include the original query,
the approval request, and the approval response in each iteration.
"""
from agent_framework import ChatMessage
result = await agent.run(query)
while len(result.user_input_requests) > 0:
# Start with the original query
@@ -63,7 +61,7 @@ async def handle_approvals(query: str, agent: "AgentProtocol"):
new_inputs.append(ChatMessage(role="assistant", contents=[user_input_needed]))
# Get user approval
user_approval = input("\nApprove function call? (y/n): ")
user_approval = await asyncio.to_thread(input, "\nApprove function call? (y/n): ")
# Add the user's approval response
new_inputs.append(
@@ -76,9 +74,57 @@ async def handle_approvals(query: str, agent: "AgentProtocol"):
return result
async def run_weather_agent_with_approval() -> None:
async def handle_approvals_streaming(query: str, agent: "AgentProtocol") -> None:
"""Handle function call approvals with streaming responses.
When we don't have a thread, we need to ensure we include the original query,
the approval request, and the approval response in each iteration.
"""
current_input: str | list[Any] = query
has_user_input_requests = True
while has_user_input_requests:
has_user_input_requests = False
user_input_requests: list[Any] = []
# Stream the response
async for chunk in agent.run_stream(current_input):
if chunk.text:
print(chunk.text, end="", flush=True)
# Collect user input requests from the stream
if chunk.user_input_requests:
user_input_requests.extend(chunk.user_input_requests)
if user_input_requests:
has_user_input_requests = True
# Start with the original query
new_inputs: list[Any] = [query]
for user_input_needed in user_input_requests:
print(
f"\n\nUser Input Request for function from {agent.name}:"
f"\n Function: {user_input_needed.function_call.name}"
f"\n Arguments: {user_input_needed.function_call.arguments}"
)
# Add the assistant message with the approval request
new_inputs.append(ChatMessage(role="assistant", contents=[user_input_needed]))
# Get user approval
user_approval = await asyncio.to_thread(input, "\nApprove function call? (y/n): ")
# Add the user's approval response
new_inputs.append(
ChatMessage(role="user", contents=[user_input_needed.create_response(user_approval.lower() == "y")])
)
# Update input with all the context for next iteration
current_input = new_inputs
async def run_weather_agent_with_approval(is_streaming: bool) -> None:
"""Example showing AI function with approval requirement."""
print("\n=== Weather Agent WITH Approval Required ===\n")
print(f"\n=== Weather Agent with Approval Required ({'Streaming' if is_streaming else 'Non-Streaming'}) ===\n")
async with ChatAgent(
chat_client=OpenAIResponsesClient(),
@@ -86,16 +132,23 @@ async def run_weather_agent_with_approval() -> None:
instructions=("You are a helpful weather assistant. Use the get_weather tool to provide weather information."),
tools=[get_weather, get_weather_detail],
) as agent:
query2 = "Can you give me an update of the weather in LA and Portland and detailed weather for Seattle?"
print(f"User: {query2}")
result2 = await handle_approvals(query2, agent)
print(f"\n{agent.name}: {result2}\n")
query = "Can you give me an update of the weather in LA and Portland and detailed weather for Seattle?"
print(f"User: {query}")
if is_streaming:
print(f"\n{agent.name}: ", end="", flush=True)
await handle_approvals_streaming(query, agent)
print()
else:
result = await handle_approvals(query, agent)
print(f"\n{agent.name}: {result}\n")
async def main() -> None:
print("=== Demonstration of a tool with approvals ===\n")
await run_weather_agent_with_approval()
await run_weather_agent_with_approval(is_streaming=False)
await run_weather_agent_with_approval(is_streaming=True)
if __name__ == "__main__":