Claude Platform Docs
Managed AgentsSandboxes autoalojados

Herramientas personalizadas en sandboxes autoalojados

Sirve herramientas personalizadas desde un worker de sandbox autoalojado y envuelve un servidor MCP dentro de tu red como herramientas personalizadas sin ejecutar un túnel.

Las herramientas personalizadas son herramientas que ejecuta tu propio código: el agente emite un evento agent.custom_tool_use y espera un user.custom_tool_result correspondiente. Tu worker puede ser ese código. Como se ejecuta dentro de tu sandbox, la herramienta alcanza los servicios internos, las credenciales y la salida de red que configuraste para el sandbox, y nada más.

La clave del entorno autoriza la publicación de resultados de herramientas personalizadas, por lo que tu clave de API de Claude se mantiene fuera del host del worker.

Servir una herramienta personalizada

  1. Declara la herramienta en el agente

    Agrega una entrada custom a las tools del agente cuyo name coincida con la herramienta que registra tu worker. Consulta Herramientas personalizadas para ver la forma completa de la declaración.

    {
      "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. Registra la implementación en el worker

    Pasa la herramienta a través de la fábrica tools del worker (consulta EnvironmentWorker), junto con el conjunto de herramientas integrado:

    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."""
        # Se ejecuta en el host del worker: llama a cualquier cosa que el sandbox pueda alcanzar.
        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())

El worker responde solo a las herramientas registradas en él. Si una herramienta está declarada en el agente pero ningún worker ni cliente la sirve, la sesión se pausa con un motivo de detención requires_action. Permanece en pausa hasta que algo publique el resultado. Consulta Manejo de llamadas a herramientas personalizadas para ver el flujo de eventos.

Envolver un servidor MCP como herramientas personalizadas

El conector MCP se conecta a servidores MCP desde el lado de Anthropic. Por lo tanto, un servidor debe exponer un endpoint HTTP al que Anthropic pueda llegar, directamente o a través de un túnel MCP.

Para usar un servidor al que solo tu red puede llegar, haz que el worker sea el cliente MCP y declara las herramientas del servidor como herramientas personalizadas. El servidor MCP no necesita conectividad entrante desde fuera de tu red. Anthropic recibe las definiciones de herramientas que declaras en el agente, la entrada de cada llamada y el resultado que tu worker publica de vuelta.

En tiempo de ejecución, el modelo llama a una herramienta envuelta como a cualquier otra herramienta personalizada:

  1. El agente emite un evento agent.custom_tool_use.
  2. El worker, dentro de tu sandbox, reenvía la llamada a través de su sesión MCP abierta al servidor en tu red.
  3. El worker publica la respuesta del servidor como el user.custom_tool_result.

Instalar un SDK de MCP

Los helpers de MCP del lado del cliente del SDK convierten las herramientas del servidor en las herramientas ejecutables que acepta el worker. Instala un SDK de MCP junto con el SDK de Anthropic: pip install "anthropic[mcp]" "mcp>=1.24".

Los ejemplos se conectan sin autenticación. Para enviar credenciales, configura el http_client que le pasas al transporte MCP.

Declarar y servir las herramientas

  1. Declara las herramientas del servidor en el agente

    Lista las herramientas del servidor MCP y declara cada una como una herramienta custom. Los campos name, description e inputSchema de MCP se asignan uno a uno a los campos de la herramienta personalizada. Si el servidor pagina su lista de herramientas, declara todas las páginas; el worker debe listar las mismas páginas.

    import asyncio
    from typing import Any, cast
    from anthropic import AsyncAnthropic
    from anthropic.types.beta import BetaManagedAgentsCustomToolParams
    from mcp import ClientSession, types
    # Requiere mcp >= 1.24, que renombró streamablehttp_client a 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:
        # Los campos MCP se corresponden uno a uno con una declaración de herramienta personalizada. El cast
        # entrega el diccionario del esquema al parámetro tipado del SDK sin cambios.
        return {
            "type": "custom",
            "name": tool.name,
            "description": tool.description or tool.name,
            "input_schema": cast(Any, tool.inputSchema),
        }
    
    
    async def main() -> None:
        # Ejecuta esto donde crees los agentes, no en el host worker:
        # se autentica con tu clave de API de 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. Sirve las herramientas desde el worker

    Conéctate al mismo servidor MCP al iniciar, convierte sus herramientas con async_mcp_tool y regístralas junto con beta_agent_toolset_20260401. Mantén una sesión MCP abierta durante toda la vida del worker.

    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
    # Requiere mcp >= 1.24, que renombró streamablehttp_client a 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"]
        # Conéctate al servidor MCP una vez al inicio y mantén la sesión abierta durante
        # la vida del worker. El timeout convierte una llamada a herramienta colgada en un
        # resultado de error en lugar de una llamada estancada.
        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())

Límites y comportamiento

Las herramientas se declaran, no se descubren en tiempo de ejecución

El worker lista las herramientas del servidor MCP una vez al iniciar y no puede agregar herramientas a una sesión en ejecución. Cuando cambien las herramientas del servidor:

  1. Vuelve a declararlas, en el agente o en una sesión inactiva mediante Actualizar la configuración del agente.
  2. Reinicia el worker.

Las declaraciones deben ajustarse a la API de Managed Agents

Los helpers de MCP conservan los nombres y descripciones del servidor, y la mayoría de los esquemas pasan sin cambios. Cambia el nombre, recorta o inserta en línea cuando una declaración infrinja una de estas reglas:

CampoRegla
nameÚnico por agente. Letras, dígitos, guiones bajos y guiones, de 1 a 128 caracteres. No puede coincidir con una herramienta integrada del agente como bash o read, ni usar el prefijo reservado mcp__.
descriptionObligatorio y no vacío.
input_schemaAcepta las palabras clave de JSON Schema que los servidores MCP emiten comúnmente, como additionalProperties y title. Rechaza palabras clave de referencia como $ref en cualquier lugar, y oneOf, anyOf y allOf en el nivel superior. Los nombres de propiedades usan letras, dígitos, guiones bajos, puntos y guiones, de 1 a 64 caracteres.
El arreglo tools del agenteComo máximo 128 entradas. Cada herramienta envuelta es una entrada, y el conjunto de herramientas integrado es una más.

Dos casos requieren trabajo adicional:

  • Dos servidores exponen el mismo nombre de herramienta: Define tú mismo el envoltorio con un nombre con prefijo y haz que llame al nombre original de la herramienta del servidor.
  • Un generador como pydantic factoriza los esquemas en $defs: Inserta esos esquemas en línea antes de declarar la herramienta.

Los fallos de herramientas aparecen como resultados de herramienta con error

Cuando el servidor MCP informa un error de herramienta, el worker publica un resultado de herramienta con error al que el modelo puede reaccionar. El contenido MCP sin equivalente en resultados de herramienta, como bloques de audio y enlaces a recursos, también aparece como error.

Establece un tiempo de espera en el cliente MCP para obtener un fallo más rápido y claro, como hace el ejemplo del worker de Python con read_timeout_seconds. Consulta Una llamada a herramienta MCP envuelta se bloquea para saber qué ocurre sin uno.

Envuelve solo servidores que operas o en los que confías

El nombre, la descripción y los resultados de una herramienta envuelta entran en el contexto del modelo como los de cualquier otra herramienta. Son entradas no confiables que pueden influir en lo que el agente hace con sus otras herramientas, incluido bash en el host del worker. Declara solo las herramientas que quieres que use el agente.

Las políticas de permisos no se aplican

Las políticas de permisos rigen los conjuntos de herramientas integrado y de MCP. El worker ejecuta cada llamada a herramienta envuelta que hace el modelo, así que coloca cualquier paso de aprobación en tu propio código de herramienta.

Was this page helpful?