Claude Platform Docs
MessagesTools

Server-Tools

Arbeite mit von Anthropic ausgeführten Tools: server_tool_use-Blöcke, pause_turn-Fortsetzung, gemischte Server- und Client-Tool-Turns sowie Domain-Filterung.

Serverseitig ausgeführte Tools teilen diese Mechanismen: den server_tool_use-Block, die pause_turn-Fortsetzung, Turns, die Server- und Client-Tools mischen, die Berechtigung für „Zero Data Retention“ (keine Datenspeicherung), oder ZDR, sowie Domain-Filterung. Zu einzelnen Tools siehe die Tool-Referenz.

Der server_tool_use-Block

Der server_tool_use-Block erscheint in Claudes Antwort, wenn ein serverseitig ausgeführtes Tool läuft. Sein id-Feld verwendet das Präfix srvtoolu_, um es von Client-Tool-Aufrufen zu unterscheiden:

{
  "type": "server_tool_use",
  "id": "srvtoolu_01A2B3C4D5E6F7G8H9",
  "name": "web_search",
  "input": { "query": "latest quantum computing breakthroughs" }
}

Die API führt das Tool intern aus. Du siehst den Aufruf und sein Ergebnis in der Antwort, kümmerst dich aber nicht um die Ausführung. Anders als bei Client-tool_use-Blöcken musst du nicht mit einem tool_result antworten. Der Ergebnisblock des Tools (zum Beispiel web_search_tool_result für die Websuche) folgt dem server_tool_use-Block im selben Assistant-Turn, zugeordnet über tool_use_id. Wenn Claude gleichzeitig eines deiner Client-Tools aufruft, erscheint der server_tool_use-Block ohne sein Ergebnis, und die Antwort endet mit stop_reason: "tool_use". Die API führt das Tool aus, wenn du die Client-tool_result-Blöcke in deiner nächsten Anfrage zurückgibst.

Die serverseitige Schleife und pause_turn

Bei der Verwendung von Server-Tools wie der Websuche führt die API Tool-Aufrufe in einer serverseitigen agentischen Schleife aus. Bei einem lang laufenden Turn kann die API diese Schleife pausieren und den Stop-Reason pause_turn zurückgeben.

So behandelst du den Stop-Reason pause_turn:

client = anthropic.Anthropic()

# Erste Anfrage mit Websuche
response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Search for comprehensive information about quantum computing breakthroughs in 2025",
        }
    ],
    tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],
)

# Prüfe, ob die Antwort den stop_reason pause_turn hat
if response.stop_reason == "pause_turn":
    # Setze die Konversation mit dem pausierten Inhalt fort
    messages = [
        {
            "role": "user",
            "content": "Search for comprehensive information about quantum computing breakthroughs in 2025",
        },
        {"role": "assistant", "content": response.content},
    ]

    # Sende die Fortsetzungsanfrage
    continuation = client.messages.create(
        model="claude-opus-5-5",
        max_tokens=1024,
        messages=messages,
        tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],
    )

    print(continuation)
else:
    print(response)

Beim Behandeln von pause_turn:

  • Setze die Konversation fort: Gib die pausierte Antwort unverändert in einer nachfolgenden Anfrage zurück, damit Claude seinen Turn fortsetzen kann.
  • Bewahre den Tool-Zustand: Füge dieselben Tools in die Fortsetzungsanfrage ein. Ein pausierter Turn kann mit einem server_tool_use-Block enden, dessen Tool noch nicht gelaufen ist, und die API gibt einen Validierungsfehler zurück, wenn dieses Tool in der Fortsetzung fehlt.
  • Wiederhole bei Bedarf: Ein fortgesetzter Turn kann erneut pausieren. Prüfe stop_reason bei jeder Antwort und setze fort, bis du einen anderen Stop-Reason erhältst, wobei du die Anzahl der Fortsetzungen wie bei jeder Retry-Schleife begrenzt.

Zu den anderen stop_reason-Werten und allgemeinen Behandlungsmustern siehe Stop-Reasons und Fallback.

Server-Tools und Client-Tools in einem Turn mischen

