mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Added support for application endpoints in Azure AI client (#2460)
* Added support for application endpoints in Azure AI client * Fixed tests * Update python/samples/getting_started/agents/azure_ai/azure_ai_with_application_endpoint.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Addressed comments --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
0c1d12feca
commit
5d8be5836c
@@ -155,7 +155,11 @@ class AzureAIClient(OpenAIBaseResponsesClient):
|
||||
self.credential = async_credential
|
||||
self.model_id = azure_ai_settings.model_deployment_name
|
||||
self.conversation_id = conversation_id
|
||||
self._should_close_client = should_close_client # Track whether we should close client connection
|
||||
|
||||
# Track whether the application endpoint is used
|
||||
self._is_application_endpoint = "/applications/" in project_client._config.endpoint # type: ignore
|
||||
# Track whether we should close client connection
|
||||
self._should_close_client = should_close_client
|
||||
|
||||
async def setup_azure_ai_observability(self, enable_sensitive_data: bool | None = None) -> None:
|
||||
"""Use this method to setup tracing in your Azure AI Project.
|
||||
@@ -316,9 +320,11 @@ class AzureAIClient(OpenAIBaseResponsesClient):
|
||||
"""Take ChatOptions and create the specific options for Azure AI."""
|
||||
prepared_messages, instructions = self._prepare_input(messages)
|
||||
run_options = await super().prepare_options(prepared_messages, chat_options, **kwargs)
|
||||
agent_reference = await self._get_agent_reference_or_create(run_options, instructions)
|
||||
|
||||
run_options["extra_body"] = {"agent": agent_reference}
|
||||
if not self._is_application_endpoint:
|
||||
# Application-scoped response APIs do not support "agent" property.
|
||||
agent_reference = await self._get_agent_reference_or_create(run_options, instructions)
|
||||
run_options["extra_body"] = {"agent": agent_reference}
|
||||
|
||||
conversation_id = chat_options.conversation_id or self.conversation_id
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ def create_test_azure_ai_client(
|
||||
client.use_latest_version = use_latest_version
|
||||
client.model_id = azure_ai_settings.model_deployment_name
|
||||
client.conversation_id = conversation_id
|
||||
client._is_application_endpoint = False # type: ignore
|
||||
client._should_close_client = should_close_client # type: ignore
|
||||
client.additional_properties = {}
|
||||
client.middleware = None
|
||||
@@ -305,6 +306,84 @@ async def test_azure_ai_client_prepare_options_basic(mock_project_client: MagicM
|
||||
assert run_options["extra_body"]["agent"]["name"] == "test-agent"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"endpoint,expects_agent",
|
||||
[
|
||||
("https://example.com/api/projects/my-project/applications/my-application/protocols", False),
|
||||
("https://example.com/api/projects/my-project", True),
|
||||
],
|
||||
)
|
||||
async def test_azure_ai_client_prepare_options_with_application_endpoint(
|
||||
mock_azure_credential: MagicMock, endpoint: str, expects_agent: bool
|
||||
) -> None:
|
||||
client = AzureAIClient(
|
||||
project_endpoint=endpoint,
|
||||
model_deployment_name="test-model",
|
||||
async_credential=mock_azure_credential,
|
||||
agent_name="test-agent",
|
||||
agent_version="1",
|
||||
)
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")])]
|
||||
chat_options = ChatOptions()
|
||||
|
||||
with (
|
||||
patch.object(client.__class__.__bases__[0], "prepare_options", return_value={"model": "test-model"}),
|
||||
patch.object(
|
||||
client,
|
||||
"_get_agent_reference_or_create",
|
||||
return_value={"name": "test-agent", "version": "1", "type": "agent_reference"},
|
||||
),
|
||||
):
|
||||
run_options = await client.prepare_options(messages, chat_options)
|
||||
|
||||
if expects_agent:
|
||||
assert "extra_body" in run_options
|
||||
assert run_options["extra_body"]["agent"]["name"] == "test-agent"
|
||||
else:
|
||||
assert "extra_body" not in run_options
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"endpoint,expects_agent",
|
||||
[
|
||||
("https://example.com/api/projects/my-project/applications/my-application/protocols", False),
|
||||
("https://example.com/api/projects/my-project", True),
|
||||
],
|
||||
)
|
||||
async def test_azure_ai_client_prepare_options_with_application_project_client(
|
||||
mock_project_client: MagicMock, endpoint: str, expects_agent: bool
|
||||
) -> None:
|
||||
mock_project_client._config = MagicMock()
|
||||
mock_project_client._config.endpoint = endpoint
|
||||
|
||||
client = AzureAIClient(
|
||||
project_client=mock_project_client,
|
||||
model_deployment_name="test-model",
|
||||
agent_name="test-agent",
|
||||
agent_version="1",
|
||||
)
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")])]
|
||||
chat_options = ChatOptions()
|
||||
|
||||
with (
|
||||
patch.object(client.__class__.__bases__[0], "prepare_options", return_value={"model": "test-model"}),
|
||||
patch.object(
|
||||
client,
|
||||
"_get_agent_reference_or_create",
|
||||
return_value={"name": "test-agent", "version": "1", "type": "agent_reference"},
|
||||
),
|
||||
):
|
||||
run_options = await client.prepare_options(messages, chat_options)
|
||||
|
||||
if expects_agent:
|
||||
assert "extra_body" in run_options
|
||||
assert run_options["extra_body"]["agent"]["name"] == "test-agent"
|
||||
else:
|
||||
assert "extra_body" not in run_options
|
||||
|
||||
|
||||
async def test_azure_ai_client_initialize_client(mock_project_client: MagicMock) -> None:
|
||||
"""Test initialize_client method."""
|
||||
client = create_test_azure_ai_client(mock_project_client)
|
||||
|
||||
@@ -16,6 +16,7 @@ This folder contains examples demonstrating different ways to create and use age
|
||||
| [`azure_ai_with_code_interpreter.py`](azure_ai_with_code_interpreter.py) | Shows how to use the `HostedCodeInterpreterTool` with Azure AI agents to write and execute Python code for mathematical problem solving and data analysis. |
|
||||
| [`azure_ai_with_existing_agent.py`](azure_ai_with_existing_agent.py) | Shows how to work with a pre-existing agent by providing the agent name and version to the Azure AI client. Demonstrates agent reuse patterns for production scenarios. |
|
||||
| [`azure_ai_with_existing_conversation.py`](azure_ai_with_existing_conversation.py) | Demonstrates how to use an existing conversation created on the service side with Azure AI agents. Shows two approaches: specifying conversation ID at the client level and using AgentThread with an existing conversation ID. |
|
||||
| [`azure_ai_with_application_endpoint.py`](azure_ai_with_application_endpoint.py) | Demonstrates calling the Azure AI application-scoped endpoint. |
|
||||
| [`azure_ai_with_explicit_settings.py`](azure_ai_with_explicit_settings.py) | Shows how to create an agent with explicitly configured `AzureAIClient` settings, including project endpoint, model deployment, and credentials rather than relying on environment variable defaults. |
|
||||
| [`azure_ai_with_file_search.py`](azure_ai_with_file_search.py) | Shows how to use the `HostedFileSearchTool` with Azure AI agents to upload files, create vector stores, and enable agents to search through uploaded documents to answer user questions. |
|
||||
| [`azure_ai_with_hosted_mcp.py`](azure_ai_with_hosted_mcp.py) | Shows how to integrate hosted Model Context Protocol (MCP) tools with Azure AI Agent. |
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework.azure import AzureAIClient
|
||||
from azure.ai.projects.aio import AIProjectClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
Azure AI Agent with Application Endpoint Example
|
||||
|
||||
This sample demonstrates working with pre-existing Azure AI Agents by providing
|
||||
application endpoint instead of project endpoint.
|
||||
"""
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
# Create the client
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
# Endpoint here should be application endpoint with format:
|
||||
# /api/projects/<project-name>/applications/<application-name>/protocols
|
||||
AIProjectClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as project_client,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIClient(
|
||||
project_client=project_client,
|
||||
),
|
||||
) as agent,
|
||||
):
|
||||
query = "How are you?"
|
||||
print(f"User: {query}")
|
||||
result = await agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user