Claude Platform Docs
Managed AgentsSandbox self-hosted

Strumenti personalizzati nelle sandbox self-hosted

Servi strumenti personalizzati da un worker di sandbox self-hosted e incapsula un server MCP all'interno della tua rete come strumenti personalizzati senza eseguire un tunnel.

Gli strumenti personalizzati sono strumenti eseguiti dal tuo codice: l'agente emette un evento agent.custom_tool_use e attende un user.custom_tool_result corrispondente. Il tuo worker può essere quel codice. Poiché viene eseguito all'interno della tua sandbox, lo strumento raggiunge i servizi interni, le credenziali e l'"egress" (traffico di rete in uscita) che hai configurato per la sandbox, e nient'altro.

La chiave dell'ambiente autorizza l'invio dei risultati degli strumenti personalizzati, quindi la tua chiave API di Claude resta fuori dall'host del worker.

Servire uno strumento personalizzato

  1. Dichiara lo strumento sull'agente

    Aggiungi una voce custom ai tools dell'agente il cui name corrisponda allo strumento registrato dal tuo worker. Consulta Strumenti personalizzati per la struttura completa della dichiarazione.

    {
      "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 l'implementazione con il worker

    Passa lo strumento attraverso la factory tools del worker (consulta EnvironmentWorker), insieme al set di strumenti integrato:

    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."""
        # Viene eseguito sull'host del worker: chiama qualsiasi cosa raggiungibile dalla sandbox.
        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())

Il worker risponde solo agli strumenti registrati presso di esso. Se uno strumento è dichiarato sull'agente ma nessun worker o client lo serve, la sessione si mette in pausa con uno "stop reason" (motivo di arresto) requires_action. Rimane in pausa finché qualcosa non invia il risultato. Consulta Gestione delle chiamate a strumenti personalizzati per il flusso degli eventi.

Incapsulare un server MCP come strumenti personalizzati

Il connettore MCP si connette ai server MCP dal lato di Anthropic. Un server deve quindi esporre un endpoint HTTP che Anthropic possa raggiungere, direttamente o tramite un tunnel MCP.

Per usare un server raggiungibile solo dalla tua rete, rendi invece il worker il client MCP e dichiara gli strumenti del server come strumenti personalizzati. Il server MCP non necessita di connettività in ingresso dall'esterno della tua rete. Anthropic riceve le definizioni degli strumenti che dichiari sull'agente, l'input di ogni chiamata e il risultato che il tuo worker invia.

In fase di esecuzione il modello chiama uno strumento incapsulato come qualsiasi altro strumento personalizzato:

  1. L'agente emette un evento agent.custom_tool_use.
  2. Il worker, all'interno della tua sandbox, inoltra la chiamata tramite la sua sessione MCP aperta al server sulla tua rete.
  3. Il worker invia la risposta del server come user.custom_tool_result.

Installare un SDK MCP

Gli helper MCP lato client dell'SDK convertono gli strumenti del server negli strumenti eseguibili accettati dal worker. Installa un SDK MCP insieme all'SDK di Anthropic: pip install "anthropic[mcp]" "mcp>=1.24".

Gli esempi si connettono senza autenticazione. Per inviare credenziali, configura il http_client che passi al trasporto MCP.

Dichiarare e servire gli strumenti

  1. Dichiara gli strumenti del server sull'agente

    Elenca gli strumenti del server MCP e dichiara ciascuno come strumento custom. I campi MCP name, description e inputSchema corrispondono uno a uno ai campi dello strumento personalizzato. Se il server pagina il suo elenco di strumenti, dichiara ogni pagina; il worker deve elencare le stesse pagine.

    import asyncio
    from typing import Any, cast
    from anthropic import AsyncAnthropic
    from anthropic.types.beta import BetaManagedAgentsCustomToolParams
    from mcp import ClientSession, types
    # Richiede mcp >= 1.24, che ha rinominato streamablehttp_client in 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:
        # I campi MCP corrispondono uno a uno a una dichiarazione di strumento personalizzato. Il cast
        # passa il dizionario dello schema al parametro tipizzato dell'SDK senza modifiche.
        return {
            "type": "custom",
            "name": tool.name,
            "description": tool.description or tool.name,
            "input_schema": cast(Any, tool.inputSchema),
        }
    
    
    async def main() -> None:
        # Esegui questo codice dove crei gli agenti, non sull'host worker: si
        # autentica con la tua chiave API di 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. Servi gli strumenti dal worker

    Connettiti allo stesso server MCP all'avvio, converti i suoi strumenti con async_mcp_tool e registrali insieme a beta_agent_toolset_20260401. Mantieni una sessione MCP aperta per tutta la durata 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
    # Richiede mcp >= 1.24, che ha rinominato streamablehttp_client in 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"]
        # Si connette al server MCP una sola volta all'avvio e mantiene la sessione aperta per
        # tutta la vita del worker. Il timeout trasforma una chiamata a uno strumento bloccata
        # in un risultato di errore anziché in una chiamata in stallo.
        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())

Limiti e comportamento

Gli strumenti vengono dichiarati, non scoperti in fase di esecuzione

Il worker elenca gli strumenti del server MCP una sola volta all'avvio e non può aggiungere strumenti a una sessione in esecuzione. Quando gli strumenti del server cambiano:

  1. Dichiarali di nuovo, sull'agente o su una sessione inattiva, come descritto in Aggiornare la configurazione dell'agente.
  2. Riavvia il worker.

Le dichiarazioni devono rispettare la Managed Agents API

Gli helper MCP mantengono i nomi e le descrizioni del server, e la maggior parte degli schemi passa invariata. Rinomina, accorcia o rendi inline dove una dichiarazione viola una di queste regole:

CampoRegola
nameUnivoco per agente. Lettere, cifre, underscore e trattini, da 1 a 128 caratteri. Non può coincidere con uno strumento integrato dell'agente come bash o read, né usare il prefisso riservato mcp__.
descriptionObbligatorio e non vuoto.
input_schemaAccetta le parole chiave JSON Schema che i server MCP emettono comunemente, come additionalProperties e title. Rifiuta parole chiave di riferimento come $ref in qualsiasi posizione, e oneOf, anyOf e allOf al livello superiore. I nomi delle proprietà usano lettere, cifre, underscore, punti e trattini, da 1 a 64 caratteri.
L'array tools dell'agenteAl massimo 128 voci. Ogni strumento incapsulato è una voce, e il set di strumenti integrato ne è un'altra.

Due casi richiedono lavoro aggiuntivo:

  • Due server espongono lo stesso nome di strumento: definisci tu stesso il wrapper con un nome prefissato e fagli chiamare il nome originale dello strumento del server.
  • Un generatore come pydantic scompone gli schemi in $defs: rendi inline quegli schemi prima di dichiarare lo strumento.

I fallimenti degli strumenti emergono come risultati di errore degli strumenti

Quando il server MCP segnala un errore dello strumento, il worker invia un risultato di errore dello strumento a cui il modello può reagire. Anche il contenuto MCP senza un equivalente come risultato di strumento, come blocchi audio e link a risorse, emerge come errore.

Imposta un timeout sul client MCP per un fallimento più rapido e chiaro, come fa l'esempio del worker Python con read_timeout_seconds. Consulta Una chiamata a uno strumento MCP incapsulato si blocca per sapere cosa succede senza di esso.

Incapsula solo server che gestisci o di cui ti fidi

Il nome, la descrizione e i risultati di uno strumento incapsulato entrano nel contesto del modello come quelli di qualsiasi altro strumento. Sono input non attendibili che possono influenzare ciò che l'agente fa con i suoi altri strumenti, incluso bash sull'host del worker. Dichiara solo gli strumenti che intendi far usare all'agente.

Le policy di autorizzazione non si applicano

Le policy di autorizzazione regolano i set di strumenti integrati e MCP. Il worker esegue ogni chiamata a uno strumento incapsulato effettuata dal modello, quindi inserisci qualsiasi passaggio di approvazione nel codice del tuo strumento.

Was this page helpful?