Selbst gehostete Sandboxes
Führe Claude Managed Agents-Sitzungen in selbst gehosteten Sandboxes aus und behalte Tool-Ausführung, Dateien und ausgehenden Netzwerkverkehr in deiner eigenen Infrastruktur.
Standardmäßig führt Managed Agents Tools und Code in von Anthropic verwalteten Cloud-Sandboxes aus. Selbst gehostete Sandboxes („self-hosted sandboxes“) belassen die Orchestrierung auf der Seite von Anthropic, verlagern aber die Tool-Ausführung in eine Infrastruktur, die du kontrollierst, sodass der Code, das Dateisystem und der ausgehende Netzwerkverkehr des Agenten deine Umgebung nie verlassen.
Die Tool-Ausführung bleibt auf deinem Host: Das Dateisystem, das der Agent liest und beschreibt, die Prozesse, die er startet, und das Netzwerk, das er erreichen kann, stehen alle unter deiner Kontrolle. Tool-Eingaben und -Ausgaben fließen weiterhin zur Control Plane von Anthropic (wo Claude läuft), damit das Modell Ergebnisse sehen und entscheiden kann, was als Nächstes zu tun ist. Die Skills des Agenten und die Inhalte aller an die Sitzung angehängten Memory Stores werden von Anthropic gespeichert und für die Sitzung in deine Sandbox kopiert; Änderungen, die der Agent an Memory-Dateien vornimmt, werden zurück in den Store synchronisiert. Siehe das Sicherheitsmodell für die vollständige Datenflussgrenze.
Wie es sich von Cloud-Umgebungen unterscheidet
| Cloud-Umgebung | Selbst gehostete Sandbox | |
|---|---|---|
| Wo Tools laufen | Von Anthropic verwaltete Sandboxes | Deine Infrastruktur |
| Netzwerkreichweite | Egress-Kontrollen von Anthropic | Deine Netzwerkrichtlinie |
| Einbinden von Dateien und GitHub-Repos | Von Anthropic verwaltet | Von dir verwaltet |
| Memory Stores | Von Anthropic unter /mnt/memory/ eingebunden | Nach /mnt/memory/ heruntergeladen und vom SDK-Worker synchronisiert |
| Lebenszyklus | Von Anthropic verwaltet | Von dir verwaltet |
Selbst-Hosting eignet sich gut, wenn der Agent mit Daten arbeiten muss, die deine Netzwerkgrenze nicht verlassen dürfen, interne Dienste erreichen muss, die nicht öffentlich routbar sind, oder unter den eigenen Compliance- und Audit-Kontrollen deiner Organisation laufen muss.
Zur Berechtigung für Zero Data Retention und HIPAA BAA siehe API und Datenaufbewahrung.
Wann eine Kombination mit MCP-Tunneln sinnvoll ist
Selbst-Hosting steuert, wo der Code des Agenten ausgeführt wird. MCP-Tunnel steuern, wie Anthropic MCP-Server in deinem Netzwerk erreicht. Beide sind unabhängig voneinander: Eine Sitzung, die in den Cloud-Sandboxes von Anthropic läuft, kann private MCP-Server weiterhin über einen Tunnel erreichen, und eine selbst gehostete Sitzung kann sowohl getunnelte als auch öffentliche MCP-Server verwenden. Verwende beides, wenn Ausführung und Tool-Zugriff innerhalb deiner Grenze bleiben sollen. Um dem Agenten Tools von einem MCP-Server in deinem Netzwerk bereitzustellen, ohne einen Tunnel zu betreiben, kannst du den Server auch als benutzerdefinierte Tools verpacken, die von deinem Worker bereitgestellt werden.
Umgebungs-Worker
Ein „environment worker“ (Umgebungs-Worker) ist ein Prozess, den du auf deiner eigenen Infrastruktur ausführst. Er empfängt Tool-Ausführungsanfragen von Anthropic und führt sie lokal aus. Die self_hosted-Umgebung fungiert als Arbeitswarteschlange: Wenn ihr eine Sitzung zugewiesen wird, reiht Anthropic die Sitzung als Arbeitselement ein. Dein Worker beansprucht Arbeitselemente aus dieser Warteschlange, startet für jedes einen Ausführungskontext, lädt die Skills des Agenten herunter (wiederverwendbare, dateisystembasierte Ressourcen, die dem Agenten domänenspezifisches Fachwissen verleihen), führt die Tool-Aufrufe aus und sendet die Ergebnisse zurück.
Arbeitselemente werden durch Polling der Warteschlange der Umgebung beansprucht: entweder durch einen Always-on-Worker, der kontinuierlich pollt, oder durch einen Webhook-ausgelösten Handler, der bei session.status_run_started aufwacht und mit dem Polling beginnt.
Sowohl die CLI als auch das SDK liefern vorgefertigte Worker mit. Die ant-CLI unterstützt nur das Always-on-Muster; das SDK unterstützt sowohl Always-on als auch Webhook-ausgelöst. Beide sind konfigurierbar: Siehe Selbst gehosteter Worker in der Referenz für CLI-Flags und SDK-Helfer auf dieser Seite für die SDK-Optionen. Für mehr Kontrolle rufe die Environments-Work-Endpunkte direkt auf und implementiere deinen eigenen Worker.
Sandbox-Dateisystem
/workspace: das Standard-Arbeitsverzeichnis des Systems für Tool-Ausführung und Skill-Download. Das--workdir-Flag der CLI verwendet standardmäßig das aktuelle Verzeichnis; übergib--workdir /workspace, um dem Systemstandard zu entsprechen. Skills werden nach<workdir>/skills/<name>/heruntergeladen. Wenn du ein anderes Arbeitsverzeichnis verwendest, aktualisiere den System-Prompt deines Agenten, damit Claude die Skill-Dateien finden kann.- Ausgaben: In selbst gehosteten Umgebungen lässt der System-Prompt der Sitzung die Anweisung
/mnt/session/outputsweg, die in von Anthropic verwalteten Sandboxes verwendet wird, sodass endgültige Ergebnisse dort landen, wo der Agent sie in deinem Sandbox-Dateisystem schreibt, typischerweise unter dem Arbeitsverzeichnis. /mnt/memory/: An die Sitzung angehängte Memory Stores werden hier vom SDK-Worker materialisiert, ein Verzeichnis pro Store unter demmount_pathdes Stores (zum Beispiel/mnt/memory/user-preferences/). Der Worker erstellt diese Verzeichnisse, wenn er die Sitzung beansprucht, und entfernt sie, wenn die Sitzung endet; siehe Memory Stores verwenden.
Bevor du beginnst
Du benötigst:
- Einen bestehenden Agenten. Wenn du keinen hast, schließe zuerst den Schnellstart ab und notiere dir dessen Agenten-ID.
- Einen Linux-Host mit
/bin/bashunter genau diesem Pfad. Das Bash-Tool des Workers ruft es direkt auf, ohnePATHzu konsultieren. Das TypeScript SDK benötigt zusätzlichunzipundtarimPATHsowie Node.js 22 oder neuer; die Python- und Go-SDKs verwenden ihre Standardbibliotheken für die Archivextraktion und haben keine zusätzlichen Binäranforderungen. - Die
ant-CLI oder ein Anthropic SDK (Python, TypeScript oder Go) auf dem Worker-Host. - Zugangsdaten: Ein Umgebungsschlüssel (in den folgenden Schritten in der Console generiert) authentifiziert den Worker gegenüber seiner Warteschlange; dein Claude API-Key erstellt Sitzungen und liest Warteschlangenstatistiken von außerhalb des Worker-Hosts. Die Schlüsselgenerierung ist nur über die Console möglich. Beanspruchte Arbeitselemente tragen außerdem ein sitzungsspezifisches
secret, das der Worker zum Einbinden von Memory Stores verwendet; du generierst es nicht, aber im Sandbox-pro-Sitzung-Muster leitest du es selbst in die Sandbox weiter (siehe Eine Sandbox pro Sitzung ausführen). - Für Memory Stores einen vorbereiteten Host. Wenn Sitzungen in dieser Umgebung Memory Stores anhängen werden, bereite
/mnt/memoryauf dem Worker-Host vor, bevor du den Worker startest; siehe Den Host vorbereiten.
Eine selbst gehostete Umgebung erstellen
In der Console: Workspace > Environments > New > Self-hosted
Oder über die API:
client = anthropic.Anthropic() environment = client.beta.environments.create( name="self-hosted", config={"type": "self_hosted"} ) print(environment.id)Einen Umgebungsschlüssel generieren
Öffne in der Console die Umgebung und klicke auf Generate environment key. Die Schlüsselgenerierung ist nur über die Console möglich, unabhängig davon, ob du die Umgebung über die Console oder die API erstellt hast. Exportiere dann die Umgebungs-ID und den Schlüssel auf dem Worker-Host:
export ANTHROPIC_ENVIRONMENT_KEY="sk-ant-oat01-..." export ANTHROPIC_ENVIRONMENT_ID="env_..."
Einen Worker ausführen
Wähle Always-on für die einfachste Einrichtung: Ein lang laufender Prozess pollt die Warteschlange kontinuierlich und benötigt nur ausgehendes HTTPS. Wähle Webhook-ausgelöst, um einen untätigen Poller zu vermeiden; dies erfordert einen Webhook-Endpunkt, den Anthropic erreichen kann (siehe Webhooks für die Endpunkt-Einrichtung und Signaturprüfung).
Die ant-CLI installieren
Führe dies auf dem Worker-Host aus.
Lade für Linux-Umgebungen die Release-Binärdatei direkt herunter.
VERSION=1.27.0 OS=$(uname -s | tr '[:upper:]' '[:lower:]') case $(uname -m) in x86_64) ARCH=amd64 ;; aarch64) ARCH=arm64 ;; esac curl -fsSL "https://github.com/anthropics/anthropic-cli/releases/download/v${VERSION}/ant_${VERSION}_${OS}_${ARCH}.tar.gz" \ | sudo tar -xz -C /usr/local/bin antAlle Releases findest du auf der GitHub-Releases-Seite.
Den Worker ausführen
Im Prozess
ant beta:worker pollbeansprucht der Umgebung zugewiesene Arbeitselemente, lädt Skills herunter, führt Tool-Aufrufe im Arbeitsverzeichnis aus und sendet Ergebnisse zurück. Es liestANTHROPIC_ENVIRONMENT_KEYundANTHROPIC_ENVIRONMENT_IDaus der Umgebung.ant beta:worker poll --workdir "/workspace"Der Worker beendet sich sauber bei SIGTERM oder SIGINT: Er bricht jeden laufenden Tool-Aufruf ab, sendet dessen Fehlerergebnis und gibt das Arbeitselement frei, bevor er stoppt.
Sandbox pro Sitzung
Wenn du stärkere Isolation benötigst (ein frisches Dateisystem, Ressourcenlimits oder sitzungsspezifische Netzwerkkontrollen), führe jede Sitzung in ihrer eigenen Sandbox aus. Erstelle ein Image mit installiertem
antundant beta:worker runals Entrypoint. Das Basis-Image muss/bin/bashbereitstellen;curlwird nur zur Build-Zeit verwendet. Wenn eine Sandbox startet, liest sie Sitzungsdetails aus Umgebungsvariablen, bearbeitet diese Sitzung und beendet sich:FROM your-base-image ARG ANT_VERSION=1.27.0 ARG TARGETARCH RUN ARCH=$([ "$TARGETARCH" = "arm64" ] && echo arm64 || echo amd64) && \ curl -fsSL "https://github.com/anthropics/anthropic-cli/releases/download/v${ANT_VERSION}/ant_${ANT_VERSION}_linux_${ARCH}.tar.gz" \ | tar -xz -C /usr/local/bin ant WORKDIR /workspace VOLUME /workspace ENTRYPOINT ["ant", "beta:worker", "run"]Schreibe dann ein Spawn-Skript, das Sitzungsdetails in eine frische Sandbox weiterleitet. Der Poller injiziert
ANTHROPIC_SESSION_ID,ANTHROPIC_WORK_ID,ANTHROPIC_ENVIRONMENT_IDundANTHROPIC_ENVIRONMENT_KEYin die Umgebung des Skripts und schreibt das beanspruchte Arbeitselement als JSON in die Standardeingabe des Skripts, einschließlich des sitzungsspezifischensecretdes Arbeitselements, wenn Anthropic eines ausgestellt hat.ANTHROPIC_BASE_URList optional und wird nur durchgereicht, wenn es auf dem Poller-Host gesetzt war; es überschreibt den Standard-API-Endpunkt. Im Beispiel ist/host/outputsein von dir gewähltes Host-Verzeichnis; es wird per Bind-Mount in das Arbeitsverzeichnis der Sandbox (/workspace) eingebunden, damit du Sitzungsergebnisse abrufen kannst, nachdem die Sandbox beendet wurde. In selbst gehosteten Umgebungen schreibt der Agent Ergebnisse unter das Arbeitsverzeichnis statt nach/mnt/session/outputs(siehe Sandbox-Dateisystem), daher erfasst das Einbinden des Arbeitsverzeichnisses diese; der Mount nimmt auch den heruntergeladenenskills/-Baum und alle Zwischendateien auf, die der Agent erstellt.#!/bin/bash # spawn.sh: wird einmal pro beanspruchtem Arbeitselement aufgerufen mkdir -p "/host/outputs/$ANTHROPIC_SESSION_ID" exec docker run --rm \ -e ANTHROPIC_SESSION_ID -e ANTHROPIC_ENVIRONMENT_KEY \ -e ANTHROPIC_WORK_ID -e ANTHROPIC_ENVIRONMENT_ID -e ANTHROPIC_BASE_URL \ -v "/host/outputs/$ANTHROPIC_SESSION_ID":/workspace \ your-imageDer Entrypoint
ant beta:worker runbindet keine Memory Stores ein. Wenn Sitzungen in dieser Umgebung Memory Stores anhängen, behalte den Poller, baue aber das sitzungsspezifische Image um den SDK-Worker herum und erweitere das Spawn-Skript so, dass es dassecretdes Arbeitselements in die Sandbox weiterleitet, wie in Eine Sandbox pro Sitzung ausführen gezeigt.Starte den Poller mit Verweis auf das Skript:
ant beta:worker poll --on-work ./spawn.sh
SDK-Helfer
Das SDK stellt drei Helfer auf unterschiedlichen Kontrollebenen bereit. EnvironmentWorker deckt die meisten Anwendungsfälle ab; greife auf die Helfer niedrigerer Ebene zurück, wenn du deinen eigenen sitzungsspezifischen Prozess starten oder Tools gegen eine bereits beanspruchte Sitzung ausführen musst.
EnvironmentWorker: der sofort einsatzbereite Worker. Übernimmt Polling, Einrichtung und Ausführung von Anfang bis Ende..run(): läuft unbegrenzt und nimmt Sitzungen auf, sobald sie eintreffen..handle_item(): bearbeitet ein einzelnes beanspruchtes Arbeitselement und beendet sich. Übergib die Arbeits-, Sitzungs- und Umgebungskennungen explizit oder lass ihn dieANTHROPIC_*-Variablen lesen, dieant beta:worker poll --on-workfür den von ihm gestarteten Prozess setzt. Damit die Sitzung ihre Memory Stores einbinden kann, übergib außerdem dassecretdes Arbeitselements alswork_secret(workSecretin TypeScript,WorkSecretin Go) oder setzeANTHROPIC_WORK_SECRET;ant beta:worker poll --on-worksetzt diese Variable nicht, lies das Secret daher aus dem Arbeitselement-JSON, das es in die Standardeingabe deines Skripts schreibt, wie in Eine Sandbox pro Sitzung ausführen gezeigt.memory_sync_interval(memorySyncIntervalMsin TypeScript,MemorySyncIntervalin Go) undmemory_sync_deletions(memorySyncDeletions,MemorySyncDeletions): wie oft angehängte Memory Stores während der laufenden Sitzung mit dem Server abgeglichen werden und ob Dateien, die der Agent lokal löscht, auch aus dem Store gelöscht werden. Siehe Synchronisierung konfigurieren für Einheiten, Standardwerte und wie du die Memory-Unterstützung deaktivierst.
work.poller(): pollt die Arbeitswarteschlange in deinem Namen und gibt dir jede beanspruchte Sitzung. Verwende dies, wenn du entscheiden möchtest, was für jede Sitzung geschieht, zum Beispiel eine Sandbox zu starten, statt Tools im Prozess auszuführen.drain: ob das Polling gestoppt werden soll, sobald die Warteschlange leer ist, statt auf neue Arbeit zu warten.block_ms: wie lange auf eintreffende Arbeit gewartet werden soll, bevor zurückgekehrt wird, in Millisekunden. Muss zwischen 1 und 999 liegen (Wartezeit pro Poll; der Helfer pollt automatisch erneut). Übergibnull(Nonein Python,param.Null[int64]()in Go) für eine nicht blockierende Prüfung; das Weglassen des Parameters verwendet den standardmäßigen Long-Poll von 999 ms.reclaim_older_than_ms: Arbeitselemente erneut beanspruchen, die beansprucht, aber innerhalb dieser Anzahl von Millisekunden nie bestätigt wurden.auto_stop(autoStopin TypeScript,AutoStopin Go): ob für jedes Arbeitselement ein Stoppsignal gesendet werden soll, sobald dein Schleifenkörper damit fertig ist. Schalte es aus, wenn das, was das Arbeitselement ausführt, den Stopp selbst sendet:handle_item()tut dies, setze es also auf false, wenn du beanspruchte Elemente anhandle_item()übergibst, wie es die Webhook-Handler auf dieser Seite tun, und ebenso eine von dir gestartete Sandbox, die den Stopp-Aufruf selbst übernimmt.
client.beta.sessions.events.tool_runner(): führt Tool-Aufrufe für eine einzelne Sitzung aus, gegeben die Sitzungs-ID und eine Tool-Liste. Verwende dies, wenn du die Arbeit bereits beansprucht hast und nur die Ausführungsschicht benötigst.
Verwende den Work-Poller direkt, wenn du deinen eigenen sitzungsspezifischen Prozess starten möchtest, zum Beispiel um für jede beanspruchte Sitzung eine Sandbox hochzufahren:
import asyncio
import os
from anthropic import AsyncAnthropic
from anthropic.types.beta.environments import BetaSelfHostedWork
SANDBOX_ENV = (
"ANTHROPIC_ENVIRONMENT_ID",
"ANTHROPIC_ENVIRONMENT_KEY",
"ANTHROPIC_WORK_ID",
"ANTHROPIC_SESSION_ID",
"ANTHROPIC_WORK_SECRET",
"ANTHROPIC_BASE_URL", # forwarded only when set on this host
)
async def launch_container(work: BetaSelfHostedWork) -> None:
print(f"claimed session {work.data.id}")
# Ersetze `docker run` durch deinen eigenen Sandbox-Launcher. Leite den Environment-
# Key (niemals deinen API-Key) und das sitzungsspezifische Secret des Work-Items weiter: Der Worker
# darin benötigt das Secret, um die Memory-Stores der Sitzung einzubinden.
env = os.environ | {
"ANTHROPIC_WORK_ID": work.id,
"ANTHROPIC_SESSION_ID": work.data.id,
"ANTHROPIC_WORK_SECRET": work.secret or "",
}
forward = [arg for name in SANDBOX_ENV for arg in ("-e", name)]
launcher = await asyncio.create_subprocess_exec(
"docker", "run", "--rm", "--detach", *forward, "your-sdk-worker-image", env=env
)
await launcher.wait()
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:
async for work in client.beta.environments.work.poller(
environment_id=environment_id,
environment_key=environment_key,
auto_stop=False, # the launched sandbox owns the stop call
):
await launch_container(work)
asyncio.run(main())Was auch immer die Sandbox startet, muss das secret des beanspruchten Arbeitselements zusammen mit den Sitzungs-, Arbeits- und Umgebungskennungen in sie weiterleiten (zum Beispiel als ANTHROPIC_WORK_SECRET), damit der Worker darin die Memory Stores der Sitzung einbinden kann; siehe Eine Sandbox pro Sitzung ausführen.
AgentToolContext ist der Ausführungskontext für Tool-Aufrufe. Er definiert das Arbeitsverzeichnis und die Pfadrichtlinie und kann die Skills der Sitzung herunterladen. Die Datei-Tools (read, write, edit, glob, grep) sind auf das Arbeitsverzeichnis plus alle in allowed_roots (allowedRoots in TypeScript, AllowedRoots in Go) aufgeführten Verzeichnisse beschränkt, und write und edit verweigern zusätzlich Pfade unter read_only_roots (readOnlyRoots, ReadOnlyRoots). EnvironmentWorker fügt die Memory-Store-Verzeichnisse der Sitzung selbst zu diesen Listen hinzu. Die Beschränkung ist nur eine Leitplanke für die Datei-Tools, keine Sandbox; sie schränkt bash nicht ein. beta_agent_toolset_20260401(env) nimmt einen AgentToolContext und gibt die Standard-Tool-Implementierungen zurück (bash, read, write, edit, glob, grep).
Mit EnvironmentWorker: Beide werden automatisch verwaltet. Übergib eine tools-Factory, um die Tool-Liste anzupassen:
EnvironmentWorker(client, ..., tools=lambda env: [beta_bash_tool(env), my_custom_tool])Mit work.poller() und tool_runner(): Übergib eine Tool-Liste als tools an client.beta.sessions.events.tool_runner(). Um diese Liste zu erstellen, richte AgentToolContext selbst ein und rufe beta_agent_toolset_20260401(env) auf:
from anthropic.lib.tools.agent_toolset import (
AgentToolContext,
beta_agent_toolset_20260401,
)
async with AgentToolContext(
workdir="/workspace", client=client, session_id=work.data.id
) as env:
# Skills heruntergeladen nach /workspace/skills/<name>/
tools = beta_agent_toolset_20260401(env)Überprüfen, ob der Worker verbunden ist
Bestätige aus einer separaten Shell, mit ANTHROPIC_API_KEY auf deinen Claude API-Key gesetzt (nicht den Umgebungsschlüssel), dass workers_polling mindestens 1 ist:
ant beta:environments:work stats --environment-id "$ANTHROPIC_ENVIRONMENT_ID"Wenn workers_polling bei 0 bleibt, erreicht der Worker die Warteschlange nicht: Bestätige, dass ANTHROPIC_ENVIRONMENT_KEY und ANTHROPIC_ENVIRONMENT_ID auf dem Worker-Host gesetzt sind. Siehe Warteschlangentiefe lesen für die vollständige Statistikantwort und Beispiele in anderen Sprachen.
Eine Sitzung starten
Sobald dein Worker läuft, erstelle eine Sitzung, die auf die Umgebung abzielt. Setze AGENT_ID auf die Agenten-ID, die du in Bevor du beginnst notiert hast. Die Sitzung gelangt in die Arbeitswarteschlange der Umgebung und wartet dort, bis ein Worker sie beansprucht; wenn kein Worker verbunden ist, bleibt die Sitzung in der Warteschlange, statt fehlzuschlagen.
Anthropic bindet keine Dateien oder GitHub-Repositories in selbst gehostete Sandboxes ein. Um sitzungsspezifische Dateien verfügbar zu machen, übergib Dateireferenzen (wie einen S3-Pfad oder einen Commit-SHA) im metadata-Feld der Sitzung. Das beanspruchte Arbeitselement trägt nicht die Metadaten der Sitzung, aber es trägt die Sitzungs-ID: Dein Spawn-Skript oder --on-work-Handler ruft die Sitzung ab (GET /v1/sessions/{session_id}), um das metadata-Feld zu lesen, und stellt dann die Dateien im Arbeitsverzeichnis bereit, bevor die Tool-Ausführung beginnt.
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
metadata={"input_file": "s3://my-bucket/data.csv"},
)Siehe Selbst gehosteter Worker in der Referenz für die vollständige Liste der CLI-Flags und SDK-Helfer für die Optionen der SDK-Helfer.
Memory Stores verwenden
Sitzungen in einer selbst gehosteten Umgebung hängen Memory Stores genau so an wie Sitzungen in Cloud-Umgebungen: Führe sie in resources auf, wenn du die Sitzung erstellst, wie in Einen Memory Store an eine Sitzung anhängen gezeigt. Eine Sitzung akzeptiert bis zu 8 Memory Stores. In einer selbst gehosteten Umgebung materialisiert der SDK-Worker statt der Infrastruktur von Anthropic jeden Store für den Agenten, daher erfordern Memory Stores dort EnvironmentWorker (oder dessen Methode handle_item()) aus dem Python-, TypeScript- oder Go-SDK.
Der ant-CLI-Worker (ant beta:worker poll und ant beta:worker run) bindet keine Memory Stores ein. Um den CLI-Poller mit Memory Stores zu kombinieren, führe den SDK-Worker in einer sitzungsspezifischen Sandbox aus, wie in Eine Sandbox pro Sitzung ausführen beschrieben.
Memory Stores können nicht an Sitzungen in selbst gehosteten Umgebungen auf Claude Platform on AWS angehängt werden.
Wie der Worker mit Memory umgeht
Wenn der Worker ein Arbeitselement beansprucht, dessen Sitzung Memory Stores angehängt hat, dann:
- Lädt er jeden angehängten Store an seinen
mount_pathauf dem Worker-Host herunter und authentifiziert sich dabei mit dem sitzungsspezifischensecretdes Arbeitselements. Dermount_pathist dasselbe Verzeichnis unter/mnt/memory/, das Cloud-Sitzungen verwenden (zum Beispiel/mnt/memory/user-preferences/für einen Store namens „User Preferences“), und der System-Prompt der Sitzung beschreibt es dem Agenten. - Fügt er diese Verzeichnisse zu den erlaubten Wurzelverzeichnissen der Datei-Tools hinzu und die Verzeichnisse von Stores, die mit
access: "read_only"angehängt sind, zu deren schreibgeschützten Wurzelverzeichnissen, sodass der Agent mit denselben Toolsread,write,edit,globundgrepan Memories arbeitet, die er im Arbeitsverzeichnis verwendet. - Gleicht er lokale und entfernte Änderungen nach Tool-Aufrufen ab, höchstens einmal pro Synchronisierungsintervall (standardmäßig 15 Sekunden): Memories, die sich im Store geändert haben, werden auf die Festplatte geschrieben, und Dateien, die der Agent geändert hat, werden in den Store hochgeladen.
- Führt er eine abschließende Synchronisierung aus, wenn die Sitzung endet, leert alle noch ausstehenden Uploads für bis zu 30 Sekunden und entfernt dann die von ihm erstellten Verzeichnisse. Ein Worker, der abgebrochen wird, während eine Sitzung läuft, überspringt die abschließende Synchronisierung, lädt aber dennoch geänderte Dateien hoch und entfernt die Verzeichnisse, bevor er sich beendet.
Der Memory Store auf der Seite von Anthropic bleibt die maßgebliche Quelle. Memory-Versionen, Schwärzung sowie das Anzeigen oder Bearbeiten von Memories in der Console funktionieren wie bei Cloud-Sitzungen, und die Memory-Lese- und -Schreibvorgänge des Agenten erscheinen im Event-Stream als gewöhnliche Tool-Ereignisse. Da jeder Worker in einem Intervall synchronisiert, wird eine in einer Sitzung geschriebene Änderung für eine andere laufende Sitzung erst sichtbar, nachdem beide synchronisiert haben, beim Standardintervall typischerweise deutlich unter einer Minute; Sitzungen in Cloud-Sandboxes sehen die Änderungen der jeweils anderen fast sofort.
Jedes Store-Verzeichnis enthält eine Markierungsdatei namens .anthropic-memory-store, die das Verzeichnis mit seinem Store verknüpft. Lass sie an Ort und Stelle: Der Worker synchronisiert kein Verzeichnis, dessen Markierung fehlt oder verändert wurde.
Den Host vorbereiten
Memory Stores in selbst gehosteten Sandboxes benötigen ein POSIX-Dateisystem auf dem Worker-Host (dem Linux-Host aus Bevor du beginnst); Windows-Hosts werden nicht unterstützt, da der Worker O_NOFOLLOW benötigt, wenn er Memory-Dateien öffnet. Ein Dateisystem mit Unterscheidung von Groß- und Kleinschreibung wird empfohlen, damit Memory-Pfade, die sich nur in der Groß-/Kleinschreibung unterscheiden, nicht kollidieren.
Erstelle vor dem Start des Workers das übergeordnete Verzeichnis und mache es für den Benutzer beschreibbar, unter dem der Worker läuft:
sudo mkdir -p /mnt/memory && sudo chown "$USER" /mnt/memoryErstelle die Verzeichnisse pro Store nicht selbst. Der Worker erstellt das mount_path-Verzeichnis jedes Stores (zum Beispiel /mnt/memory/user-preferences), wenn eine Sitzung startet, weigert sich, die Arbeit der Sitzung zu starten, wenn unter diesem Pfad bereits etwas existiert, und entfernt das Verzeichnis, wenn die Sitzung endet. Daraus folgen zwei Betriebsregeln:
- Führe eine Sitzung pro Dateisystem aus, wenn Sitzungen denselben Store anhängen. Zwei Sitzungen können denselben Store nicht gleichzeitig auf einem Host einbinden, da beide denselben Pfad benötigen. Jeder Sitzung ihre eigene Sandbox zu geben, wie in Eine Sandbox pro Sitzung ausführen beschrieben, erfüllt diese Regel.
- Stoppe Worker ordnungsgemäß. Wenn du einen Worker stoppst, während eine Sitzung läuft, lädt
EnvironmentWorkerdie geänderten Memory-Dateien der Sitzung nur dann hoch und entfernt seine Store-Verzeichnisse nur dann, wenn er abgebrochen statt hart beendet wird: Ein hart beendeter Prozess führt keinen Abbau aus, und der Worker installiert selbst keine Signal-Handler. Verbinde SIGTERM und SIGINT mit dem Abbruch in dem Prozess, der ihn ausführt: Brich in TypeScript dassignalab, das du dem Worker übergibst, brich in Go den Kontext ab und brich in Python den Task ab, derrun()oderhandle_item()ausführt. Tu dies aus einem Signal-Handler heraus, wenn dein Worker der Prozess ist, wie es die eigenständigen Worker auf dieser Seite tun, oder aus dem eigenen Shutdown-Hook deines Servers, wenn der Worker innerhalb eines Webhook-Handlers läuft, der die Signale des Servers nicht übernehmen darf. Stoppe Worker dann mit SIGTERM und gib ihnen mindestens 30 Sekunden zum Beenden, bevor du sie hart beendest, da der abschließende Upload so lange dauern kann. Wenn ein Worker hart beendet wird, bevor sein Abbau läuft, entferne das übrig gebliebene Store-Verzeichnis unter/mnt/memory/vor der nächsten Sitzung, die diesen Store anhängt; alle darin enthaltenen Bearbeitungen, die nicht synchronisiert wurden, gehen verloren.
Eine Sandbox pro Session ausführen
Das Sandbox-pro-Session-Muster in Einen Worker ausführen gibt jeder Session ein frisches Dateisystem, was Den Host vorbereiten verlangt, wenn Sessions denselben Store anhängen. Behalte ant beta:worker poll --on-work (oder den Work-Poller des SDK) als Poller auf dem Host bei.
Der dort gezeigte Entrypoint ant beta:worker run mountet keine Memory-Stores, baue das Pro-Session-Image also stattdessen um den SDK-Worker herum: Sein Entrypoint konstruiert EnvironmentWorker und ruft handle_item() auf (handleItem in TypeScript, HandleItem in Go), das die Session-, Work- und Environment-Kennungen aus den ANTHROPIC_*-Variablen und das sessionspezifische secret des Work-Items aus ANTHROPIC_WORK_SECRET liest. Du kannst das Secret auch explizit als work_secret übergeben (workSecret in TypeScript, WorkSecret in Go).
import asyncio
import contextlib
import os
import signal
from anthropic import AsyncAnthropic
from anthropic.lib.environments import EnvironmentWorker
async def main() -> None:
async with AsyncAnthropic(auth_token=os.environ["ANTHROPIC_ENVIRONMENT_KEY"]) as client:
worker = EnvironmentWorker(client, workdir="/workspace")
# Ohne Argumente liest handle_item() die ANTHROPIC_*-Variablen, die das Spawn-
# Skript weitergereicht hat, einschließlich ANTHROPIC_WORK_SECRET.
task = asyncio.create_task(worker.handle_item())
# Das Abbrechen des Tasks beim Stoppen des Containers ermöglicht dem Worker, geänderte
# Memory-Dateien hochzuladen und die Store-Verzeichnisse vor dem Beenden zu entfernen.
loop = asyncio.get_running_loop()
for signum in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(signum, task.cancel)
with contextlib.suppress(asyncio.CancelledError):
await task
asyncio.run(main())ant beta:worker poll --on-work setzt ANTHROPIC_WORK_SECRET nicht für das Skript, das es startet, daher liest das Spawn-Skript das Secret aus dem Work-Item-JSON auf seiner Standardeingabe und übergibt es in die Sandbox:
#!/bin/bash
# spawn.sh: wird einmal pro beanspruchtem Work-Item aufgerufen
# Das beanspruchte Work-Item kommt als JSON über stdin an. Sein Secret ist das
# sitzungsspezifische Credential, das die Memory-Store-Endpunkte benötigen.
ANTHROPIC_WORK_SECRET="$(jq -r '.secret // empty')"
export ANTHROPIC_WORK_SECRET
mkdir -p "/host/outputs/$ANTHROPIC_SESSION_ID"
exec docker run --rm \
-e ANTHROPIC_SESSION_ID -e ANTHROPIC_ENVIRONMENT_KEY \
-e ANTHROPIC_WORK_ID -e ANTHROPIC_ENVIRONMENT_ID -e ANTHROPIC_BASE_URL \
-e ANTHROPIC_WORK_SECRET \
-v "/host/outputs/$ANTHROPIC_SESSION_ID":/workspace \
your-sdk-worker-imageWenn du Work stattdessen mit dem Work-Poller des SDK beanspruchst, übergib das secret jedes beanspruchten Items auf dieselbe Weise in die Sandbox, die du startest. Übergib es nur in die Sandbox, die diese Session bedient, und protokolliere es niemals.
Das Sandbox-Image benötigt außerdem ein beschreibbares /mnt/memory (siehe Den Host vorbereiten). Da jede Sandbox eine Session bedient und danach verworfen wird, müssen keine übrig gebliebenen Verzeichnisse aufgeräumt werden, und die Memory-Verzeichnisse müssen nicht per Bind-Mount auf den Host gemountet werden: Der Worker lädt ihre Inhalte in den Store hoch, bevor die Sandbox beendet wird. Wenn du einen Container stoppst, bevor seine Session endet, sende ein Signal, das der Entrypoint in einen Abbruch umwandelt (siehe Den Host vorbereiten), anstatt ihn zu killen, damit dieser Upload trotzdem läuft. Gib dem Container auch Zeit, den Upload abzuschließen: Docker lässt dem Stop-Signal standardmäßig nach 10 Sekunden ein SIGKILL folgen, erhöhe dieses Limit also auf mindestens die 30 Sekunden, die Den Host vorbereiten verlangt, mit --stop-timeout bei docker run oder der Termination-Grace-Period deines Orchestrators.
Sync konfigurieren
Zwei EnvironmentWorker-Optionen steuern das Memory-Verhalten:
memory_sync_interval(Python, in Sekunden;memorySyncIntervalMsin TypeScript, in Millisekunden;MemorySyncIntervalin Go, eine Duration): wie oft angehängte Stores mit dem Server abgeglichen werden, während die Session läuft. Standardmäßig 15 Sekunden; das Minimum beträgt 5 Sekunden. Ein kürzeres Intervall verkleinert das Zeitfenster, in dem eine andere Session veraltete Memories sieht, auf Kosten von mehr Memory-Store-Anfragen.Nonein Python,nullin TypeScript oder eine negative Duration in Go deaktiviert die Memory-Unterstützung vollständig: Der Worker lädt Stores weder herunter noch synchronisiert er sie, und eine Session mit angehängten Memory-Stores läuft ohne sie, obwohl ihr System-Prompt sie weiterhin beschreibt. Deaktiviere die Memory-Unterstützung daher nur auf Workern, deren Sessions keine Memory-Stores anhängen. Solange die Memory-Unterstützung aktiviert ist, schlägt ein Work-Item, das ohne sessionspezifischessecretfür eine Session mit angehängten Stores eintrifft, fehl, anstatt ohne Memory zu laufen (siehe Fehlerbehebung bei Memory-Mounts).memory_sync_deletions(memorySyncDeletionsin TypeScript,MemorySyncDeletionsin Go): ob eine Datei, die der Agent lokal löscht, auch aus dem Store gelöscht wird. Der Wert ist einer von"enabled"(der Standard),"log_only"oder"disabled"in Python und TypeScript und eine der Konstantenenvironments.MemorySyncDeletionsEnabled(der Nullwert),environments.MemorySyncDeletionsLogOnlyoderenvironments.MemorySyncDeletionsDisabledin Go. Wenn aktiviert, löscht der Worker das Memory aus dem Store, sobald ein späterer Sync bestätigt, dass die Datei weiterhin fehlt; im Log-only-Modus führt er dieselben Prüfungen durch, protokolliert aber nur, was er gelöscht hätte, sodass du beobachten kannst, was deine Worker löschen würden, bevor du dem aktivierten Modus vertraust; wenn deaktiviert, löscht er niemals aus dem Store. Uploads und Downloads sind von dieser Einstellung nicht betroffen.
Setze diese Optionen dort, wo du den Worker konstruierst, sei es über den EnvironmentWorker-Konstruktor oder, in Python und TypeScript, über die Factory client.beta.environments.work.worker(), die der Webhook-Handler verwendet.
Um beispielsweise alle 10 Sekunden zu synchronisieren und die Löschungen, die der Worker vorgenommen hätte, nur zu protokollieren:
worker = EnvironmentWorker(
client,
environment_id=environment_id,
environment_key=environment_key,
workdir="/workspace",
memory_sync_interval=10, # seconds
memory_sync_deletions="log_only",
)Schreibgeschützte Stores und Konflikte
Bei einem Store, der mit access: "read_only" angehängt ist, weigern sich die Tools write und edit, Dateien in seinem Verzeichnis zu ändern, und der Worker lädt niemals etwas daraus hoch. Änderungen über bash oder über ein benutzerdefiniertes Tool oder einen MCP-Server, den du aus der Sandbox bereitstellst, werden lokal nicht blockiert: Sie werden niemals mit dem Store synchronisiert, und die nächste Remote-Änderung an diesem Memory überschreibt sie. Wenn die lokale Kopie selbst während der Session unverändert bleiben muss, deaktiviere das bash-Tool für diesen Agenten und gib ihm kein benutzerdefiniertes Tool, das in das Dateisystem der Sandbox schreibt; mounte den Store-Pfad nicht schreibgeschützt, da der Worker selbst das Verzeichnis erstellen und die heruntergeladenen Memories hineinschreiben muss.
Konflikte werden zugunsten des Stores aufgelöst. Wenn der Agent eine Memory-Datei ändert, die sich seit der letzten Synchronisierung durch die Session auch im Store geändert hat, behält der Worker beim nächsten Sync die Version des Stores, überschreibt die lokale Datei damit und protokolliert eine Warnung; die Tools write und edit selbst sind erfolgreich, und kein Fehler erreicht den Agenten. Wenn die Änderung des Agenten weiterhin zutrifft, kann er die Datei nach dem Sync erneut lesen und die Änderung noch einmal vornehmen.
Fehlerbehebung bei Memory-Mounts
Der Worker protokolliert Mount- und Hintergrund-Sync-Fehler, anstatt sie an die Session zu melden; nur Schreibschutz-Verweigerungen erreichen den Agenten, als Tool-Fehler (siehe Schreibgeschützte Stores und Konflikte). Wenn ein Memory-Store nicht gemountet werden kann, wenn der Worker eine Session beansprucht, lässt der Worker das Work-Item fehlschlagen: Die Session gibt kein Fehler-Event aus und bleibt idle.
| Symptom | Ursache | Lösung |
|---|---|---|
Das Worker-Log enthält the work item carried no sessions token (in Go der Fehler ErrSessionMemoryNoToken) und das Work-Item schlägt fehl. | Das sessionspezifische secret des Work-Items hat den Worker nicht erreicht: Memory-Stores auf selbst gehosteten Sandboxes sind für deine Organisation nicht aktiviert, oder dein Spawn-Skript hat das Secret nicht in die Sandbox weitergeleitet. | Leite im Sandbox-pro-Session-Muster ANTHROPIC_WORK_SECRET in die Sandbox weiter, wie in Eine Sandbox pro Session ausführen gezeigt. Wenn der Worker in einem Prozess pollt und Sessions ausführt und dies trotzdem protokolliert, kontaktiere den Support. |
Das Worker-Log enthält something already exists at the memory store's path. | Ein Verzeichnis, das von einer vorherigen Session übrig geblieben ist, meist einer, deren Worker gekillt wurde, bevor sein Teardown lief. | Entferne das übrig gebliebene Verzeichnis, das die Log-Zeile nennt. Darin enthaltene Änderungen, die nicht synchronisiert wurden, gehen verloren. |
Das Worker-Log enthält cannot create the memory store's folder und the worker host must make this mount path writable. | Der Benutzer, unter dem der Worker läuft, kann keine Verzeichnisse unter /mnt/memory erstellen. | Erstelle /mnt/memory und übertrage es per chown an diesen Benutzer; siehe Den Host vorbereiten. |
Die Session steht kurz nachdem ein Worker sie beansprucht hat auf idle mit dem Stop-Reason requires_action und ohne Fehler-Event. | Der Worker hat das Work-Item fehlschlagen lassen, weil er einen Memory-Store aus einem der vorgenannten Gründe nicht mounten konnte. | Behebe die Ursache auf dem Host und sende dann ein user.interrupt-Event: Die Work der Session wird erneut in die Warteschlange gestellt, und der nächste Worker, der sie beansprucht, versucht den Mount erneut. |
Benutzerdefinierte Tools aus deiner Sandbox bereitstellen
Benutzerdefinierte Tools („custom tools“) sind Tools, die dein eigener Code ausführt: Der Agent gibt ein agent.custom_tool_use-Event aus und wartet auf ein passendes user.custom_tool_result. Der Worker kann dieser Code sein, und da er innerhalb deiner Sandbox läuft, erreicht das Tool die internen Dienste, Zugangsdaten und den Netzwerk-Egress, die du für die Sandbox konfiguriert hast, und nichts darüber hinaus. Der Environment-Key autorisiert das Posten von Ergebnissen benutzerdefinierter Tools, sodass dein Claude-API-Key vom Worker-Host fernbleibt.
Das Tool auf dem Agenten deklarieren
Füge den
toolsdes Agenten einencustom-Eintrag hinzu, dessennamemit dem Tool übereinstimmt, das dein Worker registriert. Siehe Benutzerdefinierte Tools für die vollständige Form der Deklaration.{ "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 (siehe SDK-Helfer), 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. Ein benutzerdefiniertes Tool, das auf dem Agenten deklariert, aber bei keinem Worker oder Client registriert ist, lässt die Session mit dem Stop-Reason requires_action pausiert, bis etwas sein Ergebnis postet; siehe Umgang mit Aufrufen benutzerdefinierter Tools für den Event-Ablauf.
Einen MCP-Server als benutzerdefinierte Tools wrappen
Der MCP-Connector verbindet sich von Anthropics Seite aus mit MCP-Servern, daher muss ein Server einen HTTP-Endpunkt bereitstellen, den Anthropic erreichen kann, direkt oder über einen MCP-Tunnel. Um einen Server zu verwenden, den nur dein Netzwerk erreichen kann, mache stattdessen den Worker zum MCP-Client und deklariere die Tools des Servers als benutzerdefinierte Tools. Der MCP-Server benötigt keine eingehende Konnektivität von außerhalb deines Netzwerks; Anthropic erhält die Tool-Definitionen, die du auf dem Agenten deklarierst, die Eingabe jedes Aufrufs und das Ergebnis, das dein Worker zurückpostet. Zur Laufzeit ruft das Modell ein gewrapptes Tool wie jedes andere benutzerdefinierte Tool auf:
- Der Agent gibt ein
agent.custom_tool_use-Event aus. - Der Worker, innerhalb deiner Sandbox, leitet den Aufruf über seine offene MCP-Session an den Server in deinem Netzwerk weiter.
- Der Worker postet die Antwort des Servers als
user.custom_tool_result.
Die clientseitigen MCP-Helfer der SDKs konvertieren die Tools des Servers in die ausführbaren Tools, die der Worker akzeptiert; installiere ein MCP-SDK neben dem Anthropic-SDK (pip install "anthropic[mcp]" "mcp>=1.24", npm install @modelcontextprotocol/sdk, go get github.com/modelcontextprotocol/go-sdk). Die Beispiele verbinden sich ohne Authentifizierung; um Zugangsdaten zu senden, konfiguriere den HTTP-Client oder die Request-Optionen, die du dem MCP-Transport übergibst (http_client in Python, requestInit in TypeScript, HTTPClient in Go).
Die Tools des Servers auf dem Agenten deklarieren
Liste die Tools des MCP-Servers auf und deklariere jedes als
custom-Tool;name,descriptionundinputSchemaaus MCP werden eins zu eins auf die Felder des benutzerdefinierten Tools abgebildet. 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", tools=[ {"type": "agent_toolset_20260401"}, *[to_custom_tool(tool) for tool in listed.tools], ], ) print(agent.id) asyncio.run(main())Die Tools vom Worker bereitstellen
Verbinde dich beim Start mit demselben MCP-Server, konvertiere seine Tools mit den MCP-Helfern und registriere sie zusammen mit dem integrierten Toolset. Halte eine MCP-Session für die 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())
Beachte Folgendes, wenn du einen MCP-Server wrappst:
- Tools werden deklariert, nicht zur Laufzeit entdeckt. Der Worker listet die Tools des MCP-Servers einmal beim Start auf und kann einer laufenden Session keine Tools hinzufügen. Wenn sich die Tools des Servers ändern, deklariere sie erneut, auf dem Agenten oder auf einer idle Session über Aktualisieren der Agentenkonfiguration, und starte den Worker neu.
- Namen und Beschreibungen müssen zur Managed Agents API passen. Namen benutzerdefinierter Tools sind pro Agent eindeutig und verwenden Buchstaben, Ziffern, Unterstriche und Bindestriche (1–128 Zeichen); eine nicht leere Beschreibung ist erforderlich; und das
tools-Array eines Agenten nimmt höchstens 128 Einträge auf (jedes gewrappte Tool ist ein Eintrag, und das integrierte Toolset ist ein weiterer). Die API lehnt eine Deklaration ab, die einen Tool-Namen wiederverwendet, ein benutzerdefiniertes Tool nach einem integrierten Agenten-Tool wiebashoderreadbenennt oder das reservierte Präfixmcp__verwendet. Die MCP-Helfer behalten die Namen und Beschreibungen des Servers bei, benenne also um oder kürze, wo nötig. Wenn zwei Server denselben Tool-Namen bereitstellen, definiere den Wrapper selbst unter einem Namen mit Präfix und lass ihn den ursprünglichen Tool-Namen des Servers aufrufen. - Die meisten Schemas werden unverändert durchgereicht. Die API akzeptiert die JSON-Schema-Schlüsselwörter, die MCP-Server üblicherweise ausgeben, wie
additionalPropertiesundtitle. Sie lehnt Referenz-Schlüsselwörter wie$refüberall iminput_schemaeines benutzerdefinierten Tools ab, inline also die Schemas, die Generatoren wie pydantic in$defsauslagern. Sie lehnt außerdemoneOf,anyOfundallOfauf oberster Ebene ab sowie Property-Namen außerhalb von Buchstaben, Ziffern, Unterstrichen, Punkten und Bindestrichen (1–64 Zeichen). - Tool-Fehler erscheinen als Fehler-Tool-Ergebnisse. Wenn der MCP-Server einen Tool-Fehler meldet, postet der Worker ein Fehler-Tool-Ergebnis, auf das das Modell reagieren kann. MCP-Inhalte ohne Tool-Ergebnis-Äquivalent, wie Audio-Blöcke und Ressourcen-Links, erscheinen ebenfalls als Fehler. Setze ein Timeout auf dem MCP-Client für ein schnelleres und klareres Fehlschlagen, wie es das Python-Worker-Beispiel mit
read_timeout_secondstut. Ohne eines wird ein hängender Aufruf erst dann zu einem Fehlerergebnis, wenn das Standard-Request-Timeout des TypeScript-MCP-SDK auslöst (etwa eine Minute) oder wenn der eigene Backstop des Workers greift: etwa zweieinhalb Minuten in Python und zwei Minuten in Go, wo der Worker einen Tool-Aufruf abbricht, der seinen Standard von 120 Sekunden überdauert, und ein Fehlerergebnis postet. - Wrappe Server, die du betreibst oder denen du vertraust. Name, Beschreibung und Ergebnisse eines gewrappten Tools gelangen wie die jedes anderen Tools in den Kontext des Modells: nicht vertrauenswürdige Eingaben, die beeinflussen können, was der Agent mit seinen anderen Tools tut, einschließlich
bashauf dem Worker-Host. Deklariere nur die Tools, die der Agent deiner Absicht nach verwenden soll. - Berechtigungsrichtlinien gelten nicht für benutzerdefinierte Tools. Berechtigungsrichtlinien regeln die integrierten und MCP-Toolsets; der Worker führt jeden Aufruf eines gewrappten Tools aus, den das Modell macht, platziere also jeden Genehmigungsschritt in deinem eigenen Tool-Code.
Monitoring und Betrieb
Diese Aufrufe laufen von deinem Monitoring- oder Betriebs-Tooling aus, authentifiziert mit deinem Claude-API-Key, um die Worker-Flotte zu beobachten und zu verwalten. Die Claim- und Keep-alive-Schleife wird innerhalb der Worker-Helfer abgewickelt, sodass du diese Endpunkte nicht direkt aufrufst.
Warteschlangentiefe lesen
work.stats gibt den Warteschlangenzustand für ein Environment zurück:
depthist die Anzahl der Items, die darauf warten, beansprucht zu werden. Skaliere deine Worker-Flotte oder alarmiere bei Rückstau basierend auf diesem Wert.pendingist die Anzahl der Items, die von einem Worker beansprucht, aber noch nicht bestätigt wurden. Die Worker-Helfer bestätigen jedes Item, bevor sie es verarbeiten, daher bleibt dieser Wert im Normalbetrieb nahe null; ein anhaltend von null abweichender Wert bedeutet, dass ein Worker zwischen Beanspruchen und Bestätigen hängen geblieben ist.oldest_queued_atist der Zeitstempel des ältesten Items, das sich noch in der Warteschlange befindet, das darauf wartet, beansprucht zu werden, oder beansprucht, aber noch nicht bestätigt ist, odernull, wenn es keines gibt.workers_pollingist die Anzahl der Worker, die in den letzten 30 Sekunden gepollt haben. Verwende dies für Liveness-Alarmierung.
import os
import anthropic
client = anthropic.Anthropic()
stats = client.beta.environments.work.stats(os.environ["ANTHROPIC_ENVIRONMENT_ID"])
print(f"depth={stats.depth} pending={stats.pending}"){
"type": "work_queue_stats",
"depth": 0,
"pending": 0,
"oldest_queued_at": null,
"workers_polling": 0
}Eine Session ordnungsgemäß stoppen
Verwende work.stop, um den Worker, der eine bestimmte Session bearbeitet, aufzufordern, sie herunterzufahren. Standardmäßig wechselt das Work-Item zu stopping: Der Worker bemerkt dies bei seinem nächsten Lease-Heartbeat, bricht den laufenden Tool-Aufruf der Session ab und bestätigt das Herunterfahren, woraufhin das Work-Item zu stopped wird. Übergib force: true im Request-Body (mit der CLI übergib --force), um das Work-Item sofort als stopped zu markieren, anstatt auf die Bestätigung des Workers zu warten.
Da diese Aufrufe von deinem Betriebs-Tooling statt vom Worker-Host aus laufen, wird ANTHROPIC_WORK_ID nicht automatisch gesetzt. Setze es auf die ID des Ziel-Work-Items, bevor du die folgenden Beispiele ausführst. Um die ID eines Work-Items zu finden, liste die Work-Items des Environments über die Environments-Work-Endpunkte auf.
import os
import anthropic
client = anthropic.Anthropic()
work = client.beta.environments.work.stop(
os.environ["ANTHROPIC_WORK_ID"],
environment_id=os.environ["ANTHROPIC_ENVIRONMENT_ID"],
)
print(work.state)Nächste Schritte
Modell der geteilten Verantwortung für selbst gehostete Sandbox-Environments.
Erstelle eine Session, um deinen Agenten auszuführen und mit der Ausführung von Aufgaben zu beginnen.
Verbinde Claude sicher mit MCP-Servern, die in deinem privaten Netzwerk laufen, ohne eingehende Ports zu öffnen oder Dienste dem öffentlichen Internet auszusetzen.
Was this page helpful?