Набор инструментов Microsoft Foundry

Набор инструментов Microsoft Foundry — это именованный версионируемый серверный пакет конфигураций размещённых инструментов, таких как интерпретатор кода, поиск по файлам, генерация изображений, MCP и веб-поиск. Панели элементов позволяют управлять конфигурацией инструментов один раз в Foundry и повторно использовать ее в разных агентах.

Agent Framework охватывает использование панели элементов. Создавайте и обновляйте версии Toolbox с помощью портала Foundry или azure-ai-projects SDK.

Это важно

FoundryToolbox предоставляется бета-пакетом agent-framework-foundry-hosting и может изменяться до стабильного выпуска.

Для FoundryAgent, управляемого службой, прикрепите Toolbox к определению агента в Foundry.

Для размещенного агента, созданного с помощью Microsoft Agent Framework, используйте AddFoundryToolboxes из Microsoft.Agents.AI.Foundry.Hosting, как показано в следующем примере.

Используйте веб-проект .NET 10 с включёнными неявными using-директивами, с согласованными версиями Microsoft.Agents.AI.Foundry, Microsoft.Agents.AI.Foundry.Hosting и DotNetEnv. Установите TOOLBOX_NAME на существующий набор средств, а FOUNDRY_MODEL — на развертывание вашей модели. Foundry поставляет FOUNDRY_PROJECT_ENDPOINT развернутому хосту. Для доступа к локальной модели задайте FOUNDRY_PROJECT_ENDPOINT и войдите с помощью Azure CLI. Размещенные развертывания переключаются на azd-managed AZURE_AI_MODEL_DEPLOYMENT_NAME. Интеграция с хостом загружает инструменты набора инструментов, когда доступен FOUNDRY_PROJECT_ENDPOINT.

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 ───────────────────────────────────────────────

Та же регистрация хостинга поддерживает инструменты, настроенные на OAuth-согласие для каждого пользователя в их подключениях к панели инструментов. Пользователям по-прежнему требуются необходимые разрешения и согласие; не требуется отдельный блок регистрации узла.

Инструкции по файлам проекта и развертыванию см. в разделе Hosted-Toolbox. Сведения о настройке согласия для каждого пользователя см. в разделе Hosted-Toolbox-AuthPaths.

Установка пакетов

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

FoundryToolbox импортируется из agent_framework.foundry и поставляется agent-framework-foundry-hosting.

Настройте панель элементов

Задайте явный адрес конечной точки Toolbox MCP:

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

Или позвольте FoundryToolbox создать конечную точку:

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

Примеры размещаемого агента предпочитают FOUNDRY_MODEL локально и переключаются на AZURE_AI_MODEL_DEPLOYMENT_NAME под управлением azd при размещении.

Используйте FoundryToolbox с размещённым агентом

FoundryToolbox определяет свой конечный узел, проверяет подлинность каждого запроса MCP с использованием предоставленных учетных данных Azure, пересылает идентификатор вызова Foundry для каждого запроса и участвует в жизненном цикле подключения агента. Он обрабатывает заголовки платформы на каждой границе операции и повторно подключает его сеанс MCP при изменении фактической идентификации запроса. Поэтому долгоживущий Toolbox не сохраняет идентификатор вызова предыдущего вызывающего компонента.

В примере создаются Toolbox, клиент и учетные данные в фабрике агентов с областью видимости запроса для детерминированного владения и очистки. Используйте этот шаблон фабрики, если связанные ресурсы принадлежат текущему запросу, но он не требуется исключительно для поддержания актуальности идентификаторов вызовов Toolbox.

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()

Когда Toolbox Code Interpreter создает файл и в ответе помощника упоминается этот файл, адаптер Hosted Responses выдает собственную аннотацию container_file_citation с идентификаторами контейнера и файла. Клиенты Responses могут использовать эти идентификаторы для обнаружения и скачивания созданного файла через API файлов контейнеров.

Показать навыки панели инструментов

Набор инструментов может предоставлять навыки агента через MCP. Задайте load_tools=False , если только навыки должны быть видимыми для модели, а затем добавьте панель элементов в качестве инструмента, чтобы его сеанс MCP подключается и используется as_skills_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()

Подтверждение по-прежнему включено по умолчанию для операций с навыками. Отключайте отдельные согласования только для доверенных сценариев без участия пользователя. Держите Toolbox и ее поставщик навыков вместе, чтобы оба использовали один и тот же сеанс MCP. Для долгоживущего Toolbox кэш обнаружения компонентов заменяется при изменении действующего идентификатора заголовка платформы. Пользовательский header_provider, используемый с навыками, должен разрешаться из внешнего состояния, например из замыкания или ContextVar, так как навыки и операции чтения ресурсов не получают аргументы времени выполнения функции.

Используйте панель элементов с FoundryAgent

Подключите Toolbox к определению Prompt Agent или Hosted Agent в Foundry. FoundryAgent использует эту сохранённую конфигурацию инструмента; передача Toolbox на стороне клиента не добавляет его в управляемый агент.

Подключение через MCP с помощью FoundryToolbox

Используйте FoundryToolbox с ResponsesHostServer, чтобы подключить размещённый агент к конечной точке Toolbox MCP. Обёртка проверяет подлинность запросов MCP и передаёт контекст вызывающей стороны текущего размещённого запроса для сквозной передачи удостоверения пользователя. Фабрика с областью действия agent запроса остается самым простым вариантом, когда клиенту, учетным данным и Toolbox требуется одна граница очистки. Долговременный Toolbox также поддерживается и повторно подключается перед операцией при изменении идентификатора platform-header.

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()

Задайте TOOLBOX_ENDPOINT либо оба параметра FOUNDRY_PROJECT_ENDPOINT и TOOLBOX_NAME, как описано в разделе Настройка панели элементов. Установите FOUNDRY_MODEL для локальных запусков; размещенные развертывания используют по умолчанию azd-managed AZURE_AI_MODEL_DEPLOYMENT_NAME.

Если для операции Toolbox или MCP требуется согласие OAuth, потоковые и непотоковые вызовы FoundryAgent и FoundryChatClient возвращают Content(type="oauth_consent_request") со ссылкой для предоставления согласия вместо пустого сообщения помощника. Обработайте это содержимое как запрос ввода пользователем и представьте его consent_link пользователю.

Клиент отображает только ссылки со схемой HTTPS и допустимым хостом. Отсутствующие или недопустимые ссылки пропускаются и регистрируются.

Ограничения

  • Инструменты MCP внутри Toolbox используют серверную аутентификацию через Foundry project_connection_id; клиент Agent Framework не хранит bearer-токен вышестоящего MCP-сервера.
  • Для использования Toolbox в качестве сервера MCP требуется клиентская аутентификация Entra ID для конечной точки Toolbox.
  • Ответы на поток согласия, такие как CONSENT_REQUIRED обрабатываются во время выполнения агента, а не при создании подключения к панели элементов.

Samples

Sample Описание
foundry_toolbox/main.py FoundryToolbox с размещённым агентом Responses
foundry_toolbox_mcp_skills/main.py Навыки агента с поддержкой панели элементов
foundry_chat_client_with_toolbox.py Использование набора инструментов MCP с MCPStreamableHTTPTool
foundry_chat_client_with_toolbox_skills.py Настройка навыков на основе панели инструментов
invoke_foundry_toolbox_mcp Использование MCP на стороне рабочего процесса

В настоящее время Go не предоставляет вспомогательный компонент Foundry Toolbox. Настройте наборы инструментов через Foundry и используйте поддерживаемые локальные или размещённые объявления инструментов для агентов на Go.