Python: [BREAKING] Replace Hosted*Tool classes with tool methods (#3634)

* Replace Hosted*Tool classes with client static factory methods

* fixed failing test

* mypy fix

* mypy fix 2

* declarative mypy fix

* addressed comments

* ToolProtocol removal

* fixed test

* agents mypy fix

* fix failing tests

* mypy fix

* addressed comments

* fixed tests

* addressed comments + added factory method overrides for azureai v2 client

* mypy fix

* added kwargs to azureai tool methods

* fixed in test

* _sessions fix

* test fix
This commit is contained in:
Giles Odigwe
2026-02-10 16:04:27 -08:00
committed by GitHub
Unverified
parent d249473a6d
commit 7a88af0aef
133 changed files with 3018 additions and 2650 deletions
@@ -15,7 +15,7 @@ This folder contains examples demonstrating different ways to create and use age
| [`azure_ai_with_bing_grounding.py`](azure_ai_with_bing_grounding.py) | Shows how to use Bing Grounding search with Azure AI agents to search the web for current information and provide grounded responses with citations. Requires a Bing connection configured in your Azure AI project. |
| [`azure_ai_with_bing_custom_search.py`](azure_ai_with_bing_custom_search.py) | Shows how to use Bing Custom Search with Azure AI agents to search custom search instances and provide responses with relevant results. Requires a Bing Custom Search connection and instance configured in your Azure AI project. |
| [`azure_ai_with_browser_automation.py`](azure_ai_with_browser_automation.py) | Shows how to use Browser Automation with Azure AI agents to perform automated web browsing tasks and provide responses based on web interactions. Requires a Browser Automation connection configured in your Azure AI project. |
| [`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_code_interpreter.py`](azure_ai_with_code_interpreter.py) | Shows how to use `AzureAIClient.get_code_interpreter_tool()` with Azure AI agents to write and execute Python code for mathematical problem solving and data analysis. |
| [`azure_ai_with_code_interpreter_file_generation.py`](azure_ai_with_code_interpreter_file_generation.py) | Shows how to retrieve file IDs from code interpreter generated files using both streaming and non-streaming approaches. |
| [`azure_ai_with_code_interpreter_file_download.py`](azure_ai_with_code_interpreter_file_download.py) | Shows how to download files generated by code interpreter using the OpenAI containers API. |
| [`azure_ai_with_content_filtering.py`](azure_ai_with_content_filtering.py) | Shows how to enable content filtering (RAI policy) on Azure AI agents using `RaiConfig`. Requires creating an RAI policy in Azure AI Foundry portal first. |
@@ -23,8 +23,8 @@ This folder contains examples demonstrating different ways to create and use age
| [`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. |
| [`azure_ai_with_file_search.py`](azure_ai_with_file_search.py) | Shows how to use `AzureAIClient.get_file_search_tool()` 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 using `AzureAIClient.get_mcp_tool()`. |
| [`azure_ai_with_local_mcp.py`](azure_ai_with_local_mcp.py) | Shows how to integrate local Model Context Protocol (MCP) tools with Azure AI agents. |
| [`azure_ai_with_response_format.py`](azure_ai_with_response_format.py) | Shows how to use structured outputs (response format) with Azure AI agents using Pydantic models to enforce specific response schemas. |
| [`azure_ai_with_runtime_json_schema.py`](azure_ai_with_runtime_json_schema.py) | Shows how to use structured outputs (response format) with Azure AI agents using a JSON schema to enforce specific response schemas. |
@@ -32,12 +32,12 @@ This folder contains examples demonstrating different ways to create and use age
| [`azure_ai_with_search_context_semantic.py`](../../context_providers/azure_ai_search/azure_ai_with_search_context_semantic.py) | Shows how to use AzureAISearchContextProvider with semantic mode. Fast hybrid search with vector + keyword search and semantic ranking for RAG. Best for simple queries where speed is critical. |
| [`azure_ai_with_sharepoint.py`](azure_ai_with_sharepoint.py) | Shows how to use SharePoint grounding with Azure AI agents to search through SharePoint content and answer user questions with proper citations. Requires a SharePoint connection configured in your Azure AI project. |
| [`azure_ai_with_thread.py`](azure_ai_with_thread.py) | Demonstrates thread management with Azure AI agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
| [`azure_ai_with_image_generation.py`](azure_ai_with_image_generation.py) | Shows how to use the `ImageGenTool` with Azure AI agents to generate images based on text prompts. |
| [`azure_ai_with_image_generation.py`](azure_ai_with_image_generation.py) | Shows how to use `AzureAIClient.get_image_generation_tool()` with Azure AI agents to generate images based on text prompts. |
| [`azure_ai_with_memory_search.py`](azure_ai_with_memory_search.py) | Shows how to use memory search functionality with Azure AI agents for conversation persistence. Demonstrates creating memory stores and enabling agents to search through conversation history. |
| [`azure_ai_with_microsoft_fabric.py`](azure_ai_with_microsoft_fabric.py) | Shows how to use Microsoft Fabric with Azure AI agents to query Fabric data sources and provide responses based on data analysis. Requires a Microsoft Fabric connection configured in your Azure AI project. |
| [`azure_ai_with_openapi.py`](azure_ai_with_openapi.py) | Shows how to integrate OpenAPI specifications with Azure AI agents using dictionary-based tool configuration. Demonstrates using external REST APIs for dynamic data lookup. |
| [`azure_ai_with_reasoning.py`](azure_ai_with_reasoning.py) | Shows how to enable reasoning for a model that supports it. |
| [`azure_ai_with_web_search.py`](azure_ai_with_web_search.py) | Shows how to use the `HostedWebSearchTool` with Azure AI agents to perform web searches and retrieve up-to-date information from the internet. |
| [`azure_ai_with_web_search.py`](azure_ai_with_web_search.py) | Shows how to use `AzureAIClient.get_web_search_tool()` with Azure AI agents to perform web searches and retrieve up-to-date information from the internet. |
## Environment Variables
@@ -17,7 +17,9 @@ Shows both streaming and non-streaming responses with function tools.
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
# see samples/getting_started/tools/function_tool_with_approval.py
# and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -27,7 +27,9 @@ Each method returns a Agent that can be used for conversations.
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
# see samples/getting_started/tools/function_tool_with_approval.py
# and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -18,7 +18,9 @@ while subsequent calls with `get_agent()` reuse the latest agent version.
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
# see samples/getting_started/tools/function_tool_with_approval.py
# and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -2,8 +2,8 @@
import asyncio
from agent_framework import ChatResponse, HostedCodeInterpreterTool
from agent_framework.azure import AzureAIProjectAgentProvider
from agent_framework import ChatResponse
from agent_framework.azure import AzureAIClient, AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
from openai.types.responses.response import Response as OpenAIResponse
from openai.types.responses.response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall
@@ -11,22 +11,26 @@ from openai.types.responses.response_code_interpreter_tool_call import ResponseC
"""
Azure AI Agent Code Interpreter Example
This sample demonstrates using HostedCodeInterpreterTool with AzureAIProjectAgentProvider
This sample demonstrates using get_code_interpreter_tool() with AzureAIProjectAgentProvider
for Python code execution and mathematical problem solving.
"""
async def main() -> None:
"""Example showing how to use the HostedCodeInterpreterTool with AzureAIProjectAgentProvider."""
"""Example showing how to use the code interpreter tool with AzureAIProjectAgentProvider."""
async with (
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
code_interpreter_tool = client.get_code_interpreter_tool()
agent = await provider.create_agent(
name="MyCodeInterpreterAgent",
instructions="You are a helpful assistant that can write and execute Python code to solve problems.",
tools=HostedCodeInterpreterTool(),
tools=[code_interpreter_tool],
)
query = "Use code to get the factorial of 100?"
@@ -9,9 +9,8 @@ from agent_framework import (
AgentResponseUpdate,
Annotation,
Content,
HostedCodeInterpreterTool,
)
from agent_framework.azure import AzureAIProjectAgentProvider
from agent_framework.azure import AzureAIClient, AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
"""
@@ -119,17 +118,21 @@ async def download_container_files(file_contents: list[Annotation | Content], ag
async def non_streaming_example() -> None:
"""Example of downloading files from non-streaming response using CitationAnnotation."""
"""Example of downloading files from non-streaming response using Annotation."""
print("=== Non-Streaming Response Example ===")
async with (
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
code_interpreter_tool = client.get_code_interpreter_tool()
agent = await provider.create_agent(
name="V2CodeInterpreterFileAgent",
instructions="You are a helpful assistant that can write and execute Python code to create files.",
tools=HostedCodeInterpreterTool(),
tools=[code_interpreter_tool],
)
print(f"User: {QUERY}\n")
@@ -154,8 +157,8 @@ async def non_streaming_example() -> None:
if annotations_found:
print(f"SUCCESS: Found {len(annotations_found)} file annotation(s)")
# Download the container files
downloaded_paths = await download_container_files(annotations_found, agent)
# Download the container files (cast to Sequence for type compatibility)
downloaded_paths = await download_container_files(list(annotations_found), agent)
if downloaded_paths:
print("\nDownloaded files available at:")
@@ -166,17 +169,21 @@ async def non_streaming_example() -> None:
async def streaming_example() -> None:
"""Example of downloading files from streaming response using HostedFileContent."""
"""Example of downloading files from streaming response using Content with type='hosted_file'."""
print("\n=== Streaming Response Example ===")
async with (
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
code_interpreter_tool = client.get_code_interpreter_tool()
agent = await provider.create_agent(
name="V2CodeInterpreterFileAgentStreaming",
instructions="You are a helpful assistant that can write and execute Python code to create files.",
tools=HostedCodeInterpreterTool(),
tools=[code_interpreter_tool],
)
print(f"User: {QUERY}\n")
@@ -4,9 +4,8 @@ import asyncio
from agent_framework import (
AgentResponseUpdate,
HostedCodeInterpreterTool,
)
from agent_framework.azure import AzureAIProjectAgentProvider
from agent_framework.azure import AzureAIClient, AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
"""
@@ -31,10 +30,14 @@ async def non_streaming_example() -> None:
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
code_interpreter_tool = client.get_code_interpreter_tool()
agent = await provider.create_agent(
name="V2CodeInterpreterFileAgent",
name="CodeInterpreterFileAgent",
instructions="You are a helpful assistant that can write and execute Python code to create files.",
tools=HostedCodeInterpreterTool(),
tools=[code_interpreter_tool],
)
print(f"User: {QUERY}\n")
@@ -67,10 +70,14 @@ async def streaming_example() -> None:
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
code_interpreter_tool = client.get_code_interpreter_tool()
agent = await provider.create_agent(
name="V2CodeInterpreterFileAgentStreaming",
instructions="You are a helpful assistant that can write and execute Python code to create files.",
tools=HostedCodeInterpreterTool(),
tools=[code_interpreter_tool],
)
print(f"User: {QUERY}\n")
@@ -17,7 +17,9 @@ This sample demonstrates usage of AzureAIProjectAgentProvider with existing conv
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
# see samples/getting_started/tools/function_tool_with_approval.py
# and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -18,7 +18,9 @@ settings rather than relying on environment variable defaults.
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
# see samples/getting_started/tools/function_tool_with_approval.py
# and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -4,8 +4,7 @@ import asyncio
import os
from pathlib import Path
from agent_framework import Content, HostedFileSearchTool
from agent_framework.azure import AzureAIProjectAgentProvider
from agent_framework.azure import AzureAIClient, AzureAIProjectAgentProvider
from azure.ai.agents.aio import AgentsClient
from azure.ai.agents.models import FileInfo, VectorStore
from azure.identity.aio import AzureCliCredential
@@ -45,8 +44,9 @@ async def main() -> None:
vector_store = await agents_client.vector_stores.create_and_poll(file_ids=[file.id], name="my_vectorstore")
print(f"Created vector store, vector store ID: {vector_store.id}")
# 2. Create file search tool with uploaded resources
file_search_tool = HostedFileSearchTool(inputs=[Content.from_hosted_vector_store(vector_store_id=vector_store.id)])
# 2. Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
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
agent = await provider.create_agent(
@@ -55,7 +55,7 @@ async def main() -> None:
"You are a helpful assistant that can search through uploaded employee files "
"to answer questions about employees."
),
tools=file_search_tool,
tools=[file_search_tool],
)
# 4. Simulate conversation with the agent
@@ -3,8 +3,8 @@
import asyncio
from typing import Any
from agent_framework import AgentResponse, AgentThread, HostedMCPTool, Message, SupportsAgentRun
from agent_framework.azure import AzureAIProjectAgentProvider
from agent_framework import AgentResponse, AgentThread, Message, SupportsAgentRun
from agent_framework.azure import AzureAIClient, AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
"""
@@ -65,14 +65,19 @@ async def run_hosted_mcp_without_approval() -> None:
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
# Create MCP tool using instance method
mcp_tool = client.get_mcp_tool(
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
approval_mode="never_require",
)
agent = await provider.create_agent(
name="MyLearnDocsAgent",
instructions="You are a helpful assistant that can help with Microsoft documentation questions.",
tools=HostedMCPTool(
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
approval_mode="never_require",
),
tools=[mcp_tool],
)
query = "How to create an Azure storage account using az cli?"
@@ -91,14 +96,19 @@ async def run_hosted_mcp_with_approval_and_thread() -> None:
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
# Create MCP tool using instance method
mcp_tool = client.get_mcp_tool(
name="api-specs",
url="https://gitmcp.io/Azure/azure-rest-api-specs",
approval_mode="always_require",
)
agent = await provider.create_agent(
name="MyApiSpecsAgent",
instructions="You are a helpful agent that can use MCP tools to assist users.",
tools=HostedMCPTool(
name="api-specs",
url="https://gitmcp.io/Azure/azure-rest-api-specs",
approval_mode="always_require",
),
tools=[mcp_tool],
)
thread = agent.get_new_thread()
@@ -5,8 +5,7 @@ import tempfile
from pathlib import Path
from urllib import request as urllib_request
from agent_framework import HostedImageGenerationTool
from agent_framework.azure import AzureAIProjectAgentProvider
from agent_framework.azure import AzureAIClient, AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
"""
@@ -28,22 +27,21 @@ async def main() -> None:
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
# Create image generation tool using instance method
image_gen_tool = client.get_image_generation_tool(
model="gpt-image-1",
size="1024x1024",
output_format="png",
quality="low",
background="opaque",
)
agent = await provider.create_agent(
name="ImageGenAgent",
instructions="Generate images based on user requirements.",
tools=[
HostedImageGenerationTool(
options={
"model_id": "gpt-image-1",
"image_size": "1024x1024",
"media_type": "png",
},
additional_properties={
"quality": "low",
"background": "opaque",
},
)
],
tools=[image_gen_tool],
)
query = "Generate an image of Microsoft logo."
@@ -79,22 +79,22 @@ async def example_with_thread_persistence_in_memory() -> None:
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, options={"store": False})
print(f"Agent: {result1.text}")
first_query = "What's the weather like in Tokyo?"
print(f"User: {first_query}")
first_result = await agent.run(first_query, thread=thread, options={"store": False})
print(f"Agent: {first_result.text}")
# Second conversation using the same thread - maintains context
query2 = "How about London?"
print(f"\nUser: {query2}")
result2 = await agent.run(query2, thread=thread, options={"store": False})
print(f"Agent: {result2.text}")
second_query = "How about London?"
print(f"\nUser: {second_query}")
second_result = await agent.run(second_query, thread=thread, options={"store": False})
print(f"Agent: {second_result.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, options={"store": False})
print(f"Agent: {result3.text}")
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, options={"store": False})
print(f"Agent: {third_result.text}")
print("Note: The agent remembers context from previous messages in the same thread.\n")
@@ -121,10 +121,10 @@ async def example_with_existing_thread_id() -> None:
# Start a conversation and get the thread ID
thread = agent.get_new_thread()
query1 = "What's the weather in Paris?"
print(f"User: {query1}")
result1 = await agent.run(query1, thread=thread)
print(f"Agent: {result1.text}")
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
@@ -134,19 +134,19 @@ async def example_with_existing_thread_id() -> None:
print("\n--- Continuing with the same thread ID in a new agent instance ---")
# Create a new agent instance from the same provider
agent2 = await provider.create_agent(
second_agent = await provider.create_agent(
name="BasicWeatherAgent",
instructions="You are a helpful weather agent.",
tools=get_weather,
)
# Create a thread with the existing ID
thread = agent2.get_new_thread(service_thread_id=existing_thread_id)
thread = second_agent.get_new_thread(service_thread_id=existing_thread_id)
query2 = "What was the last city I asked about?"
print(f"User: {query2}")
result2 = await agent2.run(query2, thread=thread)
print(f"Agent: {result2.text}")
second_query = "What was the last city I asked about?"
print(f"User: {second_query}")
second_result = await second_agent.run(second_query, thread=thread)
print(f"Agent: {second_result.text}")
print("Note: The agent continues the conversation from the previous thread by using thread ID.\n")
@@ -2,15 +2,14 @@
import asyncio
from agent_framework import HostedWebSearchTool
from agent_framework.azure import AzureAIProjectAgentProvider
from agent_framework.azure import AzureAIClient, AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
"""
Azure AI Agent With Web Search
This sample demonstrates basic usage of AzureAIProjectAgentProvider to create an agent
that can perform web searches using the HostedWebSearchTool.
that can perform web searches using get_web_search_tool().
Pre-requisites:
- Make sure to set up the AZURE_AI_PROJECT_ENDPOINT and AZURE_AI_MODEL_DEPLOYMENT_NAME
@@ -25,10 +24,15 @@ async def main() -> None:
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
# Create a client to access hosted tool factory methods
client = AzureAIClient(credential=credential)
# Create web search tool using instance method
web_search_tool = client.get_web_search_tool()
agent = await provider.create_agent(
name="WebsearchAgent",
instructions="You are a helpful assistant that can search the web",
tools=[HostedWebSearchTool()],
tools=[web_search_tool],
)
query = "What's the weather today in Seattle?"