Claude kann ein Server-Tool und ein Client-Tool in derselben Gruppe paralleler Tool-Aufrufe aufrufen, zum Beispiel web_fetch zusammen mit einem benutzerdefinierten Tool. Ein Client-Tool ist jedes Tool, das dein Code ausführt und das einen tool_use-Block erzeugt, egal ob es benutzerdefiniert ist oder ein Client-Tool mit Anthropic-Schema wie das Bash-Tool. Wenn das passiert, führt die API das Server-Tool nicht aus. Sie kehrt sofort zurück, damit du zuerst das Client-Tool ausführen kannst:

  • stop_reason ist "tool_use", nicht "pause_turn".
  • content enthält den server_tool_use-Block und den Client-tool_use-Block, aber keinen Ergebnisblock für das Server-Tool: Dieser Aufruf ist nicht abgeschlossen.
  • Es gibt keine weitere Markierung. Erkenne den Zustand, indem du nach einem server_tool_use-Block suchst, dessen id keinen passenden Ergebnisblock in der Antwort hat. Ein mcp_tool_use-Block vom MCP-Connector verhält sich genauso. Server-Tool-Aufrufe, die ihren Ergebnisblock bereits in derselben Antwort haben, sind abgeschlossen und benötigen nichts von dir.
{
  "stop_reason": "tool_use",
  "content": [
    {
      "type": "text",
      "text": "I'll fetch the article and check your system at the same time."
    },
    {
      "type": "server_tool_use",
      "id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
      "name": "web_fetch",
      "input": { "url": "https://example.com/article" }
    },
    {
      "type": "tool_use",
      "id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
      "name": "run_command",
      "input": { "command": "uname -a" }
    }
  ]
}

Um den Turn fortzusetzen, führe die Client-Tools aus und sende eine User-Nachricht, deren Inhalt ausschließlich aus den tool_result-Blöcken besteht, einer für jeden tool_use-Block in dieser Antwort. Behalte dasselbe tools-Array bei: Eine Fortsetzungsanfrage, die das wartende Server-Tool nicht mehr definiert, schlägt mit einem 400 fehl, dessen Meldung mit but no `web_fetch` tool was provided endet.

{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
      "content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
    }
  ]
}

Die API hängt deine Ergebnisse an den noch offenen Assistant-Turn an, führt das zurückgestellte Server-Tool aus (bei pausierter Code-Ausführung setzt sie diese fort) und lässt Claude dann fortfahren. Bei einem Server-Tool, das Claude direkt aufgerufen hat, beginnt die nächste Antwort mit dem Ergebnisblock, der die server_tool_use-id der vorherigen Antwort beantwortet, gefolgt vom neu generierten Inhalt und einem frischen stop_reason:

{
  "stop_reason": "end_turn",
  "content": [
    {
      "type": "web_fetch_tool_result",
      "tool_use_id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
      "content": {
        "type": "web_fetch_result",
        "url": "https://example.com/article",
        "content": {
          "type": "document",
          "source": {
            "type": "text",
            "media_type": "text/plain",
            "data": "Full text content of the article..."
          }
        }
      }
    },
    {
      "type": "text",
      "text": "The article argues that... and your machine is running Linux..."
    }
  ]
}

Ein server_tool_use-Block und sein Ergebnisblock werden über tool_use_id zugeordnet, nicht über die Position: In diesem Ablauf kommen sie in zwei verschiedenen Antworten an, und der server_tool_use-Block wird in der zweiten nicht wiederholt. Behalte bei späteren Anfragen den gesamten Austausch in der richtigen Reihenfolge in deinem messages-Array: die erste Antwort als assistant-Nachricht, die tool_result-User-Nachricht und dann die nächste Antwort als weitere assistant-Nachricht, genauso wie du jeden anderen Tool-Use-Austausch ansammelst.

Wie sich das von pause_turn unterscheidet: Eine pause_turn-Antwort kann ebenfalls mit einem server_tool_use-Block enden, der nicht gelaufen ist, aber sie lässt nie einen Client-tool_use-Block auf dich warten, sodass du sie fortsetzt, indem du den Assistant-Inhalt unverändert erneut sendest. Eine Antwort, die einen Client-tool_use-Block auf dich warten lässt, hat nie den stop_reason pause_turn: Wenn Claude anhält, um deine Tools aufzurufen, ist stop_reason tool_use, und du setzt sie fort, indem du die Client-tool_result-Blöcke sendest, statt die Antwort erneut zu senden. In beiden Fällen führt die API das ausstehende Server-Tool zu Beginn der nächsten Anfrage aus.

Das folgende Beispiel aktiviert Web Fetch zusammen mit einem benutzerdefinierten run_command-Tool und behandelt die gemischte Antwort:

client = anthropic.Anthropic()

tools = [
    {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5},
    {
        "name": "run_command",
        "description": "Run a shell command on this computer and return its output.",
        "input_schema": {
            "type": "object",
            "properties": {
                "command": {"type": "string", "description": "The command to run"}
            },
            "required": ["command"],
        },
    },
]
messages = [
    {
        "role": "user",
        "content": "Summarize https://example.com/article and run uname -a to tell me what system this is on.",
    }
]

response = client.messages.create(
    model="claude-opus-4-8", max_tokens=1024, tools=tools, messages=messages
)

tool_results = [
    {
        "type": "tool_result",
        "tool_use_id": block.id,
        # Führe hier dein Tool aus. Dieses Beispiel gibt einen festen String zurück.
        "content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux",
    }
    for block in response.content
    if block.type == "tool_use"
]

if response.stop_reason == "tool_use" and tool_results:
    # Ein server_tool_use-Block ohne Ergebnisblock in dieser Antwort ist nicht abgeschlossen; sein Ergebnis kommt in einer späteren Antwort.
    # Sende nur die Client-tool_result-Blöcke zurück, mit denselben Tools.
    continuation = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=1024,
        tools=tools,
        messages=[
            *messages,
            {"role": "assistant", "content": response.content},
            {"role": "user", "content": tool_results},
        ],
    )
    # Wurde ein web_fetch aufgeschoben, läuft er bei dieser Anfrage und sein
    # web_fetch_tool_result ist der erste Block von continuation.content.
    print(continuation)
else:
    print(response)

Dieser Code ist auch korrekt, wenn Claude die beiden Arten von Aufrufen nicht mischt. Ein Turn mit ausschließlich Client-tool_use-Blöcken nimmt denselben Fortsetzungspfad, und ein Turn mit ausschließlich Server-Tool-Aufrufen benötigt keine Client-tool_result-Blöcke von dir: Seine Ergebnisblöcke sind normalerweise bereits vorhanden, und einer, der angehalten zurückkommt, wie etwa eine pause_turn-Antwort, wird stattdessen unverändert erneut gesendet.

ZDR und allowed_callers

Die Basisversionen von Web Search (web_search_20250305) und Web Fetch (web_fetch_20250910) sind für Zero Data Retention (ZDR) berechtigt.

Die Versionen _20260209 und später mit dynamischer Filterung sind standardmäßig nicht ZDR-berechtigt, da die dynamische Filterung intern auf Code-Ausführung beruht.

Um ein Server-Tool der Version _20260209 oder später mit ZDR zu verwenden, deaktiviere die dynamische Filterung, indem du "allowed_callers": ["direct"] am Tool setzt:

{
  "type": "web_search_20260209",
  "name": "web_search",
  "allowed_callers": ["direct"]
}

Dies beschränkt das Tool auf den direkten Aufruf und umgeht den internen Code-Ausführungsschritt.

allowed_callers steuert, wie ein Tool aufgerufen werden kann: direkt durch Claude ("direct"), aus einem Code-Ausführungscontainer heraus (zum Beispiel "code_execution_20260120") oder beides. Die _20260209-Versionen der Web-Tools verwenden standardmäßig nur den Code-Execution-Caller; frühere Versionen verwenden standardmäßig ["direct"]. Auf Modellen, die programmatischen Tool-Aufruf nicht unterstützen, erfordern diese Versionen allowed_callers: ["direct"]; ohne diese Angabe gibt die API einen Validierungsfehler zurück, der dazu auffordert, sie zu setzen.

Domain-Filterung

Server-Tools, die auf das Web zugreifen, akzeptieren die Parameter allowed_domains und blocked_domains, um zu steuern, welche Domains Claude erreichen kann. Beide sind Felder am Tool-Objekt:

{
  "type": "web_search_20250305",
  "name": "web_search",
  "allowed_domains": ["example.com", "docs.python.org"]
}

