Claude Platform Docs
Managed AgentsСамостоятельно размещаемые песочницы

Пользовательские инструменты в самостоятельно размещаемых песочницах

Предоставляйте пользовательские инструменты из воркера самостоятельно размещаемой песочницы и оборачивайте MCP-сервер внутри вашей сети в пользовательские инструменты без запуска туннеля.

Пользовательские инструменты — это инструменты, которые выполняет ваш собственный код: агент генерирует событие agent.custom_tool_use и ожидает соответствующего user.custom_tool_result. Этим кодом может быть ваш «worker» (воркер). Поскольку он работает внутри вашей песочницы, инструмент получает доступ к внутренним сервисам, учётным данным и исходящему сетевому трафику, которые вы настроили для песочницы, и ни к чему больше.

Ключ среды авторизует отправку результатов пользовательских инструментов, поэтому ваш ключ API Claude не попадает на хост воркера.

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

  1. Объявите инструмент в агенте

    Добавьте запись custom в tools агента, у которой name совпадает с инструментом, регистрируемым вашим воркером. Полную структуру объявления см. в разделе Пользовательские инструменты.

    {
      "type": "custom",
      "name": "get_order_status",
      "description": "Look up an order in the internal fulfillment system by order ID.",
      "input_schema": {
        "type": "object",
        "properties": {
          "order_id": { "type": "string", "description": "The order ID" }
        },
        "required": ["order_id"]
      }
    }
  2. Зарегистрируйте реализацию в воркере

    Передайте инструмент через фабрику tools воркера (см. EnvironmentWorker) вместе со встроенным набором инструментов:

    import asyncio
    import os
    from anthropic import AsyncAnthropic, beta_async_tool
    from anthropic.lib.environments import EnvironmentWorker
    from anthropic.lib.tools.agent_toolset import beta_agent_toolset_20260401
    
    
    @beta_async_tool
    async def get_order_status(order_id: str) -> str:
        """Look up an order in the internal fulfillment system by order ID."""
        # Выполняется на хосте воркера: можно вызывать всё, к чему у песочницы есть доступ.
        return f"Order {order_id}: shipped"
    
    
    async def main() -> None:
        environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
        environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
        async with AsyncAnthropic(auth_token=environment_key) as client:
            await EnvironmentWorker(
                client,
                environment_id=environment_id,
                environment_key=environment_key,
                workdir="/workspace",
                tools=lambda env: [*beta_agent_toolset_20260401(env), get_order_status],
            ).run()
    
    
    asyncio.run(main())

Воркер отвечает только на вызовы зарегистрированных в нём инструментов. Если инструмент объявлен в агенте, но ни один воркер или клиент его не обслуживает, сеанс приостанавливается с причиной остановки requires_action. Он остаётся приостановленным, пока что-либо не отправит результат. Описание потока событий см. в разделе Обработка вызовов пользовательских инструментов.

Обёртывание MCP-сервера в пользовательские инструменты

Коннектор MCP подключается к MCP-серверам со стороны Anthropic. Поэтому сервер должен предоставлять конечную точку HTTP, доступную для Anthropic напрямую или через MCP-туннель.

Чтобы использовать сервер, доступный только из вашей сети, сделайте MCP-клиентом воркер и объявите инструменты сервера как пользовательские инструменты. MCP-серверу не требуется входящее подключение извне вашей сети. Anthropic получает определения инструментов, которые вы объявляете в агенте, входные данные каждого вызова и результат, который отправляет обратно ваш воркер.

Во время выполнения модель вызывает обёрнутый инструмент так же, как любой другой пользовательский инструмент:

  1. Агент генерирует событие agent.custom_tool_use.
  2. Воркер внутри вашей песочницы перенаправляет вызов через открытую MCP-сессию на сервер в вашей сети.
  3. Воркер отправляет ответ сервера в виде user.custom_tool_result.

Установка MCP SDK

Клиентские вспомогательные функции MCP в SDK преобразуют инструменты сервера в исполняемые инструменты, которые принимает воркер. Установите MCP SDK вместе с Anthropic SDK: pip install "anthropic[mcp]" "mcp>=1.24".

Примеры подключаются без аутентификации. Чтобы передавать учётные данные, настройте http_client, который вы передаёте транспорту MCP.

