diff --git a/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_basic.py b/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_basic.py new file mode 100644 index 0000000000..1d717fff00 --- /dev/null +++ b/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_basic.py @@ -0,0 +1,63 @@ +# Copyright (c) Microsoft. All rights reserved. + +import asyncio +from random import randint +from typing import Annotated + +from agent_framework import ChatClientAgent +from agent_framework.azure import AzureResponsesClient +from pydantic import Field + + +def get_weather( + location: Annotated[str, Field(description="The location to get the weather for.")], +) -> str: + """Get the weather for a given location.""" + conditions = ["sunny", "cloudy", "rainy", "stormy"] + return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C." + + +async def non_streaming_example() -> None: + """Example of non-streaming response (get the complete result at once).""" + print("=== Non-streaming Response Example ===") + + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) + + query = "What's the weather like in Seattle?" + print(f"User: {query}") + result = await agent.run(query) + print(f"Result: {result}\n") + + +async def streaming_example() -> None: + """Example of streaming response (get results as they are generated).""" + print("=== Streaming Response Example ===") + + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) + + query = "What's the weather like in Portland?" + print(f"User: {query}") + print("Agent: ", end="", flush=True) + async for chunk in agent.run_streaming(query): + if chunk.text: + print(chunk.text, end="", flush=True) + print("\n") + + +async def main() -> None: + print("=== Basic Azure OpenAI Responses Client Agent Example ===") + + await non_streaming_example() + await streaming_example() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_code_interpreter.py b/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_code_interpreter.py new file mode 100644 index 0000000000..2fa186ca11 --- /dev/null +++ b/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_code_interpreter.py @@ -0,0 +1,38 @@ +# Copyright (c) Microsoft. All rights reserved. + +import asyncio + +from agent_framework import ChatClientAgent, ChatResponse, HostedCodeInterpreterTool +from agent_framework.azure import AzureResponsesClient +from openai.types.responses.response import Response as OpenAIResponse +from openai.types.responses.response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall + + +async def main() -> None: + """Example showing how to use the HostedCodeInterpreterTool with Azure OpenAI Responses.""" + print("=== Azure OpenAI Responses Agent with Code Interpreter Example ===") + + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful assistant that can write and execute Python code to solve problems.", + tools=HostedCodeInterpreterTool(), + ) + + query = "Use code to calculate the factorial of 100?" + print(f"User: {query}") + result = await agent.run(query) + print(f"Result: {result}\n") + + if ( + isinstance(result.raw_representation, ChatResponse) + and isinstance(result.raw_representation.raw_representation, OpenAIResponse) + and len(result.raw_representation.raw_representation.output) > 0 + and isinstance(result.raw_representation.raw_representation.output[0], ResponseCodeInterpreterToolCall) + ): + generated_code = result.raw_representation.raw_representation.output[0].code + + print(f"Generated code:\n{generated_code}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_function_tools.py b/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_function_tools.py new file mode 100644 index 0000000000..96ec5df5c5 --- /dev/null +++ b/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_function_tools.py @@ -0,0 +1,120 @@ +# Copyright (c) Microsoft. All rights reserved. + +import asyncio +from datetime import datetime, timezone +from random import randint +from typing import Annotated + +from agent_framework import ChatClientAgent +from agent_framework.azure import AzureResponsesClient +from pydantic import Field + + +def get_weather( + location: Annotated[str, Field(description="The location to get the weather for.")], +) -> str: + """Get the weather for a given location.""" + conditions = ["sunny", "cloudy", "rainy", "stormy"] + return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C." + + +def get_time() -> str: + """Get the current UTC time.""" + current_time = datetime.now(timezone.utc) + return f"The current UTC time is {current_time.strftime('%Y-%m-%d %H:%M:%S')}." + + +async def tools_on_agent_level() -> None: + """Example showing tools defined when creating the agent.""" + print("=== Tools Defined on Agent Level ===") + + # Tools are provided when creating the agent + # The agent can use these tools for any query during its lifetime + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful assistant that can provide weather and time information.", + tools=[get_weather, get_time], # Tools defined at agent creation + ) + + # First query - agent can use weather tool + query1 = "What's the weather like in New York?" + print(f"User: {query1}") + result1 = await agent.run(query1) + print(f"Agent: {result1}\n") + + # Second query - agent can use time tool + query2 = "What's the current UTC time?" + print(f"User: {query2}") + result2 = await agent.run(query2) + print(f"Agent: {result2}\n") + + # Third query - agent can use both tools if needed + query3 = "What's the weather in London and what's the current UTC time?" + print(f"User: {query3}") + result3 = await agent.run(query3) + print(f"Agent: {result3}\n") + + +async def tools_on_run_level() -> None: + """Example showing tools passed to the run method.""" + print("=== Tools Passed to Run Method ===") + + # Agent created without tools + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful assistant.", + # No tools defined here + ) + + # First query with weather tool + query1 = "What's the weather like in Seattle?" + print(f"User: {query1}") + result1 = await agent.run(query1, tools=[get_weather]) # Tool passed to run method + print(f"Agent: {result1}\n") + + # Second query with time tool + query2 = "What's the current UTC time?" + print(f"User: {query2}") + result2 = await agent.run(query2, tools=[get_time]) # Different tool for this query + print(f"Agent: {result2}\n") + + # Third query with multiple tools + query3 = "What's the weather in Chicago and what's the current UTC time?" + print(f"User: {query3}") + result3 = await agent.run(query3, tools=[get_weather, get_time]) # Multiple tools + print(f"Agent: {result3}\n") + + +async def mixed_tools_example() -> None: + """Example showing both agent-level tools and run-method tools.""" + print("=== Mixed Tools Example (Agent + Run Method) ===") + + # Agent created with some base tools + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a comprehensive assistant that can help with various information requests.", + tools=[get_weather], # Base tool available for all queries + ) + + # Query using both agent tool and additional run-method tools + query = "What's the weather in Denver and what's the current UTC time?" + print(f"User: {query}") + + # Agent has access to get_weather (from creation) + additional tools from run method + result = await agent.run( + query, + tools=[get_time], # Additional tools for this specific query + ) + print(f"Agent: {result}\n") + + +async def main() -> None: + print("=== Azure OpenAI Responses Client Agent with Function Tools Examples ===\n") + + await tools_on_agent_level() + await tools_on_run_level() + await mixed_tools_example() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_thread.py b/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_thread.py new file mode 100644 index 0000000000..bd22c3a49c --- /dev/null +++ b/python/samples/getting_started/agents/azure_responses_client/azure_responses_client_with_thread.py @@ -0,0 +1,144 @@ +# Copyright (c) Microsoft. All rights reserved. + +import asyncio +from random import randint +from typing import Annotated + +from agent_framework import ChatClientAgent, ChatClientAgentThread +from agent_framework.azure import AzureResponsesClient +from pydantic import Field + + +def get_weather( + location: Annotated[str, Field(description="The location to get the weather for.")], +) -> str: + """Get the weather for a given location.""" + conditions = ["sunny", "cloudy", "rainy", "stormy"] + return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C." + + +async def example_with_automatic_thread_creation() -> None: + """Example showing automatic thread creation.""" + print("=== Automatic Thread Creation Example ===") + + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) + + # First conversation - no thread provided, will be created automatically + query1 = "What's the weather like in Seattle?" + print(f"User: {query1}") + result1 = await agent.run(query1) + print(f"Agent: {result1.text}") + + # Second conversation - still no thread provided, will create another new thread + query2 = "What was the last city I asked about?" + print(f"\nUser: {query2}") + result2 = await agent.run(query2) + print(f"Agent: {result2.text}") + print("Note: Each call creates a separate thread, so the agent doesn't remember previous context.\n") + + +async def example_with_thread_persistence_in_memory() -> None: + """ + Example showing thread persistence across multiple conversations. + In this example, messages are stored in-memory. + """ + print("=== Thread Persistence Example (In-Memory) ===") + + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) + + # Create a new thread that will be reused + thread = agent.get_new_thread() + assert isinstance(thread, ChatClientAgentThread) + + # First conversation + query1 = "What's the weather like in Tokyo?" + print(f"User: {query1}") + result1 = await agent.run(query1, thread=thread) + print(f"Agent: {result1.text}") + print(f"Thread contains {len(thread.chat_messages or [])} messages in-memory.") + + # Second conversation using the same thread - maintains context + query2 = "How about London?" + print(f"\nUser: {query2}") + result2 = await agent.run(query2, thread=thread) + print(f"Agent: {result2.text}") + print(f"Thread contains {len(thread.chat_messages or [])} messages in-memory.") + + # Third conversation - agent should remember both previous cities + query3 = "Which of the cities I asked about has better weather?" + print(f"\nUser: {query3}") + result3 = await agent.run(query3, thread=thread) + print(f"Agent: {result3.text}") + print(f"Thread contains {len(thread.chat_messages or [])} messages in-memory.") + print("Note: The agent remembers context from previous messages in the same thread.\n") + + +async def example_with_existing_thread_id() -> None: + """ + Example showing how to work with an existing thread ID from the service. + In this example, messages are stored on the server using Azure OpenAI conversation state. + """ + print("=== Existing Thread ID Example ===") + + # First, create a conversation and capture the thread ID + existing_thread_id = None + + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) + + # Start a conversation and get the thread ID + thread = agent.get_new_thread() + assert isinstance(thread, ChatClientAgentThread) + + query1 = "What's the weather in Paris?" + print(f"User: {query1}") + # Enable Azure OpenAI conversation state by setting `store` parameter to True + result1 = await agent.run(query1, thread=thread, store=True) + print(f"Agent: {result1.text}") + print(f"Thread contains {len(thread.chat_messages or [])} messages in-memory.") + + # The thread ID is set after the first response + existing_thread_id = thread.id + print(f"Thread ID: {existing_thread_id}") + + if existing_thread_id: + print("\n--- Continuing with the same thread ID in a new agent instance ---") + + agent = ChatClientAgent( + chat_client=AzureResponsesClient(), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) + + # Create a thread with the existing ID + thread = ChatClientAgentThread(id=existing_thread_id) + + query2 = "What was the last city I asked about?" + print(f"User: {query2}") + result2 = await agent.run(query2, thread=thread, store=True) + print(f"Agent: {result2.text}") + print(f"Thread contains {len(thread.chat_messages or [])} messages in-memory.") + print("Note: The agent continues the conversation from the previous thread by using thread ID.\n") + + +async def main() -> None: + print("=== Azure OpenAI Response Client Agent Thread Management Examples ===\n") + + await example_with_automatic_thread_creation() + await example_with_thread_persistence_in_memory() + await example_with_existing_thread_id() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/samples/getting_started/agents/openai_responses_client/openai_responses_client_with_thread.py b/python/samples/getting_started/agents/openai_responses_client/openai_responses_client_with_thread.py index 2e7f0b6b22..8c735c9361 100644 --- a/python/samples/getting_started/agents/openai_responses_client/openai_responses_client_with_thread.py +++ b/python/samples/getting_started/agents/openai_responses_client/openai_responses_client_with_thread.py @@ -129,7 +129,7 @@ async def example_with_existing_thread_id() -> None: result2 = await agent.run(query2, thread=thread, store=True) print(f"Agent: {result2.text}") print(f"Thread contains {len(thread.chat_messages or [])} messages in-memory.") - print("Note: The agent continues the conversation from the previous thread.\n") + print("Note: The agent continues the conversation from the previous thread by using thread ID.\n") async def main() -> None: