diff --git a/python/packages/azure-ai/agent_framework_azure_ai/__init__.py b/python/packages/azure-ai/agent_framework_azure_ai/__init__.py index abf5531fa6..68d88b66ed 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/__init__.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/__init__.py @@ -3,7 +3,7 @@ import importlib.metadata from ._chat_client import AzureAIAgentClient, AzureAISettings -from ._chat_client_v2 import AzureAIAgentClientV2 +from ._client import AzureAIClient try: __version__ = importlib.metadata.version(__name__) @@ -12,7 +12,7 @@ __all__ = [ "AzureAIAgentClient", - "AzureAIAgentClientV2", + "AzureAIClient", "AzureAISettings", "__version__", ] diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_chat_client_v2.py b/python/packages/azure-ai/agent_framework_azure_ai/_client.py similarity index 95% rename from python/packages/azure-ai/agent_framework_azure_ai/_chat_client_v2.py rename to python/packages/azure-ai/agent_framework_azure_ai/_client.py index 5de6bc058a..90e460c0ac 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_chat_client_v2.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_client.py @@ -37,14 +37,14 @@ logger = get_logger("agent_framework.azure") -TAzureAIAgentClient = TypeVar("TAzureAIAgentClient", bound="AzureAIAgentClientV2") +TAzureAIClient = TypeVar("TAzureAIClient", bound="AzureAIClient") @use_function_invocation @use_observability @use_chat_middleware -class AzureAIAgentClientV2(OpenAIBaseResponsesClient): - """Azure AI Agent Chat client.""" +class AzureAIClient(OpenAIBaseResponsesClient): + """Azure AI Agent client.""" OTEL_PROVIDER_NAME: ClassVar[str] = "azure.ai" # type: ignore[reportIncompatibleVariableOverride, misc] @@ -121,12 +121,6 @@ def __init__( "or 'AZURE_AI_PROJECT_ENDPOINT' environment variable." ) - if not azure_ai_settings.model_deployment_name: - raise ServiceInitializationError( - "Azure AI model deployment name is required. Set via 'model_deployment_name' parameter " - "or 'AZURE_AI_MODEL_DEPLOYMENT_NAME' environment variable." - ) - # Use provided credential if not async_credential: raise ServiceInitializationError("Azure credential is required when project_client is not provided.") @@ -139,7 +133,6 @@ def __init__( # Initialize parent super().__init__( - model_id=azure_ai_settings.model_deployment_name, # type: ignore **kwargs, ) diff --git a/python/packages/azure-ai/tests/test_azure_ai_agent_client_v2.py b/python/packages/azure-ai/tests/test_azure_ai_client.py similarity index 73% rename from python/packages/azure-ai/tests/test_azure_ai_agent_client_v2.py rename to python/packages/azure-ai/tests/test_azure_ai_client.py index a37f2f61f6..b77ac69ee0 100644 --- a/python/packages/azure-ai/tests/test_azure_ai_agent_client_v2.py +++ b/python/packages/azure-ai/tests/test_azure_ai_client.py @@ -13,23 +13,23 @@ from agent_framework.exceptions import ServiceInitializationError from pydantic import ValidationError -from agent_framework_azure_ai import AzureAIAgentClientV2, AzureAISettings +from agent_framework_azure_ai import AzureAIClient, AzureAISettings -def create_test_azure_ai_client_v2( +def create_test_azure_ai_client( mock_project_client: MagicMock, agent_name: str | None = None, agent_version: str | None = None, conversation_id: str | None = None, azure_ai_settings: AzureAISettings | None = None, should_close_client: bool = False, -) -> AzureAIAgentClientV2: - """Helper function to create AzureAIAgentClientV2 instances for testing, bypassing normal validation.""" +) -> AzureAIClient: + """Helper function to create AzureAIClient instances for testing, bypassing normal validation.""" if azure_ai_settings is None: azure_ai_settings = AzureAISettings(env_file_path="test.env") # Create client instance directly - client = object.__new__(AzureAIAgentClientV2) + client = object.__new__(AzureAIClient) # Set attributes directly client.project_client = mock_project_client @@ -70,13 +70,13 @@ def test_azure_ai_settings_init_with_explicit_values() -> None: assert settings.model_deployment_name == "custom-model" -def test_azure_ai_client_v2_init_with_project_client(mock_project_client: MagicMock) -> None: - """Test AzureAIAgentClientV2 initialization with existing project_client.""" - with patch("agent_framework_azure_ai._chat_client_v2.AzureAISettings") as mock_settings: +def test_azure_ai_client_init_with_project_client(mock_project_client: MagicMock) -> None: + """Test AzureAIClient initialization with existing project_client.""" + with patch("agent_framework_azure_ai._client.AzureAISettings") as mock_settings: mock_settings.return_value.project_endpoint = None mock_settings.return_value.model_deployment_name = "test-model" - client = AzureAIAgentClientV2( + client = AzureAIClient( project_client=mock_project_client, agent_name="test-agent", agent_version="1.0", @@ -89,16 +89,16 @@ def test_azure_ai_client_v2_init_with_project_client(mock_project_client: MagicM assert isinstance(client, ChatClientProtocol) -def test_azure_ai_client_v2_init_auto_create_client( +def test_azure_ai_client_init_auto_create_client( azure_ai_unit_test_env: dict[str, str], mock_azure_credential: MagicMock, ) -> None: - """Test AzureAIAgentClientV2 initialization with auto-created project_client.""" - with patch("agent_framework_azure_ai._chat_client_v2.AIProjectClient") as mock_ai_project_client: + """Test AzureAIClient initialization with auto-created project_client.""" + with patch("agent_framework_azure_ai._client.AIProjectClient") as mock_ai_project_client: mock_project_client = MagicMock() mock_ai_project_client.return_value = mock_project_client - client = AzureAIAgentClientV2( + client = AzureAIClient( project_endpoint=azure_ai_unit_test_env["AZURE_AI_PROJECT_ENDPOINT"], model_deployment_name=azure_ai_unit_test_env["AZURE_AI_MODEL_DEPLOYMENT_NAME"], async_credential=mock_azure_credential, @@ -113,64 +113,54 @@ def test_azure_ai_client_v2_init_auto_create_client( mock_ai_project_client.assert_called_once() -def test_azure_ai_client_v2_init_missing_project_endpoint() -> None: - """Test AzureAIAgentClientV2 initialization when project_endpoint is missing and no project_client provided.""" - with patch("agent_framework_azure_ai._chat_client_v2.AzureAISettings") as mock_settings: +def test_azure_ai_client_init_missing_project_endpoint() -> None: + """Test AzureAIClient initialization when project_endpoint is missing and no project_client provided.""" + with patch("agent_framework_azure_ai._client.AzureAISettings") as mock_settings: mock_settings.return_value.project_endpoint = None mock_settings.return_value.model_deployment_name = "test-model" with pytest.raises(ServiceInitializationError, match="Azure AI project endpoint is required"): - AzureAIAgentClientV2(async_credential=MagicMock()) + AzureAIClient(async_credential=MagicMock()) -def test_azure_ai_client_v2_init_missing_model_deployment() -> None: - """Test AzureAIAgentClientV2 initialization when model deployment is missing for agent creation.""" - with patch("agent_framework_azure_ai._chat_client_v2.AzureAISettings") as mock_settings: - mock_settings.return_value.project_endpoint = "https://test.com" - mock_settings.return_value.model_deployment_name = None - - with pytest.raises(ServiceInitializationError, match="Azure AI model deployment name is required"): - AzureAIAgentClientV2(async_credential=MagicMock()) - - -def test_azure_ai_client_v2_init_missing_credential(azure_ai_unit_test_env: dict[str, str]) -> None: - """Test AzureAIAgentClientV2.__init__ when async_credential is missing and no project_client provided.""" +def test_azure_ai_client_init_missing_credential(azure_ai_unit_test_env: dict[str, str]) -> None: + """Test AzureAIClient.__init__ when async_credential is missing and no project_client provided.""" with pytest.raises( ServiceInitializationError, match="Azure credential is required when project_client is not provided" ): - AzureAIAgentClientV2( + AzureAIClient( project_endpoint=azure_ai_unit_test_env["AZURE_AI_PROJECT_ENDPOINT"], model_deployment_name=azure_ai_unit_test_env["AZURE_AI_MODEL_DEPLOYMENT_NAME"], ) -def test_azure_ai_client_v2_init_validation_error(mock_azure_credential: MagicMock) -> None: +def test_azure_ai_client_init_validation_error(mock_azure_credential: MagicMock) -> None: """Test that ValidationError in AzureAISettings is properly handled.""" - with patch("agent_framework_azure_ai._chat_client_v2.AzureAISettings") as mock_settings: + with patch("agent_framework_azure_ai._client.AzureAISettings") as mock_settings: mock_settings.side_effect = ValidationError.from_exception_data("test", []) with pytest.raises(ServiceInitializationError, match="Failed to create Azure AI settings"): - AzureAIAgentClientV2(async_credential=mock_azure_credential) + AzureAIClient(async_credential=mock_azure_credential) -async def test_azure_ai_client_v2_get_agent_reference_or_create_existing_version( +async def test_azure_ai_client_get_agent_reference_or_create_existing_version( mock_project_client: MagicMock, ) -> None: """Test _get_agent_reference_or_create when agent_version is already provided.""" - client = create_test_azure_ai_client_v2(mock_project_client, agent_name="existing-agent", agent_version="1.0") + client = create_test_azure_ai_client(mock_project_client, agent_name="existing-agent", agent_version="1.0") agent_ref = await client._get_agent_reference_or_create({}, None) # type: ignore assert agent_ref == {"name": "existing-agent", "version": "1.0", "type": "agent_reference"} -async def test_azure_ai_client_v2_get_agent_reference_or_create_new_agent( +async def test_azure_ai_client_get_agent_reference_or_create_new_agent( mock_project_client: MagicMock, azure_ai_unit_test_env: dict[str, str], ) -> None: """Test _get_agent_reference_or_create when creating a new agent.""" azure_ai_settings = AzureAISettings(model_deployment_name=azure_ai_unit_test_env["AZURE_AI_MODEL_DEPLOYMENT_NAME"]) - client = create_test_azure_ai_client_v2( + client = create_test_azure_ai_client( mock_project_client, agent_name="new-agent", azure_ai_settings=azure_ai_settings ) @@ -188,32 +178,32 @@ async def test_azure_ai_client_v2_get_agent_reference_or_create_new_agent( assert client.agent_version == "1.0" -async def test_azure_ai_client_v2_get_agent_reference_missing_model( +async def test_azure_ai_client_get_agent_reference_missing_model( mock_project_client: MagicMock, ) -> None: """Test _get_agent_reference_or_create when model is missing for agent creation.""" - client = create_test_azure_ai_client_v2(mock_project_client, agent_name="test-agent") + client = create_test_azure_ai_client(mock_project_client, agent_name="test-agent") with pytest.raises(ServiceInitializationError, match="Model deployment name is required for agent creation"): await client._get_agent_reference_or_create({}, None) # type: ignore -async def test_azure_ai_client_v2_get_conversation_id_or_create_existing( +async def test_azure_ai_client_get_conversation_id_or_create_existing( mock_project_client: MagicMock, ) -> None: """Test _get_conversation_id_or_create when conversation_id is already provided.""" - client = create_test_azure_ai_client_v2(mock_project_client, conversation_id="existing-conversation") + client = create_test_azure_ai_client(mock_project_client, conversation_id="existing-conversation") conversation_id = await client._get_conversation_id_or_create({}) # type: ignore assert conversation_id == "existing-conversation" -async def test_azure_ai_client_v2_get_conversation_id_or_create_new( +async def test_azure_ai_client_get_conversation_id_or_create_new( mock_project_client: MagicMock, ) -> None: """Test _get_conversation_id_or_create when creating a new conversation.""" - client = create_test_azure_ai_client_v2(mock_project_client) + client = create_test_azure_ai_client(mock_project_client) # Mock conversation creation response mock_conversation = MagicMock() @@ -226,11 +216,11 @@ async def test_azure_ai_client_v2_get_conversation_id_or_create_new( client.client.conversations.create.assert_called_once() -async def test_azure_ai_client_v2_prepare_input_with_system_messages( +async def test_azure_ai_client_prepare_input_with_system_messages( mock_project_client: MagicMock, ) -> None: """Test _prepare_input converts system/developer messages to instructions.""" - client = create_test_azure_ai_client_v2(mock_project_client) + client = create_test_azure_ai_client(mock_project_client) messages = [ ChatMessage(role=Role.SYSTEM, contents=[TextContent(text="You are a helpful assistant.")]), @@ -246,11 +236,11 @@ async def test_azure_ai_client_v2_prepare_input_with_system_messages( assert instructions == "You are a helpful assistant." -async def test_azure_ai_client_v2_prepare_input_no_system_messages( +async def test_azure_ai_client_prepare_input_no_system_messages( mock_project_client: MagicMock, ) -> None: """Test _prepare_input with no system/developer messages.""" - client = create_test_azure_ai_client_v2(mock_project_client) + client = create_test_azure_ai_client(mock_project_client) messages = [ ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")]), @@ -263,9 +253,9 @@ async def test_azure_ai_client_v2_prepare_input_no_system_messages( assert instructions is None -async def test_azure_ai_client_v2_prepare_options_basic(mock_project_client: MagicMock) -> None: +async def test_azure_ai_client_prepare_options_basic(mock_project_client: MagicMock) -> None: """Test prepare_options basic functionality.""" - client = create_test_azure_ai_client_v2(mock_project_client, agent_name="test-agent", agent_version="1.0") + client = create_test_azure_ai_client(mock_project_client, agent_name="test-agent", agent_version="1.0") messages = [ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")])] chat_options = ChatOptions() @@ -284,9 +274,9 @@ async def test_azure_ai_client_v2_prepare_options_basic(mock_project_client: Mag assert run_options["extra_body"]["agent"]["name"] == "test-agent" -async def test_azure_ai_client_v2_prepare_options_with_store(mock_project_client: MagicMock) -> None: +async def test_azure_ai_client_prepare_options_with_store(mock_project_client: MagicMock) -> None: """Test prepare_options with store=True creates conversation.""" - client = create_test_azure_ai_client_v2(mock_project_client, agent_name="test-agent", agent_version="1.0") + client = create_test_azure_ai_client(mock_project_client, agent_name="test-agent", agent_version="1.0") # Mock conversation creation mock_conversation = MagicMock() @@ -312,9 +302,9 @@ async def test_azure_ai_client_v2_prepare_options_with_store(mock_project_client assert run_options["conversation"] == "new-conversation-456" -async def test_azure_ai_client_v2_initialize_client(mock_project_client: MagicMock) -> None: +async def test_azure_ai_client_initialize_client(mock_project_client: MagicMock) -> None: """Test initialize_client method.""" - client = create_test_azure_ai_client_v2(mock_project_client) + client = create_test_azure_ai_client(mock_project_client) mock_openai_client = MagicMock() mock_project_client.get_openai_client = AsyncMock(return_value=mock_openai_client) @@ -325,9 +315,9 @@ async def test_azure_ai_client_v2_initialize_client(mock_project_client: MagicMo mock_project_client.get_openai_client.assert_called_once() -def test_azure_ai_client_v2_get_conversation_id_from_response(mock_project_client: MagicMock) -> None: +def test_azure_ai_client_get_conversation_id_from_response(mock_project_client: MagicMock) -> None: """Test get_conversation_id method.""" - client = create_test_azure_ai_client_v2(mock_project_client) + client = create_test_azure_ai_client(mock_project_client) # Test with conversation and store=True mock_response = MagicMock() @@ -346,9 +336,9 @@ def test_azure_ai_client_v2_get_conversation_id_from_response(mock_project_clien assert conversation_id is None -def test_azure_ai_client_v2_update_agent_name(mock_project_client: MagicMock) -> None: +def test_azure_ai_client_update_agent_name(mock_project_client: MagicMock) -> None: """Test _update_agent_name method.""" - client = create_test_azure_ai_client_v2(mock_project_client) + client = create_test_azure_ai_client(mock_project_client) # Test updating agent name when current is None with patch.object(client, "_update_agent_name") as mock_update: @@ -367,9 +357,9 @@ def test_azure_ai_client_v2_update_agent_name(mock_project_client: MagicMock) -> mock_update.assert_called_once_with(None) -async def test_azure_ai_client_v2_async_context_manager(mock_project_client: MagicMock) -> None: +async def test_azure_ai_client_async_context_manager(mock_project_client: MagicMock) -> None: """Test async context manager functionality.""" - client = create_test_azure_ai_client_v2(mock_project_client, should_close_client=True) + client = create_test_azure_ai_client(mock_project_client, should_close_client=True) mock_project_client.close = AsyncMock() @@ -380,9 +370,9 @@ async def test_azure_ai_client_v2_async_context_manager(mock_project_client: Mag mock_project_client.close.assert_called_once() -async def test_azure_ai_client_v2_close_method(mock_project_client: MagicMock) -> None: +async def test_azure_ai_client_close_method(mock_project_client: MagicMock) -> None: """Test close method.""" - client = create_test_azure_ai_client_v2(mock_project_client, should_close_client=True) + client = create_test_azure_ai_client(mock_project_client, should_close_client=True) mock_project_client.close = AsyncMock() @@ -391,9 +381,9 @@ async def test_azure_ai_client_v2_close_method(mock_project_client: MagicMock) - mock_project_client.close.assert_called_once() -async def test_azure_ai_client_v2_close_client_when_should_close_false(mock_project_client: MagicMock) -> None: +async def test_azure_ai_client_close_client_when_should_close_false(mock_project_client: MagicMock) -> None: """Test _close_client_if_needed when should_close_client is False.""" - client = create_test_azure_ai_client_v2(mock_project_client, should_close_client=False) + client = create_test_azure_ai_client(mock_project_client, should_close_client=False) mock_project_client.close = AsyncMock() @@ -403,11 +393,11 @@ async def test_azure_ai_client_v2_close_client_when_should_close_false(mock_proj mock_project_client.close.assert_not_called() -async def test_azure_ai_client_v2_agent_creation_with_instructions( +async def test_azure_ai_client_agent_creation_with_instructions( mock_project_client: MagicMock, ) -> None: """Test agent creation with combined instructions.""" - client = create_test_azure_ai_client_v2(mock_project_client, agent_name="test-agent") + client = create_test_azure_ai_client(mock_project_client, agent_name="test-agent") # Mock agent creation response mock_agent = MagicMock() @@ -425,11 +415,11 @@ async def test_azure_ai_client_v2_agent_creation_with_instructions( assert call_args[1]["definition"].instructions == "Message instructions. Option instructions. " -async def test_azure_ai_client_v2_agent_creation_with_tools( +async def test_azure_ai_client_agent_creation_with_tools( mock_project_client: MagicMock, ) -> None: """Test agent creation with tools.""" - client = create_test_azure_ai_client_v2(mock_project_client, agent_name="test-agent") + client = create_test_azure_ai_client(mock_project_client, agent_name="test-agent") # Mock agent creation response mock_agent = MagicMock() diff --git a/python/packages/core/agent_framework/azure/__init__.py b/python/packages/core/agent_framework/azure/__init__.py index e4f78cd492..23b2085cbc 100644 --- a/python/packages/core/agent_framework/azure/__init__.py +++ b/python/packages/core/agent_framework/azure/__init__.py @@ -6,7 +6,7 @@ _IMPORTS: dict[str, tuple[str, str]] = { "AzureAIAgentClient": ("agent_framework_azure_ai", "azure-ai"), - "AzureAIAgentClientV2": ("agent_framework_azure_ai", "azure-ai"), + "AzureAIClient": ("agent_framework_azure_ai", "azure-ai"), "AzureOpenAIAssistantsClient": ("agent_framework.azure._assistants_client", "core"), "AzureOpenAIChatClient": ("agent_framework.azure._chat_client", "core"), "AzureAISettings": ("agent_framework_azure_ai", "azure-ai"), diff --git a/python/packages/core/agent_framework/azure/__init__.pyi b/python/packages/core/agent_framework/azure/__init__.pyi index 140d5e6fa9..582c7a05be 100644 --- a/python/packages/core/agent_framework/azure/__init__.pyi +++ b/python/packages/core/agent_framework/azure/__init__.pyi @@ -1,6 +1,6 @@ # Copyright (c) Microsoft. All rights reserved. -from agent_framework_azure_ai import AzureAIAgentClient, AzureAIAgentClientV2, AzureAISettings +from agent_framework_azure_ai import AzureAIAgentClient, AzureAIClient, AzureAISettings from agent_framework.azure._assistants_client import AzureOpenAIAssistantsClient from agent_framework.azure._chat_client import AzureOpenAIChatClient @@ -10,7 +10,7 @@ from agent_framework.azure._shared import AzureOpenAISettings __all__ = [ "AzureAIAgentClient", - "AzureAIAgentClientV2", + "AzureAIClient", "AzureAISettings", "AzureOpenAIAssistantsClient", "AzureOpenAIChatClient", diff --git a/python/packages/core/agent_framework/openai/_responses_client.py b/python/packages/core/agent_framework/openai/_responses_client.py index 22be93428e..83a7cb8098 100644 --- a/python/packages/core/agent_framework/openai/_responses_client.py +++ b/python/packages/core/agent_framework/openai/_responses_client.py @@ -338,6 +338,8 @@ async def prepare_options( # model id if not run_options.get("model"): + if not self.model_id: + raise ValueError("model_id must be a non-empty string") run_options["model"] = self.model_id # messages diff --git a/python/packages/core/agent_framework/openai/_shared.py b/python/packages/core/agent_framework/openai/_shared.py index 38995eb0e6..bd7c2ccadd 100644 --- a/python/packages/core/agent_framework/openai/_shared.py +++ b/python/packages/core/agent_framework/openai/_shared.py @@ -127,18 +127,18 @@ class OpenAIBase(SerializationMixin): INJECTABLE: ClassVar[set[str]] = {"client"} - def __init__(self, *, model_id: str, client: AsyncOpenAI | None = None, **kwargs: Any) -> None: + def __init__(self, *, model_id: str | None = None, client: AsyncOpenAI | None = None, **kwargs: Any) -> None: """Initialize OpenAIBase. Keyword Args: client: The AsyncOpenAI client instance. - model_id: The AI model ID to use (non-empty, whitespace stripped). + model_id: The AI model ID to use. **kwargs: Additional keyword arguments. """ - if not model_id or not model_id.strip(): - raise ValueError("model_id must be a non-empty string") self.client = client - self.model_id = model_id.strip() + self.model_id = None + if model_id: + self.model_id = model_id.strip() # Call super().__init__() to continue MRO chain (e.g., BaseChatClient) # Extract known kwargs that belong to other base classes diff --git a/python/packages/core/tests/openai/test_openai_responses_client.py b/python/packages/core/tests/openai/test_openai_responses_client.py index cb4f0dc0d3..1b044c99be 100644 --- a/python/packages/core/tests/openai/test_openai_responses_client.py +++ b/python/packages/core/tests/openai/test_openai_responses_client.py @@ -2075,27 +2075,27 @@ def test_create_response_content_image_generation_fallback(): assert f"data:image/png;base64,{unrecognized_base64}" == content.uri -def test_prepare_options_store_parameter_handling() -> None: +async def test_prepare_options_store_parameter_handling() -> None: client = OpenAIResponsesClient(model_id="test-model", api_key="test-key") messages = [ChatMessage(role="user", text="Test message")] test_conversation_id = "test-conversation-123" chat_options = ChatOptions(store=True, conversation_id=test_conversation_id) - options = client._prepare_options(messages, chat_options) # type: ignore + options = await client.prepare_options(messages, chat_options) # type: ignore assert options["store"] is True assert options["previous_response_id"] == test_conversation_id chat_options = ChatOptions(store=False, conversation_id="") - options = client._prepare_options(messages, chat_options) # type: ignore + options = await client.prepare_options(messages, chat_options) # type: ignore assert options["store"] is False chat_options = ChatOptions(store=None, conversation_id=None) - options = client._prepare_options(messages, chat_options) # type: ignore + options = await client.prepare_options(messages, chat_options) # type: ignore assert options["store"] is False assert "previous_response_id" not in options chat_options = ChatOptions() - options = client._prepare_options(messages, chat_options) # type: ignore + options = await client.prepare_options(messages, chat_options) # type: ignore assert options["store"] is False assert "previous_response_id" not in options diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_basic.py b/python/samples/getting_started/agents/azure_ai/azure_ai_basic.py index 633b5b9daa..1517ed8f60 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_basic.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_basic.py @@ -4,15 +4,15 @@ from random import randint from typing import Annotated -from agent_framework.azure import AzureAIAgentClient +from agent_framework.azure import AzureAIClient from azure.identity.aio import AzureCliCredential from pydantic import Field """ Azure AI Agent Basic Example -This sample demonstrates basic usage of AzureAIAgentClient to create agents with automatic -lifecycle management. Shows both streaming and non-streaming responses with function tools. +This sample demonstrates basic usage of AzureAIAgentClient. +Shows both streaming and non-streaming responses with function tools. """ @@ -28,14 +28,13 @@ async def non_streaming_example() -> None: """Example of non-streaming response (get the complete result at once).""" print("=== Non-streaming Response Example ===") - # Since no Agent ID is provided, the agent will be automatically created - # and deleted after getting a response + # Since no Agent ID is provided, the agent will be automatically created. # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred # authentication option. async with ( AzureCliCredential() as credential, - AzureAIAgentClient(async_credential=credential).create_agent( - name="WeatherAgent", + AzureAIClient(async_credential=credential).create_agent( + name="BasicWeatherAgent", instructions="You are a helpful weather agent.", tools=get_weather, ) as agent, @@ -50,14 +49,13 @@ async def streaming_example() -> None: """Example of streaming response (get results as they are generated).""" print("=== Streaming Response Example ===") - # Since no Agent ID is provided, the agent will be automatically created - # and deleted after getting a response + # Since no Agent ID is provided, the agent will be automatically created. # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred # authentication option. async with ( AzureCliCredential() as credential, - AzureAIAgentClient(async_credential=credential).create_agent( - name="WeatherAgent", + AzureAIClient(async_credential=credential).create_agent( + name="BasicWeatherAgent", instructions="You are a helpful weather agent.", tools=get_weather, ) as agent, diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_thread.py b/python/samples/getting_started/agents/azure_ai/azure_ai_with_thread.py index e2dd175657..310f5c8eee 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_with_thread.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_with_thread.py @@ -4,16 +4,16 @@ from random import randint from typing import Annotated -from agent_framework import AgentThread, ChatAgent -from agent_framework.azure import AzureAIAgentClient +from agent_framework import AgentThread +from agent_framework.azure import AzureAIClient from azure.identity.aio import AzureCliCredential from pydantic import Field """ Azure AI Agent with Thread Management Example -This sample demonstrates thread management with Azure AI Agents, comparing -automatic thread creation with explicit thread management for persistent context. +This sample demonstrates thread management with Azure AI Agent, showing +persistent conversation context and simplified response handling. """ @@ -26,44 +26,42 @@ def get_weather( async def example_with_automatic_thread_creation() -> None: - """Example showing automatic thread creation (service-managed thread).""" + """Example showing automatic thread creation.""" print("=== Automatic Thread Creation Example ===") - # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred - # authentication option. async with ( AzureCliCredential() as credential, - ChatAgent( - chat_client=AzureAIAgentClient(async_credential=credential), + AzureAIClient(async_credential=credential).create_agent( + name="BasicWeatherAgent", instructions="You are a helpful weather agent.", tools=get_weather, ) as agent, ): # First conversation - no thread provided, will be created automatically - first_query = "What's the weather like in Seattle?" - print(f"User: {first_query}") - first_result = await agent.run(first_query) - print(f"Agent: {first_result.text}") + 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 - second_query = "What was the last city I asked about?" - print(f"\nUser: {second_query}") - second_result = await agent.run(second_query) - print(f"Agent: {second_result.text}") + 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() -> None: - """Example showing thread persistence across multiple conversations.""" - print("=== Thread Persistence Example ===") - print("Using the same thread across multiple conversations to maintain 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) ===") - # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred - # authentication option. async with ( AzureCliCredential() as credential, - ChatAgent( - chat_client=AzureAIAgentClient(async_credential=credential), + AzureAIClient(async_credential=credential).create_agent( + name="BasicWeatherAgent", instructions="You are a helpful weather agent.", tools=get_weather, ) as agent, @@ -72,81 +70,81 @@ async def example_with_thread_persistence() -> None: thread = agent.get_new_thread() # First conversation - first_query = "What's the weather like in Tokyo?" - print(f"User: {first_query}") - first_result = await agent.run(first_query, thread=thread) - print(f"Agent: {first_result.text}") + query1 = "What's the weather like in Tokyo?" + print(f"User: {query1}") + result1 = await agent.run(query1, thread=thread) + print(f"Agent: {result1.text}") # Second conversation using the same thread - maintains context - second_query = "How about London?" - print(f"\nUser: {second_query}") - second_result = await agent.run(second_query, thread=thread) - print(f"Agent: {second_result.text}") + query2 = "How about London?" + print(f"\nUser: {query2}") + result2 = await agent.run(query2, thread=thread) + print(f"Agent: {result2.text}") # Third conversation - agent should remember both previous cities - third_query = "Which of the cities I asked about has better weather?" - print(f"\nUser: {third_query}") - third_result = await agent.run(third_query, thread=thread) - print(f"Agent: {third_result.text}") + 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("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.""" + """ + Example showing how to work with an existing thread ID from the service. + In this example, messages are stored on the server using Azure AI conversation state. + """ print("=== Existing Thread ID Example ===") - print("Using a specific thread ID to continue an existing conversation.\n") # First, create a conversation and capture the thread ID existing_thread_id = None - # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred - # authentication option. async with ( AzureCliCredential() as credential, - ChatAgent( - chat_client=AzureAIAgentClient(async_credential=credential), + AzureAIClient(async_credential=credential).create_agent( + name="BasicWeatherAgent", instructions="You are a helpful weather agent.", tools=get_weather, ) as agent, ): # Start a conversation and get the thread ID thread = agent.get_new_thread() - first_query = "What's the weather in Paris?" - print(f"User: {first_query}") - first_result = await agent.run(first_query, thread=thread) - print(f"Agent: {first_result.text}") + + query1 = "What's the weather in Paris?" + print(f"User: {query1}") + # Enable Azure AI conversation state by setting `store` parameter to True + result1 = await agent.run(query1, thread=thread, store=True) + print(f"Agent: {result1.text}") # The thread ID is set after the first response existing_thread_id = thread.service_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 ---") + if existing_thread_id: + print("\n--- Continuing with the same thread ID in a new agent instance ---") - # Create a new agent instance but use the existing thread ID - async with ( - AzureCliCredential() as credential, - ChatAgent( - chat_client=AzureAIAgentClient(thread_id=existing_thread_id, async_credential=credential), - instructions="You are a helpful weather agent.", - tools=get_weather, - ) as agent, - ): - # Create a thread with the existing ID - thread = AgentThread(service_thread_id=existing_thread_id) + async with ( + AzureAIClient(async_credential=credential).create_agent( + name="BasicWeatherAgent", + instructions="You are a helpful weather agent.", + tools=get_weather, + ) as agent, + ): + # Create a thread with the existing ID + thread = AgentThread(service_thread_id=existing_thread_id) - second_query = "What was the last city I asked about?" - print(f"User: {second_query}") - second_result = await agent.run(second_query, thread=thread) - print(f"Agent: {second_result.text}") - print("Note: The agent continues the conversation from the previous thread.\n") + 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("Note: The agent continues the conversation from the previous thread by using thread ID.\n") async def main() -> None: - print("=== Azure AI Chat Client Agent Thread Management Examples ===\n") + print("=== Azure AI Agent Thread Management Examples ===\n") await example_with_automatic_thread_creation() - await example_with_thread_persistence() + await example_with_thread_persistence_in_memory() await example_with_existing_thread_id() diff --git a/python/samples/getting_started/agents/azure_ai/README.md b/python/samples/getting_started/agents/azure_ai_agent/README.md similarity index 100% rename from python/samples/getting_started/agents/azure_ai/README.md rename to python/samples/getting_started/agents/azure_ai_agent/README.md diff --git a/python/samples/getting_started/agents/azure_ai_v2/azure_ai_basic.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_basic.py similarity index 80% rename from python/samples/getting_started/agents/azure_ai_v2/azure_ai_basic.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_basic.py index b0ea6c7871..633b5b9daa 100644 --- a/python/samples/getting_started/agents/azure_ai_v2/azure_ai_basic.py +++ b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_basic.py @@ -4,15 +4,15 @@ from random import randint from typing import Annotated -from agent_framework.azure import AzureAIAgentClientV2 +from agent_framework.azure import AzureAIAgentClient from azure.identity.aio import AzureCliCredential from pydantic import Field """ Azure AI Agent Basic Example -This sample demonstrates basic usage of AzureAIAgentClient. -Shows both streaming and non-streaming responses with function tools. +This sample demonstrates basic usage of AzureAIAgentClient to create agents with automatic +lifecycle management. Shows both streaming and non-streaming responses with function tools. """ @@ -28,13 +28,14 @@ async def non_streaming_example() -> None: """Example of non-streaming response (get the complete result at once).""" print("=== Non-streaming Response Example ===") - # Since no Agent ID is provided, the agent will be automatically created. + # Since no Agent ID is provided, the agent will be automatically created + # and deleted after getting a response # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred # authentication option. async with ( AzureCliCredential() as credential, - AzureAIAgentClientV2(async_credential=credential).create_agent( - name="BasicWeatherAgent", + AzureAIAgentClient(async_credential=credential).create_agent( + name="WeatherAgent", instructions="You are a helpful weather agent.", tools=get_weather, ) as agent, @@ -49,13 +50,14 @@ async def streaming_example() -> None: """Example of streaming response (get results as they are generated).""" print("=== Streaming Response Example ===") - # Since no Agent ID is provided, the agent will be automatically created. + # Since no Agent ID is provided, the agent will be automatically created + # and deleted after getting a response # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred # authentication option. async with ( AzureCliCredential() as credential, - AzureAIAgentClientV2(async_credential=credential).create_agent( - name="BasicWeatherAgent", + AzureAIAgentClient(async_credential=credential).create_agent( + name="WeatherAgent", instructions="You are a helpful weather agent.", tools=get_weather, ) as agent, diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_azure_ai_search.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_azure_ai_search.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_azure_ai_search.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_azure_ai_search.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_bing_grounding.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_bing_grounding.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_bing_grounding.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_bing_grounding.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_code_interpreter.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_code_interpreter.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_code_interpreter.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_existing_agent.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_existing_agent.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_existing_agent.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_existing_agent.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_existing_thread.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_existing_thread.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_existing_thread.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_existing_thread.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_explicit_settings.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_explicit_settings.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_explicit_settings.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_explicit_settings.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_file_search.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_file_search.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_file_search.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_file_search.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_function_tools.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_function_tools.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_function_tools.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_function_tools.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_hosted_mcp.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_hosted_mcp.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_hosted_mcp.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_hosted_mcp.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_local_mcp.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_local_mcp.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_local_mcp.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_local_mcp.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_multiple_tools.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_multiple_tools.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_multiple_tools.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_multiple_tools.py diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_openapi_tools.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_openapi_tools.py similarity index 100% rename from python/samples/getting_started/agents/azure_ai/azure_ai_with_openapi_tools.py rename to python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_openapi_tools.py diff --git a/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_thread.py b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_thread.py new file mode 100644 index 0000000000..e2dd175657 --- /dev/null +++ b/python/samples/getting_started/agents/azure_ai_agent/azure_ai_with_thread.py @@ -0,0 +1,154 @@ +# Copyright (c) Microsoft. All rights reserved. + +import asyncio +from random import randint +from typing import Annotated + +from agent_framework import AgentThread, ChatAgent +from agent_framework.azure import AzureAIAgentClient +from azure.identity.aio import AzureCliCredential +from pydantic import Field + +""" +Azure AI Agent with Thread Management Example + +This sample demonstrates thread management with Azure AI Agents, comparing +automatic thread creation with explicit thread management for persistent context. +""" + + +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 (service-managed thread).""" + print("=== Automatic Thread Creation Example ===") + + # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred + # authentication option. + async with ( + AzureCliCredential() as credential, + ChatAgent( + chat_client=AzureAIAgentClient(async_credential=credential), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) as agent, + ): + # First conversation - no thread provided, will be created automatically + first_query = "What's the weather like in Seattle?" + print(f"User: {first_query}") + first_result = await agent.run(first_query) + print(f"Agent: {first_result.text}") + + # Second conversation - still no thread provided, will create another new thread + second_query = "What was the last city I asked about?" + print(f"\nUser: {second_query}") + second_result = await agent.run(second_query) + print(f"Agent: {second_result.text}") + print("Note: Each call creates a separate thread, so the agent doesn't remember previous context.\n") + + +async def example_with_thread_persistence() -> None: + """Example showing thread persistence across multiple conversations.""" + print("=== Thread Persistence Example ===") + print("Using the same thread across multiple conversations to maintain context.\n") + + # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred + # authentication option. + async with ( + AzureCliCredential() as credential, + ChatAgent( + chat_client=AzureAIAgentClient(async_credential=credential), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) as agent, + ): + # Create a new thread that will be reused + thread = agent.get_new_thread() + + # First conversation + first_query = "What's the weather like in Tokyo?" + print(f"User: {first_query}") + first_result = await agent.run(first_query, thread=thread) + print(f"Agent: {first_result.text}") + + # Second conversation using the same thread - maintains context + second_query = "How about London?" + print(f"\nUser: {second_query}") + second_result = await agent.run(second_query, thread=thread) + print(f"Agent: {second_result.text}") + + # Third conversation - agent should remember both previous cities + third_query = "Which of the cities I asked about has better weather?" + print(f"\nUser: {third_query}") + third_result = await agent.run(third_query, thread=thread) + print(f"Agent: {third_result.text}") + 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.""" + print("=== Existing Thread ID Example ===") + print("Using a specific thread ID to continue an existing conversation.\n") + + # First, create a conversation and capture the thread ID + existing_thread_id = None + + # For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred + # authentication option. + async with ( + AzureCliCredential() as credential, + ChatAgent( + chat_client=AzureAIAgentClient(async_credential=credential), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) as agent, + ): + # Start a conversation and get the thread ID + thread = agent.get_new_thread() + first_query = "What's the weather in Paris?" + print(f"User: {first_query}") + first_result = await agent.run(first_query, thread=thread) + print(f"Agent: {first_result.text}") + + # The thread ID is set after the first response + existing_thread_id = thread.service_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 ---") + + # Create a new agent instance but use the existing thread ID + async with ( + AzureCliCredential() as credential, + ChatAgent( + chat_client=AzureAIAgentClient(thread_id=existing_thread_id, async_credential=credential), + instructions="You are a helpful weather agent.", + tools=get_weather, + ) as agent, + ): + # Create a thread with the existing ID + thread = AgentThread(service_thread_id=existing_thread_id) + + second_query = "What was the last city I asked about?" + print(f"User: {second_query}") + second_result = await agent.run(second_query, thread=thread) + print(f"Agent: {second_result.text}") + print("Note: The agent continues the conversation from the previous thread.\n") + + +async def main() -> None: + print("=== Azure AI Chat Client Agent Thread Management Examples ===\n") + + await example_with_automatic_thread_creation() + await example_with_thread_persistence() + await example_with_existing_thread_id() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/samples/getting_started/agents/azure_ai_v2/azure_ai_with_thread.py b/python/samples/getting_started/agents/azure_ai_v2/azure_ai_with_thread.py deleted file mode 100644 index 147b523beb..0000000000 --- a/python/samples/getting_started/agents/azure_ai_v2/azure_ai_with_thread.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright (c) Microsoft. All rights reserved. - -import asyncio -from random import randint -from typing import Annotated - -from agent_framework import AgentThread -from agent_framework.azure import AzureAIAgentClientV2 -from azure.identity.aio import AzureCliCredential -from pydantic import Field - -""" -Azure AI Agent with Thread Management Example - -This sample demonstrates thread management with Azure AI Agent, showing -persistent conversation context and simplified response handling. -""" - - -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 ===") - - async with ( - AzureCliCredential() as credential, - AzureAIAgentClientV2(async_credential=credential).create_agent( - name="BasicWeatherAgent", - instructions="You are a helpful weather agent.", - tools=get_weather, - ) as agent, - ): - # 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) ===") - - async with ( - AzureCliCredential() as credential, - AzureAIAgentClientV2(async_credential=credential).create_agent( - name="BasicWeatherAgent", - instructions="You are a helpful weather agent.", - tools=get_weather, - ) as agent, - ): - # Create a new thread that will be reused - thread = agent.get_new_thread() - - # 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}") - - # 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}") - - # 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("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 AI conversation state. - """ - print("=== Existing Thread ID Example ===") - - # First, create a conversation and capture the thread ID - existing_thread_id = None - - async with ( - AzureCliCredential() as credential, - AzureAIAgentClientV2(async_credential=credential).create_agent( - name="BasicWeatherAgent", - instructions="You are a helpful weather agent.", - tools=get_weather, - ) as agent, - ): - # Start a conversation and get the thread ID - thread = agent.get_new_thread() - - query1 = "What's the weather in Paris?" - print(f"User: {query1}") - # Enable Azure AI conversation state by setting `store` parameter to True - result1 = await agent.run(query1, thread=thread, store=True) - print(f"Agent: {result1.text}") - - # The thread ID is set after the first response - existing_thread_id = thread.service_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 ---") - - async with ( - AzureAIAgentClientV2(async_credential=credential).create_agent( - name="BasicWeatherAgent", - instructions="You are a helpful weather agent.", - tools=get_weather, - ) as agent, - ): - # Create a thread with the existing ID - thread = AgentThread(service_thread_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("Note: The agent continues the conversation from the previous thread by using thread ID.\n") - - -async def main() -> None: - print("=== Azure AI 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())