Python: Fix Azure AI sample errors (#4021)

* Python: Fix Azure AI sample errors

- azure_ai_with_application_endpoint: Add missing name to Agent constructor
- azure_ai_with_file_search: Fix resource path (parents[2] -> parents[3])
- azure_ai_with_openapi: Fix resource path (parents[2] -> parents[3])
- azure_ai_with_session: Use get_agent/get_session to reuse existing agent
  version and preserve conversation context across agent instances

* Python: Fix resource paths in azure_ai_agent samples

- azure_ai_with_file_search: Fix path to employees.pdf (parent.parent -> parents[3]/shared)
- azure_ai_with_openapi_tools: Fix path to weather.json/countries.json (parents[2] -> parents[3])

* fix V1 SDK hosted tools (FileSearchTool, etc.) silently dropped during agent creation

* fix: V2 file search sample uses correct SDK (AIProjectClient instead of AgentsClient)

The azure_ai/azure_ai_with_file_search.py sample incorrectly used the V1
AgentsClient for file/vector store operations. Replaced with V2 pattern:
AIProjectClient + get_openai_client() for file upload and vector store
management, matching the official Azure AI Projects SDK samples.

* fix: use context manager for file open in V2 file search sample
This commit is contained in:
Giles Odigwe
2026-02-17 21:27:19 -08:00
committed by GitHub
Unverified
parent 2dd731f90f
commit 28e3fc308b
8 changed files with 42 additions and 50 deletions
@@ -24,6 +24,7 @@ async def main() -> None:
# /api/projects/<project-name>/applications/<application-name>/protocols
AIProjectClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as project_client,
Agent(
name="ApplicationAgent",
client=AzureAIClient(
project_client=project_client,
),
@@ -1,12 +1,12 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import contextlib
import os
from pathlib import Path
from agent_framework.azure import AzureAIClient, AzureAIProjectAgentProvider
from azure.ai.agents.aio import AgentsClient
from azure.ai.agents.models import FileInfo, VectorStore
from azure.ai.projects.aio import AIProjectClient
from azure.identity.aio import AzureCliCredential
"""
@@ -25,27 +25,30 @@ USER_INPUTS = [
async def main() -> None:
"""Main function demonstrating Azure AI agent with file search capabilities."""
file: FileInfo | None = None
vector_store: VectorStore | None = None
async with (
AzureCliCredential() as credential,
AgentsClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as agents_client,
AzureAIProjectAgentProvider(credential=credential) as provider,
AIProjectClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as project_client,
AzureAIProjectAgentProvider(project_client=project_client) as provider,
):
openai_client = project_client.get_openai_client()
try:
# 1. Upload file and create vector store
pdf_file_path = Path(__file__).parents[2] / "shared" / "resources" / "employees.pdf"
# 1. Upload file and create vector store via OpenAI client
pdf_file_path = Path(__file__).parents[3] / "shared" / "resources" / "employees.pdf"
print(f"Uploading file from: {pdf_file_path}")
file = await agents_client.files.upload_and_poll(file_path=str(pdf_file_path), purpose="assistants")
print(f"Uploaded file, file ID: {file.id}")
vector_store = await agents_client.vector_stores.create_and_poll(file_ids=[file.id], name="my_vectorstore")
vector_store = await openai_client.vector_stores.create(name="my_vectorstore")
print(f"Created vector store, vector store ID: {vector_store.id}")
# 2. Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
with open(pdf_file_path, "rb") as f:
file = await openai_client.vector_stores.files.upload_and_poll(
vector_store_id=vector_store.id,
file=f,
)
print(f"Uploaded file, file ID: {file.id}")
# 2. Create a file search tool
client = AzureAIClient(project_client=project_client)
file_search_tool = client.get_file_search_tool(vector_store_ids=[vector_store.id])
# 3. Create an agent with file search capabilities using the provider
@@ -64,11 +67,9 @@ async def main() -> None:
response = await agent.run(user_input)
print(f"# Agent: {response.text}")
finally:
# 5. Cleanup: Delete the vector store and file in case of earlier failure to prevent orphaned resources.
if vector_store:
await agents_client.vector_stores.delete(vector_store.id)
if file:
await agents_client.files.delete(file.id)
# 5. Cleanup: Delete the vector store (also deletes associated files)
with contextlib.suppress(Exception):
await openai_client.vector_stores.delete(vector_store.id)
if __name__ == "__main__":
@@ -20,7 +20,7 @@ Prerequisites:
async def main() -> None:
# Load the OpenAPI specification
resources_path = Path(__file__).parents[2] / "shared" / "resources" / "countries.json"
resources_path = Path(__file__).parents[3] / "shared" / "resources" / "countries.json"
with open(resources_path) as f:
openapi_countries = json.load(f)
@@ -133,15 +133,14 @@ async def example_with_existing_session_id() -> None:
if existing_session_id:
print("\n--- Continuing with the same session ID in a new agent instance ---")
# Create a new agent instance from the same provider
second_agent = await provider.create_agent(
# Retrieve the same agent (reuses existing agent version on the service)
second_agent = await provider.get_agent(
name="BasicWeatherAgent",
instructions="You are a helpful weather agent.",
tools=get_weather,
)
# Create a session with the existing ID
session = second_agent.create_session(service_session_id=existing_session_id)
# Attach the existing service session ID so conversation context is preserved
session = second_agent.get_session(service_session_id=existing_session_id)
second_query = "What was the last city I asked about?"
print(f"User: {second_query}")
@@ -35,7 +35,7 @@ async def main() -> None:
):
try:
# 1. Upload file and create vector store
pdf_file_path = Path(__file__).parent.parent / "resources" / "employees.pdf"
pdf_file_path = Path(__file__).parents[3] / "shared" / "resources" / "employees.pdf"
print(f"Uploading file from: {pdf_file_path}")
file = await agents_client.files.upload_and_poll(file_path=str(pdf_file_path), purpose="assistants")
@@ -23,7 +23,7 @@ USER_INPUTS = [
def load_openapi_specs() -> tuple[dict[str, Any], dict[str, Any]]:
"""Load OpenAPI specification files."""
resources_path = Path(__file__).parents[2] / "shared" / "resources"
resources_path = Path(__file__).parents[3] / "shared" / "resources"
with open(resources_path / "weather.json") as weather_file:
weather_spec = json.load(weather_file)