Benutzerdefinierte Tools in selbst gehosteten Sandboxes
Stelle benutzerdefinierte Tools über einen Worker in einer selbst gehosteten Sandbox bereit und kapsle einen MCP-Server in deinem Netzwerk als benutzerdefinierte Tools, ohne einen Tunnel zu betreiben.
Benutzerdefinierte Tools sind Tools, die dein eigener Code ausführt: Der Agent sendet ein agent.custom_tool_use-Event und wartet auf ein passendes user.custom_tool_result. Dein Worker kann dieser Code sein. Da er innerhalb deiner Sandbox läuft, erreicht das Tool die internen Dienste, Anmeldedaten und den ausgehenden Netzwerkverkehr („network egress“), die du für die Sandbox konfiguriert hast, und nichts darüber hinaus.
Der Umgebungsschlüssel autorisiert das Senden von Ergebnissen benutzerdefinierter Tools, sodass dein Claude-API-Key nicht auf dem Worker-Host liegen muss.
Ein benutzerdefiniertes Tool bereitstellen
Das Tool am Agenten deklarieren
Füge den
toolsdes Agenten einencustom-Eintrag hinzu, dessennamemit dem Tool übereinstimmt, das dein Worker registriert. Die vollständige Struktur der Deklaration findest du unter Benutzerdefinierte Tools.{ "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"] } }Die Implementierung beim Worker registrieren
Übergib das Tool über die
tools-Factory des Workers (sieheEnvironmentWorker), zusammen mit dem integrierten Toolset: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.""" # Läuft auf dem Worker-Host: Rufe alles auf, was die Sandbox erreichen kann. 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())
Der Worker beantwortet nur die bei ihm registrierten Tools. Wenn ein Tool am Agenten deklariert ist, aber kein Worker oder Client es bereitstellt, pausiert die Sitzung mit dem Stop-Grund requires_action. Sie bleibt pausiert, bis etwas das Ergebnis sendet. Den Event-Ablauf findest du unter Umgang mit Custom-Tool-Aufrufen.
Einen MCP-Server als benutzerdefinierte Tools kapseln
Der MCP-Connector verbindet sich von Anthropics Seite aus mit MCP-Servern. Ein Server muss daher einen HTTP-Endpunkt bereitstellen, den Anthropic erreichen kann, direkt oder über einen MCP-Tunnel.
Um einen Server zu nutzen, den nur dein Netzwerk erreichen kann, machst du stattdessen den Worker zum MCP-Client und deklarierst die Tools des Servers als benutzerdefinierte Tools. Der MCP-Server benötigt keine eingehende Verbindung von außerhalb deines Netzwerks. Anthropic erhält die Tool-Definitionen, die du am Agenten deklarierst, die Eingabe jedes Aufrufs und das Ergebnis, das dein Worker zurücksendet.
Zur Laufzeit ruft das Modell ein gekapseltes Tool wie jedes andere benutzerdefinierte Tool auf:
- Der Agent sendet ein
agent.custom_tool_use-Event. - Der Worker leitet den Aufruf innerhalb deiner Sandbox über seine offene MCP-Sitzung an den Server in deinem Netzwerk weiter.
- Der Worker sendet die Antwort des Servers als
user.custom_tool_result.
Ein MCP-SDK installieren
Die clientseitigen MCP-Helfer des SDK wandeln die Tools des Servers in ausführbare Tools um, die der Worker akzeptiert. Installiere ein MCP-SDK zusätzlich zum Anthropic-SDK: pip install "anthropic[mcp]" "mcp>=1.24".
Die Beispiele verbinden sich ohne Authentifizierung. Um Anmeldedaten zu senden, konfiguriere den http_client, den du an den MCP-Transport übergibst.
Die Tools deklarieren und bereitstellen
Die Tools des Servers am Agenten deklarieren
Liste die Tools des MCP-Servers auf und deklariere jedes als
custom-Tool. Die MCP-Feldername,descriptionundinputSchemalassen sich eins zu eins auf die Felder des benutzerdefinierten Tools abbilden. Wenn der Server seine Tool-Liste paginiert, deklariere jede Seite; der Worker muss dieselben Seiten auflisten.import asyncio from typing import Any, cast from anthropic import AsyncAnthropic from anthropic.types.beta import BetaManagedAgentsCustomToolParams from mcp import ClientSession, types # Erfordert mcp >= 1.24, das streamablehttp_client in streamable_http_client umbenannt hat. 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: # Die MCP-Felder lassen sich eins zu eins auf eine Custom-Tool-Deklaration abbilden. Der Cast # übergibt das Schema-Dictionary unverändert an den typisierten Parameter des SDK. return { "type": "custom", "name": tool.name, "description": tool.description or tool.name, "input_schema": cast(Any, tool.inputSchema), } async def main() -> None: # Führe dies dort aus, wo du Agenten erstellst, nicht auf dem Worker-Host: # es authentifiziert sich mit deinem Claude-API-Key (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())Die Tools über den Worker bereitstellen
Verbinde dich beim Start mit demselben MCP-Server, wandle seine Tools mit
async_mcp_toolum und registriere sie zusammen mitbeta_agent_toolset_20260401. Halte eine MCP-Sitzung für die gesamte Lebensdauer des Workers offen.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 # Erfordert mcp >= 1.24, das streamablehttp_client in streamable_http_client umbenannt hat. 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"] # Verbinde dich beim Start einmal mit dem MCP-Server und halte die Session offen für # die Lebensdauer des Workers. Das Timeout wandelt einen hängenden Tool-Aufruf # in ein Fehlerergebnis statt eines blockierten Aufrufs um. 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())
Grenzen und Verhalten
Tools werden deklariert, nicht zur Laufzeit erkannt
Der Worker listet die Tools des MCP-Servers einmal beim Start auf und kann einer laufenden Sitzung keine Tools hinzufügen. Wenn sich die Tools des Servers ändern:
- Deklariere sie erneut, am Agenten oder an einer inaktiven Sitzung über Aktualisieren der Agent-Konfiguration.
- Starte den Worker neu.
Deklarationen müssen zur Managed Agents API passen
Die MCP-Helfer übernehmen die Namen und Beschreibungen des Servers, und die meisten Schemas werden unverändert durchgereicht. Benenne um, kürze oder bette inline ein, wo eine Deklaration gegen eine dieser Regeln verstößt:
| Feld | Regel |
|---|---|
name | Eindeutig pro Agent. Buchstaben, Ziffern, Unterstriche und Bindestriche, 1–128 Zeichen. Darf nicht mit einem integrierten Agenten-Tool wie bash oder read übereinstimmen oder das reservierte Präfix mcp__ verwenden. |
description | Erforderlich und nicht leer. |
input_schema | Akzeptiert die JSON-Schema-Schlüsselwörter, die MCP-Server üblicherweise ausgeben, wie additionalProperties und title. Lehnt Referenz-Schlüsselwörter wie $ref an beliebiger Stelle sowie oneOf, anyOf und allOf auf oberster Ebene ab. Eigenschaftsnamen verwenden Buchstaben, Ziffern, Unterstriche, Punkte und Bindestriche, 1–64 Zeichen. |
Das tools-Array des Agenten | Höchstens 128 Einträge. Jedes gekapselte Tool ist ein Eintrag, und das integrierte Toolset ist ein weiterer. |
Zwei Fälle erfordern zusätzlichen Aufwand:
- Zwei Server stellen denselben Tool-Namen bereit: Definiere den Wrapper selbst unter einem Namen mit Präfix und lass ihn den ursprünglichen Tool-Namen des Servers aufrufen.
- Ein Generator wie pydantic lagert Schemas in
$defsaus: Bette diese Schemas inline ein, bevor du das Tool deklarierst.
Tool-Fehler erscheinen als Fehlerergebnisse
Wenn der MCP-Server einen Tool-Fehler meldet, sendet der Worker ein Fehlerergebnis, auf das das Modell reagieren kann. MCP-Inhalte ohne Entsprechung in Tool-Ergebnissen, wie Audio-Blöcke und Ressourcen-Links, erscheinen ebenfalls als Fehler.
Lege ein Timeout für den MCP-Client fest, um einen schnelleren und klareren Fehler zu erhalten, wie es das Python-Worker-Beispiel mit read_timeout_seconds tut. Was ohne Timeout passiert, erfährst du unter Ein gekapselter MCP-Tool-Aufruf hängt.
Kapsle nur Server, die du betreibst oder denen du vertraust
Name, Beschreibung und Ergebnisse eines gekapselten Tools gelangen wie die jedes anderen Tools in den Kontext des Modells. Sie sind nicht vertrauenswürdige Eingaben, die beeinflussen können, was der Agent mit seinen anderen Tools tut, einschließlich bash auf dem Worker-Host. Deklariere nur die Tools, die der Agent verwenden soll.
Berechtigungsrichtlinien gelten nicht
Berechtigungsrichtlinien steuern die integrierten und die MCP-Toolsets. Der Worker führt jeden gekapselten Tool-Aufruf aus, den das Modell tätigt, also baue jeden Genehmigungsschritt in deinen eigenen Tool-Code ein.
Was this page helpful?