Bei der Verwendung von Domain-Filtern:

  • Domains sollten das HTTP/HTTPS-Schema nicht enthalten (verwende example.com statt https://example.com).
  • Subdomains werden automatisch eingeschlossen (example.com deckt docs.example.com ab).
  • Spezifische Subdomains beschränken die Ergebnisse auf genau diese Subdomain (docs.example.com liefert nur Ergebnisse von dieser Subdomain, nicht von example.com oder api.example.com).
  • Unterpfade werden für die Websuche unterstützt und passen auf alles nach dem Pfad (example.com/blog passt auf example.com/blog/post-1).
  • Web Fetch gleicht nur die Domain ab: Ein Eintrag, der einen Pfad enthält, passt nie auf eine Web-Fetch-URL.
  • Du kannst entweder allowed_domains oder blocked_domains verwenden, aber nicht beide in derselben Anfrage.

Wildcard-Unterstützung:

  • Wildcards (*) sind in der Domain selbst nicht erlaubt, nur im Pfad danach.
  • Gültig: example.com/*, example.com/*/articles
  • Ungültig: *.example.com, ex*.com

Ungültige Domain-Formate werden zum Zeitpunkt der Anfrage mit einem 400 invalid_request_error abgelehnt.

Claude Managed Agents verwendet dieselben Felder allowed_domains und blocked_domains an den Einträgen web_search und web_fetch des Agent-Toolsets. Bei Managed Agents enthält jede Liste höchstens 64 Einträge, für web_fetch aufgeführte Domains dürfen keinen Pfad enthalten, und Felder, die spezifisch für die Messages-API-Tools sind, wie max_uses, citations und cache_control, sind nicht verfügbar. Siehe Web-Search- und Web-Fetch-Domains einschränken für die vollständigen Regeln.

Web-Search- und Web-Fetch-Einstellungen auf Organisationsebene in der Claude Console gelten nur für Messages-API-Anfragen; sie gelten nicht für Managed-Agents-Sitzungen, die ausschließlich die Listen pro Tool am Agent-Toolset verwenden.

Dynamische Filterung mit Code-Ausführung

Die Versionen _20260209 und später von Web Search und Web Fetch verwenden intern Code-Ausführung, um dynamische Filter auf Suchergebnisse anzuwenden.

Streaming von Server-Tool-Events

Server-Tool-Events werden als Teil des normalen Flusses von „server-sent events“ (vom Server gesendete Ereignisse), oder SSE, gestreamt. Ein server_tool_use-Block, den Claude direkt aufruft, wird wie ein Client-tool_use-Block gestreamt: ein content_block_start-Event, gefolgt von input_json_delta-Events. Der Ergebnisblock kommt vollständig in einem einzigen content_block_start-Event an, ohne Deltas.

Siehe Streaming für die vollständige Event-Referenz. Die einzelnen Tool-Seiten dokumentieren toolspezifische Event-Namen, wo sie abweichen.

Batch-Anfragen

Alle Server-Tools unterstützen Batch-Verarbeitung. In einem Batch läuft die agentische Schleife genauso wie bei synchronen Anfragen, mit einem höheren Iterationslimit pro Turn. Wenn die Schleife dieses Limit erreicht, endet die Antwort mit stop_reason: "pause_turn"; du kannst sie fortsetzen, indem du eine Folgeanfrage mit dem zurückgegebenen Inhalt einreichst. Siehe Server-Tools und die agentische Schleife für Details.

Häufige Batch-Workloads umfassen das Anreichern eines Datensatzes mit Informationen aus dem Web, das Prüfen einer großen Menge von Dokumenten gegen aktuelle Quellen und das Ausführen von Analysecode über viele Dateien.

Nächste Schritte

Behebe die häufigsten Tool-Use-Fehler mit Diagnosetabellen vom Symptom zur Lösung.

Durchsuche das Web und zitiere Ergebnisse.

Rufe Inhalte von bestimmten URLs ab und lies sie, um Claudes Kontext mit Live-Webinhalten zu erweitern.

Führe Python- und Bash-Code in einem Sandbox-Container aus, um Daten zu analysieren, Dateien zu generieren und Lösungen iterativ zu verbessern.

Entdecke und lade Tools bei Bedarf.

Was this page helpful?