Python: Azure AI Search Support Update + Refactored Samples & Unit Tests (#1683)

* azure ai search sample update

* azure ai search update

* small fix
This commit is contained in:
Giles Odigwe
2025-10-29 19:30:06 -07:00
committed by GitHub
Unverified
parent 943d92674e
commit 2059e7b3e8
5 changed files with 152 additions and 266 deletions
@@ -51,8 +51,6 @@ from azure.ai.agents.models import (
AgentStreamEvent,
AsyncAgentEventHandler,
AsyncAgentRunStream,
AzureAISearchQueryType,
AzureAISearchTool,
BingCustomSearchTool,
BingGroundingTool,
CodeInterpreterToolDefinition,
@@ -88,7 +86,6 @@ from azure.ai.agents.models import (
ToolOutput,
)
from azure.ai.projects.aio import AIProjectClient
from azure.ai.projects.models import ConnectionType
from azure.core.credentials_async import AsyncTokenCredential
from azure.core.exceptions import HttpResponseError, ResourceNotFoundError
from pydantic import ValidationError
@@ -988,49 +985,6 @@ class AzureAIAgentClient(BaseChatClient):
# Set tool_resources for file search to work properly with Azure AI
if run_options is not None and "tool_resources" not in run_options:
run_options["tool_resources"] = file_search.resources
else:
additional_props = tool.additional_properties or {}
index_name = additional_props.get("index_name") or os.getenv("AZURE_AI_SEARCH_INDEX_NAME")
if not index_name:
raise ServiceInitializationError(
"File search tool requires at least one vector store input, "
"for file search in the Azure AI Project "
"or an 'index_name' to use Azure AI Search, "
"in additional_properties or environment variable 'AZURE_AI_SEARCH_INDEX_NAME'."
)
try:
azs_conn_id = await self.project_client.connections.get_default(
ConnectionType.AZURE_AI_SEARCH
)
except ValueError as err:
raise ServiceInitializationError(
"No default Azure AI Search connection found in the Azure AI Project. "
"Please create one or provide vector store inputs for the file search tool.",
err,
) from err
else:
query_type_enum = AzureAISearchQueryType.SIMPLE
if query_type := additional_props.get("query_type"):
try:
query_type_enum = AzureAISearchQueryType(query_type)
except ValueError as ex:
raise ServiceInitializationError(
f"Invalid query_type '{query_type}' for Azure AI Search. "
f"Valid values are: {[qt.value for qt in AzureAISearchQueryType]}",
ex,
) from ex
ai_search = AzureAISearchTool(
index_connection_id=azs_conn_id.id,
index_name=index_name,
query_type=query_type_enum,
top_k=additional_props.get("top_k", 3),
filter=additional_props.get("filter", ""),
)
tool_definitions.extend(ai_search.definitions)
# Add tool resources for Azure AI Search
if run_options is not None:
run_options.setdefault("tool_resources", {})
run_options["tool_resources"].update(ai_search.resources)
case ToolDefinition():
tool_definitions.append(tool)
case dict():
@@ -48,12 +48,10 @@ from azure.ai.agents.models import (
ThreadRun,
VectorStore,
)
from azure.ai.projects.models import ConnectionType
from azure.core.credentials_async import AsyncTokenCredential
from azure.core.exceptions import HttpResponseError, ResourceNotFoundError
from azure.identity.aio import AzureCliCredential
from pydantic import BaseModel, Field, ValidationError
from pytest import MonkeyPatch
from agent_framework_azure_ai import AzureAIAgentClient, AzureAISettings
@@ -141,8 +139,8 @@ def test_azure_ai_chat_client_init_auto_create_client(
chat_client.project_client = mock_ai_project_client
chat_client.agent_id = None
chat_client.thread_id = None
chat_client._should_delete_agent = False
chat_client._should_close_client = False
chat_client._should_delete_agent = False # type: ignore
chat_client._should_close_client = False # type: ignore
chat_client.credential = None
chat_client.model_id = azure_ai_settings.model_deployment_name
chat_client.agent_name = None
@@ -697,7 +695,7 @@ async def test_azure_ai_chat_client_create_run_options_with_none_tool_choice(
chat_options = ChatOptions()
chat_options.tool_choice = "none"
run_options, _ = await chat_client._create_run_options([], chat_options)
run_options, _ = await chat_client._create_run_options([], chat_options) # type: ignore
from azure.ai.agents.models import AgentsToolChoiceOptionMode
@@ -713,7 +711,7 @@ async def test_azure_ai_chat_client_create_run_options_with_auto_tool_choice(
chat_options = ChatOptions()
chat_options.tool_choice = "auto"
run_options, _ = await chat_client._create_run_options([], chat_options)
run_options, _ = await chat_client._create_run_options([], chat_options) # type: ignore
from azure.ai.agents.models import AgentsToolChoiceOptionMode
@@ -732,7 +730,7 @@ async def test_azure_ai_chat_client_create_run_options_with_response_format(
chat_options = ChatOptions()
chat_options.response_format = TestResponseModel
run_options, _ = await chat_client._create_run_options([], chat_options)
run_options, _ = await chat_client._create_run_options([], chat_options) # type: ignore
assert "response_format" in run_options
response_format = run_options["response_format"]
@@ -1028,101 +1026,67 @@ async def test_azure_ai_chat_client_prep_tools_file_search_with_vector_stores(
mock_file_search.assert_called_once_with(vector_store_ids=["vs-123"])
async def test_azure_ai_chat_client_prep_tools_file_search_with_ai_search(mock_ai_project_client: MagicMock) -> None:
"""Test _prep_tools with HostedFileSearchTool using Azure AI Search."""
chat_client = create_test_azure_ai_chat_client(mock_ai_project_client, agent_id="test-agent")
file_search_tool = HostedFileSearchTool(
additional_properties={
"index_name": "test-index",
"query_type": "simple",
"top_k": 5,
"filter": "category eq 'docs'",
}
)
# Mock connections.get_default
mock_connection = MagicMock()
mock_connection.id = "search-connection-id"
mock_ai_project_client.connections.get_default = AsyncMock(return_value=mock_connection)
# Mock AzureAISearchTool
with patch("agent_framework_azure_ai._chat_client.AzureAISearchTool") as mock_ai_search:
mock_search_tool = MagicMock()
mock_search_tool.definitions = [{"type": "azure_ai_search"}]
mock_ai_search.return_value = mock_search_tool
# Mock AzureAISearchQueryType
with patch("agent_framework_azure_ai._chat_client.AzureAISearchQueryType") as mock_query_type:
mock_query_type.SIMPLE = "simple"
mock_query_type.return_value = "simple"
result = await chat_client._prep_tools([file_search_tool]) # type: ignore
assert len(result) == 1
assert result[0] == {"type": "azure_ai_search"}
mock_ai_project_client.connections.get_default.assert_called_once_with(ConnectionType.AZURE_AI_SEARCH)
mock_ai_search.assert_called_once_with(
index_connection_id="search-connection-id",
index_name="test-index",
query_type="simple",
top_k=5,
filter="category eq 'docs'",
)
async def test_azure_ai_chat_client_prep_tools_file_search_invalid_query_type(
async def test_azure_ai_chat_client_setup_azure_ai_observability_success(
mock_ai_project_client: MagicMock,
) -> None:
"""Test _prep_tools with HostedFileSearchTool using invalid query_type."""
"""Test setup_azure_ai_observability success case with connection string."""
chat_client = create_test_azure_ai_chat_client(mock_ai_project_client, agent_id="test-agent")
file_search_tool = HostedFileSearchTool(
additional_properties={"index_name": "test-index", "query_type": "invalid_type"}
# Mock successful connection string retrieval
mock_ai_project_client.telemetry.get_application_insights_connection_string = AsyncMock(
return_value="InstrumentationKey=test-key;IngestionEndpoint=https://test.com"
)
# Mock connections.get_default
mock_connection = MagicMock()
mock_connection.id = "search-connection-id"
mock_ai_project_client.connections.get_default = AsyncMock(return_value=mock_connection)
# Mock setup_observability function (it's imported inside the method)
with patch("agent_framework.observability.setup_observability") as mock_setup:
await chat_client.setup_azure_ai_observability(enable_sensitive_data=True)
# Mock AzureAISearchQueryType to raise ValueError
with patch("agent_framework_azure_ai._chat_client.AzureAISearchQueryType") as mock_query_type:
mock_query_type.side_effect = ValueError("Invalid query type")
with pytest.raises(ServiceInitializationError, match="Invalid query_type 'invalid_type'"):
await chat_client._prep_tools([file_search_tool]) # type: ignore
# Verify setup_observability was called with the correct parameters
mock_setup.assert_called_once_with(
applicationinsights_connection_string="InstrumentationKey=test-key;IngestionEndpoint=https://test.com",
enable_sensitive_data=True,
)
async def test_azure_ai_chat_client_prep_tools_file_search_no_connection(mock_ai_project_client: MagicMock) -> None:
"""Test _prep_tools with HostedFileSearchTool when no AI Search connection exists."""
chat_client = create_test_azure_ai_chat_client(mock_ai_project_client, agent_id="test-agent")
file_search_tool = HostedFileSearchTool(additional_properties={"index_name": "test-index"})
# Mock connections.get_default to raise ValueError
mock_ai_project_client.connections.get_default = AsyncMock(side_effect=ValueError("No connection found"))
with pytest.raises(ServiceInitializationError, match="No default Azure AI Search connection found"):
await chat_client._prep_tools([file_search_tool]) # type: ignore
async def test_azure_ai_chat_client_prep_tools_file_search_no_index_name(
mock_ai_project_client: MagicMock, monkeypatch: MonkeyPatch
async def test_azure_ai_chat_client_create_agent_stream_submit_tool_approvals(
mock_ai_project_client: MagicMock,
) -> None:
"""Test _prep_tools with HostedFileSearchTool missing index_name and vector stores."""
monkeypatch.delenv("AZURE_AI_SEARCH_INDEX_NAME", raising=False)
"""Test _create_agent_stream with tool approvals submission path."""
chat_client = create_test_azure_ai_chat_client(mock_ai_project_client, agent_id="test-agent")
# File search tool with no vector stores and no index_name
file_search_tool = HostedFileSearchTool()
# Mock active thread run that matches the tool run ID
mock_thread_run = MagicMock()
mock_thread_run.thread_id = "test-thread"
mock_thread_run.id = "test-run-id"
chat_client._get_active_thread_run = AsyncMock(return_value=mock_thread_run) # type: ignore
with pytest.raises(ServiceInitializationError, match="File search tool requires at least one vector store input"):
await chat_client._prep_tools([file_search_tool]) # type: ignore
# Mock required action results with approval response that matches run ID
approval_response = FunctionApprovalResponseContent(
id='["test-run-id", "test-call-id"]',
function_call=FunctionCallContent(
call_id='["test-run-id", "test-call-id"]', name="test_function", arguments="{}"
),
approved=True,
)
# Mock submit_tool_outputs_stream
mock_handler = MagicMock()
mock_ai_project_client.agents.runs.submit_tool_outputs_stream = AsyncMock()
with patch("azure.ai.agents.models.AsyncAgentEventHandler", return_value=mock_handler):
stream, final_thread_id = await chat_client._create_agent_stream( # type: ignore
"test-thread", "test-agent", {}, [approval_response]
)
# Verify the approvals path was taken
assert final_thread_id == "test-thread"
# Verify submit_tool_outputs_stream was called with approvals
mock_ai_project_client.agents.runs.submit_tool_outputs_stream.assert_called_once()
call_args = mock_ai_project_client.agents.runs.submit_tool_outputs_stream.call_args[1]
assert "tool_approvals" in call_args
assert call_args["tool_approvals"][0].tool_call_id == "test-call-id"
assert call_args["tool_approvals"][0].approve is True
async def test_azure_ai_chat_client_prep_tools_dict_tool(mock_ai_project_client: MagicMock) -> None:
@@ -1156,7 +1120,7 @@ async def test_azure_ai_chat_client_get_active_thread_run_with_active_run(mock_a
mock_run = MagicMock()
mock_run.status = RunStatus.IN_PROGRESS
async def mock_list_runs(*args, **kwargs):
async def mock_list_runs(*args, **kwargs): # type: ignore
yield mock_run
mock_ai_project_client.agents.runs.list = mock_list_runs
@@ -1175,7 +1139,7 @@ async def test_azure_ai_chat_client_get_active_thread_run_no_active_run(mock_ai_
mock_run = MagicMock()
mock_run.status = RunStatus.COMPLETED
async def mock_list_runs(*args, **kwargs):
async def mock_list_runs(*args, **kwargs): # type: ignore
yield mock_run
mock_ai_project_client.agents.runs.list = mock_list_runs
@@ -1432,7 +1396,7 @@ async def test_azure_ai_chat_client_get_agent_id_or_create_with_tool_resources(
async def test_azure_ai_chat_client_close_method(mock_ai_project_client: MagicMock) -> None:
"""Test close method."""
chat_client = create_test_azure_ai_chat_client(mock_ai_project_client, should_delete_agent=True)
chat_client._should_close_client = True
chat_client._should_close_client = True # type: ignore
chat_client.agent_id = "test-agent"
# Mock cleanup methods
@@ -1456,7 +1420,7 @@ async def test_azure_ai_chat_client_create_agent_stream_submit_tool_outputs(
mock_thread_run = MagicMock()
mock_thread_run.thread_id = "test-thread"
mock_thread_run.id = "test-run-id"
chat_client._get_active_thread_run = AsyncMock(return_value=mock_thread_run)
chat_client._get_active_thread_run = AsyncMock(return_value=mock_thread_run) # type: ignore
# Mock required action results with matching run ID
function_result = FunctionResultContent(call_id='["test-run-id", "test-call-id"]', result="test result")
@@ -1466,7 +1430,7 @@ async def test_azure_ai_chat_client_create_agent_stream_submit_tool_outputs(
mock_ai_project_client.agents.runs.submit_tool_outputs_stream = AsyncMock()
with patch("azure.ai.agents.models.AsyncAgentEventHandler", return_value=mock_handler):
stream, final_thread_id = await chat_client._create_agent_stream(
stream, final_thread_id = await chat_client._create_agent_stream( # type: ignore
thread_id="test-thread", agent_id="test-agent", run_options={}, required_action_results=[function_result]
)
@@ -1520,87 +1484,6 @@ def test_azure_ai_chat_client_extract_url_citations_with_citations(mock_ai_proje
assert citation.annotated_regions[0].end_index == 20
def test_azure_ai_chat_client_extract_url_citations_no_citations(mock_ai_project_client: MagicMock) -> None:
"""Test _extract_url_citations with MessageDeltaChunk containing no citations."""
chat_client = create_test_azure_ai_chat_client(mock_ai_project_client, agent_id="test-agent")
# Create mock text content without annotations
mock_text_content = MagicMock(spec=MessageDeltaTextContent)
mock_text_content.text = None # No text, so no annotations
# Create mock delta
mock_delta = MagicMock()
mock_delta.content = [mock_text_content]
# Create mock MessageDeltaChunk
mock_chunk = MagicMock(spec=MessageDeltaChunk)
mock_chunk.delta = mock_delta
# Call the method
citations = chat_client._extract_url_citations(mock_chunk) # type: ignore
# Verify no citations returned
assert len(citations) == 0
def test_azure_ai_chat_client_extract_url_citations_empty_delta(mock_ai_project_client: MagicMock) -> None:
"""Test _extract_url_citations with empty delta content."""
chat_client = create_test_azure_ai_chat_client(mock_ai_project_client, agent_id="test-agent")
# Create mock delta with empty content
mock_delta = MagicMock()
mock_delta.content = []
# Create mock MessageDeltaChunk
mock_chunk = MagicMock(spec=MessageDeltaChunk)
mock_chunk.delta = mock_delta
# Call the method
citations = chat_client._extract_url_citations(mock_chunk) # type: ignore
# Verify no citations returned
assert len(citations) == 0
def test_azure_ai_chat_client_extract_url_citations_without_indices(mock_ai_project_client: MagicMock) -> None:
"""Test _extract_url_citations with URL citations that don't have start/end indices."""
chat_client = create_test_azure_ai_chat_client(mock_ai_project_client, agent_id="test-agent")
# Create mock URL citation annotation without indices
mock_url_citation = MagicMock()
mock_url_citation.url = "https://example.com/no-indices"
mock_annotation = MagicMock(spec=MessageDeltaTextUrlCitationAnnotation)
mock_annotation.url_citation = mock_url_citation
mock_annotation.start_index = None
mock_annotation.end_index = None
# Create mock text content with annotations
mock_text = MagicMock()
mock_text.annotations = [mock_annotation]
mock_text_content = MagicMock(spec=MessageDeltaTextContent)
mock_text_content.text = mock_text
# Create mock delta
mock_delta = MagicMock()
mock_delta.content = [mock_text_content]
# Create mock MessageDeltaChunk
mock_chunk = MagicMock(spec=MessageDeltaChunk)
mock_chunk.delta = mock_delta
# Call the method
citations = chat_client._extract_url_citations(mock_chunk) # type: ignore
# Verify results
assert len(citations) == 1
citation = citations[0]
assert citation.url == "https://example.com/no-indices"
assert citation.annotated_regions is not None
assert len(citation.annotated_regions) == 0 # No regions when indices are None
async def test_azure_ai_chat_client_setup_azure_ai_observability_resource_not_found(
mock_ai_project_client: MagicMock,
) -> None:
@@ -1,9 +1,12 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from agent_framework import ChatAgent, HostedFileSearchTool
from agent_framework import ChatAgent, CitationAnnotation
from agent_framework.azure import AzureAIAgentClient
from azure.ai.projects.aio import AIProjectClient
from azure.ai.projects.models import ConnectionType
from azure.identity.aio import AzureCliCredential
"""
@@ -18,55 +21,98 @@ Prerequisites:
3. The search index "hotels-sample-index" should exist in your Azure AI Search service
(you can create this using the Azure portal with sample hotel data)
Environment variables:
- AZURE_AI_PROJECT_ENDPOINT: Your Azure AI project endpoint
- AZURE_AI_MODEL_DEPLOYMENT_NAME: The name of your model deployment
"""
NOTE: To ensure consistent search tool usage:
- Include explicit instructions for the agent to use the search tool
- Mention the search requirement in your queries
- Use `tool_choice="required"` to force tool usage
# Test queries to verify Azure AI Search is working with the hotels-sample-index
USER_INPUTS = [
"Search the hotel database for Stay-Kay City Hotel and give me detailed information.",
]
More info on `query type` can be found here:
https://learn.microsoft.com/en-us/python/api/azure-ai-agents/azure.ai.agents.models.aisearchindexresource?view=azure-python-preview
"""
async def main() -> None:
"""Main function demonstrating Azure AI agent with Azure AI Search capabilities."""
"""Main function demonstrating Azure AI agent with raw Azure AI Search tool."""
print("=== Azure AI Agent with Raw Azure AI Search Tool ===")
# 1. Create Azure AI Search tool using HostedFileSearchTool
# The tool will automatically use the default Azure AI Search connection from your project
azure_ai_search_tool = HostedFileSearchTool(
additional_properties={
"index_name": "hotels-sample-index", # Name of your search index
"query_type": "simple", # Use simple search
"top_k": 10, # Get more comprehensive results
},
)
# 2. Use AzureAIAgentClient as async context manager for automatic cleanup
# Create the client and manually create an agent with Azure AI Search tool
async with (
AzureAIAgentClient(async_credential=AzureCliCredential()) as client,
ChatAgent(
chat_client=client,
name="HotelSearchAgent",
instructions=("You are a helpful travel assistant that searches hotel information."),
tools=azure_ai_search_tool,
) as agent,
AzureCliCredential() as credential,
AIProjectClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as client,
):
print("=== Azure AI Agent with Azure AI Search ===")
print("This agent can search through hotel data to help you find accommodations.\n")
ai_search_conn_id = ""
async for connection in client.connections.list():
if connection.type == ConnectionType.AZURE_AI_SEARCH:
ai_search_conn_id = connection.id
break
# 3. Simulate conversation with the agent
for user_input in USER_INPUTS:
print(f"User: {user_input}")
print("Agent: ", end="", flush=True)
# 1. Create Azure AI agent with the search tool
azure_ai_agent = await client.agents.create_agent(
model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
name="HotelSearchAgent",
instructions=(
"You are a helpful agent that searches hotel information using Azure AI Search. "
"Always use the search tool and index to find hotel data and provide accurate information."
),
tools=[{"type": "azure_ai_search"}],
tool_resources={
"azure_ai_search": {
"indexes": [
{
"index_connection_id": ai_search_conn_id,
"index_name": "hotels-sample-index",
"query_type": "vector",
}
]
}
},
)
# Stream the response for better user experience
async for chunk in agent.run_stream(user_input):
if chunk.text:
print(chunk.text, end="", flush=True)
print("\n" + "=" * 50 + "\n")
# 2. Create chat client with the existing agent
chat_client = AzureAIAgentClient(project_client=client, agent_id=azure_ai_agent.id)
print("Hotel search conversation completed!")
try:
async with ChatAgent(
chat_client=chat_client,
# Additional instructions for this specific conversation
instructions=("You are a helpful agent that uses the search tool and index to find hotel information."),
) as agent:
print("This agent uses raw Azure AI Search tool to search hotel data.\n")
# 3. Simulate conversation with the agent
user_input = (
"Use Azure AI search knowledge tool to find detailed information about a winter hotel."
" Use the search tool and index." # You can modify prompt to force tool usage
)
print(f"User: {user_input}")
print("Agent: ", end="", flush=True)
# Stream the response and collect citations
citations: list[CitationAnnotation] = []
async for chunk in agent.run_stream(user_input):
if chunk.text:
print(chunk.text, end="", flush=True)
# Collect citations from Azure AI Search responses
for content in getattr(chunk, "contents", []):
annotations = getattr(content, "annotations", [])
if annotations:
citations.extend(annotations)
print()
# Display collected citations
if citations:
print("\n\nCitations:")
for i, citation in enumerate(citations, 1):
print(f"[{i}] Reference: {citation.url}")
print("\n" + "=" * 50 + "\n")
print("Hotel search conversation completed!")
finally:
# Clean up the agent manually
await client.agents.delete_agent(azure_ai_agent.id)
if __name__ == "__main__":
@@ -7,21 +7,23 @@ This folder contains examples demonstrating different ways to create and use age
| File | Description |
|------|-------------|
| [`azure_assistants_basic.py`](azure_assistants_basic.py) | The simplest way to create an agent using `ChatAgent` with `AzureOpenAIAssistantsClient`. Shows both streaming and non-streaming responses with automatic assistant creation and cleanup. |
| [`azure_assistants_with_code_interpreter.py`](azure_assistants_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with Azure agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`azure_assistants_with_existing_assistant.py`](azure_assistants_with_existing_assistant.py) | Shows how to work with a pre-existing assistant by providing the assistant ID to the Azure Assistants client. Demonstrates proper cleanup of manually created assistants. |
| [`azure_assistants_with_explicit_settings.py`](azure_assistants_with_explicit_settings.py) | Shows how to initialize an agent with a specific assistants client, configuring settings explicitly including endpoint and deployment name. |
| [`azure_assistants_with_function_tools.py`](azure_assistants_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
| [`azure_assistants_with_code_interpreter.py`](azure_assistants_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with Azure agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`azure_assistants_with_thread.py`](azure_assistants_with_thread.py) | Demonstrates thread management with Azure agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
| [`azure_chat_client_basic.py`](azure_chat_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `AzureOpenAIChatClient`. Shows both streaming and non-streaming responses for chat-based interactions with Azure OpenAI models. |
| [`azure_chat_client_with_explicit_settings.py`](azure_chat_client_with_explicit_settings.py) | Shows how to initialize an agent with a specific chat client, configuring settings explicitly including endpoint and deployment name. |
| [`azure_chat_client_with_function_tools.py`](azure_chat_client_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
| [`azure_chat_client_with_thread.py`](azure_chat_client_with_thread.py) | Demonstrates thread management with Azure agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
| [`azure_responses_client_basic.py`](azure_responses_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `AzureOpenAIResponsesClient`. Shows both streaming and non-streaming responses for structured response generation with Azure OpenAI models. |
| [`azure_responses_client_code_interpreter_files.py`](azure_responses_client_code_interpreter_files.py) | Demonstrates using HostedCodeInterpreterTool with file uploads for data analysis. Shows how to create, upload, and analyze CSV files using Python code execution with Azure OpenAI Responses. |
| [`azure_responses_client_image_analysis.py`](azure_responses_client_image_analysis.py) | Shows how to use Azure OpenAI Responses for image analysis and vision tasks. Demonstrates multi-modal messages combining text and image content using remote URLs. |
| [`azure_responses_client_with_code_interpreter.py`](azure_responses_client_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with Azure agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`azure_responses_client_with_explicit_settings.py`](azure_responses_client_with_explicit_settings.py) | Shows how to initialize an agent with a specific responses client, configuring settings explicitly including endpoint and deployment name. |
| [`azure_responses_client_with_function_tools.py`](azure_responses_client_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
| [`azure_responses_client_with_code_interpreter.py`](azure_responses_client_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with Azure agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`azure_responses_client_with_local_mcp.py`](azure_responses_client_with_local_mcp.py) | Shows how to integrate Azure OpenAI Responses Client with local Model Context Protocol (MCP) servers using MCPStreamableHTTPTool for extended functionality. |
| [`azure_responses_client_with_thread.py`](azure_responses_client_with_thread.py) | Demonstrates thread management with Azure agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
| [`azure_responses_client_image_analysis.py`](azure_responses_client_image_analysis.py) | Shows how to use Azure OpenAI Responses for image analysis and vision tasks. Demonstrates multi-modal messages combining text and image content using remote URLs. |
## Environment Variables
@@ -7,11 +7,11 @@ This folder contains examples demonstrating different ways to create and use age
| File | Description |
|------|-------------|
| [`openai_assistants_basic.py`](openai_assistants_basic.py) | The simplest way to create an agent using `ChatAgent` with `OpenAIAssistantsClient`. Shows both streaming and non-streaming responses with automatic assistant creation and cleanup. |
| [`openai_assistants_with_code_interpreter.py`](openai_assistants_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with OpenAI agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`openai_assistants_with_existing_assistant.py`](openai_assistants_with_existing_assistant.py) | Shows how to work with a pre-existing assistant by providing the assistant ID to the OpenAI Assistants client. Demonstrates proper cleanup of manually created assistants. |
| [`openai_assistants_with_explicit_settings.py`](openai_assistants_with_explicit_settings.py) | Shows how to initialize an agent with a specific assistants client, configuring settings explicitly including API key and model ID. |
| [`openai_assistants_with_function_tools.py`](openai_assistants_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
| [`openai_assistants_with_code_interpreter.py`](openai_assistants_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with OpenAI agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`openai_assistants_with_file_search.py`](openai_assistants_with_file_search.py) | Demonstrates how to use file search capabilities with OpenAI agents, allowing the agent to search through uploaded files to answer questions. |
| [`openai_assistants_with_function_tools.py`](openai_assistants_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
| [`openai_assistants_with_thread.py`](openai_assistants_with_thread.py) | Demonstrates thread management with OpenAI agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
| [`openai_chat_client_basic.py`](openai_chat_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `OpenAIChatClient`. Shows both streaming and non-streaming responses for chat-based interactions with OpenAI models. |
| [`openai_chat_client_with_explicit_settings.py`](openai_chat_client_with_explicit_settings.py) | Shows how to initialize an agent with a specific chat client, configuring settings explicitly including API key and model ID. |
@@ -21,6 +21,7 @@ This folder contains examples demonstrating different ways to create and use age
| [`openai_chat_client_with_web_search.py`](openai_chat_client_with_web_search.py) | Shows how to use web search capabilities with OpenAI agents to retrieve and use information from the internet in responses. |
| [`openai_responses_client_basic.py`](openai_responses_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `OpenAIResponsesClient`. Shows both streaming and non-streaming responses for structured response generation with OpenAI models. |
| [`openai_responses_client_image_analysis.py`](openai_responses_client_image_analysis.py) | Demonstrates how to use vision capabilities with agents to analyze images. |
| [`openai_responses_client_image_generation.py`](openai_responses_client_image_generation.py) | Demonstrates how to use image generation capabilities with OpenAI agents to create images based on text descriptions. Requires PIL (Pillow) for image display. |
| [`openai_responses_client_reasoning.py`](openai_responses_client_reasoning.py) | Demonstrates how to use reasoning capabilities with OpenAI agents, showing how the agent can provide detailed reasoning for its responses. |
| [`openai_responses_client_with_code_interpreter.py`](openai_responses_client_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with OpenAI agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`openai_responses_client_with_explicit_settings.py`](openai_responses_client_with_explicit_settings.py) | Shows how to initialize an agent with a specific responses client, configuring settings explicitly including API key and model ID. |