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
Declara la herramienta en el agente
Agrega una entrada
customa lastoolsdel agente cuyonamecoincida 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"] } }Registra la implementación en el worker
Pasa la herramienta a través de la fábrica
toolsdel worker (consultaEnvironmentWorker), 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:
- El agente emite un evento
agent.custom_tool_use. - El worker, dentro de tu sandbox, reenvía la llamada a través de su sesión MCP abierta al servidor en tu red.
- 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
Declara las herramientas del servidor en el agente
Lista las herramientas del servidor MCP y declara cada una como una herramienta
custom. Los camposname,descriptioneinputSchemade 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())Sirve las herramientas desde el worker
Conéctate al mismo servidor MCP al iniciar, convierte sus herramientas con
async_mcp_tooly regístralas junto conbeta_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:
- Vuelve a declararlas, en el agente o en una sesión inactiva mediante Actualizar la configuración del agente.
- 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:
| Campo | Regla |
|---|---|
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__. |
description | Obligatorio y no vacío. |
input_schema | Acepta 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 agente | Como 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?