Объявление и предоставление инструментов

  1. Объявите инструменты сервера в агенте

    Получите список инструментов MCP-сервера и объявите каждый из них как инструмент custom. Поля MCP name, description и inputSchema один к одному соответствуют полям пользовательского инструмента. Если сервер разбивает список инструментов на страницы, объявите все страницы; воркер должен получать те же страницы.

    import asyncio
    from typing import Any, cast
    from anthropic import AsyncAnthropic
    from anthropic.types.beta import BetaManagedAgentsCustomToolParams
    from mcp import ClientSession, types
    # Требуется mcp >= 1.24, где streamablehttp_client переименован в streamable_http_client.
    from mcp.client.streamable_http import streamable_http_client
    
    MCP_SERVER_URL = "http://mcp.internal.example.com:8000/mcp"
    
    
    def to_custom_tool(tool: types.Tool) -> BetaManagedAgentsCustomToolParams:
        # Поля MCP один к одному соответствуют объявлению пользовательского инструмента. Приведение типа
        # передаёт словарь схемы в типизированный параметр SDK без изменений.
        return {
            "type": "custom",
            "name": tool.name,
            "description": tool.description or tool.name,
            "input_schema": cast(Any, tool.inputSchema),
        }
    
    
    async def main() -> None:
        # Запускайте это там, где вы создаёте агентов, а не на рабочем хосте: скрипт
        # аутентифицируется с помощью вашего ключа API Claude (ANTHROPIC_API_KEY).
        async with (
            streamable_http_client(MCP_SERVER_URL) as (read, write, _),
            ClientSession(read, write) as mcp_session,
            AsyncAnthropic() as client,
        ):
            await mcp_session.initialize()
            listed = await mcp_session.list_tools()
            agent = await client.beta.agents.create(
                name="Internal tools agent",
                model="claude-opus-5-5",
                tools=[
                    {"type": "agent_toolset_20260401"},
                    *[to_custom_tool(tool) for tool in listed.tools],
                ],
            )
            print(agent.id)
    
    
    asyncio.run(main())
  2. Предоставьте инструменты из воркера

    При запуске подключитесь к тому же MCP-серверу, преобразуйте его инструменты с помощью async_mcp_tool и зарегистрируйте их вместе с beta_agent_toolset_20260401. Держите одну MCP-сессию открытой на протяжении всего времени работы воркера.

    import asyncio
    import os
    from datetime import timedelta
    from anthropic import AsyncAnthropic
    from anthropic.lib.environments import EnvironmentWorker
    from anthropic.lib.tools.agent_toolset import beta_agent_toolset_20260401
    from anthropic.lib.tools.mcp import async_mcp_tool
    from mcp import ClientSession
    # Требуется mcp >= 1.24, где streamablehttp_client переименован в streamable_http_client.
    from mcp.client.streamable_http import streamable_http_client
    
    MCP_SERVER_URL = "http://mcp.internal.example.com:8000/mcp"
    
    
    async def main() -> None:
        environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
        environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
        # Подключаемся к серверу MCP один раз при запуске и держим сессию открытой
        # на всё время жизни воркера. Тайм-аут превращает зависший вызов инструмента в результат
        # с ошибкой вместо застрявшего вызова.
        async with (
            streamable_http_client(MCP_SERVER_URL) as (read, write, _),
            ClientSession(read, write, read_timeout_seconds=timedelta(seconds=60)) as mcp_session,
            AsyncAnthropic(auth_token=environment_key) as client,
        ):
            await mcp_session.initialize()
            listed = await mcp_session.list_tools()
            mcp_tools = [async_mcp_tool(tool, mcp_session) for tool in listed.tools]
            await EnvironmentWorker(
                client,
                environment_id=environment_id,
                environment_key=environment_key,
                workdir="/workspace",
                tools=lambda env: [*beta_agent_toolset_20260401(env), *mcp_tools],
            ).run()
    
    
    asyncio.run(main())

Ограничения и поведение

Инструменты объявляются, а не обнаруживаются во время выполнения

Воркер получает список инструментов MCP-сервера один раз при запуске и не может добавлять инструменты в работающий сеанс. Когда инструменты сервера меняются:

  1. Объявите их заново — в агенте или в неактивном сеансе, как описано в разделе Обновление конфигурации агента.
  2. Перезапустите воркер.

Объявления должны соответствовать Managed Agents API

Вспомогательные функции MCP сохраняют имена и описания сервера, и большинство схем передаются без изменений. Переименуйте, сократите или встройте определения там, где объявление нарушает одно из следующих правил:

ПолеПравило
nameУникально в пределах агента. Буквы, цифры, подчёркивания и дефисы, от 1 до 128 символов. Не может совпадать со встроенным инструментом агента, например bash или read, или использовать зарезервированный префикс mcp__.
descriptionОбязательно и не может быть пустым.
input_schemaПринимает ключевые слова JSON Schema, которые обычно генерируют MCP-серверы, например additionalProperties и title. Отклоняет ссылочные ключевые слова, такие как $ref, в любом месте, а также oneOf, anyOf и allOf на верхнем уровне. Имена свойств состоят из букв, цифр, подчёркиваний, точек и дефисов, от 1 до 64 символов.
Массив tools агентаНе более 128 записей. Каждый обёрнутый инструмент — одна запись, и встроенный набор инструментов — ещё одна.

Два случая требуют дополнительной работы:

  • Два сервера предоставляют инструмент с одинаковым именем: определите обёртку самостоятельно под именем с префиксом и сделайте так, чтобы она вызывала исходное имя инструмента на сервере.
  • Генератор, например pydantic, выносит схемы в $defs: встройте эти схемы перед объявлением инструмента.

Сбои инструментов возвращаются как результаты инструментов с ошибкой

Когда MCP-сервер сообщает об ошибке инструмента, воркер отправляет результат инструмента с ошибкой, на который модель может отреагировать. Содержимое MCP, не имеющее эквивалента в результатах инструментов, например аудиоблоки и ссылки на ресурсы, также возвращается как ошибка.

Установите тайм-аут в MCP-клиенте, чтобы сбой происходил быстрее и был понятнее, как это делает пример воркера на Python с помощью read_timeout_seconds. О том, что происходит без тайм-аута, см. в разделе Вызов обёрнутого инструмента MCP зависает.

Оборачивайте только серверы, которыми вы управляете или которым доверяете

Имя, описание и результаты обёрнутого инструмента попадают в контекст модели так же, как и у любого другого инструмента. Это недоверенные входные данные, которые могут влиять на то, что агент делает с другими своими инструментами, включая bash на хосте воркера. Объявляйте только те инструменты, которые агент должен использовать.

Политики разрешений не применяются

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

Was this page helpful?