chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:25 +08:00
commit db620d33df
5151 changed files with 925932 additions and 0 deletions
@@ -0,0 +1,49 @@
# Foundry Provider Samples
This folder contains Azure AI Foundry and Foundry Local samples for Agent Framework.
## FoundryAgent Samples
| File | Description |
|------|-------------|
| [`foundry_agent_basic.py`](foundry_agent_basic.py) | Foundry Agent basic example |
| [`foundry_agent_custom_client.py`](foundry_agent_custom_client.py) | Foundry Agent custom client configuration |
| [`foundry_agent_hosted.py`](foundry_agent_hosted.py) | Foundry Agent for hosted agents |
| [`foundry_agent_with_function_tools.py`](foundry_agent_with_function_tools.py) | Foundry Agent with local function tools |
## FoundryChatClient Samples
| File | Description |
|------|-------------|
| [`foundry_chat_client.py`](foundry_chat_client.py) | Foundry Chat Client with project endpoint example |
| [`foundry_chat_client_basic.py`](foundry_chat_client_basic.py) | Foundry Chat Client basic example |
| [`foundry_chat_client_code_interpreter_files.py`](foundry_chat_client_code_interpreter_files.py) | Foundry Chat Client with code interpreter and files |
| [`foundry_chat_client_image_analysis.py`](foundry_chat_client_image_analysis.py) | Foundry Chat Client with image analysis |
| [`foundry_chat_client_with_code_interpreter.py`](foundry_chat_client_with_code_interpreter.py) | Foundry Chat Client with code interpreter |
| [`foundry_chat_client_with_explicit_settings.py`](foundry_chat_client_with_explicit_settings.py) | Foundry Chat Client with explicit settings |
| [`foundry_chat_client_with_file_search.py`](foundry_chat_client_with_file_search.py) | Foundry Chat Client with file search |
| [`foundry_chat_client_with_function_tools.py`](foundry_chat_client_with_function_tools.py) | Foundry Chat Client with function tools |
| [`foundry_chat_client_with_hosted_mcp.py`](foundry_chat_client_with_hosted_mcp.py) | Foundry Chat Client with hosted MCP |
| [`foundry_chat_client_with_local_mcp.py`](foundry_chat_client_with_local_mcp.py) | Foundry Chat Client with local MCP |
| [`foundry_chat_client_with_session.py`](foundry_chat_client_with_session.py) | Foundry Chat Client with session management |
| [`foundry_chat_client_with_toolbox.py`](foundry_chat_client_with_toolbox.py) | Foundry Chat Client connected to a toolbox via its MCP endpoint using `MCPStreamableHTTPTool` |
| [`foundry_chat_client_with_toolbox_skills.py`](foundry_chat_client_with_toolbox_skills.py) | Foundry Chat Client that discovers MCP-based skills from a Foundry Toolbox endpoint via `MCPSkillsSource` (uses an Azure AD bearer token and the toolbox preview header) |
## FoundryLocalClient Samples
### Prerequisites
1. Install Foundry Local and required local runtime components.
2. Install the connector package:
```bash
pip install agent-framework-foundry-local --pre
```
| File | Description |
|------|-------------|
| [`foundry_local_agent.py`](foundry_local_agent.py) | Basic Foundry Local agent usage with streaming and non-streaming responses, plus function tool calling. |
### Environment Variables
- `FOUNDRY_LOCAL_MODEL`: Optional model alias/ID to use by default when `model` is not passed to `FoundryLocalClient`.
@@ -0,0 +1,42 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from agent_framework.foundry import FoundryAgent
from azure.identity import AzureCliCredential
"""
Foundry Agent — Connect to a pre-configured agent in Microsoft Foundry
This sample shows the simplest way to connect to an existing PromptAgent
in Azure AI Foundry and run it. The agent's instructions, model, and hosted
tools are all configured on the service — you just connect and run.
Environment variables:
FOUNDRY_PROJECT_ENDPOINT — Azure AI Foundry project endpoint
FOUNDRY_AGENT_NAME — Name of the agent in Foundry
FOUNDRY_AGENT_VERSION — Version of the agent (for PromptAgents)
"""
async def main() -> None:
agent = FoundryAgent(
project_endpoint="https://your-project.services.ai.azure.com",
agent_name="my-prompt-agent",
agent_version="1.0",
credential=AzureCliCredential(),
)
result = await agent.run("What is the capital of France?")
print(f"Agent: {result}")
# Streaming
print("Agent (streaming): ", end="", flush=True)
async for chunk in agent.run("Tell me a fun fact.", stream=True):
if chunk.text:
print(chunk.text, end="", flush=True)
print()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,63 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from agent_framework import Agent
from agent_framework.foundry import FoundryAgent, RawFoundryAgentChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
load_dotenv()
"""
Foundry Agent — Custom client configuration
This sample demonstrates three ways to customize the FoundryAgent client layer:
1. Default: FoundryAgent creates a RawFoundryAgentChatClient (full middleware) internally
2. client_type: Pass RawFoundryAgentChatClient for no client middleware
3. Composition: Use Agent(client=RawFoundryAgentChatClient(...)) directly
Environment variables:
FOUNDRY_PROJECT_ENDPOINT — Azure AI Foundry project endpoint
FOUNDRY_AGENT_NAME — Name of the agent in Foundry
FOUNDRY_AGENT_VERSION — Version of the agent
"""
async def main() -> None:
# Option 1: Default — full middleware on both agent and client
agent = FoundryAgent(
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
agent_name=os.getenv("FOUNDRY_AGENT_NAME"),
agent_version=os.getenv("FOUNDRY_AGENT_VERSION"),
credential=AzureCliCredential(),
)
result = await agent.run("Hello from the default setup!")
print(f"Default: {result}\n")
# Option 2: Raw client — no client-level middleware (agent middleware still active)
agent_raw_client = FoundryAgent(
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
agent_name=os.getenv("FOUNDRY_AGENT_NAME"),
agent_version=os.getenv("FOUNDRY_AGENT_VERSION"),
credential=AzureCliCredential(),
client_type=RawFoundryAgentChatClient,
)
result = await agent_raw_client.run("Hello from raw client!")
print(f"Raw client: {result}\n")
# Option 3: Composition — use Agent(client=...) directly
# this will not run the checks that the `FoundryAgent` does on things like tools.
client = RawFoundryAgentChatClient(
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
agent_name=os.getenv("FOUNDRY_AGENT_NAME"),
agent_version=os.getenv("FOUNDRY_AGENT_VERSION"),
credential=AzureCliCredential(),
)
agent_composed = Agent(client=client)
result = await agent_composed.run("Hello from composed setup!")
print(f"Composed: {result}")
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,37 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from agent_framework.foundry import FoundryAgent
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
load_dotenv()
"""
Foundry Agent — Connect to a HostedAgent (no version needed)
HostedAgents in Azure AI Foundry are pre-deployed agents that don't require
a version number. You only need the agent name to connect.
Environment variables:
FOUNDRY_PROJECT_ENDPOINT — Azure AI Foundry project endpoint
FOUNDRY_AGENT_NAME — Name of the hosted agent
"""
async def main() -> None:
# HostedAgents don't need agent_version
agent = FoundryAgent(
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
agent_name=os.getenv("FOUNDRY_AGENT_NAME"),
credential=AzureCliCredential(),
)
result = await agent.run("Summarize the latest news about AI.")
print(f"Agent: {result}")
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,50 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from typing import Annotated
from agent_framework.foundry import FoundryAgent
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
load_dotenv()
"""
Foundry Agent with Local Function Tools
This sample shows how to connect to a Foundry agent and provide local function
tools. The Foundry agent must already have these tools defined in its configuration
(as declaration-only tools). The local implementations are matched by name.
Only FunctionTool objects are accepted — hosted tools (code interpreter, file search,
web search, etc.) must be configured on the agent definition in the service.
Environment variables:
FOUNDRY_PROJECT_ENDPOINT — Azure AI Foundry project endpoint
FOUNDRY_AGENT_NAME — Name of the agent in Foundry
FOUNDRY_AGENT_VERSION — Version of the agent
"""
def get_weather(
location: Annotated[str, "The city to get weather for."],
) -> str:
"""Get the current weather for a location."""
return f"The weather in {location} is sunny, 22°C."
async def main() -> None:
agent = FoundryAgent(
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
agent_name=os.getenv("FOUNDRY_AGENT_NAME"),
agent_version=os.getenv("FOUNDRY_AGENT_VERSION"),
credential=AzureCliCredential(),
tools=get_weather,
)
result = await agent.run("What's the weather in Paris?")
print(f"Agent: {result}")
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,115 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from random import randint
from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Project Endpoint Example
This sample demonstrates how to create a FoundryChatClient using a
Foundry project endpoint. Instead of providing a service endpoint
directly, you provide a Foundry project endpoint and the client is created via
the Azure AI Foundry project SDK.
This requires:
- The `FOUNDRY_PROJECT_ENDPOINT` environment variable set to your Foundry project endpoint.
- The `FOUNDRY_MODEL` environment variable set to the model deployment name.
"""
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, "The location to get the weather for."],
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
async def non_streaming_example() -> None:
"""Example of non-streaming response (get the complete result at once)."""
print("=== Non-streaming Response Example ===")
# 1. Create the FoundryChatClient using a Foundry project endpoint.
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
credential = AzureCliCredential()
_client = FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ["FOUNDRY_MODEL"],
credential=credential,
)
agent = Agent(
client=_client,
instructions="You are a helpful weather agent.",
tools=get_weather,
)
# 2. Run a query and print the result.
query = "What's the weather like in Seattle?"
print(f"User: {query}")
result = await agent.run(query)
print(f"Result: {result}\n")
async def streaming_example() -> None:
"""Example of streaming response (get results as they are generated)."""
print("=== Streaming Response Example ===")
# 1. Create the FoundryChatClient using a Foundry project endpoint.
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
credential = AzureCliCredential()
_client = FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ["FOUNDRY_MODEL"],
credential=credential,
)
agent = Agent(
client=_client,
instructions="You are a helpful weather agent.",
tools=get_weather,
)
# 2. Stream the response and print each chunk as it arrives.
query = "What's the weather like in Portland?"
print(f"User: {query}")
print("Agent: ", end="", flush=True)
async for chunk in agent.run(query, stream=True):
if chunk.text:
print(chunk.text, end="", flush=True)
print("\n")
async def main() -> None:
print("=== Foundry Chat Client with Project Endpoint Example ===")
await non_streaming_example()
await streaming_example()
if __name__ == "__main__":
asyncio.run(main())
"""
Sample output:
=== Foundry Chat Client with Project Endpoint Example ===
=== Non-streaming Response Example ===
User: What's the weather like in Seattle?
Result: The weather in Seattle is cloudy with a high of 18°C.
=== Streaming Response Example ===
User: What's the weather like in Portland?
Agent: The weather in Portland is sunny with a high of 25°C.
"""
@@ -0,0 +1,86 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from random import randint
from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
from pydantic import Field
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client Basic Example
This sample demonstrates basic usage of FoundryChatClient for structured
response generation, showing both streaming and non-streaming responses.
This uses a deployed model in Foundry, with the Responses API endpoint of Foundry.
The client has full support for tools, response formats, etc.
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
# see samples/02-agents/tools/function_tool_with_approval.py
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
async def non_streaming_example() -> None:
"""Example of non-streaming response (get the complete result at once)."""
print("=== Non-streaming Response Example ===")
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a helpful weather agent.",
tools=get_weather,
)
query = "What's the weather like in Seattle?"
print(f"User: {query}")
result = await agent.run(query)
print(f"Result: {result}\n")
async def streaming_example() -> None:
"""Example of streaming response (get results as they are generated)."""
print("=== Streaming Response Example ===")
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a helpful weather agent.",
tools=get_weather,
)
query = "What's the weather like in Portland?"
print(f"User: {query}")
print("Agent: ", end="", flush=True)
async for chunk in agent.run(query, stream=True):
if chunk.text:
print(chunk.text, end="", flush=True)
print("\n")
async def main() -> None:
print("=== Foundry Chat Client Basic Example ===")
await non_streaming_example()
await streaming_example()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,97 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
import tempfile
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
from openai import AsyncOpenAI
load_dotenv()
"""
Foundry Chat Client with Code Interpreter and Files Example
This sample demonstrates using get_code_interpreter_tool() with Responses on Foundry
for Python code execution and data analysis with uploaded files.
Environment variables:
FOUNDRY_PROJECT_ENDPOINT — Foundry project endpoint
FOUNDRY_MODEL — Foundry model to use (e.g. "gpt-4o-mini")
"""
# Helper functions
async def create_sample_file_and_upload(openai_client: AsyncOpenAI) -> tuple[str, str]:
"""Create a sample CSV file and upload it for Foundry code interpreter use."""
csv_data = """name,department,salary,years_experience
Alice Johnson,Engineering,95000,5
Bob Smith,Sales,75000,3
Carol Williams,Engineering,105000,8
David Brown,Marketing,68000,2
Emma Davis,Sales,82000,4
Frank Wilson,Engineering,88000,6
"""
# Create temporary CSV file
with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as temp_file:
temp_file.write(csv_data)
temp_file_path = temp_file.name
# Upload file for the code interpreter tool
print("Uploading file for code interpreter...")
with open(temp_file_path, "rb") as file:
uploaded_file = await openai_client.files.create(
file=file,
purpose="assistants", # Required for code interpreter
)
print(f"File uploaded with ID: {uploaded_file.id}")
return temp_file_path, uploaded_file.id
async def cleanup_files(openai_client: AsyncOpenAI, temp_file_path: str, file_id: str) -> None:
"""Clean up both local temporary file and uploaded file."""
# Clean up: delete the uploaded file
await openai_client.files.delete(file_id)
print(f"Cleaned up uploaded file: {file_id}")
# Clean up temporary local file
os.unlink(temp_file_path)
print(f"Cleaned up temporary file: {temp_file_path}")
async def main() -> None:
print("=== Foundry Chat Client with Code Interpreter and File Upload ===")
# Create the FoundryChatClient
client = FoundryChatClient(
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
model=os.getenv("FOUNDRY_MODEL"),
credential=AzureCliCredential(),
)
# use the openai client from the foundry client to upload files for the code interpreter tool
openai_client = getattr(client.project_client, "get_openai_client")() # noqa: B009
temp_file_path, file_id = await create_sample_file_and_upload(openai_client)
# Create agent with code interpreter tool with file access
agent = Agent(
client=client,
instructions="You are a helpful assistant that can analyze data files using Python code.",
tools=FoundryChatClient.get_code_interpreter_tool(file_ids=[file_id]),
)
try:
# Test the code interpreter with the uploaded file
query = "Analyze the employee data in the uploaded CSV file. Calculate average salary by department."
print(f"User: {query}")
result = await agent.run(query)
print(f"Agent: {result.text}")
finally:
await cleanup_files(openai_client, temp_file_path, file_id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,44 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from agent_framework import Agent, Content
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Image Analysis Example
This sample demonstrates using FoundryChatClient for image analysis and vision tasks,
showing multi-modal messages combining text and image content.
"""
async def main():
print("=== Foundry Chat Client with Image Analysis ===")
# 1. Create a Foundry-backed agent with vision capabilities
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
name="VisionAgent",
instructions="You are a image analysist, you get a image and need to respond with what you see in the picture.",
)
# 2. Get the agent's response
print("User: What do you see in this image? [Image provided]")
result = await agent.run(
Content.from_uri(
uri="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800",
media_type="image/jpeg",
)
)
print(f"Agent: {result.text}")
print()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,57 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from agent_framework import Agent, ChatResponse
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
from openai.types.responses.response import Response as OpenAIResponse
from openai.types.responses.response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Code Interpreter Example
This sample demonstrates using get_code_interpreter_tool() with FoundryChatClient
for Python code execution and mathematical problem solving.
"""
async def main() -> None:
"""Example showing how to use the code interpreter tool with FoundryChatClient."""
print("=== Foundry Chat Client with Code Interpreter Example ===")
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
client = FoundryChatClient(credential=AzureCliCredential())
# Create code interpreter tool using instance method
code_interpreter_tool = client.get_code_interpreter_tool()
agent = Agent(
client=client,
instructions="You are a helpful assistant that can write and execute Python code to solve problems.",
tools=[code_interpreter_tool],
)
query = "Use code to calculate the factorial of 100?"
print(f"User: {query}")
result = await agent.run(query)
print(f"Result: {result}\n")
if (
isinstance(result.raw_representation, ChatResponse)
and isinstance(result.raw_representation.raw_representation, OpenAIResponse)
and len(result.raw_representation.raw_representation.output) > 0
and isinstance(result.raw_representation.raw_representation.output[0], ResponseCodeInterpreterToolCall)
):
generated_code = result.raw_representation.raw_representation.output[0].code
print(f"Generated code:\n{generated_code}")
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,58 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from random import randint
from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
from pydantic import Field
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Explicit Settings Example
This sample demonstrates creating FoundryChatClient with explicit project endpoint and
model settings rather than relying on environment variable defaults.
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
# see samples/02-agents/tools/function_tool_with_approval.py
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
async def main() -> None:
print("=== Foundry Chat Client with Explicit Settings ===")
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
_client = FoundryChatClient(
model=os.environ["FOUNDRY_MODEL"],
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
credential=AzureCliCredential(),
)
agent = Agent(
client=_client,
instructions="You are a helpful weather agent.",
tools=[get_weather],
)
result = await agent.run("What's the weather like in New York?")
print(f"Result: {result}\n")
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,81 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import contextlib
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with File Search Example
This sample demonstrates using get_file_search_tool() with FoundryChatClient
for direct document-based question answering and information retrieval.
Prerequisites:
- Set environment variables:
- FOUNDRY_PROJECT_ENDPOINT: Your Foundry project endpoint URL
- FOUNDRY_MODEL: Your Responses API deployment name
- Authenticate via 'az login' for AzureCliCredential
"""
# Helper functions
async def create_vector_store(client: FoundryChatClient) -> tuple[str, str]:
"""Create a vector store with sample documents."""
file = await client.client.files.create(
file=("todays_weather.txt", b"The weather today is sunny with a high of 75F."), purpose="assistants"
)
vector_store = await client.client.vector_stores.create(
name="knowledge_base",
expires_after={"anchor": "last_active_at", "days": 1},
)
result = await client.client.vector_stores.files.create_and_poll(vector_store_id=vector_store.id, file_id=file.id)
if result.last_error is not None:
raise Exception(f"Vector store file processing failed with status: {result.last_error.message}")
return file.id, vector_store.id
async def delete_vector_store(client: FoundryChatClient, file_id: str, vector_store_id: str) -> None:
"""Delete the vector store after using it."""
with contextlib.suppress(Exception):
await client.client.vector_stores.delete(vector_store_id=vector_store_id)
with contextlib.suppress(Exception):
await client.client.files.delete(file_id=file_id)
async def main() -> None:
print("=== Foundry Chat Client with File Search Example ===\n")
# Initialize the Foundry chat client
# Make sure you're logged in via 'az login' before running this sample
client = FoundryChatClient(credential=AzureCliCredential())
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=[file_search_tool],
)
query = "What is the weather today? Do a file search to find the answer."
print(f"User: {query}")
result = await agent.run(query)
print(f"Agent: {result}\n")
await delete_vector_store(client, file_id, vector_store_id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,143 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from datetime import datetime, timezone
from random import randint
from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
from pydantic import Field
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Function Tools Example
This sample demonstrates function tool integration with FoundryChatClient,
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/02-agents/tools/function_tool_with_approval.py
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
@tool(approval_mode="never_require")
def get_time() -> str:
"""Get the current UTC time."""
current_time = datetime.now(timezone.utc)
return f"The current UTC time is {current_time.strftime('%Y-%m-%d %H:%M:%S')}."
async def tools_on_agent_level() -> None:
"""Example showing tools defined when creating the agent."""
print("=== Tools Defined on Agent Level ===")
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a helpful assistant that can provide weather and time information.",
tools=[get_weather, get_time], # Tools defined at agent creation
)
# First query - agent can use weather tool
query1 = "What's the weather like in New York?"
print(f"User: {query1}")
result1 = await agent.run(query1)
print(f"Agent: {result1}\n")
# Second query - agent can use time tool
query2 = "What's the current UTC time?"
print(f"User: {query2}")
result2 = await agent.run(query2)
print(f"Agent: {result2}\n")
# Third query - agent can use both tools if needed
query3 = "What's the weather in London and what's the current UTC time?"
print(f"User: {query3}")
result3 = await agent.run(query3)
print(f"Agent: {result3}\n")
async def tools_on_run_level() -> None:
"""Example showing tools passed to the run method."""
print("=== Tools Passed to Run Method ===")
# Agent created without tools
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a helpful assistant.",
# No tools defined here
)
# First query with weather tool
query1 = "What's the weather like in Seattle?"
print(f"User: {query1}")
result1 = await agent.run(query1, tools=[get_weather]) # Tool passed to run method
print(f"Agent: {result1}\n")
# Second query with time tool
query2 = "What's the current UTC time?"
print(f"User: {query2}")
result2 = await agent.run(query2, tools=[get_time]) # Different tool for this query
print(f"Agent: {result2}\n")
# Third query with multiple tools
query3 = "What's the weather in Chicago and what's the current UTC time?"
print(f"User: {query3}")
result3 = await agent.run(query3, tools=[get_weather, get_time]) # Multiple tools
print(f"Agent: {result3}\n")
async def mixed_tools_example() -> None:
"""Example showing both agent-level tools and run-method tools."""
print("=== Mixed Tools Example (Agent + Run Method) ===")
# Agent created with some base tools
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a comprehensive assistant that can help with various information requests.",
tools=[get_weather], # Base tool available for all queries
)
# Query using both agent tool and additional run-method tools
query = "What's the weather in Denver and what's the current UTC time?"
print(f"User: {query}")
# Agent has access to get_weather (from creation) + additional tools from run method
result = await agent.run(
query,
tools=[get_time], # Additional tools for this specific query
)
print(f"Agent: {result}\n")
async def main() -> None:
print("=== Foundry Chat Client with Function Tools Examples ===\n")
await tools_on_agent_level()
await tools_on_run_level()
await mixed_tools_example()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,271 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import TYPE_CHECKING, Any
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Hosted MCP Example
This sample demonstrates integrating hosted Model Context Protocol (MCP) tools with
FoundryChatClient, including user approval workflows for function call security.
"""
if TYPE_CHECKING:
from agent_framework import AgentSession
async def handle_approvals_without_session(query: str, agent: Agent[Any]):
"""When we don't have a session, we need to ensure we return with the input, approval request and approval."""
from agent_framework import Message
result = await agent.run(query)
while len(result.user_input_requests) > 0:
new_inputs: list[Any] = [query]
for user_input_needed in result.user_input_requests:
if user_input_needed.function_call is None:
continue
print(
f"User Input Request for function from {agent.name}: {user_input_needed.function_call.name}"
f" with arguments: {user_input_needed.function_call.arguments}"
)
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")],
)
)
result = await agent.run(new_inputs)
return result
async def handle_approvals_with_session(query: str, agent: Agent[Any], session: "AgentSession"):
"""Here we let the session deal with the previous responses, and we just rerun with the approval."""
from agent_framework import ChatOptions, Message
result = await agent.run(query, session=session, options=ChatOptions(store=True))
while len(result.user_input_requests) > 0:
new_input: list[Any] = []
for user_input_needed in result.user_input_requests:
if user_input_needed.function_call is None:
continue
print(
f"User Input Request for function from {agent.name}: {user_input_needed.function_call.name}"
f" with arguments: {user_input_needed.function_call.arguments}"
)
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")],
)
)
result = await agent.run(new_input, session=session, options=ChatOptions(store=True))
return result
async def handle_approvals_with_session_streaming(query: str, agent: Agent[Any], session: "AgentSession"):
"""Here we let the session deal with the previous responses, and we just rerun with the approval."""
from agent_framework import ChatOptions, Message
new_input: list[Message | str] = [query]
new_input_added = True
while new_input_added:
new_input_added = False
async for update in agent.run(new_input, session=session, options=ChatOptions(store=True), stream=True):
if update.user_input_requests:
# Reset input to only contain new approval responses for the next iteration
new_input = []
for user_input_needed in update.user_input_requests:
if user_input_needed.function_call is None:
continue
print(
f"User Input Request for function from {agent.name}: {user_input_needed.function_call.name}"
f" with arguments: {user_input_needed.function_call.arguments}"
)
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")],
)
)
new_input_added = True
else:
yield update
async def run_hosted_mcp_without_session_and_specific_approval() -> None:
"""Example showing Mcp Tools with approvals without using a session."""
print("=== Mcp with approvals and without session ===")
credential = AzureCliCredential()
client = FoundryChatClient(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=client,
name="DocsAgent",
instructions="You are a helpful assistant that uses your MCP tool "
"to help with microsoft documentation questions.",
tools=[mcp_tool],
) as agent:
# First query
query1 = "How to create an Azure storage account using az cli?"
print(f"User: {query1}")
result1 = await handle_approvals_without_session(query1, agent)
print(f"{agent.name}: {result1}\n")
print("\n=======================================\n")
# Second query
query2 = "What is Microsoft Agent Framework?"
print(f"User: {query2}")
result2 = await handle_approvals_without_session(query2, agent)
print(f"{agent.name}: {result2}\n")
async def run_hosted_mcp_without_approval() -> None:
"""Example showing Mcp Tools without approvals."""
print("=== Mcp without approvals ===")
credential = AzureCliCredential()
client = FoundryChatClient(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=client,
name="DocsAgent",
instructions="You are a helpful assistant that uses your MCP tool "
"to help with Microsoft documentation questions.",
tools=[mcp_tool],
) as agent:
# First query
query1 = "How to create an Azure storage account using az cli?"
print(f"User: {query1}")
result1 = await handle_approvals_without_session(query1, agent)
print(f"{agent.name}: {result1}\n")
print("\n=======================================\n")
# Second query
query2 = "What is Microsoft Agent Framework?"
print(f"User: {query2}")
result2 = await handle_approvals_without_session(query2, agent)
print(f"{agent.name}: {result2}\n")
async def run_hosted_mcp_with_session() -> None:
"""Example showing Mcp Tools with approvals using a session."""
print("=== Mcp with approvals and with session ===")
credential = AzureCliCredential()
client = FoundryChatClient(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=client,
name="DocsAgent",
instructions="You are a helpful assistant that uses your MCP tool "
"to help with microsoft documentation questions.",
tools=[mcp_tool],
) as agent:
# First query
session = agent.create_session()
query1 = "How to create an Azure storage account using az cli?"
print(f"User: {query1}")
result1 = await handle_approvals_with_session(query1, agent, session)
print(f"{agent.name}: {result1}\n")
print("\n=======================================\n")
# Second query
query2 = "What is Microsoft Agent Framework?"
print(f"User: {query2}")
result2 = await handle_approvals_with_session(query2, agent, session)
print(f"{agent.name}: {result2}\n")
async def run_hosted_mcp_with_session_streaming() -> None:
"""Example showing Mcp Tools with approvals using a session."""
print("=== Mcp with approvals and with session ===")
credential = AzureCliCredential()
client = FoundryChatClient(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=client,
name="DocsAgent",
instructions="You are a helpful assistant that uses your MCP tool "
"to help with microsoft documentation questions.",
tools=[mcp_tool],
) as agent:
# First query
session = agent.create_session()
query1 = "How to create an Azure storage account using az cli?"
print(f"User: {query1}")
print(f"{agent.name}: ", end="")
async for update in handle_approvals_with_session_streaming(query1, agent, session):
print(update, end="")
print("\n")
print("\n=======================================\n")
# Second query
query2 = "What is Microsoft Agent Framework?"
print(f"User: {query2}")
print(f"{agent.name}: ", end="")
async for update in handle_approvals_with_session_streaming(query2, agent, session):
print(update, end="")
print("\n")
async def main() -> None:
print("=== Foundry Chat Client with Hosted MCP Examples ===\n")
await run_hosted_mcp_without_approval()
await run_hosted_mcp_without_session_and_specific_approval()
await run_hosted_mcp_with_session()
await run_hosted_mcp_with_session_streaming()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,66 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from agent_framework import Agent, MCPStreamableHTTPTool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Local Model Context Protocol (MCP) Example
This sample demonstrates integration of FoundryChatClient with local Model Context Protocol (MCP)
servers.
"""
# --- Below code uses Microsoft Learn MCP server over Streamable HTTP ---
# --- Users can set these environment variables, or just edit the values below to their desired local MCP server
MCP_NAME = os.environ.get("MCP_NAME", "Microsoft Learn MCP") # example name
MCP_URL = os.environ.get("MCP_URL", "https://learn.microsoft.com/api/mcp") # example endpoint
# Environment variables for FoundryChatClient authentication
# FOUNDRY_PROJECT_ENDPOINT="<your-foundry-project-endpoint>"
# FOUNDRY_MODEL="<your-deployment-name>"
async def main():
"""Example showing local MCP tools for a Foundry Chat Client agent."""
# AuthN: use Azure CLI
credential = AzureCliCredential()
# Build an agent backed by FoundryChatClient
# (project endpoint and model can also come from env vars above)
responses_client = FoundryChatClient(
credential=credential,
)
agent: Agent = Agent(
client=responses_client,
name="DocsAgent",
instructions=("You are a helpful assistant that can help with Microsoft documentation questions."),
)
# Connect to the MCP server (Streamable HTTP)
async with MCPStreamableHTTPTool(
name=MCP_NAME,
url=MCP_URL,
) as mcp_tool:
# First query — expect the agent to use the MCP tool if it helps
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)
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__":
asyncio.run(main())
@@ -0,0 +1,161 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from random import randint
from typing import Annotated
from agent_framework import Agent, AgentSession, InMemoryHistoryProvider, tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
from pydantic import Field
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Session Management Example
This sample demonstrates session management with FoundryChatClient, comparing
automatic session creation with explicit session management for persistent context.
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
# see samples/02-agents/tools/function_tool_with_approval.py
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
async def example_with_automatic_session_creation() -> None:
"""Example showing automatic session creation (service-managed session)."""
print("=== Automatic Session Creation Example ===")
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a helpful weather agent.",
tools=get_weather,
)
# First conversation - no session provided, will be created automatically
query1 = "What's the weather like in Seattle?"
print(f"User: {query1}")
result1 = await agent.run(query1)
print(f"Agent: {result1.text}")
# Second conversation - still no session provided, will create another new session
query2 = "What was the last city I asked about?"
print(f"\nUser: {query2}")
result2 = await agent.run(query2)
print(f"Agent: {result2.text}")
print("Note: Each call creates a separate session, so the agent doesn't remember previous context.\n")
async def example_with_session_persistence() -> None:
"""Example showing session persistence across multiple conversations."""
print("=== Session Persistence Example ===")
print("Using the same session across multiple conversations to maintain context.\n")
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a helpful weather agent.",
tools=get_weather,
)
# Create a new session that will be reused
session = agent.create_session()
# First conversation
query1 = "What's the weather like in Tokyo?"
print(f"User: {query1}")
result1 = await agent.run(query1, session=session)
print(f"Agent: {result1.text}")
# Second conversation using the same session - maintains context
query2 = "How about London?"
print(f"\nUser: {query2}")
result2 = await agent.run(query2, session=session)
print(f"Agent: {result2.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, session=session)
print(f"Agent: {result3.text}")
print("Note: The agent remembers context from previous messages in the same session.\n")
async def example_with_existing_session_messages() -> None:
"""Example showing how to work with existing session messages for Foundry-backed agents."""
print("=== Existing Session Messages Example ===")
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
# authentication option.
agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a helpful weather agent.",
tools=get_weather,
)
# Start a conversation and build up message history
session = agent.create_session()
query1 = "What's the weather in Paris?"
print(f"User: {query1}")
result1 = await agent.run(query1, session=session)
print(f"Agent: {result1.text}")
# The session now contains the conversation history in state
memory_state = session.state.get(InMemoryHistoryProvider.DEFAULT_SOURCE_ID, {})
messages = memory_state.get("messages", [])
if messages:
print(f"Session contains {len(messages)} messages")
print("\n--- Continuing with the same session in a new agent instance ---")
# Create a new agent instance but use the existing session with its message history
new_agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
instructions="You are a helpful weather agent.",
tools=get_weather,
)
# Use the same session object which contains the conversation history
query2 = "What was the last city I asked about?"
print(f"User: {query2}")
result2 = await new_agent.run(query2, session=session)
print(f"Agent: {result2.text}")
print("Note: The agent continues the conversation using the local message history.\n")
print("\n--- Alternative: Creating a new session from existing messages ---")
# You can also create a new session from existing messages
new_session = AgentSession()
query3 = "How does the Paris weather compare to London?"
print(f"User: {query3}")
result3 = await new_agent.run(query3, session=new_session)
print(f"Agent: {result3.text}")
print("Note: This creates a new session with the same conversation history.\n")
async def main() -> None:
print("=== Foundry Chat Client Session Management Examples ===\n")
await example_with_automatic_session_creation()
await example_with_session_persistence()
await example_with_existing_session_messages()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,118 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from collections.abc import Callable
from typing import Any
from agent_framework import Agent, MCPStreamableHTTPTool
from agent_framework.foundry import FoundryChatClient
from azure.core.credentials import TokenCredential
from azure.identity import AzureCliCredential, DefaultAzureCredential, get_bearer_token_provider
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
"""
Foundry Toolbox via MAF ``MCPStreamableHTTPTool``
Instead of fetching the toolbox and fanning out individual tool specs, point
MAF's ``MCPStreamableHTTPTool`` at the toolbox's MCP endpoint. The agent
discovers and calls the toolbox's tools over MCP at runtime.
Prerequisites:
- A Microsoft Foundry project with a toolbox configured
- FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_MODEL environment variables set
- FOUNDRY_TOOLBOX_ENDPOINT: the toolbox's MCP endpoint URL, e.g.
``https://<account>.services.ai.azure.com/api/projects/<project>/toolsets/<name>/mcp?api-version=v1``
- Azure CLI authentication (``az login``)
"""
# Must match the ``<name>`` segment of FOUNDRY_TOOLBOX_ENDPOINT.
TOOLBOX_NAME = "research_toolbox"
def create_sample_toolbox(name: str) -> str:
"""Create (or replace) a toolbox version in the Foundry project.
Toolboxes are normally configured in the Foundry portal or a deployment
script, not the application itself. This helper exists so the sample can
be run end-to-end without first setting a toolbox up by hand — delete any
existing toolbox under ``name``, then create a fresh version containing a
single MCP tool. Returns the created version identifier.
"""
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import MCPTool, Tool
from azure.core.exceptions import ResourceNotFoundError
with (
AzureCliCredential() as credential,
AIProjectClient(credential=credential, endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"]) as project_client,
):
try:
project_client.beta.toolboxes.delete(name)
print(f"Toolbox `{name}` deleted")
except ResourceNotFoundError:
pass
tools: list[Tool] = [
MCPTool(
server_label="api_specs",
server_url="https://gitmcp.io/Azure/azure-rest-api-specs",
require_approval="never",
)
]
created = project_client.beta.toolboxes.create_version(
name=name,
description="Toolbox version with MCP require_approval set to 'never'.",
tools=tools,
)
print(f"Created toolbox {created.name}@{created.version} ({len(created.tools)} tool(s))")
return created.version
def make_toolbox_header_provider(credential: TokenCredential) -> Callable[[dict[str, Any]], dict[str, str]]:
"""Build a header_provider that injects a fresh Azure AI bearer token on every MCP request."""
get_token = get_bearer_token_provider(credential, "https://ai.azure.com/.default")
def provide(_kwargs: dict[str, Any]) -> dict[str, str]:
return {
"Authorization": f"Bearer {get_token()}",
}
return provide
async def main() -> None:
credential = DefaultAzureCredential()
# Comment out if the toolbox already exists in your Foundry project.
create_sample_toolbox(TOOLBOX_NAME)
toolbox_tool = MCPStreamableHTTPTool(
name="foundry_toolbox",
description="Tools exposed by the configured Foundry toolbox",
url=os.environ["FOUNDRY_TOOLBOX_ENDPOINT"],
header_provider=make_toolbox_header_provider(credential),
load_prompts=False,
)
async with Agent(
client=FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ["FOUNDRY_MODEL"],
credential=credential,
),
instructions="You are a helpful assistant. Use the available toolbox tools to answer the user.",
tools=toolbox_tool,
) as agent:
query = "What tools do you have access to?"
print(f"User: {query}")
result = await agent.run(query)
print(f"Assistant: {result}")
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,88 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from collections.abc import Generator
import httpx
from agent_framework import Agent, MCPSkillsSource, SkillsProvider, ToolApprovalMiddleware
from agent_framework.foundry import FoundryChatClient
from azure.core.credentials import TokenCredential
from azure.identity import AzureCliCredential, get_bearer_token_provider
from dotenv import load_dotenv
from mcp.client.session import ClientSession
from mcp.client.streamable_http import streamable_http_client
# Load environment variables from .env file
load_dotenv()
"""
Foundry Chat Client with Toolbox-Hosted Skills
Discover Agent Skills served by a Microsoft Foundry Toolbox MCP endpoint
and inject them into a ``FoundryChatClient`` agent via ``MCPSkillsSource``.
The toolbox's discovery document (``skill://index.json``) is read once at
startup; SKILL.md bodies are fetched on demand as the agent uses them.
Prerequisites:
- A Microsoft Foundry project with a toolbox that exposes
``skill://index.json`` with ``skill-md`` entries
- FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_MODEL environment variables set
- FOUNDRY_TOOLBOX_MCP_SERVER_URL: the toolbox's MCP endpoint URL, e.g.
``https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<name>/mcp?api-version=v1``
- Azure CLI authentication (``az login``)
"""
class _BearerAuth(httpx.Auth):
"""Attach a fresh Foundry bearer token to every request."""
def __init__(self, credential: TokenCredential) -> None:
self._get_token = get_bearer_token_provider(credential, "https://ai.azure.com/.default")
def auth_flow(self, request: httpx.Request) -> Generator[httpx.Request, httpx.Response, None]:
request.headers["Authorization"] = f"Bearer {self._get_token()}"
yield request
async def main() -> None:
"""Example showing toolbox-hosted MCP skills for a Foundry Chat Client agent."""
credential = AzureCliCredential()
# HTTP client that signs every request with a fresh Foundry bearer token
# and advertises the toolbox preview feature flag, plus the MCP streamable
# HTTP transport that uses it.
async with (
httpx.AsyncClient(
auth=_BearerAuth(credential),
timeout=httpx.Timeout(30.0, read=300.0),
follow_redirects=True,
) as http_client,
streamable_http_client(
url=os.environ["FOUNDRY_TOOLBOX_MCP_SERVER_URL"],
http_client=http_client,
) as (read, write, _),
ClientSession(read, write) as session,
):
await session.initialize()
# Discover skills served by the toolbox and inject them as a context provider.
skills_provider = SkillsProvider(MCPSkillsSource(client=session))
async with Agent(
client=FoundryChatClient(credential=credential),
name="ToolboxMCPSkillsAgent",
instructions="You are a helpful assistant. Use available skills to answer the user.",
context_providers=[skills_provider],
middleware=[ToolApprovalMiddleware(auto_approval_rules=[SkillsProvider.all_tools_auto_approval_rule])],
) as agent:
query = input("User: ").strip() # noqa: ASYNC250
if not query:
return
session = agent.create_session()
response = await agent.run(query, session=session)
print(f"Assistant: {response.text}")
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,79 @@
# Copyright (c) Microsoft. All rights reserved.
# ruff: noqa
from __future__ import annotations
import asyncio
from random import randint
from typing import Annotated, Any
from agent_framework import Agent
from agent_framework.foundry import FoundryLocalClient
"""
This sample demonstrates basic usage of the FoundryLocalClient.
Shows both streaming and non-streaming responses with function tools.
Running this sample the first time will be slow, as the model needs to be
downloaded and initialized.
Also, not every model supports function calling, so be sure to check the
model capabilities in the Foundry catalog, or pick one from the list printed
when running this sample.
"""
def get_weather(
location: Annotated[str, "The location to get the weather for."],
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
async def non_streaming_example(agent: Agent[Any]) -> None:
"""Example of non-streaming response (get the complete result at once)."""
print("=== Non-streaming Response Example ===")
query = "What's the weather like in Seattle?"
print(f"User: {query}")
result = await agent.run(query)
print(f"Agent: {result}\n")
async def streaming_example(agent: Agent[Any]) -> None:
"""Example of streaming response (get results as they are generated)."""
print("=== Streaming Response Example ===")
query = "What's the weather like in Amsterdam?"
print(f"User: {query}")
print("Agent: ", end="", flush=True)
async for chunk in agent.run(query, stream=True):
if chunk.text:
print(chunk.text, end="", flush=True)
print("\n")
async def main() -> None:
print("=== Basic Foundry Local Client Agent Example ===")
client = FoundryLocalClient(model="phi-4-mini")
print(f"Client Model ID: {client.model}\n")
print("Other available models (tool calling supported only):")
for model in client.manager.list_catalog_models():
if model.supports_tool_calling:
print(
f"- {model.alias} for {model.task} - id={model.id} - {(model.file_size_mb / 1000):.2f} GB - {model.license}"
)
agent = Agent(
client=client,
name="LocalAgent",
instructions="You are a helpful agent.",
tools=get_weather,
)
await non_streaming_example(agent)
await streaming_example(agent)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,152 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from random import randint
from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.foundry import FoundryAgent, FoundryChatClient, to_prompt_agent
from azure.ai.projects.aio import AIProjectClient
from azure.identity.aio import AzureCliCredential
from dotenv import load_dotenv
from pydantic import Field
load_dotenv()
"""
Foundry Prompt Agent: Convert, Publish, Connect, and Run
This sample shows the end-to-end loop:
1. Build an ``Agent`` backed by ``FoundryChatClient`` with a local ``@tool``
function and Foundry-hosted tools.
2. Run the local ``Agent`` directly against the Foundry Responses API.
3. Convert it with ``to_prompt_agent(agent)`` and publish via
``AIProjectClient.agents.create_version(...)``.
4. Connect to the deployed prompt agent with ``FoundryAgent`` and pass the
*same* ``book_hotel`` callable through ``tools=`` so the server-side prompt
agent and the client share a single tool definition.
The Foundry prompt agent only receives the ``book_hotel`` *declaration* (its
JSON schema). When the deployed agent decides to call the tool, ``FoundryAgent``
executes the local Python implementation by matching tool names — keeping the
schema on the server and the implementation on the client in sync.
Local ``Agent`` vs deployed prompt agent — compare & contrast when calling
``run`` on each:
* **Runtime / latency.** ``Agent.run`` issues a single ``responses.create``
call against the Foundry Responses API. ``FoundryAgent.run`` against a
published prompt agent goes through the Foundry Agents service, which
resolves the stored ``PromptAgentDefinition`` (instructions, tools,
generation parameters, RAI config) on every call before forwarding to the
model. Expect a small per-call overhead on the deployed path in exchange
for centrally managed configuration.
* **Configurability.** With the local ``Agent``, model, instructions, tools,
``default_options``, etc. live in your process — change them, restart, and
the next ``run`` picks them up. With the deployed prompt agent, those same
fields are versioned server-side: publishing a new version updates every
consumer at once and you keep an audit trail of previous versions, but you
must call ``create_version`` (or pin ``agent_version``) to roll changes
out or back.
* **Persistence / sharing.** A local ``Agent`` instance only exists for the
lifetime of the process that created it; tools and instructions are not
discoverable by anything else. A published prompt agent is a first-class
Foundry resource — other services, other languages, and the Foundry portal
can all bind to it by ``agent_name`` (+ optional ``agent_version``) and get
the same behaviour. Local ``@tool`` callables stay on the client; only
their JSON schema is persisted, so the implementation must be supplied
again at connection time via ``FoundryAgent(tools=[...])``.
``to_prompt_agent`` is experimental
(``ExperimentalFeature.TO_PROMPT_AGENT``) and may change before being released.
"""
@tool
def book_hotel(
city: Annotated[str, Field(description="The city to book the hotel in.")],
nights: Annotated[int, Field(description="Number of nights to stay.")],
) -> str:
"""Book a hotel room for the given city and number of nights."""
return f"Booked a hotel in {city} for {nights} nights. Confirmation #CTX-{randint(1000, 9999)}."
async def main() -> None:
print("=== Foundry Prompt Agent: Convert, Publish, Connect, and Run ===\n")
project_endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
model = os.environ["FOUNDRY_MODEL"]
# Use ``async with`` so the credential and project client are closed even if the
# body below raises. The ``try/finally`` around ``delete`` further guarantees we
# don't leave an orphaned prompt agent in the Foundry project after a failure.
async with (
AzureCliCredential() as credential,
AIProjectClient(endpoint=project_endpoint, credential=credential) as project_client,
):
# 1) Define the Agent. `name` / `description` set here become the Foundry agent identity
# on publish; `book_hotel` is the local implementation that backs the published declaration.
agent = Agent(
client=FoundryChatClient(
project_endpoint=project_endpoint,
model=model,
credential=credential,
),
name="travel-agent",
description="Helps Contoso employees book travel.",
instructions="You are a helpful travel assistant. Use the booking tool when asked.",
tools=[
FoundryChatClient.get_web_search_tool(),
book_hotel,
],
default_options={"reasoning": {"effort": "medium"}},
)
query = "Book me a hotel in Seattle for 3 nights."
# 2) Run the local Agent. This calls the Foundry Responses API directly — instructions,
# tools, and generation parameters live in this process only.
print(f"User (local Agent): {query}")
local_result = await agent.run(query)
print(f"Local Agent: {local_result}\n")
# 3) Convert and publish. The version returned by Foundry includes the version label
# we need when connecting back to that specific deployment.
if agent.name is None:
raise ValueError("Agent name is required to create a prompt agent version.")
created = await project_client.agents.create_version(
agent_name=agent.name,
# note this line:
definition=to_prompt_agent(agent),
description=agent.description,
)
print(f"Published prompt agent: {created.name} v{created.version}\n")
try:
# 4) Connect to the deployed prompt agent with FoundryAgent and pass the *same* callable
# tool. FoundryAgent runs the local function when the server-side agent invokes the tool,
# matching by name. Compared to step 2, instructions/tools/generation parameters now
# come from the stored PromptAgentDefinition rather than this process.
deployed = FoundryAgent(
project_endpoint=project_endpoint,
agent_name=created.name,
agent_version=created.version,
credential=credential,
tools=[book_hotel],
)
print(f"User (deployed agent): {query}")
deployed_result = await deployed.run(query)
print(f"Deployed Agent: {deployed_result}")
finally:
# 5) Cleanup: delete the deployed prompt agent (and all its versions) even if step 4
# raised, so re-running the sample stays idempotent and we don't leak resources in
# the Foundry project.
await project_client.agents.delete(agent_name=created.name)
print(f"\nDeleted prompt agent {created.name!r} and all its versions.")
if __name__ == "__main__":
asyncio.run(main())