---
title: System-Nachrichten und Tool-Änderungen mitten im Gespräch
url: https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages
description: Ändere Systemanweisungen oder die Tool-Verfügbarkeit mitten in einem Gespräch, ohne das gecachte Präfix davor ungültig zu machen.
---

<Note>
  Um zu erfahren, wie „zero data retention“ (Null-Datenspeicherung), oder ZDR, auf diese Funktion angewendet wird, siehe [API und Datenspeicherung](https://platform.claude.com/docs/de/manage-claude/api-and-data-retention).
</Note>

Systemanweisungen stehen normalerweise im Top-Level-Feld `system`, vor jeder Nachricht im Gespräch. Diese Position ist ideal für [„prompt caching“ (Prompt-Caching)](https://platform.claude.com/docs/de/build-with-claude/prompt-caching): Der „system prompt“ (System-Prompt) ist Teil des stabilen Präfixes, sodass nachfolgende Turns den Cache treffen. Für Anweisungen, von denen du erst mitten in einer Sitzung merkst, dass du sie brauchst, ist diese Position dagegen ungünstig. Wenn du das Top-Level-Feld `system` bearbeitest, änderst du nämlich den allerersten Teil des Prompts und machst den Cache für alles Nachfolgende ungültig.

„Mid-conversation system messages“ (System-Nachrichten mitten im Gespräch) schließen diese Lücke. Anstatt das Top-Level-Feld `system` zu bearbeiten, hängst du eine `{"role": "system"}`-Nachricht an der Stelle im Gespräch an, an der die neue Anweisung relevant wird. Das gecachte Präfix bleibt gleich, sodass die nächste Anfrage es weiterhin aus dem Cache liest. Die neue Anweisung wird trotzdem als Systemanweisung angewendet und nicht als gewöhnlicher Benutzertext.

<Note>
  System-Nachrichten mitten im Gespräch sind auf der Claude API, [Claude in Amazon Bedrock](https://platform.claude.com/docs/de/build-with-claude/claude-in-amazon-bedrock) und [Google Cloud](https://platform.claude.com/docs/de/build-with-claude/claude-on-vertex-ai) verfügbar.

  Diese Funktion ist verfügbar auf Claude Fable 5.1, [Claude Mythos 5.1](https://platform.claude.com/docs/de/models/mythos-5-1/overview), Claude Fable 5, [Claude Mythos 5](https://platform.claude.com/docs/de/models/mythos-5/overview), Claude Opus 5.5, Claude Opus 4.8, Claude Opus 5, Claude Sonnet 5.5 und Claude Haiku 5.5. Für System-Nachrichten mitten im Gespräch ist kein Beta-Header erforderlich. Diese Funktion ist auf Claude Sonnet 5 nicht verfügbar. Verwende dort stattdessen das oberste `system`-Feld.

  [Tool-Änderungen mitten im Gespräch](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes) sind auf denselben Modellen in der Beta. Sende auf der Claude API den Beta-Header `inline-tools-2026-09-15`, der auch das [Definieren eines Tools innerhalb eines `tool_addition`-Blocks](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta) abdeckt. Für das [Hinzufügen eines MCP-Servers auf diese Weise](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta) ist ein zweiter Beta-Header erforderlich, `mcp-client-2026-09-15`, der auf der Claude API verfügbar ist. Der Header `mid-conversation-tool-changes-2026-07-01` funktioniert für Änderungen, die ein Tool per Referenz benennen, auf der Claude API, Amazon Bedrock und Google Cloud.

  [Turn-bezogene System-Nachrichten](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) (`clear_at`) befinden sich in der Beta und erfordern den Beta-Header `mid-conversation-system-clear-at-2026-08-21`. Sie sind auf denselben Modellen und Plattformen verfügbar wie System-Nachrichten mitten im Gespräch.
</Note>

## Tool-Änderungen mitten im Gespräch

Das `tools`-Array steht im gehashten Anfragepräfix noch vor dem obersten `system`-Feld, daher macht eine Änderung daran den [Prompt-Cache](https://platform.claude.com/docs/de/build-with-claude/prompt-caching) für das gesamte Gespräch ungültig. Tool-Änderungen mitten im Gespräch sind das Gegenstück zu Systemnachrichten mitten im Gespräch für Tools. Anstatt die Tool-Liste für die gesamte Dauer des Gesprächs festzulegen, änderst du zwischen den Turns, welche Tools dem Modell angeboten werden: Deklariere den vollständigen Tool-Satz vorab in `tools` und verwende dann `tool_addition`- und `tool_removal`-Blöcke, um dem Modell ein Tool ab einem bestimmten Punkt im Gespräch anzubieten oder es zurückzuziehen. Das `tools`-Array selbst ändert sich nie, sodass das gecachte Präfix intakt bleibt. Tool-Änderungen mitten im Gespräch sind in der Beta und verwenden auf der Claude API den Beta-Header `inline-tools-2026-09-15`.

`tool_addition` und `tool_removal` sind Content-Blöcke im `content`-Array einer `role: "system"`-Nachricht und können in derselben Nachricht mit `text`-Blöcken kombiniert werden. Die Nachricht folgt den Platzierungsregeln für jede Systemnachricht mitten im Gespräch, mit einer zusätzlichen Einschränkung nach einem pausierten Turn (siehe [Einschränkungen](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#limitations)), und die Änderung gilt ab diesem Punkt im Gespräch. Das `tool`-Feld jedes Blocks referenziert ein Tool, anstatt eines zu definieren: `{"type": "tool_reference", "name": "..."}` benennt ein Tool, das im `tools`-Array der Anfrage deklariert ist, und Tools des [MCP-Connectors](https://platform.claude.com/docs/de/agents-and-tools/mcp-connector) können einzeln mit `mcp_tool_reference` (`server_name` und `name`) oder als ganzes Toolset mit `mcp_toolset_reference` (`server_name`) referenziert werden. Die Referenzierung eines Namens, der nicht in `tools` deklariert ist, gibt einen 400-Fehler zurück (auf der Claude API mit `error.details.error_code` auf `tool_reference_unresolved` gesetzt). Ein `tool_addition`-Block kann stattdessen [die vollständige Definition des Tools enthalten](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta), was der Header `mid-conversation-tool-changes-2026-07-01` nicht unterstützt.

Jedes in `tools` deklarierte Tool wird dem Modell ab Beginn des Gesprächs angeboten, es sei denn, es ist mit `defer_loading: true` deklariert. Dann bleibt es zurückgehalten, bis ein `tool_addition`-Block es verfügbar macht. `tool_addition` bietet außerdem ein Tool erneut an, das ein früherer `tool_removal`-Block entzogen hat.

Die folgende Anfrage deklariert `get_weather` in `tools` und zieht es nach dem ersten Benutzer-Turn mit einem `tool_removal`-Block zurück. Die Anfrage sendet den Beta-Header `inline-tools-2026-09-15`.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "Say OK."
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_removal",
              "tool": {"type": "tool_reference", "name": "get_weather"}
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta inline-tools-2026-09-15 \
    --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: Say OK.
    - role: system
      content:
        - type: tool_removal
          tool:
            type: tool_reference
            name: get_weather
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15"],
      # Das vollständige Tool-Set wird vorab deklariert und ändert sich nie, sodass der
      # gecachte Präfix intakt bleibt.
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {
              "role": "user",
              "content": "Say OK.",
          },
          # Ab hier get_weather zurückziehen. Der Block referenziert
          # das Tool per Name, statt `tools` zu bearbeiten, sodass frühere Turns
          # byte-identisch bleiben und der Cache weiterhin trifft.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_removal",
                      "tool": {"type": "tool_reference", "name": "get_weather"},
                  },
              ],
          },
      ],
  )

  for block in response.content:
      if block.type == "text":
          print(block.text)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15"],
    // Das vollständige Tool-Set wird vorab deklariert und ändert sich nie, sodass der
    // gecachte Präfix intakt bleibt.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: {
              type: "string",
              description: "City name"
            }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "Say OK." },
      // Entziehe get_weather ab diesem Punkt. Der Block referenziert das
      // Tool per Name, statt `tools` zu bearbeiten, sodass frühere Turns
      // byte-identisch bleiben und der Cache weiterhin greift.
      {
        role: "system",
        content: [
          {
            type: "tool_removal",
            tool: { type: "tool_reference", name: "get_weather" }
          }
        ]
      }
    ]
  });

  for (const block of response.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15],
      // Das vollständige Tool-Set wird vorab deklariert und ändert sich nie, sodass der
      // gecachte Präfix intakt bleibt.
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "Say OK." },
          // Entziehe get_weather ab diesem Punkt. Der Block referenziert
          // das Tool per Name, statt `Tools` zu bearbeiten, sodass frühere Turns
          // byte-identisch bleiben und der Cache weiterhin trifft.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolRemovalBlock
                  {
                      Tool = new BetaToolChangeToolReference { Name = "get_weather" },
                  },
              ]),
          },
      ],
  });

  foreach (var block in response.Content)
  {
      if (block.TryPickText(out var text))
      {
          Console.WriteLine(text.Text);
      }
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaInlineTools2026_09_15},
  	// Das vollständige Tool-Set wird vorab deklariert und ändert sich nie, sodass der
  	// gecachte Präfix intakt bleibt.
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Say OK.")),
  		// Entziehe get_weather ab diesem Punkt. Der Block referenziert
  		// das Tool per Name, statt Tools zu bearbeiten, sodass frühere Turns
  		// byte-identisch bleiben und der Cache weiterhin trifft.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolRemovalBlock(anthropic.BetaToolChangeToolReferenceParam{
  					Name: "get_weather",
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.BetaRequestToolRemovalBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      // Das vollständige Tool-Set wird vorab deklariert und ändert sich nie, sodass der
      // gecachte Präfix intakt bleibt.
      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          .addTool(weatherTool)
          .addUserMessage("Say OK.")
          // Ab hier get_weather zurückziehen. Der Block referenziert
          // das Tool per Name, statt `tools` zu bearbeiten, sodass frühere Turns
          // byte-identisch bleiben und der Cache weiterhin trifft.
          .addMessage(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.SYSTEM)
              .contentOfBetaContentBlockParams(List.of(
                  BetaContentBlockParam.ofToolRemoval(BetaRequestToolRemovalBlock.builder()
                      .referenceTool("get_weather")
                      .build())))
              .build())
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [AnthropicBeta::INLINE_TOOLS_2026_09_15],
      // Das vollständige Tool-Set wird vorab deklariert und ändert sich nie, daher
      // bleibt das gecachte Präfix intakt.
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => 'Say OK.'],
          // Entziehe get_weather ab diesem Punkt. Der Block referenziert
          // das Tool per Name, statt `tools` zu bearbeiten, sodass frühere Turns
          // byte-identisch bleiben und der Cache weiterhin trifft.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_removal',
                      'tool' => ['type' => 'tool_reference', 'name' => 'get_weather'],
                  ],
              ],
          ],
      ],
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15],
    # Das vollständige Tool-Set wird vorab deklariert und ändert sich nie, sodass der
    # gecachte Präfix intakt bleibt.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "Say OK." },
      # Entziehe get_weather ab diesem Punkt. Der Block referenziert
      # das Tool per Name, statt `tools` zu bearbeiten, sodass frühere Turns
      # byte-identisch bleiben und der Cache weiterhin trifft.
      {
        role: "system",
        content: [
          {
            type: "tool_removal",
            tool: { type: "tool_reference", name: "get_weather" }
          }
        ]
      }
    ]
  )

  response.content.each do |block|
    puts block.text if block.type == :text
  end
  ```
</CodeGroup>

### Tools in einer Nachricht definieren (Beta)

Mit dem Beta-Header `inline-tools-2026-09-15` kann ein `tool_addition`-Block ein Tool per Wert definieren, also mit seiner vollständigen Definition, statt es per Referenz zu benennen. So kannst du ein Tool, das zu Beginn des Gesprächs unbekannt ist oder dessen Schema sich später ändert, durch Anhängen einer `role: "system"`-Nachricht einführen. Das `tools`-Array und alle früheren Nachrichten bleiben genau so, wie sie gesendet wurden, sodass der Prompt-Cache weiterhin trifft und nur die angehängte Nachricht als neue Eingabe verarbeitet wird. Die einzige Ausnahme, ein `tools`-Array ohne nicht zurückgestelltes Tool, wird in den Regeln unten behandelt. Der Header deckt auch das Hinzufügen und Entfernen von Tools per Referenz ab, sodass du `mid-conversation-tool-changes-2026-07-01` nicht zusätzlich senden musst.

Verpacke die Definition in ein `tool`-Objekt vom Typ `tool_definition`. Die `definition` ist ein `tools`-Eintrag, etwa ein benutzerdefiniertes Tool oder ein von Anthropic definiertes Client- oder Server-Tool, mit seiner üblichen Konfiguration, einschließlich `cache_control` und `defer_loading`. Während der Beta-Phase können einige Tool-Typen (darunter das Computer-Use-Tool) noch nicht in einer Nachricht definiert werden und geben einen 400-Fehler mit einem entsprechenden Hinweis zurück; deklariere diese in `tools` und füge sie per Referenz hinzu. So definierst du beispielsweise ein benutzerdefiniertes Tool mitten im Gespräch:

```json
{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": {
          "name": "db_query",
          "description": "Run a read-only SQL query against the analytics database.",
          "input_schema": {
            "type": "object",
            "properties": { "sql": { "type": "string" } },
            "required": ["sql"]
          }
        }
      }
    }
  ]
}
```

Ab dieser Position kann das Modell das Tool genauso aufrufen wie ein in `tools` deklariertes Tool. Das erneute Senden einer identischen Definition ändert nichts, sodass ein Client sie gefahrlos erneut senden kann, zum Beispiel bei einem Retry.

Die folgende Anfrage behält `get_weather` in `tools` und definiert `db_query` nach dem ersten Benutzer-Turn:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "How many orders shipped yesterday?"
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_addition",
              "tool": {
                "type": "tool_definition",
                "definition": {
                  "name": "db_query",
                  "description": "Run a read-only SQL query against the analytics database.",
                  "input_schema": {
                    "type": "object",
                    "properties": {"sql": {"type": "string"}},
                    "required": ["sql"]
                  }
                }
              }
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta inline-tools-2026-09-15 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  # Behalte mindestens ein nicht verzögertes Tool in `tools`, damit ein später
  # definiertes Tool den Anfang des gerenderten Prompts nicht verändert.
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: How many orders shipped yesterday?
    # Definiere db_query ab hier per Wert. `tools` und die
    # früheren Nachrichten bleiben exakt wie gesendet, also trifft der Cache weiterhin.
    - role: system
      content:
        - type: tool_addition
          tool:
            type: tool_definition
            definition:
              name: db_query
              description: Run a read-only SQL query against the analytics database.
              input_schema:
                type: object
                properties:
                  sql:
                    type: string
                required:
                  - sql
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15"],
      # Behalte mindestens ein nicht verzögertes Tool in `tools`, damit ein Tool, das
      # später definiert wird, den Anfang des gerenderten Prompts nicht verändert.
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {"role": "user", "content": "How many orders shipped yesterday?"},
          # Definiere db_query ab hier per Wert. `tools` und die
          # früheren Nachrichten bleiben exakt wie gesendet, daher greift der Cache weiterhin.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "name": "db_query",
                              "description": "Run a read-only SQL query against the analytics database.",
                              "input_schema": {
                                  "type": "object",
                                  "properties": {"sql": {"type": "string"}},
                                  "required": ["sql"],
                              },
                          },
                      },
                  },
              ],
          },
      ],
  )

  for block in response.content:
      if block.type == "tool_use":
          print(block.name, block.input)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15"],
    // Behalte mindestens ein nicht verzögertes Tool in `tools`, damit ein später
    // definiertes Tool den Anfang des gerenderten Prompts nicht verändert.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "How many orders shipped yesterday?" },
      // Definiere db_query ab hier per Wert. `tools` und die früheren
      // Nachrichten bleiben exakt wie gesendet, daher trifft der Cache weiterhin.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: {
                name: "db_query",
                description: "Run a read-only SQL query against the analytics database.",
                input_schema: {
                  type: "object",
                  properties: { sql: { type: "string" } },
                  required: ["sql"]
                }
              }
            }
          }
        ]
      }
    ]
  });

  for (const block of response.content) {
    if (block.type === "tool_use") {
      console.log(block.name, JSON.stringify(block.input));
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15],
      // Behalte mindestens ein nicht verzögertes Tool in `Tools`, damit ein später
      // definiertes Tool den Anfang des gerenderten Prompts nicht verändert.
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "How many orders shipped yesterday?" },
          // Definiere db_query ab hier per Wert. `Tools` und die
          // früheren Nachrichten bleiben exakt wie gesendet, also trifft der Cache weiterhin.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaTool
                          {
                              Name = "db_query",
                              Description = "Run a read-only SQL query against the analytics database.",
                              InputSchema = new InputSchema
                              {
                                  Properties = new Dictionary<string, JsonElement>
                                  {
                                      ["sql"] = JsonSerializer.SerializeToElement(new { type = "string" }),
                                  },
                                  Required = ["sql"],
                              },
                          },
                      },
                  },
              ]),
          },
      ],
  });

  foreach (var block in response.Content)
  {
      if (block.TryPickToolUse(out var toolUse))
      {
          Console.WriteLine($"{toolUse.Name} {JsonSerializer.Serialize(toolUse.Input)}");
      }
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaInlineTools2026_09_15},
  	// Behalte mindestens ein nicht verzögertes Tool in Tools, damit ein später
  	// definiertes Tool den Anfang des gerenderten Prompts nicht ändert.
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("How many orders shipped yesterday?")),
  		// Definiere db_query ab hier per Wert. Tools und die
  		// früheren Nachrichten bleiben exakt wie gesendet, daher greift der Cache weiterhin.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolAdditionBlock(anthropic.BetaToolChangeToolDefinitionParam{
  					Definition: anthropic.BetaToolUnionParam{OfTool: &anthropic.BetaToolParam{
  						Name:        "db_query",
  						Description: anthropic.String("Run a read-only SQL query against the analytics database."),
  						InputSchema: anthropic.BetaToolInputSchemaParam{
  							Properties: map[string]any{
  								"sql": map[string]any{"type": "string"},
  							},
  							Required: []string{"sql"},
  						},
  					}},
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if toolUse, ok := block.AsAny().(anthropic.BetaToolUseBlock); ok {
  		fmt.Println(toolUse.Name, toolUse.Input)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaRequestToolAdditionBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      BetaTool dbQueryTool = BetaTool.builder()
          .name("db_query")
          .description("Run a read-only SQL query against the analytics database.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("sql", JsonValue.from(Map.of("type", "string")))
                  .build())
              .addRequired("sql")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          // Behalte mindestens ein nicht zurückgestelltes Tool in `tools`, damit ein später
          // definiertes Tool den Anfang des gerenderten Prompts nicht verändert.
          .addTool(weatherTool)
          .addUserMessage("How many orders shipped yesterday?")
          // Definiere db_query ab hier per Wert. `tools` und die
          // früheren Nachrichten bleiben exakt wie gesendet, also trifft der Cache weiterhin.
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(dbQueryTool)
                  .build())))
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.toolUse().stream())
          .forEach(toolUse -> IO.println(toolUse.name() + " " + toolUse._input()));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaToolUseBlock;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [AnthropicBeta::INLINE_TOOLS_2026_09_15],
      // Behalte mindestens ein nicht verzögertes Tool in `tools`, damit ein später
      // definiertes Tool den Anfang des gerenderten Prompts nicht verändert.
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => 'How many orders shipped yesterday?'],
          // Definiere db_query ab hier per Wert. `tools` und die
          // früheren Nachrichten bleiben exakt wie gesendet, daher greift der Cache weiterhin.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'name' => 'db_query',
                              'description' => 'Run a read-only SQL query against the analytics database.',
                              'input_schema' => [
                                  'type' => 'object',
                                  'properties' => ['sql' => ['type' => 'string']],
                                  'required' => ['sql'],
                              ],
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

  foreach ($response->content as $block) {
      if ($block instanceof BetaToolUseBlock) {
          echo $block->name, ' ', json_encode($block->input), PHP_EOL;
      }
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15],
    # Behalte mindestens ein nicht verzögertes Tool in `tools`, damit ein später
    # definiertes Tool den Anfang des gerenderten Prompts nicht verändert.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "How many orders shipped yesterday?" },
      # Definiere db_query ab hier per Wert. `tools` und die
      # früheren Nachrichten bleiben exakt wie gesendet, daher greift der Cache weiterhin.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: {
                name: "db_query",
                description: "Run a read-only SQL query against the analytics database.",
                input_schema: {
                  type: "object",
                  properties: { sql: { type: "string" } },
                  required: ["sql"]
                }
              }
            }
          }
        ]
      }
    ]
  )

  response.content.each do |block|
    puts "#{block.name} #{block.input}" if block.is_a?(Anthropic::Beta::BetaToolUseBlock)
  end
  ```
