Muokkaa

Microsoft Foundry Toolbox

A Microsoft Foundry Toolbox is a named, versioned server-side bundle of hosted tool configurations, such as code interpreter, file search, image generation, MCP, and web search. Toolboxes let you manage tool configuration once in Foundry and reuse it across agents.

Agent Framework covers Toolbox consumption. Create and update Toolbox versions through the Foundry portal or the azure-ai-projects SDK.

Important

FoundryToolbox is provided by the beta agent-framework-foundry-hosting package and can change before stable release.

For a service-managed FoundryAgent, attach the Toolbox to the agent definition in Foundry.

For a hosted agent built with Microsoft Agent Framework, use AddFoundryToolboxes from Microsoft.Agents.AI.Foundry.Hosting, as shown in the following example.

Use a .NET 10 web project with implicit usings enabled, matching versions of Microsoft.Agents.AI.Foundry and Microsoft.Agents.AI.Foundry.Hosting, and DotNetEnv. Set TOOLBOX_NAME to an existing toolbox and FOUNDRY_MODEL to your model deployment. Foundry supplies FOUNDRY_PROJECT_ENDPOINT to the deployed host. For local model access, set FOUNDRY_PROJECT_ENDPOINT and sign in with Azure CLI. Hosted deployments fall back to the azd-managed AZURE_AI_MODEL_DEPLOYMENT_NAME. The hosting integration loads toolbox tools when FOUNDRY_PROJECT_ENDPOINT is available.

using DotNetEnv;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Foundry.Hosting;

// Load .env file if present (for local development)
Env.TraversePath().Load();

string endpoint = System.Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
    ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = FirstNonBlank(
    System.Environment.GetEnvironmentVariable("FOUNDRY_MODEL"),
    System.Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME"),
    "gpt-4o")!;
string toolboxName = FirstNonBlank(
    System.Environment.GetEnvironmentVariable("TOOLBOX_NAME"),
    "my-toolset")!;

// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
// Use a chained credential: try a temporary dev token first (for local Docker debugging),
// then fall back to DefaultAzureCredential (for local dev via dotnet run / managed identity in production).
    .AsAIAgent(
        model: deploymentName,
            Use the available tools to answer user questions.
            If a tool is not available for a request, let the user know clearly.
            """,
        name: System.Environment.GetEnvironmentVariable("AGENT_NAME") ?? "hosted-toolbox-agent",
        description: "Hosted agent backed by Foundry Toolbox MCP tools");

// ── Build the host ────────────────────────────────────────────────────────────

var builder = WebApplication.CreateBuilder(args);

// Register the agent and response handler
// Register Foundry Toolbox: connects to the MCP proxy at startup and makes tools available.
// The toolbox name must match a toolbox registered in your Foundry project.
// When FOUNDRY_PROJECT_ENDPOINT is absent (e.g., in local development without Foundry
// infrastructure), startup succeeds without error and no toolbox tools are loaded.
builder.Services.AddFoundryToolboxes(credential, toolboxName);

app.Run();

static string? FirstNonBlank(params string?[] candidates) =>
    Array.Find(candidates, candidate => !string.IsNullOrWhiteSpace(candidate));

// ── DevTemporaryTokenCredential ───────────────────────────────────────────────

The same hosting registration supports tools configured for per-user OAuth consent on their toolbox connections. Users still need the required permissions and consent; no separate host-registration block is needed.

For the project files and deployment instructions, see Hosted-Toolbox. For per-user consent setup, see Hosted-Toolbox-AuthPaths.

Install the packages

pip install agent-framework-foundry-hosting agent-framework-foundry --pre

FoundryToolbox is imported from agent_framework.foundry and supplied by agent-framework-foundry-hosting.

Configure the Toolbox

Set an explicit Toolbox MCP endpoint:

TOOLBOX_ENDPOINT="https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<name>/mcp?api-version=v1"

Or let FoundryToolbox construct the endpoint:

FOUNDRY_PROJECT_ENDPOINT="https://<account>.services.ai.azure.com/api/projects/<project>"
TOOLBOX_NAME="<toolbox-name>"

The hosted-agent samples prefer FOUNDRY_MODEL locally and fall back to the azd-managed AZURE_AI_MODEL_DEPLOYMENT_NAME when hosted.

Use FoundryToolbox with a hosted agent

FoundryToolbox resolves its endpoint, authenticates every MCP request with the supplied Azure credential, forwards the Foundry per-request call ID, and participates in the agent's connection lifecycle. It resolves platform headers at each operation boundary and reconnects its MCP session when the effective request identity changes. A long-lived Toolbox therefore doesn't retain an earlier caller's call ID.

The sample creates the Toolbox, client, and credential inside the request-scoped agent factory for deterministic ownership and cleanup. Use this factory pattern when related resources are request-owned, but it isn't required solely to keep Toolbox call IDs current.

import asyncio
import os
from contextlib import AsyncExitStack
from types import TracebackType

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient, FoundryToolbox
from agent_framework_foundry_hosting import ResponsesHostServer
from azure.ai.agentserver.core import AgentConfig, get_request_context
from azure.identity.aio import AzureCliCredential, ManagedIdentityCredential
from dotenv import load_dotenv


def create_agent() -> Agent:
    """Create request-owned SDK resources and close them with the agent."""
    endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
    model = os.environ.get("FOUNDRY_MODEL") or os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"]
    credential = (
        ManagedIdentityCredential(client_id=os.environ.get("FOUNDRY_AGENT_INSTANCE_CLIENT_ID"))
        if AgentConfig.from_env().is_hosted
        else AzureCliCredential()
    )

    class RequestClient(FoundryChatClient):
        async def __aenter__(self) -> RequestClient:
            return self

        async def __aexit__(
            self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None
        ) -> None:
            async with AsyncExitStack() as cleanup:
                cleanup.push_async_callback(credential.close)
                cleanup.push_async_callback(self.project_client.close)
                cleanup.push_async_callback(self.client.close)

    toolbox = FoundryToolbox(credential)
    client = RequestClient(
        project_endpoint=endpoint,
        model=model,
        credential=credential,
        default_headers=get_request_context().platform_headers(),
    )
    return Agent(
        client=client,
        instructions="You are a friendly assistant. Keep your answers brief.",
        tools=toolbox,
    )


async def main() -> None:
    load_dotenv()
    server = ResponsesHostServer(agent=create_agent, history_source="agent_server")
    await server.run_async()

When Toolbox Code Interpreter produces a file and the assistant response names that file, the hosted Responses adapter emits a native container_file_citation annotation with the container and file IDs. Responses clients can use those IDs to discover and download the generated file through the container files API.

Expose Toolbox skills

A Toolbox can expose Agent Skills over MCP. Set load_tools=False when only skills should be model-visible, then add the Toolbox as a tool so its MCP session connects and use as_skills_provider() as a context provider.

import asyncio
import os
from contextlib import AsyncExitStack
from types import TracebackType

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient, FoundryToolbox
from agent_framework_foundry_hosting import ResponsesHostServer
from azure.ai.agentserver.core import AgentConfig, get_request_context
from azure.identity.aio import AzureCliCredential, ManagedIdentityCredential
from dotenv import load_dotenv


def create_agent() -> Agent:
    """Keep skill caches, credentials and the MCP lifecycle request-owned."""
    endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
    model = os.environ.get("FOUNDRY_MODEL") or os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"]
    credential = (
        ManagedIdentityCredential(client_id=os.environ.get("FOUNDRY_AGENT_INSTANCE_CLIENT_ID"))
        if AgentConfig.from_env().is_hosted
        else AzureCliCredential()
    )

    class RequestClient(FoundryChatClient):
        async def __aenter__(self) -> RequestClient:
            return self

        async def __aexit__(
            self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None
        ) -> None:
            async with AsyncExitStack() as cleanup:
                cleanup.push_async_callback(credential.close)
                cleanup.push_async_callback(self.project_client.close)
                cleanup.push_async_callback(self.client.close)

    # tools= connects the MCP session; context_providers= reads skills from that same session.
    toolbox = FoundryToolbox(credential, load_tools=False)
    skills_provider = toolbox.as_skills_provider(disable_load_skill_approval=True)
    client = RequestClient(
        project_endpoint=endpoint,
        model=model,
        credential=credential,
        default_headers=get_request_context().platform_headers(),
    )
    return Agent(
        client=client,
        name=os.environ.get("AGENT_NAME", "hosted-toolbox-mcp-skills"),
        instructions="You are a helpful assistant.",
        tools=toolbox,
        context_providers=[skills_provider],
    )


async def main() -> None:
    load_dotenv()
    server = ResponsesHostServer(agent=create_agent, history_source="agent_server")
    await server.run_async()

Approval remains enabled by default for skill operations. Disable individual approvals only for trusted, unattended scenarios. Keep the Toolbox and its skills provider together so both use the same MCP session. For a long-lived Toolbox, the skill discovery cache is replaced when the effective platform-header identity changes. A custom header_provider used with skills must resolve from ambient state, such as a closure or ContextVar, because skill and resource reads don't receive function runtime arguments.

Use a Toolbox with FoundryAgent

Attach the Toolbox to the Prompt or Hosted Agent definition in Foundry. FoundryAgent uses that stored tool configuration; passing a Toolbox client-side doesn't add it to the managed agent.

Connect through MCP with FoundryToolbox

Use FoundryToolbox with ResponsesHostServer to connect a hosted agent to the Toolbox MCP endpoint. The wrapper authenticates MCP requests and forwards the current hosted request's caller context for per-user identity passthrough. The request-scoped agent factory remains the simplest option when the client, credential, and Toolbox need one cleanup boundary. A long-lived Toolbox is also supported and reconnects before an operation when the platform-header identity changes.

import asyncio
import os
from contextlib import AsyncExitStack
from types import TracebackType

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient, FoundryToolbox
from agent_framework_foundry_hosting import ResponsesHostServer
from azure.ai.agentserver.core import AgentConfig, get_request_context
from azure.identity.aio import AzureCliCredential, ManagedIdentityCredential
from dotenv import load_dotenv


def create_agent() -> Agent:
    """Create request-owned SDK resources and close them with the agent."""
    endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
    model = os.environ.get("FOUNDRY_MODEL") or os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"]
    credential = (
        ManagedIdentityCredential(client_id=os.environ.get("FOUNDRY_AGENT_INSTANCE_CLIENT_ID"))
        if AgentConfig.from_env().is_hosted
        else AzureCliCredential()
    )

    class RequestClient(FoundryChatClient):
        async def __aenter__(self) -> RequestClient:
            return self

        async def __aexit__(
            self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None
        ) -> None:
            async with AsyncExitStack() as cleanup:
                cleanup.push_async_callback(credential.close)
                cleanup.push_async_callback(self.project_client.close)
                cleanup.push_async_callback(self.client.close)

    toolbox = FoundryToolbox(credential)
    client = RequestClient(
        project_endpoint=endpoint,
        model=model,
        credential=credential,
        default_headers=get_request_context().platform_headers(),
    )
    return Agent(
        client=client,
        instructions="You are a friendly assistant. Keep your answers brief.",
        tools=toolbox,
    )


async def main() -> None:
    load_dotenv()
    server = ResponsesHostServer(agent=create_agent, history_source="agent_server")
    await server.run_async()

Set TOOLBOX_ENDPOINT, or set both FOUNDRY_PROJECT_ENDPOINT and TOOLBOX_NAME, as described in Configure the Toolbox. Set FOUNDRY_MODEL for local runs; hosted deployments fall back to the azd-managed AZURE_AI_MODEL_DEPLOYMENT_NAME.

Limitations

  • MCP tools inside a Toolbox use server-side authentication through a Foundry project_connection_id; the Agent Framework client doesn't hold the upstream MCP bearer token.
  • Consuming a Toolbox as an MCP server requires client-side Entra ID authentication for the Toolbox endpoint.
  • Consent-flow responses such as CONSENT_REQUIRED are handled while the agent runs, not while the Toolbox connection is created.

Samples

Sample Description
foundry_toolbox/main.py FoundryToolbox with a hosted Responses agent
foundry_toolbox_mcp_skills/main.py Toolbox-backed Agent Skills
foundry_chat_client_with_toolbox.py Toolbox MCP consumption with MCPStreamableHTTPTool
foundry_chat_client_with_toolbox_skills.py Toolbox-backed skills configuration
invoke_foundry_toolbox_mcp Workflow-side MCP consumption

Go doesn't currently expose a Foundry Toolbox helper. Configure Toolboxes through Foundry and use supported local or hosted tool declarations for Go agents.