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-11 00:04:27 +00:00
committed by GitHub
parent d249473a6d
commit 7a88af0aef
133 changed files with 3018 additions and 2650 deletions
@@ -7,7 +7,7 @@ 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 `Agent` 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_code_interpreter.py`](azure_assistants_with_code_interpreter.py) | Shows how to use `AzureOpenAIAssistantsClient.get_code_interpreter_tool()` 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). |
@@ -17,12 +17,13 @@ This folder contains examples demonstrating different ways to create and use age
| [`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 `Agent` 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_code_interpreter_files.py`](azure_responses_client_code_interpreter_files.py) | Demonstrates using `AzureOpenAIResponsesClient.get_code_interpreter_tool()` 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_code_interpreter.py`](azure_responses_client_with_code_interpreter.py) | Shows how to use `AzureOpenAIResponsesClient.get_code_interpreter_tool()` 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_file_search.py`](azure_responses_client_with_file_search.py) | Demonstrates using HostedFileSearchTool with Azure OpenAI Responses Client for direct document-based question answering and information retrieval from vector stores. |
| [`azure_responses_client_with_file_search.py`](azure_responses_client_with_file_search.py) | Demonstrates using `AzureOpenAIResponsesClient.get_file_search_tool()` with Azure OpenAI Responses Client for direct document-based question answering and information retrieval from vector stores. |
| [`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_hosted_mcp.py`](azure_responses_client_with_hosted_mcp.py) | Shows how to integrate Azure OpenAI Responses Client with hosted Model Context Protocol (MCP) servers using `AzureOpenAIResponsesClient.get_mcp_tool()` for extended functionality. |
| [`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. |
@@ -2,9 +2,8 @@
import asyncio
from agent_framework import Agent, AgentResponseUpdate, ChatResponseUpdate, HostedCodeInterpreterTool
from agent_framework import Agent, AgentResponseUpdate, ChatResponseUpdate
from agent_framework.azure import AzureOpenAIAssistantsClient
from azure.identity import AzureCliCredential
from openai.types.beta.threads.runs import (
CodeInterpreterToolCallDelta,
RunStepDelta,
@@ -16,7 +15,7 @@ from openai.types.beta.threads.runs.code_interpreter_tool_call_delta import Code
"""
Azure OpenAI Assistants with Code Interpreter Example
This sample demonstrates using HostedCodeInterpreterTool with Azure OpenAI Assistants
This sample demonstrates using get_code_interpreter_tool() with Azure OpenAI Assistants
for Python code execution and mathematical problem solving.
"""
@@ -41,15 +40,19 @@ def get_code_interpreter_chunk(chunk: AgentResponseUpdate) -> str | None:
async def main() -> None:
"""Example showing how to use the HostedCodeInterpreterTool with Azure OpenAI Assistants."""
"""Example showing how to use the code interpreter tool with Azure OpenAI Assistants."""
print("=== Azure OpenAI Assistants Agent with Code Interpreter Example ===")
# Create code interpreter tool using static method
client = AzureOpenAIAssistantsClient()
code_interpreter_tool = client.get_code_interpreter_tool()
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
async with Agent(
client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
client=client,
instructions="You are a helpful assistant that can write and execute Python code to solve problems.",
tools=HostedCodeInterpreterTool(),
tools=[code_interpreter_tool],
) as agent:
query = "What is current datetime?"
print(f"User: {query}")
@@ -19,7 +19,9 @@ using existing assistant IDs rather than creating new ones.
"""
# 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.")],
@@ -18,7 +18,9 @@ showing both agent-level and query-level tool configuration patterns.
"""
# 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.")],
@@ -17,7 +17,9 @@ automatic thread creation with explicit thread management for persistent context
"""
# 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.")],
@@ -17,7 +17,9 @@ interactions, showing both streaming and non-streaming responses.
"""
# 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.")],
@@ -18,7 +18,9 @@ showing both agent-level and query-level tool configuration patterns.
"""
# 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.")],
@@ -17,7 +17,9 @@ automatic thread creation with explicit thread management for persistent context
"""
# 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.")],
@@ -17,7 +17,9 @@ response generation, showing both streaming and non-streaming responses.
"""
# 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,7 +4,7 @@ import asyncio
import os
import tempfile
from agent_framework import Agent, HostedCodeInterpreterTool
from agent_framework import Agent
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
from openai import AsyncAzureOpenAI
@@ -12,7 +12,7 @@ from openai import AsyncAzureOpenAI
"""
Azure OpenAI Responses Client with Code Interpreter and Files Example
This sample demonstrates using HostedCodeInterpreterTool with Azure OpenAI Responses
This sample demonstrates using get_code_interpreter_tool() with Azure OpenAI Responses
for Python code execution and data analysis with uploaded files.
"""
@@ -76,10 +76,15 @@ async def main() -> None:
temp_file_path, file_id = await create_sample_file_and_upload(openai_client)
# Create agent using Azure OpenAI Responses client
client = AzureOpenAIResponsesClient(credential=credential)
# Create code interpreter tool with file access
code_interpreter_tool = client.get_code_interpreter_tool(file_ids=[file_id])
agent = Agent(
client=AzureOpenAIResponsesClient(credential=credential),
client=client,
instructions="You are a helpful assistant that can analyze data files using Python code.",
tools=HostedCodeInterpreterTool(inputs=[{"file_id": file_id}]),
tools=[code_interpreter_tool],
)
# Test the code interpreter with the uploaded file
@@ -27,9 +27,9 @@ async def main():
user_message = Message(
role="user",
contents=[
Content.from_text(text="What do you see in this image?"),
Content.from_text("What do you see in this image?"),
Content.from_uri(
uri="https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg",
uri="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800",
media_type="image/jpeg",
),
],
@@ -2,7 +2,7 @@
import asyncio
from agent_framework import Agent, ChatResponse, HostedCodeInterpreterTool
from agent_framework import Agent, ChatResponse
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
from openai.types.responses.response import Response as OpenAIResponse
@@ -11,21 +11,26 @@ from openai.types.responses.response_code_interpreter_tool_call import ResponseC
"""
Azure OpenAI Responses Client with Code Interpreter Example
This sample demonstrates using HostedCodeInterpreterTool with Azure OpenAI Responses
This sample demonstrates using get_code_interpreter_tool() with Azure OpenAI Responses
for Python code execution and mathematical problem solving.
"""
async def main() -> None:
"""Example showing how to use the HostedCodeInterpreterTool with Azure OpenAI Responses."""
"""Example showing how to use the code interpreter tool with Azure OpenAI Responses."""
print("=== Azure OpenAI Responses Agent with Code Interpreter Example ===")
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
client = AzureOpenAIResponsesClient(credential=AzureCliCredential())
# Create code interpreter tool using instance method
code_interpreter_tool = client.get_code_interpreter_tool()
agent = Agent(
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
client=client,
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 calculate the factorial of 100?"
@@ -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.")],
@@ -2,14 +2,14 @@
import asyncio
from agent_framework import Agent, Content, HostedFileSearchTool
from agent_framework import Agent, Content
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
"""
Azure OpenAI Responses Client with File Search Example
This sample demonstrates using HostedFileSearchTool with Azure OpenAI Responses Client
This sample demonstrates using get_file_search_tool() with Azure OpenAI Responses Client
for direct document-based question answering and information retrieval.
Prerequisites:
@@ -51,12 +51,15 @@ async def main() -> None:
# Make sure you're logged in via 'az login' before running this sample
client = AzureOpenAIResponsesClient(credential=AzureCliCredential())
file_id, vector_store = await create_vector_store(client)
file_id, vector_store_id = await create_vector_store(client)
# Create file search tool using instance method
file_search_tool = client.get_file_search_tool(vector_store_ids=[vector_store_id])
agent = Agent(
client=client,
instructions="You are a helpful assistant that can search through files to find information.",
tools=[HostedFileSearchTool(inputs=vector_store)],
tools=[file_search_tool],
)
query = "What is the weather today? Do a file search to find the answer."
@@ -64,7 +67,7 @@ async def main() -> None:
result = await agent.run(query)
print(f"Agent: {result}\n")
await delete_vector_store(client, file_id, vector_store.vector_store_id)
await delete_vector_store(client, file_id, vector_store_id)
if __name__ == "__main__":
@@ -18,7 +18,9 @@ showing both agent-level and query-level tool configuration patterns.
"""
# 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.")],
@@ -3,7 +3,7 @@
import asyncio
from typing import TYPE_CHECKING, Any
from agent_framework import Agent, HostedMCPTool
from agent_framework import Agent
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
@@ -33,7 +33,10 @@ async def handle_approvals_without_thread(query: str, agent: "SupportsAgentRun")
new_inputs.append(Message(role="assistant", contents=[user_input_needed]))
user_approval = input("Approve function call? (y/n): ")
new_inputs.append(
Message(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")])
Message(
role="user",
contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")],
)
)
result = await agent.run(new_inputs)
@@ -82,7 +85,8 @@ async def handle_approvals_with_thread_streaming(query: str, agent: "SupportsAge
user_approval = input("Approve function call? (y/n): ")
new_input.append(
Message(
role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")]
role="user",
contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")],
)
)
new_input_added = True
@@ -94,21 +98,24 @@ async def run_hosted_mcp_without_thread_and_specific_approval() -> None:
"""Example showing Mcp Tools with approvals without using a thread."""
print("=== Mcp with approvals and without thread ===")
credential = AzureCliCredential()
client = AzureOpenAIResponsesClient(credential=credential)
# Create MCP tool with specific approval settings
mcp_tool = client.get_mcp_tool(
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
# we don't require approval for microsoft_docs_search tool calls
# but we do for any other tool
approval_mode={"never_require_approval": ["microsoft_docs_search"]},
)
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
async with Agent(
client=AzureOpenAIResponsesClient(
credential=credential,
),
client=client,
name="DocsAgent",
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",
# we don't require approval for microsoft_docs_search tool calls
# but we do for any other tool
approval_mode={"never_require_approval": ["microsoft_docs_search"]},
),
tools=[mcp_tool],
) as agent:
# First query
query1 = "How to create an Azure storage account using az cli?"
@@ -127,22 +134,25 @@ async def run_hosted_mcp_without_approval() -> None:
"""Example showing Mcp Tools without approvals."""
print("=== Mcp without approvals ===")
credential = AzureCliCredential()
client = AzureOpenAIResponsesClient(credential=credential)
# Create MCP tool without approval requirements
mcp_tool = client.get_mcp_tool(
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
# we don't require approval for any function calls
# this means we will not see the approval messages,
# it is fully handled by the service and a final response is returned.
approval_mode="never_require",
)
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
async with Agent(
client=AzureOpenAIResponsesClient(
credential=credential,
),
client=client,
name="DocsAgent",
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",
# we don't require approval for any function calls
# this means we will not see the approval messages,
# it is fully handled by the service and a final response is returned.
approval_mode="never_require",
),
tools=[mcp_tool],
) as agent:
# First query
query1 = "How to create an Azure storage account using az cli?"
@@ -161,20 +171,23 @@ async def run_hosted_mcp_with_thread() -> None:
"""Example showing Mcp Tools with approvals using a thread."""
print("=== Mcp with approvals and with thread ===")
credential = AzureCliCredential()
client = AzureOpenAIResponsesClient(credential=credential)
# Create MCP tool with always require approval
mcp_tool = client.get_mcp_tool(
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
# we require approval for all function calls
approval_mode="always_require",
)
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
async with Agent(
client=AzureOpenAIResponsesClient(
credential=credential,
),
client=client,
name="DocsAgent",
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",
# we require approval for all function calls
approval_mode="always_require",
),
tools=[mcp_tool],
) as agent:
# First query
thread = agent.get_new_thread()
@@ -194,20 +207,23 @@ async def run_hosted_mcp_with_thread_streaming() -> None:
"""Example showing Mcp Tools with approvals using a thread."""
print("=== Mcp with approvals and with thread ===")
credential = AzureCliCredential()
client = AzureOpenAIResponsesClient(credential=credential)
# Create MCP tool with always require approval
mcp_tool = client.get_mcp_tool(
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
# we require approval for all function calls
approval_mode="always_require",
)
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
async with Agent(
client=AzureOpenAIResponsesClient(
credential=credential,
),
client=client,
name="DocsAgent",
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",
# we require approval for all function calls
approval_mode="always_require",
),
tools=[mcp_tool],
) as agent:
# First query
thread = agent.get_new_thread()
@@ -48,14 +48,14 @@ async def main():
url=MCP_URL,
) as mcp_tool:
# First query — expect the agent to use the MCP tool if it helps
q1 = "How to create an Azure storage account using az cli?"
r1 = await agent.run(q1, tools=mcp_tool)
print("\n=== Answer 1 ===\n", r1.text)
first_query = "How to create an Azure storage account using az cli?"
first_response = await agent.run(first_query, tools=mcp_tool)
print("\n=== Answer 1 ===\n", first_response.text)
# Follow-up query (connection is reused)
q2 = "What is Microsoft Agent Framework?"
r2 = await agent.run(q2, tools=mcp_tool)
print("\n=== Answer 2 ===\n", r2.text)
second_query = "What is Microsoft Agent Framework?"
second_response = await agent.run(second_query, tools=mcp_tool)
print("\n=== Answer 2 ===\n", second_response.text)
if __name__ == "__main__":
@@ -17,7 +17,9 @@ automatic thread creation with explicit thread management for persistent context
"""
# 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.")],