</CodeGroup>

Der `content` der Antwort enthält einen `tool_use`-Block für das neue Tool, zum Beispiel:

```json
{
  "type": "tool_use",
  "id": "toolu_01A09q90qw90lq917835lq9",
  "name": "db_query",
  "input": {
    "sql": "SELECT COUNT(*) FROM orders WHERE shipped_at::date = CURRENT_DATE - 1"
  }
}
```

Um das Schema eines Tools zu ändern oder ein Server-Tool auf eine neuere Version umzustellen, sende eine andere Definition unter demselben Namen. Die neue Definition ersetzt die frühere ab dieser Position. Eine Definition, die den Namen eines Tools eines anderen Typs wiederverwendet, gibt einen 400-Fehler zurück, bei dem `error.details.error_code` auf `tool_name_conflict` gesetzt ist. Eine neuere Version desselben Tools gilt nicht als anderer Typ. `tool_removal` nimmt weiterhin eine Referenz entgegen, und ein entferntes Tool kann später erneut definiert oder wieder angeboten werden.

Aus der Stelle, an der die Definition gerendert wird, ergeben sich einige Regeln:

* **Deklariere vorab, was du weißt.** Ein Tool, das dir bei der ersten Anfrage bekannt ist, gehört in `tools`, mit `defer_loading: true` und einer späteren `tool_addition`-Referenz, falls das Modell es noch nicht sehen soll. Definiere nur das per Wert, was bei der ersten Anfrage unbekannt ist oder sich später ändert.
* **Behalte mindestens ein nicht zurückgestelltes Tool in `tools`.** Ein Gespräch, dessen `tools`-Array kein nicht zurückgestelltes Tool enthält, wird akzeptiert, aber das erste Tool, das es per Wert definiert, verändert den Anfang des gerenderten Prompts, was bei dieser Anfrage einen vollständigen Cache-Miss kostet. Ein [Tool-Search-Tool](https://platform.claude.com/docs/de/agents-and-tools/tool-use/tool-search-tool) zählt als nicht zurückgestellt.
* **Datierte Tool-Typen behalten ihre eigenen Beta-Header.** Wenn ein Server-Tool, das du per Wert definierst, einen eigenen Beta-Header erfordert, sende diesen Header bei jeder späteren Anfrage im Gespräch.
* **`cache_control` gehört entweder an den Block oder in die Definition, nicht an beide,** und zählt zum Breakpoint-Limit der Anfrage. Eine zurückgestellte Definition kann kein `cache_control` enthalten.

Eine Anfrage gibt einen 400-Fehler zurück, bei dem `error.details.error_code` auf `available_tools_limit_exceeded` gesetzt ist, wenn eines dieser Limits überschritten wird:

* Nach einer beliebigen Nachricht sind mehr als 10.000 zurückgestellte Tools verfügbar.
* Nach einer beliebigen Nachricht sind mehr als 10.000 Tools verfügbar, die nach der ersten Benutzernachricht definiert wurden.
* Die nach der ersten Benutzernachricht gesendeten Tool-Definitionen, die nach einer beliebigen Nachricht noch verfügbar sind, umfassen insgesamt mehr als 4 MB (4.194.304 Bytes).
* Der gerenderte Tool-Text ist größer als 4 MB (4.194.304 Bytes).

### Einen MCP-Server mitten im Gespräch hinzufügen (Beta)

Um mitten in einem Gespräch einen Server des [MCP-Connectors](https://platform.claude.com/docs/de/agents-and-tools/mcp-connector) hinzuzufügen, sende den Beta-Header `mcp-client-2026-09-15` zusammen mit `inline-tools-2026-09-15`. Die `definition` in einem `tool_addition`-Block kann dann ein `mcp_toolset` sein, sodass die Tools des Servers verfügbar werden, ohne `tools` zu bearbeiten. Gib die Verbindungsdetails des Servers wie gewohnt in `mcp_servers` an und hänge dann das Toolset an der Stelle an, an der der Server verfügbar wurde:

```json
{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": { "type": "mcp_toolset", "mcp_server_name": "calendar" }
      }
    }
  ]
}
```

Das `mcp_toolset`-Objekt ist dasselbe, das du in `tools` angeben würdest, einschließlich `default_config` und `configs`. Ein `tool_addition`-Block enthält niemals eine Server-URL oder ein Token. Diese bleiben in `mcp_servers`.

Die folgende Anfrage behält `get_weather` in `tools`, listet den Kalenderserver in `mcp_servers` auf und fügt das Toolset des Servers nach dem ersten Benutzer-Turn hinzu:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15,mcp-client-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "mcp_servers": [
        {
          "type": "url",
          "url": "https://mcp.example.com/calendar",
          "name": "calendar",
          "authorization_token": "YOUR_TOKEN"
        }
      ],
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "What'\''s on my calendar tomorrow?"
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_addition",
              "tool": {
                "type": "tool_definition",
                "definition": {
                  "type": "mcp_toolset",
                  "mcp_server_name": "calendar"
                }
              }
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --beta inline-tools-2026-09-15,mcp-client-2026-09-15 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  mcp_servers:
    - type: url
      url: https://mcp.example.com/calendar
      name: calendar
      authorization_token: YOUR_TOKEN
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: What's on my calendar tomorrow?
    # Stelle die Tools des Kalender-Servers ab diesem Punkt zur Verfügung.
    # Der Block benennt den Server; er enthält nie eine URL oder ein Token.
    - role: system
      content:
        - type: tool_addition
          tool:
            type: tool_definition
            definition:
              type: mcp_toolset
              mcp_server_name: calendar
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
      mcp_servers=[
          {
              "type": "url",
              "url": "https://mcp.example.com/calendar",
              "name": "calendar",
              "authorization_token": "YOUR_TOKEN",
          },
      ],
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {"role": "user", "content": "What's on my calendar tomorrow?"},
          # Stelle die Tools des Kalender-Servers ab diesem Punkt zur Verfügung.
          # Der Block benennt den Server; er enthält nie eine URL oder ein Token.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "type": "mcp_toolset",
                              "mcp_server_name": "calendar",
                          },
                      },
                  },
              ],
          },
      ],
  )

  # Die Antwort beginnt mit einem mcp_tool_listing-Block für den Kalender-Server,
  # prüfe also den Typ jedes Blocks, statt content[0] zu lesen.
  for block in response.content:
      match block.type:
          case "mcp_tool_listing":
              print(block.mcp_server_name, [tool.name for tool in block.tools])
          case "text":
              print(block.text)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
    mcp_servers: [
      {
        type: "url",
        url: "https://mcp.example.com/calendar",
        name: "calendar",
        authorization_token: "YOUR_TOKEN"
      }
    ],
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "What's on my calendar tomorrow?" },
      // Stelle die Tools des Kalender-Servers ab diesem Punkt zur Verfügung.
      // Der Block benennt den Server; er enthält nie eine URL oder ein Token.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  });

  // Die Antwort beginnt mit einem mcp_tool_listing-Block für den Kalender-Server,
  // prüfe also den Typ jedes Blocks, statt content[0] zu lesen.
  for (const block of response.content) {
    switch (block.type) {
      case "mcp_tool_listing":
        console.log(
          block.mcp_server_name,
          block.tools.map((tool) => tool.name)
        );
        break;
      case "text":
        console.log(block.text);
        break;
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15, AnthropicBeta.McpClient2026_09_15],
      McpServers =
      [
          new BetaRequestMcpServerUrlDefinition
          {
              Url = "https://mcp.example.com/calendar",
              Name = "calendar",
              AuthorizationToken = "YOUR_TOKEN",
          },
      ],
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "What's on my calendar tomorrow?" },
          // Stelle die Tools des Kalender-Servers ab hier zur Verfügung.
          // Der Block benennt den Server; er enthält nie eine URL oder ein Token.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaMcpToolset("calendar"),
                      },
                  },
              ]),
          },
      ],
  });

  // Die Antwort beginnt mit einem mcp_tool_listing-Block für den Kalender-Server,
  // prüfe also den Typ jedes Blocks, statt Content[0] zu lesen.
  foreach (var block in response.Content)
  {
      if (block.TryPickMcpToolListing(out var listing))
      {
          Console.WriteLine($"{listing.McpServerName} {JsonSerializer.Serialize(listing.Tools.Select(tool => tool.Name))}");
      }
      else if (block.TryPickText(out var text))
      {
          Console.WriteLine(text.Text);
      }
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas: []anthropic.AnthropicBeta{
  		anthropic.AnthropicBetaInlineTools2026_09_15,
  		anthropic.AnthropicBetaMCPClient2026_09_15,
  	},
  	MCPServers: []anthropic.BetaRequestMCPServerURLDefinitionParam{
  		{
  			URL:                "https://mcp.example.com/calendar",
  			Name:               "calendar",
  			AuthorizationToken: anthropic.String("YOUR_TOKEN"),
  		},
  	},
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's on my calendar tomorrow?")),
  		// Stelle die Tools des Kalender-Servers ab diesem Punkt zur Verfügung.
  		// Der Block benennt den Server; er enthält nie eine URL oder ein Token.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolAdditionBlock(anthropic.BetaToolChangeToolDefinitionParam{
  					Definition: anthropic.BetaToolUnionParam{OfMCPToolset: &anthropic.BetaMCPToolsetParam{
  						MCPServerName: "calendar",
  					}},
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  // Die Antwort beginnt mit einem mcp_tool_listing-Block für den Kalender-Server,
  // prüfe also den Typ jedes Blocks, statt Content[0] zu lesen.
  for _, block := range response.Content {
  	switch variant := block.AsAny().(type) {
  	case anthropic.BetaMCPToolListingBlock:
  		var toolNames []string
  		for _, tool := range variant.Tools {
  			toolNames = append(toolNames, tool.Name)
  		}
  		fmt.Println(variant.MCPServerName, toolNames)
  	case anthropic.BetaTextBlock:
  		fmt.Println(variant.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMcpTool;
  import com.anthropic.models.beta.messages.BetaMcpToolset;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaRequestMcpServerUrlDefinition;
  import com.anthropic.models.beta.messages.BetaRequestToolAdditionBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          .addBeta(AnthropicBeta.MCP_CLIENT_2026_09_15)
          .addMcpServer(BetaRequestMcpServerUrlDefinition.builder()
              .url("https://mcp.example.com/calendar")
              .name("calendar")
              .authorizationToken("YOUR_TOKEN")
              .build())
          .addTool(weatherTool)
          .addUserMessage("What's on my calendar tomorrow?")
          // Stelle die Tools des Kalender-Servers ab diesem Punkt zur Verfügung.
          // Der Block benennt den Server; er enthält nie eine URL oder ein Token.
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(BetaMcpToolset.builder()
                      .mcpServerName("calendar")
                      .build())
                  .build())))
          .build();

      BetaMessage response = client.beta().messages().create(params);

      // Die Antwort beginnt mit einem mcp_tool_listing-Block für den Kalender-Server,
      // prüfe also den Typ jedes Blocks, statt nur den ersten Block zu lesen.
      for (var block : response.content()) {
          switch (block.type().value()) {
              case MCP_TOOL_LISTING -> {
                  var listing = block.asMcpToolListing();
                  var toolNames = listing.tools().stream().map(BetaMcpTool::name).toList();
                  IO.println(listing.mcpServerName() + " " + toolNames);
              }
              case TEXT -> IO.println(block.asText().text());
          }
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaMCPTool;
  use Anthropic\Beta\Messages\BetaMCPToolListingBlock;
  use Anthropic\Beta\Messages\BetaTextBlock;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [
          AnthropicBeta::INLINE_TOOLS_2026_09_15,
          AnthropicBeta::MCP_CLIENT_2026_09_15,
      ],
      mcpServers: [
          [
              'type' => 'url',
              'url' => 'https://mcp.example.com/calendar',
              'name' => 'calendar',
              'authorization_token' => 'YOUR_TOKEN',
          ],
      ],
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => "What's on my calendar tomorrow?"],
          // Stelle die Tools des Kalender-Servers ab diesem Punkt zur Verfügung.
          // Der Block benennt den Server; er enthält nie eine URL oder ein Token.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'type' => 'mcp_toolset',
                              'mcp_server_name' => 'calendar',
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

  // Die Antwort beginnt mit einem mcp_tool_listing-Block für den Kalender-Server,
  // prüfe also den Typ jedes Blocks, statt content[0] zu lesen.
  foreach ($response->content as $block) {
      switch (true) {
          case $block instanceof BetaMCPToolListingBlock:
              $toolNames = array_map(fn (BetaMCPTool $tool) => $tool->name, $block->tools);
              echo $block->mcpServerName, ' ', json_encode($toolNames), PHP_EOL;
              break;
          case $block instanceof BetaTextBlock:
              echo $block->text, PHP_EOL;
              break;
      }
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [
      Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15,
      Anthropic::AnthropicBeta::MCP_CLIENT_2026_09_15
    ],
    mcp_servers: [
      {
        type: "url",
        url: "https://mcp.example.com/calendar",
        name: "calendar",
        authorization_token: "YOUR_TOKEN"
      }
    ],
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "What's on my calendar tomorrow?" },
      # Stelle die Tools des Kalender-Servers ab diesem Punkt zur Verfügung.
      # Der Block benennt den Server; er enthält nie eine URL oder ein Token.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  )

  # Die Antwort beginnt mit einem mcp_tool_listing-Block für den Kalender-Server,
  # prüfe also den Typ jedes Blocks, statt content[0] zu lesen.
  response.content.each do |block|
    case block
    when Anthropic::Beta::BetaMCPToolListingBlock
      puts "#{block.mcp_server_name} #{block.tools.map(&:name)}"
    when Anthropic::Beta::BetaTextBlock
      puts block.text
    end
  end
  ```
</CodeGroup>

Mit `mcp-client-2026-09-15` beginnt eine Antwort, für die die API die Tool-Liste eines Servers abgerufen hat, mit einem `mcp_tool_listing`-Block, einem für jeden abgerufenen Server. Wenn dein Code `content[0]` liest, überspringe diese Blöcke. Sende die Assistant-Nachricht unverändert zurück, einschließlich dieses Blocks, und sende `mcp-client-2026-09-15` weiterhin bei jeder Anfrage, die ihn enthält. Spätere Anfragen verwenden dann die aufgezeichnete Liste, statt den Server erneut abzufragen. Um ein Toolset selbst zu fixieren, kopiere diese Liste in das Feld `tools` des `mcp_toolset`, wie unter [Die Tool-Liste eines MCP-Servers fixieren](https://platform.claude.com/docs/de/agents-and-tools/mcp-connector#pin-mcp-tool-list) beschrieben.

`mcp-client-2026-09-15` umfasst alles, was `mcp-client-2025-11-20` umfasst, sodass du nicht beide senden musst. Diese Funktionen sind auf der Claude API verfügbar. Für Anfragen, die den MCP-Connector verwenden, gelten weiterhin dessen Bedingungen zur [Datenaufbewahrung](https://platform.claude.com/docs/de/agents-and-tools/mcp-connector#data-retention).

## Wann eine System-Nachricht mitten im Gespräch sinnvoll ist

[Prompt-Caching](https://platform.claude.com/docs/de/build-with-claude/prompt-caching) hasht das Anfragepräfix der Reihe nach: `tools`, dann `system`, dann `messages`. Ein Cache-Treffer erfordert, dass das Präfix bis zum Cache-Breakpoint Byte für Byte exakt mit einer kürzlich gestellten Anfrage übereinstimmt.

Diese Reihenfolge bedeutet, dass das Top-Level-Feld `system` ganz am Anfang des gehashten Präfixes liegt. Jede Änderung daran, selbst das Anhängen eines Satzes, erzeugt einen anderen Hash, und die Anfrage verfehlt den Cache für den System-Prompt und jede gecachte Nachricht danach.

Mit System-Nachrichten mitten im Gespräch kannst du die Anweisung stattdessen am **Ende** des Nachrichtenverlaufs hinzufügen. Alles vor der neuen Anweisung bleibt unverändert, sodass der bestehende Cache-Eintrag weiterhin passt und nur die neue Nachricht als frische Eingabe verarbeitet wird.

Einige Situationen, in denen das wichtig ist:

* **Richtlinien- oder Persona-Änderungen mitten in der Sitzung.** Eine lange agentische Sitzung benötigt nach Dutzenden gecachter Turns eine neue Einschränkung („schreibe ab jetzt alle SQL-Abfragen als parametrisierte Queries“). Sie dem Top-Level-Feld `system` hinzuzufügen, würde den gesamten Verlauf neu verarbeiten.
* **Turn-bezogener Kontext, der maßgeblich sein muss.** Du möchtest einen Aktualitätshinweis, eine Sitzungsfrist oder eine Änderung der Tool-Verfügbarkeit mit Systemgewicht einfügen, und er ändert sich zu oft, um im gecachten Präfix zu stehen.
* **Turn-bezogene Erinnerungen, die sich nicht anhäufen sollen.** Ein Harness stupst das Modell nach jedem Stapel von Tool-Ergebnissen an („fordere unabhängige Lesevorgänge gemeinsam an“, „der Benutzer hat schon eine Weile nichts von dir gehört“) und möchte, dass das Modell nur die neueste Kopie sieht. Eine [turn-bezogene System-Nachricht](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) wird für einen Turn gerendert und kostet danach nichts, ohne dass etwas aus dem Verlauf gelöscht wird.
* **Zustandsänderungen, die deine Anwendung beobachtet.** Deine Anwendung bemerkt etwas, das Claude als Tatsache auf Betreiberebene behandeln sollte: Dateien auf der Festplatte haben sich geändert, der Benutzer hat eine Auto-Approve-Einstellung umgeschaltet, die verfügbaren Tools haben sich geändert oder das verbleibende Token-Budget ist unter einen Schwellenwert gefallen.
* **Benutzereingaben, die eine agentische Schleife nicht unterbrechen sollen.** Ein Benutzer tippt eine Folgefrage, während Claude noch Tools für die vorherige Anfrage ausführt. Wenn du sie als System-Nachricht nach dem nächsten Tool-Ergebnis weiterleitest, kann Claude die neue Eingabe in die bereits laufende Arbeit einbeziehen, anstatt sie als neue Anfrage zu behandeln, zu der gewechselt werden muss. Hänge bei Claude Sonnet 5.5 und Claude Haiku 5.5 die Worte des Benutzers stattdessen als `text`-Block nach dem letzten `tool_result` in derselben `user`-Nachricht an. Siehe [Platzierung nach Tool-Ergebnissen](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#placement-after-tool-results).
* **Moduswechsel, die dauerhafte Berechtigungen erteilen.** Ein Modus auf Sitzungsebene kann eine System-Nachricht mitten im Gespräch verwenden, um eine dauerhafte Zustimmung zu einer teuren Fähigkeit zu erteilen, etwa dem automatischen Starten von Multiagenten-Workflows, mit einer kurzen Auffrischung alle paar Turns und einem Hinweis beim Verlassen, wenn der Modus ausgeschaltet wird. Ein ausgearbeitetes Beispiel findest du unter [Einen Orchestrierungsmodus erstellen](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-effort-example).

In all diesen Fällen könntest du die Anweisung in eine reguläre `user`-Nachricht setzen, und Claude befolgt durchaus Anweisungen, die in Benutzer-Turns eintreffen. Der Unterschied liegt in der Priorität: Eine `user`-Nachricht wird so behandelt, als käme sie vom Endbenutzer, während eine `system`-Nachricht so behandelt wird, als käme sie von dir, dem Betreiber der Anwendung. Wenn beide in Konflikt stehen, haben Systemanweisungen Vorrang. Verwende daher die `system`-Rolle für Tatsachen und Einschränkungen auf Betreiberebene, die auch dann gelten sollen, wenn der Endbenutzer etwas anderes verlangt. Eine System-Nachricht mitten im Gespräch behält diese Priorität auf Betreiberebene, ohne die Cache-Miss-Kosten für das Bearbeiten des Top-Level-Felds `system` zu zahlen.

## Funktionsweise

Füge dem `messages`-Array eine Nachricht mit `"role": "system"` hinzu. Verwende für `content` einen einfachen String oder Content-Blöcke, genau wie bei einem `user`- oder `assistant`-Turn. Die Anweisung gilt ab diesem Punkt im Gespräch. Wenn Anweisungen im Widerspruch stehen, haben spätere System-Nachrichten Vorrang vor früheren, und System-Nachrichten mitten im Gespräch haben für die nachfolgenden Turns Vorrang vor dem Top-Level-Feld `system`.

Du kannst das Top-Level-Feld `system` weiterhin für Anweisungen setzen, die für das gesamte Gespräch gelten sollen. Reserviere System-Nachrichten mitten im Gespräch für Anweisungen, die erst später relevant werden oder die du hinzufügen möchtest, ohne das gecachte Präfix ungültig zu machen.

Eine `role: "system"`-Nachricht kann außerdem `output_config.effort` enthalten, um das [Effort](https://platform.claude.com/docs/de/build-with-claude/effort)-Level mitten in einem Gespräch zu ändern. Dies ist als Beta für Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 und Claude Haiku 5.5 auf der Claude API und Google Cloud verfügbar und erfordert den Beta-Header `mid-conversation-output-config-2026-07-01`. Auf Amazon Bedrock ist es als Beta für Claude Fable 5.1, Claude Mythos 5.1 und Claude Opus 5.5 verfügbar, mit demselben Beta-Wert. Claude Opus 5 unterstützt es auf Amazon Bedrock nicht. Siehe [Effort pro Nachricht](https://platform.claude.com/docs/de/build-with-claude/effort#change-effort-mid-conversation-beta).

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "cache_control": {"type": "ephemeral"},
      "system": "You are a code review assistant. Be concise.",
      "messages": [
        {
          "role": "user",
          "content": "Review process() in utils.py for performance issues."
        },
        {
          "role": "assistant",
          "content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
        },
        {
          "role": "user",
          "content": "Now review the calling code that invokes process()."
        },
        {
          "role": "system",
          "content": "From now on, every suggestion must include explicit type annotations."
        }
      ]
    }'
  ```

  ```bash CLI
  ant messages create --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  cache_control:
    type: ephemeral
  system: You are a code review assistant. Be concise.
  messages:
    - role: user
      content: Review process() in utils.py for performance issues.
    - role: assistant
      content: >-
        The list comprehension is fine for small inputs. For large inputs,
        consider a generator to avoid materializing the full list.
    - role: user
      content: Now review the calling code that invokes process().
    - role: system
      content: From now on, every suggestion must include explicit type annotations.
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      # Automatisches Prompt-Caching: Jede Anfrage cacht die bisherige Konversation,
      # und die nächste Anfrage liest das unveränderte Präfix aus dem Cache.
      cache_control={"type": "ephemeral"},
      system="You are a code review assistant. Be concise.",
      messages=[
          {
              "role": "user",
              "content": "Review process() in utils.py for performance issues.",
          },
          {
              "role": "assistant",
              "content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.",
          },
          {
              "role": "user",
              "content": "Now review the calling code that invokes process().",
          },
          # Der Reviewer merkt mitten in der Sitzung, dass alle Vorschläge
          # auch die strikte Typisierungsrichtlinie des Teams erfüllen müssen. Hängst du die
          # Anweisung hier an, bleiben frühere Turns byte-identisch, sodass das
          # von der vorherigen Anfrage gecachte Präfix weiterhin aus dem Cache gelesen wird.
          {
              "role": "system",
              "content": "From now on, every suggestion must include explicit type annotations.",
          },
      ],
  )

  for block in response.content:
      if block.type == "text":
          print(block.text)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    // Automatisches Prompt-Caching: Jede Anfrage cacht die bisherige Konversation,
    // und die nächste Anfrage liest das unveränderte Präfix aus dem Cache.
    cache_control: { type: "ephemeral" },
    system: "You are a code review assistant. Be concise.",
    messages: [
      {
        role: "user",
        content: "Review process() in utils.py for performance issues."
      },
      {
        role: "assistant",
        content:
          "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
      },
      {
        role: "user",
        content: "Now review the calling code that invokes process()."
      },
      // Der Reviewer merkt mitten in der Sitzung, dass alle Vorschläge auch die
      // strikte Typisierungsrichtlinie des Teams erfüllen müssen. Wird die Anweisung hier angehängt,
      // bleiben frühere Turns byte-identisch, sodass das von der vorherigen Anfrage
      // gecachte Präfix weiterhin aus dem Cache gelesen wird.
      {
        role: "system",
        content: "From now on, every suggestion must include explicit type annotations."
      }
    ]
  });

  const textBlock = response.content.find(
    (block): block is Anthropic.TextBlock => block.type === "text"
  );
  console.log(textBlock?.text);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      // Automatisches Prompt-Caching: Jede Anfrage cacht die bisherige Konversation,
      // und die nächste Anfrage liest das unveränderte Präfix aus dem Cache.
      CacheControl = new CacheControlEphemeral(),
      System = "You are a code review assistant. Be concise.",
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = "Review process() in utils.py for performance issues."
          },
          new()
          {
              Role = Role.Assistant,
              Content = "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
          },
          new()
          {
              Role = Role.User,
              Content = "Now review the calling code that invokes process()."
          },
          // Der Reviewer merkt mitten in der Sitzung, dass alle Vorschläge auch
          // die strikte Typisierungsrichtlinie des Teams erfüllen müssen. Hängst du die Anweisung hier an, bleiben
          // frühere Turns byte-identisch, sodass das von der vorherigen
          // Anfrage gecachte Präfix weiterhin aus dem Cache gelesen wird.
          new()
          {
              Role = Role.System,
              Content = "From now on, every suggestion must include explicit type annotations."
          }
      ]
  };

  var response = await client.Messages.Create(parameters);
  Console.WriteLine(response);
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	// Automatisches Prompt-Caching: Jede Anfrage cacht die bisherige Konversation,
  	// und die nächste Anfrage liest das unveränderte Präfix aus dem Cache.
  	CacheControl: anthropic.NewCacheControlEphemeralParam(),
  	System: []anthropic.TextBlockParam{
  		{Text: "You are a code review assistant. Be concise."},
  	},
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Review process() in utils.py for performance issues.")),
  		anthropic.NewAssistantMessage(anthropic.NewTextBlock("The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.")),
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Now review the calling code that invokes process().")),
  		// Der Reviewer merkt mitten in der Sitzung, dass alle Vorschläge auch
  		// die strenge Typisierungsrichtlinie des Teams erfüllen müssen. Die Anweisung
  		// hier anzuhängen hält frühere Turns byte-identisch, sodass das Präfix, das
  		// die vorherige Anfrage gecacht hat, weiterhin aus dem Cache gelesen wird.
  		{
  			Role: anthropic.MessageParamRoleSystem,
  			Content: []anthropic.ContentBlockParamUnion{
  				anthropic.NewTextBlock("From now on, every suggestion must include explicit type annotations."),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.messages.CacheControlEphemeral;
  // ...
  import com.anthropic.models.messages.MessageParam;
  // ...
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          // Automatisches Prompt-Caching: Jede Anfrage cacht die bisherige Konversation,
          // und die nächste Anfrage liest das unveränderte Präfix aus dem Cache.
          .cacheControl(CacheControlEphemeral.builder().build())
          .system("You are a code review assistant. Be concise.")
          .addUserMessage("Review process() in utils.py for performance issues.")
          .addAssistantMessage("The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.")
          .addUserMessage("Now review the calling code that invokes process().")
          // Der Reviewer merkt mitten in der Sitzung, dass alle Vorschläge auch die
          // strikte Typisierungsrichtlinie des Teams erfüllen müssen. Wird die Anweisung hier angehängt, bleiben
          // frühere Turns byte-identisch, sodass das von der vorherigen Anfrage gecachte Präfix
          // weiterhin aus dem Cache gelesen wird.
          .addMessage(MessageParam.builder()
              .role(MessageParam.Role.SYSTEM)
              .content("From now on, every suggestion must include explicit type annotations.")
              .build())
          .build();

      Message response = client.messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  ```

  ```php PHP
  use Anthropic\Messages\CacheControlEphemeral;
  // ...
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [
          ['role' => 'user', 'content' => 'Review process() in utils.py for performance issues.'],
          ['role' => 'assistant', 'content' => 'The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.'],
          ['role' => 'user', 'content' => 'Now review the calling code that invokes process().'],
          // Der Reviewer merkt mitten in der Sitzung, dass alle Vorschläge zusätzlich
          // die strikte Typisierungsrichtlinie des Teams erfüllen müssen. Hängst du die Anweisung hier an, bleiben
          // frühere Turns byte-identisch, sodass das von der vorherigen Anfrage gecachte Präfix
          // weiterhin aus dem Cache gelesen wird.
          ['role' => 'system', 'content' => 'From now on, every suggestion must include explicit type annotations.']
      ],
      model: 'claude-opus-5-5',
      // Automatisches Prompt-Caching: Jede Anfrage cacht die bisherige Konversation,
      // und die nächste Anfrage liest das unveränderte Präfix aus dem Cache.
      cacheControl: CacheControlEphemeral::with(),
      system: 'You are a code review assistant. Be concise.',
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    # Automatisches Prompt-Caching: Jede Anfrage cacht die bisherige Konversation,
    # und die nächste Anfrage liest das unveränderte Präfix aus dem Cache.
    cache_control: { type: "ephemeral" },
    system: "You are a code review assistant. Be concise.",
    messages: [
      { role: "user", content: "Review process() in utils.py for performance issues." },
      { role: "assistant", content: "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list." },
      { role: "user", content: "Now review the calling code that invokes process()." },
      # Der Reviewer merkt mitten in der Sitzung, dass alle Vorschläge auch
      # die strikte Typisierungsrichtlinie des Teams erfüllen müssen. Hängst du die Anweisung hier an, bleiben
      # frühere Turns byte-identisch, sodass das von der vorherigen Anfrage gecachte Präfix
      # weiterhin aus dem Cache gelesen wird.
      { role: "system", content: "From now on, every suggestion must include explicit type annotations." }
    ]
  )

  response.content.each do |block|
    puts block.text if block.type == :text
  end
  ```
</CodeGroup>

Dieses Beispiel aktiviert [automatisches Caching](https://platform.claude.com/docs/de/build-with-claude/prompt-caching#automatic-caching) mit dem Top-Level-Feld `cache_control`. Prompt-Caching ist optional: Wenn eine Anfrage kein `cache_control`-Feld enthält (automatisch oder als [expliziter Breakpoint](https://platform.claude.com/docs/de/build-with-claude/prompt-caching#explicit-cache-breakpoints)), wird nichts gecacht, und jede Anfrage zahlt den regulären Preis für Eingabe-Token für das gesamte Gespräch. Bei aktiviertem Caching lässt das Anhängen der System-Nachricht die bereits gecachten Turns unverändert, sodass die Anfrage mit der neuen Anweisung sie weiterhin aus dem Cache liest, statt sie erneut zu verarbeiten. Caching setzt außerdem voraus, dass das Gespräch die [minimale cachebare Prompt-Länge](https://platform.claude.com/docs/de/build-with-claude/prompt-caching#cache-limitations) erreicht; ein so kurzes Beispiel wie dieses liegt darunter, sodass `cache_creation_input_tokens` und `cache_read_input_tokens` bei 0 bleiben, bis das Gespräch wächst.

Eine System-Nachricht mitten im Gespräch, die Inhalt enthält (`text`-, `tool_addition`- oder `tool_removal`-Blöcke), muss unmittelbar auf einen `user`-Turn folgen (oder auf einen `assistant`-Turn, der mit einem Server-Tool-Ergebnis endet) und muss entweder der letzte Eintrag in `messages` sein oder unmittelbar von einem `assistant`-Turn gefolgt werden. Eine `user`-Nachricht mit `tool_result`-Blöcken zählt ebenfalls: In einer agentischen Schleife kannst du die System-Nachricht direkt nach den Tool-Ergebnissen platzieren, vor Claudes nächstem Turn. Jede andere Position für eine Nachricht mit Inhalt, auch eine zwischen einem `assistant`-`tool_use`-Block und dem `tool_result`, das ihn beantwortet, gibt einen 400-Fehler zurück. Eine Nachricht mit leerem `content`, die nur [`output_config.effort`](https://platform.claude.com/docs/de/build-with-claude/effort#change-effort-mid-conversation-beta) setzt, wird überall in `messages` akzeptiert. Aufeinanderfolgende `system`-Nachrichten werden gemeinsam beurteilt, sodass eine reine Effort-Nachricht neben einer Nachricht mit Inhalt der Regel für Inhalte folgt.

### Platzierung nach Tool-Ergebnissen

In einer [agentischen Schleife](https://platform.claude.com/docs/de/agents-and-tools/tool-use/overview) steht die System-Nachricht nach der `user`-Nachricht, die die Tool-Ergebnisse liefert. Bei den meisten Modellen ist dies auch die Stelle, an der deine Anwendung Eingaben weiterleiten kann, die der Benutzer getippt hat, während Claude gearbeitet hat, sodass der neue Kontext aufgenommen wird, ohne den Turn neu zu starten (für Claude Sonnet 5.5 und Claude Haiku 5.5 siehe das Ende dieses Abschnitts):

```json
[
  { "role": "user", "content": "Run the test suite and fix any failures." },
  {
    "role": "assistant",
    "content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
  },
  {
    "role": "user",
    "content": [
      { "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" }
    ]
  },
  {
    "role": "system",
    "content": "The user sent the following message while you were working: also update the changelog before you finish."
  }
]
```

Formuliere den Systeminhalt als Kontext und nicht als Befehl, der den Benutzer übersteuert. Nenne die Tatsache („neue Eingabe vom Benutzer eingetroffen: X“, „das verbleibende Token-Budget beträgt jetzt Y“) und lass Claude darauf reagieren. Claude ist darauf trainiert, Anweisungen zu widerstehen, die gegen den Benutzer zu arbeiten scheinen, und dieser Schutz gilt auch für die System-Rolle. Formulierungen wie „ignoriere, was der Benutzer gesagt hat“ sind daher weniger wirksam als die Angabe, was sich geändert hat.

Dieses Muster dient dazu, Eingaben des eigenen Endbenutzers des Gesprächs weiterzuleiten. Verwende es nicht, um Tool-Ausgaben, abgerufene Dokumente oder andere Inhalte Dritter zu übergeben; belasse solche Inhalte in `tool_result`-Blöcken (siehe [Einschränkungen](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#limitations)).

Übermittle bei Claude Sonnet 5.5 und Claude Haiku 5.5 die Worte des Benutzers stattdessen im Benutzer-Turn. Diese Modelle sind darauf trainiert, Prompt-Injection über Tool-Ergebnisse zu widerstehen, sodass sie eine direkt nach einem Tool-Ergebnis platzierte System-Nachricht als nicht vertrauenswürdigen Text behandeln und ignorieren können. Hänge die Worte des Benutzers als `text`-Block nach dem letzten `tool_result` in derselben `user`-Nachricht an. Behalte Harness-Hinweise, etwa Erinnerungen, in einer separaten System-Nachricht mitten im Gespräch nach dieser `user`-Nachricht, und setze niemals einen Hinweis und die Worte des Benutzers in denselben Block:

```json
[
  { "role": "user", "content": "Run the test suite and fix any failures." },
  {
    "role": "assistant",
    "content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
  },
  {
    "role": "user",
    "content": [
      { "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" },
      { "type": "text", "text": "Also update the changelog before you finish." }
    ]
  }
]
```

Mehr zu diesem Verhalten findest du unter [Prompting für Claude Sonnet 5.5](https://platform.claude.com/docs/de/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#mid-turn-user-messages-and-task-budgets) und [Prompting für Claude Haiku 5.5](https://platform.claude.com/docs/de/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#mid-turn-user-messages).

### Turn-bezogene System-Nachrichten

Um eine `role: "system"`-Nachricht auf den aktuellen Turn zu beschränken, setze ihr Feld `clear_at`. Es nimmt einen von zwei Werten an:

* `"never"` (Standard): Die Nachricht wird bei jeder Anfrage, die sie enthält, an ihrer Position gerendert. Das Weglassen des Felds ist gleichbedeutend.
* `"next_user_message"`: Die Nachricht ist „turn-scoped“ (**Turn-bezogen**). Ihr Text wird nur gerendert, solange in `messages` keine `role: "user"`-Nachricht nach ihr folgt. Eine Benutzernachricht, die nur `tool_result`-Blöcke enthält, zählt hier als Benutzernachricht. Sobald eine spätere Benutzernachricht existiert, wird die Nachricht „cleared“ (**geleert**): Sie bleibt im Array, rendert aber nichts und kostet keine Eingabe-Token, bei dieser Anfrage und bei jeder späteren.

Turn-bezogene System-Nachrichten befinden sich in der Beta-Phase. Füge den [Beta-Header](https://platform.claude.com/docs/de/api/beta-headers) `mid-conversation-system-clear-at-2026-08-21` hinzu. Ohne ihn wird `clear_at` als unbekanntes Feld abgelehnt.

```json
{
  "role": "system",
  "clear_at": "next_user_message",
  "content": "First privately list what you need next; then request every item that doesn't depend on another's result in this one response."
}
```

Der Hauptanwendungsfall ist eine Erinnerung pro Turn in einer Tool-Schleife. Hänge die Erinnerung jedes Mal nach der `tool_result`-Nachricht an, wenn das Modell sie sehen soll, und lass jede frühere Kopie an ihrem Platz. Das Modell sieht nur die Kopien, die nach der letzten Benutzernachricht kommen, sodass sich die Erinnerung nie anhäuft. Nichts weiter vorne in `messages` ändert sich, sodass der [Prompt-Cache](https://platform.claude.com/docs/de/build-with-claude/prompt-caching) weiterhin übereinstimmt. Auf Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 und Claude Haiku 5.5 hält dies außerdem spätere [Thinking-Blöcke gültig](https://platform.claude.com/docs/de/build-with-claude/thinking#preserved-in-conversation): Das Löschen einer früheren Erinnerung würde das Gespräch vor diesen Blöcken verändern und die Gesprächsprüfung fehlschlagen lassen, während eine geleerte Nachricht im Array bleibt und dieses Gespräch unverändert lässt.

Die folgende Anfrage ist ein späterer Schritt einer Agent-Schleife. `messages[3]` wurde bei der früheren Anfrage gerendert, als sie die letzte Nachricht im Array war. Sobald `messages[5]` (eine spätere Benutzernachricht) existiert, wird `messages[3]` geleert: Die geleerte Nachricht bleibt im Array, sodass das Gespräch vor dem Thinking-Block in `messages[4]` unverändert ist, aber das Modell sieht ihren Text nicht mehr. `messages[6]` und `messages[7]` werden beide in dieser Reihenfolge gerendert.

```json
{
  "model": "claude-fable-5-1",
  "max_tokens": 16000,
  "messages": [
    { "role": "user", "content": "Fix the failing test." },
    {
      "role": "assistant",
      "content": [
        { "type": "thinking", "thinking": "", "signature": "..." },
        {
          "type": "tool_use",
          "id": "toolu_01",
          "name": "read_file",
          "input": { "path": "test_auth.py" }
        }
      ]
    },
    {
      "role": "user",
      "content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "Request independent reads in one turn."
    },
    {
      "role": "assistant",
      "content": [
        { "type": "thinking", "thinking": "", "signature": "..." },
        {
          "type": "tool_use",
          "id": "toolu_02",
          "name": "read_file",
          "input": { "path": "auth.py" }
        },
        {
          "type": "tool_use",
          "id": "toolu_03",
          "name": "read_file",
          "input": { "path": "tokens.py" }
        }
      ]
    },
    {
      "role": "user",
      "content": [
        { "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." },
        {
          "type": "tool_result",
          "tool_use_id": "toolu_03",
          "content": "...",
          "cache_control": { "type": "ephemeral" }
        }
      ]
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "Request independent reads in one turn."
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "The shell exited with status 137."
    }
  ]
}
```

Regeln für Turn-bezogene Nachrichten:

* **Sende geleerte Nachrichten wortgetreu erneut.** Eine geleerte Nachricht ist weiterhin Teil des Gesprächsverlaufs. Sie aus dem aktuellen Zustand neu aufzubauen (eine frische Token-Zählung, ein Zeitstempel), sie als überflüssig wegzulassen oder ihren `clear_at`-Wert zu ändern, ist eine Bearbeitung einer früheren Nachricht. Der Prompt-Cache verfehlt ab diesem Punkt, und auf Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 und Claude Haiku 5.5 besteht jeder danach erzeugte Thinking-Block die [Gesprächsprüfung](https://platform.claude.com/docs/de/build-with-claude/thinking#preserved-in-conversation) nicht.
* **Nur Text.** `content` besteht aus einem oder mehreren `text`-Blöcken (oder einem String). `tool_addition`- und `tool_removal`-Blöcke geben bei einer Turn-bezogenen Nachricht einen 400-Fehler zurück, ebenso `output_config`. Verwende dafür eine separate `role: "system"`-Nachricht ohne `clear_at`.
* **Kein `cache_control` an ihren Blöcken.** Eine geleerte Nachricht ist nie Teil eines Cache-Schlüssels, daher könnte ein Breakpoint an ihr nie übereinstimmen. Setze den Breakpoint stattdessen an den letzten Block des vorangehenden Benutzer-Turns, wie im Beispiel. Das oberste Feld für [automatisches Caching](https://platform.claude.com/docs/de/build-with-claude/prompt-caching#automatic-caching) überspringt Turn-bezogene Nachrichten, wenn es einen Breakpoint auswählt. Bei der Anfrage, die eine Nachricht leert, endet das wiederverwendbare gecachte Präfix beim Benutzer-Turn davor, sodass nur der eine Assistant-Turn zwischen dieser Nachricht und der neuen Benutzernachricht erneut verarbeitet wird.
* **Platzierungsregeln gelten weiterhin**, ob geleert oder nicht. Eine Turn-bezogene Nachricht muss auf einen `user`-Turn folgen (oder auf einen `assistant`-Turn, der mit einem Server-Tool-Ergebnis endet) und einem `assistant`-Turn vorangehen oder das Array beenden, wie jede Systemnachricht mitten im Gespräch. Eine, die das Array beendet, wird immer gerendert. Eine, auf die direkt eine weitere `user`-Nachricht folgt, ist ein 400-Fehler und keine geleerte Nachricht: Fasse alle Ergebnisse einer Tool-Runde in einer Benutzernachricht zusammen und setze die Erinnerungen danach.
* **Assistant-Turns leeren sie nicht.** Ein vorausgefüllter oder [pausierter](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#pause-turn) Assistant-Turn nach der Nachricht oder eine serverseitige Tool-Schleife fügt keine Benutzernachricht hinzu, sodass die Nachricht bei dieser Fortsetzung weiterhin gerendert wird. Um eine Erinnerung während einer clientseitigen Tool-Schleife sichtbar zu halten, hänge sie nach jeder `tool_result`-Nachricht erneut an.
* **Die Token-Zählung folgt dem, was gerendert wird.** Eine geleerte Nachricht trägt nichts zu `usage.input_tokens` oder zu einer [Token-Zählung](https://platform.claude.com/docs/de/build-with-claude/token-counting) bei.
* **Importierter Verlauf.** In einem Transkript, das du in einem Schritt erstellst (Few-Shot-Beispiele, ein migriertes Gespräch), wird eine Turn-bezogene Nachricht, auf die bereits ein Assistant-Turn und eine Benutzernachricht folgen, ab der ersten Anfrage geleert und nie gerendert. Das ist der richtige Zustand für eine Erinnerung pro Turn, die du übernimmst. Lass `clear_at` nur bei einer Nachricht ungesetzt, die das Modell bei jeder Anfrage sehen soll.

Die Validierungsfehler sind:

```text wrap
messages.3.clear_at: Extra inputs are not permitted
messages.3.clear_at: clear_at is only permitted on role 'system' messages
messages.3.clear_at: Input should be 'next_user_message' or 'never'
messages.3: a turn-scoped system message supports text blocks only (clear_at: 'next_user_message')
messages.3: output_config is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
messages.3.content.0: cache_control is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
```

Der erste ist der Fehler, der ohne den Beta-Header zurückgegeben wird. Sende auf Google Cloud und [Claude in Amazon Bedrock](https://platform.claude.com/docs/de/build-with-claude/claude-in-amazon-bedrock) den Beta-Wert im `anthropic-beta`-Header, wie auf der Claude API (siehe [Beta-Header](https://platform.claude.com/docs/de/api/beta-headers)). Mit der Amazon Bedrock [InvokeModel API](https://platform.claude.com/docs/de/build-with-claude/claude-on-amazon-bedrock-legacy) setzt du ihn stattdessen in das `anthropic_beta`-Array des Anfrage-Bodys.

Setze über das SDK `clear_at` (csharp, go: `ClearAt`; java: `.clearAt()`; php: `clearAt`) auf dem `role: "system"`-Eintrag in `messages` und sende den Beta-Header. Das folgende Beispiel hängt eine Turn-bezogene Erinnerung nach dem Benutzer-Turn an; bei der nächsten Anfrage, sobald eine spätere Benutzernachricht existiert, bleibt die Erinnerung im Array, wird aber nicht mehr gerendert:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: mid-conversation-system-clear-at-2026-08-21" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5-1",
      "max_tokens": 4096,
      "messages": [
        {"role": "user", "content": "Draft a short status update on the database migration for the team channel."},
        {"role": "system", "clear_at": "next_user_message", "content": "The reader is on call: keep this reply under 50 words."}
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta mid-conversation-system-clear-at-2026-08-21 \
    --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-fable-5-1
  max_tokens: 4096
  messages:
    - role: user
      content: Draft a short status update on the database migration for the team channel.
    # Turn-bezogene Erinnerung: wird für diesen Turn gerendert und entfernt, sobald eine spätere User-Nachricht existiert.
    - role: system
      clear_at: next_user_message
      content: "The reader is on call: keep this reply under 50 words."
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.beta.messages.create(
      model="claude-fable-5-1",
      max_tokens=4096,
      messages=[
          {
              "role": "user",
              "content": "Draft a short status update on the database migration for the team channel.",
          },
          # Turn-bezogene Erinnerung: wird für diesen Turn gerendert und entfernt, sobald eine spätere User-Nachricht existiert.
          {
              "role": "system",
              "clear_at": "next_user_message",
              "content": "The reader is on call: keep this reply under 50 words.",
          },
      ],
      betas=["mid-conversation-system-clear-at-2026-08-21"],
  )

  for block in response.content:
      if block.type == "text":
          print(block.text)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await client.beta.messages.create({
    model: "claude-fable-5-1",
    max_tokens: 4096,
    messages: [
      {
        role: "user",
        content: "Draft a short status update on the database migration for the team channel."
      },
      // Turn-bezogene Erinnerung: wird für diesen Turn gerendert und entfernt, sobald eine spätere User-Nachricht existiert.
      {
        role: "system",
        clear_at: "next_user_message",
        content: "The reader is on call: keep this reply under 50 words."
      }
    ],
    betas: ["mid-conversation-system-clear-at-2026-08-21"]
  });

  for (const block of response.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeFable5_1,
      MaxTokens = 4096,
      Messages =
      [
          new() { Role = Role.User, Content = "Draft a short status update on the database migration for the team channel." },
          // Turn-bezogene Erinnerung: wird für diesen Turn gerendert und entfernt, sobald eine spätere User-Nachricht existiert.
          new()
          {
              Role = Role.System,
              ClearAt = ClearAt.NextUserMessage,
              Content = "The reader is on call: keep this reply under 50 words.",
          },
      ],
      Betas = [AnthropicBeta.MidConversationSystemClearAt2026_08_21],
  });

  foreach (var block in response.Content)
  {
      if (block.TryPickText(out var textBlock))
      {
          Console.WriteLine(textBlock.Text);
      }
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5_1,
  	MaxTokens: 4096,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Draft a short status update on the database migration for the team channel.")),
  		// Turn-bezogene Erinnerung: wird für diesen Turn gerendert und entfernt, sobald eine spätere User-Nachricht existiert.
  		{
  			Role:    anthropic.BetaMessageParamRoleSystem,
  			ClearAt: anthropic.BetaMessageParamClearAtNextUserMessage,
  			Content: []anthropic.BetaContentBlockParamUnion{anthropic.NewBetaTextBlock("The reader is on call: keep this reply under 50 words.")},
  		},
  	},
  	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMidConversationSystemClearAt2026_08_21},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  import com.anthropic.models.messages.Model;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5_1)
          .maxTokens(4096L)
          .addBeta(AnthropicBeta.MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21)
          .addUserMessage("Draft a short status update on the database migration for the team channel.")
          // Turn-bezogene Erinnerung: wird für diesen Turn gerendert und entfernt, sobald eine spätere Nutzernachricht existiert.
          .addMessage(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.SYSTEM)
              .clearAt(BetaMessageParam.ClearAt.NEXT_USER_MESSAGE)
              .content("The reader is on call: keep this reply under 50 words.")
              .build())
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaMessageParam;
  use Anthropic\Client;

  $client = new Client();

  $response = $client->beta->messages->create(
      model: 'claude-fable-5-1',
      maxTokens: 4096,
      messages: [
          BetaMessageParam::with(role: 'user', content: 'Draft a short status update on the database migration for the team channel.'),
          // Turn-bezogene Erinnerung: wird für diesen Turn gerendert und entfernt, sobald eine spätere User-Nachricht existiert.
          BetaMessageParam::with(
              role: 'system',
              clearAt: 'next_user_message',
              content: 'The reader is on call: keep this reply under 50 words.',
          ),
      ],
      betas: [AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21],
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  response = client.beta.messages.create(
    model: "claude-fable-5-1",
    max_tokens: 4096,
    messages: [
      {role: "user", content: "Draft a short status update on the database migration for the team channel."},
      # Turn-bezogene Erinnerung: wird für diesen Turn gerendert und entfernt, sobald eine spätere User-Nachricht existiert.
      {role: "system", clear_at: :next_user_message, content: "The reader is on call: keep this reply under 50 words."}
    ],
    betas: [Anthropic::AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21]
  )

  response.content.each do |block|
    puts block.text if block.type == :text
  end
  ```
</CodeGroup>

## Kombination mit Prompt-Caching

System-Nachrichten mitten im Gespräch und [Prompt-Caching](https://platform.claude.com/docs/de/build-with-claude/prompt-caching) sind für die gemeinsame Verwendung konzipiert:

* **Aktiviere das Caching explizit.** Caching findet nur statt, wenn die Anfrage `cache_control` enthält, entweder als Top-Level-Feld für [automatisches Caching](https://platform.claude.com/docs/de/build-with-claude/prompt-caching#automatic-caching) oder als [expliziten Breakpoint](https://platform.claude.com/docs/de/build-with-claude/prompt-caching#explicit-cache-breakpoints) an einem Content-Block. Eine System-Nachricht mitten im Gespräch erzeugt von sich aus keinen Cache-Eintrag, und ohne aktiviertes Caching gibt es keine Einsparungen, die erhalten bleiben könnten.
* **Cache das stabile Präfix wie gewohnt.** Setze `cache_control` an den letzten Block, der über Anfragen hinweg gleich bleibt, sei es das Ende des Top-Level-Felds `system`, das Ende deiner Tool-Definitionen oder ein stabiler Punkt im Nachrichtenverlauf.
* **Hänge die System-Nachricht nach dem Breakpoint an.** Da sie nach dem gecachten Präfix kommt, ändert sie den Präfix-Hash nicht, und der Cache wird weiterhin getroffen.
* **Eine System-Nachricht mitten im Gespräch ist selbst cachebar.** Sobald sie Teil des Gesprächs ist, gehört sie zum stabilen Verlauf. Im nächsten Turn kannst du deinen Cache-Breakpoint hinter sie verschieben (oder dich darauf verlassen, dass [automatisches Caching](https://platform.claude.com/docs/de/build-with-claude/prompt-caching#automatic-caching) dies übernimmt), und die System-Nachricht wird wie jeder andere Turn aus dem Cache gelesen.

Vermeide es, eine bereits gesendete System-Nachricht mitten im Gespräch zu bearbeiten oder zu entfernen. Wie jede andere Änderung an früheren Nachrichten macht dies den Cache ab diesem Punkt ungültig. Auf Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 und Claude Haiku 5.5 macht es außerdem die [Thinking-Blöcke](https://platform.claude.com/docs/de/build-with-claude/thinking#preserved-in-conversation) in jedem späteren Assistant-Turn ungültig. Für Hinweise, die nur für einen Turn gelten sollen, verwende eine [Turn-bezogene System-Nachricht](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) und lass sie an ihrem Platz. Wenn sich die Anweisung weiterentwickeln muss, hänge eine neue System-Nachricht an, anstatt die alte umzuschreiben. Aufeinanderfolgende System-Nachrichten werden akzeptiert und als ein einziger System-Abschnitt behandelt, der als Ganzes derselben Platzierungsregel folgt.

## Einschränkungen

* **Nicht für die erste Nachricht.** Eine `system`-Nachricht mit Inhalt kann nicht der erste Eintrag in `messages` sein. Verwende das Top-Level-Feld `system` für Anweisungen, die von Anfang an gelten.
* **Die Platzierung ist eingeschränkt.** Eine `system`-Nachricht mit Inhalt (`text`-, `tool_addition`- oder `tool_removal`-Blöcke) muss unmittelbar auf einen `user`-Turn folgen (einschließlich eines `user`-Turns mit `tool_result`-Blöcken) oder auf einen `assistant`-Turn, der mit einem Server-Tool-Ergebnis endet, und muss einem `assistant`-Turn vorangehen oder das Array beenden. Sie kann nicht zwischen einem `tool_use`-Block und seinem `tool_result` stehen. Eine Platzierung an anderer Stelle gibt einen 400-Fehler zurück. Eine Ausnahme: `tool_addition`- und `tool_removal`-Blöcke werden unmittelbar nach einem [pausierten](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#pause-turn) `assistant`-Turn (einem, der mit einem Server-Tool-Ergebnis endet) nicht akzeptiert, `text`-Blöcke hingegen schon; setze zuerst den pausierten Turn fort und sende die Tool-Änderung dann in der nächsten `system`-Nachricht. Eine Nachricht mit leerem `content`, die nur [`output_config.effort`](https://platform.claude.com/docs/de/build-with-claude/effort#change-effort-mid-conversation-beta) setzt, rendert an ihrer Position nichts und wird überall in `messages` akzeptiert, auch als erster Eintrag oder zwischen einem `assistant`-Turn und einem `user`-Turn. Aufeinanderfolgende `system`-Nachrichten werden gemeinsam beurteilt, sodass das Hinzufügen einer Nachricht mit Text neben einer reinen Effort-Nachricht dazu führt, dass die gesamte Gruppe der Regel für Inhalte folgt.
* **Turn-bezogene Nachrichten enthalten nur Text und werden unverändert erneut gesendet.** Eine `clear_at: "next_user_message"`-Nachricht enthält kein `tool_addition`, `tool_removal`, `output_config` oder `cache_control`, und sobald sie geleert ist, muss sie bei späteren Anfragen Byte für Byte in `messages` bleiben. Siehe [Turn-bezogene Systemnachrichten](https://platform.claude.com/docs/de/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages).
* **Kein Ort für nicht vertrauenswürdige Inhalte.** Claude behandelt Systeminhalte als Operator-Anweisungen und befolgt sie. Platziere keinen Text von außerhalb der Konversation, etwa rohe Tool-Ausgaben, abgerufene Dokumente oder Webinhalte, direkt in einer Systemnachricht; dadurch erhält dieser Text Autorität auf Operator-Ebene. Belasse solche Daten in `tool_result`-Blöcken und befolge weiterhin [Jailbreaks und Prompt-Injections abwehren](https://platform.claude.com/docs/de/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks).

## Verwandte Themen

<CardGroup cols={2}>
  <Card title="Prompt-Caching" icon="bolt" href="https://platform.claude.com/docs/de/build-with-claude/prompt-caching">
    Wie Caching funktioniert, wo Breakpoints platziert werden und wie die Cache-Nutzungsfelder zu lesen sind.
  </Card>

  <Card title="Cache-Diagnose" icon="magnifying-glass" href="https://platform.claude.com/docs/de/build-with-claude/cache-diagnostics">
    Finde genau heraus, wo zwei Anfragen voneinander abwichen, wenn ein erwarteter Cache-Treffer nicht eintritt.
  </Card>

  <Card title="Die Messages API verwenden" icon="message" href="https://platform.claude.com/docs/de/build-with-claude/working-with-messages">
    Nachrichtenstruktur, Gespräche über mehrere Turns und das `system`-Feld.
  </Card>

  <Card title="Best Practices für Prompting" icon="text" href="https://platform.claude.com/docs/de/build-with-claude/prompt-engineering/claude-prompting-best-practices">
    Effektive Prompts und Systemanweisungen schreiben.
  </Card>

  <Card title="Tool-Nutzung mit Claude" icon="wrench" href="https://platform.claude.com/docs/de/agents-and-tools/tool-use/overview">
    Wie `tool_use`- und `tool_result`-Blöcke im `messages`-Array strukturiert sind.
  </Card>
</CardGroup>
