---
title: Stop-Gründe und Fallback
url: https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons
description: Erfahre, was jeder stop_reason-Wert bedeutet und wie du Abschneidung, Tool-Nutzung, pausierte Turns und Ablehnungen in deiner Anwendung behandelst.
---

Jede Antwort der Messages API enthält ein Feld `stop_reason`, das dir mitteilt, warum Claude die Generierung beendet hat. Prüfe dieses Feld, um zu entscheiden, ob du die Antwort unverändert verwendest, die Konversation fortsetzt, es erneut versuchst oder auf ein anderes Modell zurückfällst.

Das vollständige Antwortschema findest du in der [Messages-API-Referenz](https://platform.claude.com/docs/de/api/messages/create).

## Kurzübersicht

| Wert                                                                                                                                         | Wann er auftritt                                            | Was zu tun ist                                                                                                                                              |
| -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`end_turn`](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#end-turn)                                           | Claude hat seine Antwort auf natürliche Weise beendet.      | Verwende die Antwort.                                                                                                                                       |
| [`max_tokens`](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#max-tokens)                                       | Die Antwort hat dein `max_tokens`-Limit erreicht.           | Erhöhe `max_tokens` oder [setze die Antwort fort](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#ensuring-complete-responses). |
| [`stop_sequence`](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#stop-sequence)                                 | Claude hat eine deiner `stop_sequences` ausgegeben.         | Lies `stop_sequence`, um zu sehen, welche ausgelöst wurde.                                                                                                  |
| [`tool_use`](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#tool-use)                                           | Claude ruft ein Tool auf.                                   | Führe das Tool aus und gib das Ergebnis zurück. Ein Server-Tool-Aufruf, dem sein Ergebnisblock noch fehlt, wird in einer späteren Antwort abgeschlossen.    |
| [`pause_turn`](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#pause-turn)                                       | Eine Server-Tool-Schleife hat ihr Iterationslimit erreicht. | Sende den Assistant-Inhalt zurück, um fortzufahren.                                                                                                         |
| [`refusal`](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#refusal)                                             | Claude hat eine Antwort abgelehnt.                          | Lies `stop_details` und [versuche es erneut mit einem Fallback-Modell](https://platform.claude.com/docs/de/build-with-claude/refusals-and-fallback).        |
| [`model_context_window_exceeded`](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#model-context-window-exceeded) | Die Antwort hat das Kontextfenster des Modells gefüllt.     | Behandle die Antwort als abgeschnitten.                                                                                                                     |

## Das Feld stop\_reason

Das Feld `stop_reason` ist Teil jeder erfolgreichen Antwort der Messages API. Anders als Fehler, die auf Probleme bei der Verarbeitung deiner Anfrage hinweisen, teilt dir `stop_reason` mit, warum Claude die Generierung seiner Antwort abgeschlossen hat.

```json Example response
{
  "id": "msg_01234",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Here's the answer to your question..."
    }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "stop_details": null,
  "usage": {
    "input_tokens": 100,
    "output_tokens": 50
  }
}
```

## Werte von stop\_reason

### end\_turn

Der häufigste Stop-Grund. Zeigt an, dass Claude seine Antwort auf natürliche Weise beendet hat.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [{"role": "user", "content": "Hello!"}]
    }' | jq 'if .stop_reason == "end_turn" then (.content[] | select(.type == "text") | .text) else . end'
  ```

  ```bash CLI
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "Hello!"}' \
    --format json | jq 'if .stop_reason == "end_turn" then (.content[] | select(.type == "text") | .text) else . end'
  ```

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

  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Hello!"}],
  )
  if response.stop_reason == "end_turn":
      # Verarbeite die vollständige Antwort
      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,
    messages: [{ role: "user", content: "Hello!" }]
  });

  if (response.stop_reason === "end_turn") {
    // Verarbeite die vollständige Antwort
    const textBlock = response.content.find(
      (block): block is Anthropic.TextBlock => block.type === "text"
    );
    console.log(textBlock?.text);
  }
  ```

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

  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [new() { Role = Role.User, Content = "Hello!" }]
  });

  if (response.StopReason == "end_turn")
  {
      // Verarbeite die vollständige Antwort
      foreach (var block in response.Content)
      {
          if (block.TryPickText(out var textBlock))
          {
              Console.WriteLine(textBlock.Text);
          }
      }
  }
  ```

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

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Hello!")),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == "end_turn" {
  	// Verarbeite die vollständige Antwort
  	for _, block := range response.Content {
  		if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  			fmt.Println(textBlock.Text)
  		}
  	}
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  Message response = client.messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024L)
          .addUserMessage("Hello!")
          .build()
  );

  if (response.stopReason().map(StopReason.END_TURN::equals).orElse(false)) {
      // Verarbeite die vollständige Antwort
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  }
  ```

  ```php PHP
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello!']],
      model: 'claude-opus-5-5',
  );

  if ($response->stopReason === 'end_turn') {
      // Verarbeite die vollständige Antwort
      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,
    messages: [{ role: "user", content: "Hello!" }]
  )

  if response.stop_reason == :end_turn
    # Verarbeite die vollständige Antwort
    response.content.each do |block|
      puts block.text if block.type == :text
    end
  end
  ```
</CodeGroup>

<Accordion title="Leere Antworten mit end_turn">
  Manchmal gibt Claude eine leere Antwort (genau 2–3 Token ohne Inhalt) mit `stop_reason: "end_turn"` zurück. Dies tritt typischerweise auf, wenn Claude interpretiert, dass der Assistant-Turn abgeschlossen ist, insbesondere nach Tool-Ergebnissen.

  **Häufige Ursachen:**

  * Hinzufügen von Textblöcken unmittelbar nach Tool-Ergebnissen (Claude lernt zu erwarten, dass der Nutzer nach Tool-Ergebnissen immer Text einfügt, und beendet daher seinen Turn, um dem Muster zu folgen)
  * Zurücksenden von Claudes abgeschlossener Antwort, ohne etwas hinzuzufügen (Claude hat bereits festgestellt, dass es fertig ist, also bleibt es fertig)

  **So verhinderst du leere Antworten:**

  <CodeGroup exclude="shell">
    ```python Python
    # FALSCH: Text direkt nach tool_result hinzufügen
    messages = [
        {"role": "user", "content": "Calculate the sum of 1234 and 5678"},
        {
            "role": "assistant",
            "content": [
                {
                    "type": "tool_use",
                    "id": "toolu_123",
                    "name": "calculator",
                    "input": {"operation": "add", "a": 1234, "b": 5678},
                }
            ],
        },
        {
            "role": "user",
            "content": [
                {"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"},
                {
                    "type": "text",
                    "text": "Here's the result",  # Don't add text after tool_result
                },
            ],
        },
    ]

    # RICHTIG: Tool-Ergebnisse direkt ohne zusätzlichen Text senden
    messages = [
        {"role": "user", "content": "Calculate the sum of 1234 and 5678"},
        {
            "role": "assistant",
            "content": [
                {
                    "type": "tool_use",
                    "id": "toolu_123",
                    "name": "calculator",
                    "input": {"operation": "add", "a": 1234, "b": 5678},
                }
            ],
        },
        {
            "role": "user",
            "content": [
                {"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"}
            ],
        },  # Just the tool_result, no additional text
    ]
    ```

    ```typescript TypeScript
    // FALSCH: Text direkt nach tool_result hinzufügen
    let messages: Anthropic.MessageParam[] = [
      { role: "user", content: "Calculate the sum of 1234 and 5678" },
      {
        role: "assistant",
        content: [
          {
            type: "tool_use",
            id: "toolu_123",
            name: "calculator",
            input: { operation: "add", a: 1234, b: 5678 }
          }
        ]
      },
      {
        role: "user",
        content: [
          { type: "tool_result", tool_use_id: "toolu_123", content: "6912" },
          { type: "text", text: "Here's the result" } // Don't add text after tool_result
        ]
      }
    ];

    // RICHTIG: Tool-Ergebnisse direkt ohne zusätzlichen Text senden
    messages = [
      { role: "user", content: "Calculate the sum of 1234 and 5678" },
      {
        role: "assistant",
        content: [
          {
            type: "tool_use",
            id: "toolu_123",
            name: "calculator",
            input: { operation: "add", a: 1234, b: 5678 }
          }
        ]
      },
      {
        role: "user",
        // Nur das tool_result, kein zusätzlicher Text
        content: [{ type: "tool_result", tool_use_id: "toolu_123", content: "6912" }]
      }
    ];
    ```

    ```csharp C#
    using System.Text.Json;
    using Anthropic.Models.Messages;

    var input = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
        """{"operation":"add","a":1234,"b":5678}"""
    )!;

    // FALSCH: Text unmittelbar nach tool_result hinzufügen
    List<MessageParam> messages =
    [
        new() { Role = Role.User, Content = "Calculate the sum of 1234 and 5678" },
        new()
        {
            Role = Role.Assistant,
            Content = new List<ContentBlockParam>
            {
                new ToolUseBlockParam { ID = "toolu_123", Name = "calculator", Input = input }
            }
        },
        new()
        {
            Role = Role.User,
            Content = new List<ContentBlockParam>
            {
                new ToolResultBlockParam { ToolUseID = "toolu_123", Content = "6912" },
                new TextBlockParam { Text = "Here's the result" } // Don't add text after tool_result
            }
        }
    ];

    // RICHTIG: Tool-Ergebnisse direkt ohne zusätzlichen Text senden
    messages =
    [
        new() { Role = Role.User, Content = "Calculate the sum of 1234 and 5678" },
        new()
        {
            Role = Role.Assistant,
            Content = new List<ContentBlockParam>
            {
                new ToolUseBlockParam { ID = "toolu_123", Name = "calculator", Input = input }
            }
        },
        new()
        {
            Role = Role.User,
            // Nur das tool_result, kein zusätzlicher Text
            Content = new List<ContentBlockParam>
            {
                new ToolResultBlockParam { ToolUseID = "toolu_123", Content = "6912" }
            }
        }
    ];
    ```

    ```go Go
    input := map[string]any{"operation": "add", "a": 1234, "b": 5678}

    // FALSCH: Text direkt nach tool_result hinzufügen
    messages := []anthropic.MessageParam{
    	anthropic.NewUserMessage(anthropic.NewTextBlock("Calculate the sum of 1234 and 5678")),
    	anthropic.NewAssistantMessage(
    		anthropic.NewToolUseBlock("toolu_123", input, "calculator"),
    	),
    	anthropic.NewUserMessage(
    		anthropic.NewToolResultBlock("toolu_123", "6912", false),
    		anthropic.NewTextBlock("Here's the result"), // Don't add text after tool_result
    	),
    }

    // RICHTIG: Tool-Ergebnisse direkt ohne zusätzlichen Text senden
    messages = []anthropic.MessageParam{
    	anthropic.NewUserMessage(anthropic.NewTextBlock("Calculate the sum of 1234 and 5678")),
    	anthropic.NewAssistantMessage(
    		anthropic.NewToolUseBlock("toolu_123", input, "calculator"),
    	),
    	// Nur das tool_result, kein zusätzlicher Text
    	anthropic.NewUserMessage(
    		anthropic.NewToolResultBlock("toolu_123", "6912", false),
    	),
    }
    ```

    ```java Java
    ToolUseBlockParam toolUse = ToolUseBlockParam.builder()
        .id("toolu_123")
        .name("calculator")
        .input(ToolUseBlockParam.Input.builder()
            .putAdditionalProperty("operation", JsonValue.from("add"))
            .putAdditionalProperty("a", JsonValue.from(1234))
            .putAdditionalProperty("b", JsonValue.from(5678))
            .build())
        .build();

    // FALSCH: Text direkt nach tool_result hinzufügen
    List<MessageParam> messages = List.of(
        MessageParam.builder().role(MessageParam.Role.USER)
            .content("Calculate the sum of 1234 and 5678").build(),
        MessageParam.builder().role(MessageParam.Role.ASSISTANT)
            .contentOfBlockParams(List.of(ContentBlockParam.ofToolUse(toolUse))).build(),
        MessageParam.builder().role(MessageParam.Role.USER)
            .contentOfBlockParams(List.of(
                ContentBlockParam.ofToolResult(
                    ToolResultBlockParam.builder().toolUseId("toolu_123").content("6912").build()),
                // Füge keinen Text nach tool_result hinzu
                ContentBlockParam.ofText(TextBlockParam.builder().text("Here's the result").build())
            )).build()
    );

    // RICHTIG: Sende Tool-Ergebnisse direkt ohne zusätzlichen Text
    messages = List.of(
        MessageParam.builder().role(MessageParam.Role.USER)
            .content("Calculate the sum of 1234 and 5678").build(),
        MessageParam.builder().role(MessageParam.Role.ASSISTANT)
            .contentOfBlockParams(List.of(ContentBlockParam.ofToolUse(toolUse))).build(),
        // Nur das tool_result, kein zusätzlicher Text
        MessageParam.builder().role(MessageParam.Role.USER)
            .contentOfBlockParams(List.of(
                ContentBlockParam.ofToolResult(
                    ToolResultBlockParam.builder().toolUseId("toolu_123").content("6912").build())
            )).build()
    );
    ```

    ```php PHP
    // FALSCH: Text direkt nach tool_result hinzufügen
    $messages = [
        ['role' => 'user', 'content' => 'Calculate the sum of 1234 and 5678'],
        [
            'role' => 'assistant',
            'content' => [
                [
                    'type' => 'tool_use',
                    'id' => 'toolu_123',
                    'name' => 'calculator',
                    'input' => ['operation' => 'add', 'a' => 1234, 'b' => 5678],
                ],
            ],
        ],
        [
            'role' => 'user',
            'content' => [
                ['type' => 'tool_result', 'tool_use_id' => 'toolu_123', 'content' => '6912'],
                // Füge keinen Text nach tool_result hinzu
                ['type' => 'text', 'text' => "Here's the result"],
            ],
        ],
    ];

    // RICHTIG: Sende Tool-Ergebnisse direkt ohne zusätzlichen Text
    $messages = [
        ['role' => 'user', 'content' => 'Calculate the sum of 1234 and 5678'],
        [
            'role' => 'assistant',
            'content' => [
                [
                    'type' => 'tool_use',
                    'id' => 'toolu_123',
                    'name' => 'calculator',
                    'input' => ['operation' => 'add', 'a' => 1234, 'b' => 5678],
                ],
            ],
        ],
        [
            'role' => 'user',
            // Nur das tool_result, kein zusätzlicher Text
            'content' => [
                ['type' => 'tool_result', 'tool_use_id' => 'toolu_123', 'content' => '6912'],
            ],
        ],
    ];
    ```

    ```ruby Ruby
    # FALSCH: Text direkt nach tool_result hinzufügen
    messages = [
      { role: "user", content: "Calculate the sum of 1234 and 5678" },
      {
        role: "assistant",
        content: [
          {
            type: "tool_use",
            id: "toolu_123",
            name: "calculator",
            input: { operation: "add", a: 1234, b: 5678 }
          }
        ]
      },
      {
        role: "user",
        content: [
          { type: "tool_result", tool_use_id: "toolu_123", content: "6912" },
          # Füge keinen Text nach tool_result hinzu
          { type: "text", text: "Here's the result" }
        ]
      }
    ]

    # RICHTIG: Sende Tool-Ergebnisse direkt ohne zusätzlichen Text
    messages = [
      { role: "user", content: "Calculate the sum of 1234 and 5678" },
      {
        role: "assistant",
        content: [
          {
            type: "tool_use",
            id: "toolu_123",
            name: "calculator",
            input: { operation: "add", a: 1234, b: 5678 }
          }
        ]
      },
      {
        role: "user",
        # Nur das tool_result, kein zusätzlicher Text
        content: [
          { type: "tool_result", tool_use_id: "toolu_123", content: "6912" }
        ]
      }
    ]
    ```
  </CodeGroup>

  Wenn du nach der Korrektur der Nachrichtenstruktur weiterhin leere Antworten erhältst, füge einen Fortsetzungs-Prompt in einer neuen User-Nachricht hinzu, anstatt es mit der leeren Antwort erneut zu versuchen:

  <CodeGroup exclude="shell">
    ```python Python
    def handle_empty_response(client, messages):
        response = client.messages.create(
            model="claude-opus-5-5", max_tokens=1024, messages=messages
        )

        # Prüfe, ob die Antwort leer ist
        if response.stop_reason == "end_turn" and not response.content:
            # FALSCH: Wiederhole die Anfrage nicht einfach mit der leeren Antwort
            # Das funktioniert nicht, weil Claude bereits entschieden hat, dass es fertig ist

            # RICHTIG: Füge einen Fortsetzungs-Prompt in einer NEUEN User-Nachricht hinzu
            messages.append({"role": "user", "content": "Please continue"})

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

        return response
    ```

    ```typescript TypeScript
    async function handleEmptyResponse(
      client: Anthropic,
      messages: Anthropic.MessageParam[]
    ): Promise<Anthropic.Message> {
      let response = await client.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages
      });

      // Prüfe, ob die Antwort leer ist
      if (response.stop_reason === "end_turn" && response.content.length === 0) {
        // FALSCH: Wiederhole die Anfrage nicht einfach mit der leeren Antwort
        // Das funktioniert nicht, weil Claude bereits entschieden hat, dass es fertig ist

        // RICHTIG: Füge einen Fortsetzungs-Prompt in einer NEUEN User-Nachricht hinzu
        messages.push({ role: "user", content: "Please continue" });

        response = await client.messages.create({
          model: "claude-opus-5-5",
          max_tokens: 1024,
          messages
        });
      }

      return response;
    }
    ```

    ```csharp C#
    static async Task<Message> HandleEmptyResponse(AnthropicClient client, List<MessageParam> messages)
    {
        var response = await client.Messages.Create(new MessageCreateParams
        {
            Model = Model.ClaudeOpus5_5,
            MaxTokens = 1024,
            Messages = messages
        });

        // Prüfe, ob die Antwort leer ist
        if (response.StopReason == "end_turn" && response.Content.Count == 0)
        {
            // RICHTIG: Füge einen Fortsetzungs-Prompt in einer NEUEN User-Nachricht hinzu
            messages.Add(new() { Role = Role.User, Content = "Please continue" });

            response = await client.Messages.Create(new MessageCreateParams
            {
                Model = Model.ClaudeOpus5_5,
                MaxTokens = 1024,
                Messages = messages
            });
        }

        return response;
    }
    ```

    ```go Go
    func handleEmptyResponse(client anthropic.Client, messages []anthropic.MessageParam) (*anthropic.Message, error) {
    	response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
    		Model:     anthropic.ModelClaudeOpus5_5,
    		MaxTokens: 1024,
    		Messages:  messages,
    	})
    	if err != nil {
    		return nil, err
    	}

    	// Prüfe, ob die Antwort leer ist
    	if response.StopReason == "end_turn" && len(response.Content) == 0 {
    		// RICHTIG: Füge einen Fortsetzungs-Prompt in einer NEUEN User-Nachricht hinzu
    		messages = append(messages, anthropic.NewUserMessage(anthropic.NewTextBlock("Please continue")))

    		response, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
    			Model:     anthropic.ModelClaudeOpus5_5,
    			MaxTokens: 1024,
    			Messages:  messages,
    		})
    		if err != nil {
    			return nil, err
    		}
    	}

    	return response, nil
    }
    ```

    ```java Java
    static Message handleEmptyResponse(AnthropicClient client, List<MessageParam> messages) {
        Message response = client.messages().create(
            MessageCreateParams.builder()
                .model(Model.CLAUDE_OPUS_5_5)
                .maxTokens(1024L)
                .messages(messages)
                .build()
        );

        // Prüfe, ob die Antwort leer ist
        boolean isEndTurn = response.stopReason().map(StopReason.END_TURN::equals).orElse(false);
        if (isEndTurn && response.content().isEmpty()) {
            // RICHTIG: Füge einen Fortsetzungs-Prompt in einer NEUEN User-Nachricht hinzu
            List<MessageParam> extended = new ArrayList<>(messages);
            extended.add(MessageParam.builder()
                .role(MessageParam.Role.USER)
                .content("Please continue")
                .build());

            response = client.messages().create(
                MessageCreateParams.builder()
                    .model(Model.CLAUDE_OPUS_5_5)
                    .maxTokens(1024L)
                    .messages(extended)
                    .build()
            );
        }

        return response;
    }
    ```

    ```php PHP
    function handle_empty_response(Client $client, array $messages)
    {
        $response = $client->messages->create(
            maxTokens: 1024,
            messages: $messages,
            model: 'claude-opus-5-5',
        );

        // Prüfe, ob die Antwort leer ist
        if ($response->stopReason === 'end_turn' && count($response->content) === 0) {
            // RICHTIG: Füge einen Fortsetzungs-Prompt in einer NEUEN User-Nachricht hinzu
            $messages[] = ['role' => 'user', 'content' => 'Please continue'];

            $response = $client->messages->create(
                maxTokens: 1024,
                messages: $messages,
                model: 'claude-opus-5-5',
            );
        }

        return $response;
    }
    ```

    ```ruby Ruby
    def handle_empty_response(client, messages)
      response = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages: messages
      )

      # Prüfe, ob die Antwort leer ist
      if response.stop_reason == :end_turn && response.content.empty?
        # RICHTIG: Füge einen Fortsetzungs-Prompt in einer NEUEN User-Nachricht hinzu
        messages << { role: "user", content: "Please continue" }

        response = client.messages.create(
          model: "claude-opus-5-5",
          max_tokens: 1024,
          messages: messages
        )
      end

      response
    end
    ```
  </CodeGroup>

  **Best Practices:**

  1. **Füge niemals Textblöcke unmittelbar nach Tool-Ergebnissen hinzu:** Dies bringt Claude bei, nach jeder Tool-Nutzung eine Nutzereingabe zu erwarten.
  2. **Versuche leere Antworten nicht ohne Änderung erneut:** Das Zurücksenden der leeren Antwort hilft nicht.
  3. **Verwende Fortsetzungs-Prompts als letztes Mittel:** Nur wenn diese Korrekturen das Problem nicht lösen.
</Accordion>

### max\_tokens

Claude hat gestoppt, weil es das in deiner Anfrage angegebene `max_tokens`-Limit erreicht hat.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 10,
      "messages": [{"role": "user", "content": "Explain quantum physics"}]
    }' | jq '.stop_reason'
  ```

  ```bash CLI
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 10 \
    --message '{role: user, content: "Explain quantum physics"}' \
    --format json | jq '.stop_reason'
  ```

  ```python Python
  client = anthropic.Anthropic()
  # Anfrage mit begrenzten Tokens
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=10,
      messages=[{"role": "user", "content": "Explain quantum physics"}],
  )

  if response.stop_reason == "max_tokens":
      # Antwort wurde abgeschnitten
      print("Response was cut off at token limit")
      # Erwäge eine weitere Anfrage, um fortzufahren
  ```

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

  // Anfrage mit begrenzten Tokens
  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 10,
    messages: [{ role: "user", content: "Explain quantum physics" }]
  });

  if (response.stop_reason === "max_tokens") {
    // Antwort wurde abgeschnitten
    console.log("Response was cut off at token limit");
    // Erwäge eine weitere Anfrage, um fortzufahren
  }
  ```

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

  // Anfrage mit begrenzten Token
  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 10,
      Messages = [new() { Role = Role.User, Content = "Explain quantum physics" }]
  });

  if (response.StopReason == "max_tokens")
  {
      // Antwort wurde abgeschnitten
      Console.WriteLine("Response was cut off at token limit");
      // Erwäge eine weitere Anfrage, um fortzufahren
  }
  ```

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

  // Anfrage mit begrenzten Tokens
  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 10,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Explain quantum physics")),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == "max_tokens" {
  	// Antwort wurde abgeschnitten
  	fmt.Println("Response was cut off at token limit")
  	// Erwäge eine weitere Anfrage, um fortzufahren
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  // Anfrage mit begrenzten Tokens
  Message response = client.messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(10L)
          .addUserMessage("Explain quantum physics")
          .build()
  );

  if (response.stopReason().map(StopReason.MAX_TOKENS::equals).orElse(false)) {
      // Antwort wurde abgeschnitten
      IO.println("Response was cut off at token limit");
      // Erwäge eine weitere Anfrage, um fortzufahren
  }
  ```

  ```php PHP
  $client = new Client();

  // Anfrage mit begrenzten Token
  $response = $client->messages->create(
      maxTokens: 10,
      messages: [['role' => 'user', 'content' => 'Explain quantum physics']],
      model: 'claude-opus-5-5',
  );

  if ($response->stopReason === 'max_tokens') {
      // Antwort wurde abgeschnitten
      echo 'Response was cut off at token limit', PHP_EOL;
      // Erwäge eine weitere Anfrage, um fortzufahren
  }
  ```

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

  # Anfrage mit begrenzten Token
  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 10,
    messages: [{ role: "user", content: "Explain quantum physics" }]
  )

  if response.stop_reason == :max_tokens
    # Antwort wurde abgeschnitten
    puts "Response was cut off at token limit"
    # Erwäge eine weitere Anfrage, um fortzufahren
  end
  ```
</CodeGroup>

<Accordion title="Unvollständige Tool-Use-Blöcke">
  Wenn Claudes Antwort abgeschnitten wird, weil sie das `max_tokens`-Limit erreicht hat, und die abgeschnittene Antwort einen unvollständigen Tool-Use-Block enthält, musst du die Anfrage mit einem höheren `max_tokens`-Wert erneut senden, um die vollständige Tool-Nutzung zu erhalten.

  <CodeGroup exclude="shell:cURL">
    ```bash CLI
    RESPONSE=$(ant messages create --max-tokens 1024 --format jsonl <<'YAML'
    model: claude-opus-5-5
    tools:
      - name: get_weather
        description: Get the current weather in a given location
        input_schema:
          type: object
          properties:
            location:
              type: string
          required:
            - location
    messages:
      - role: user
        content: What is the weather in San Francisco?
    YAML
    )

    # Prüfe, ob die Antwort mitten in der Tool-Nutzung abgeschnitten wurde
    STOP_REASON=$(jq -r '.stop_reason' <<<"$RESPONSE")
    LAST_TYPE=$(jq -r '.content[-1].type' <<<"$RESPONSE")
    if [ "$STOP_REASON" = "max_tokens" ] && [ "$LAST_TYPE" = "tool_use" ]; then
      # Versuche es erneut mit einem höheren max_tokens
      ant messages create --max-tokens 4096 <<'YAML'
    model: claude-opus-5-5
    tools:
      - name: get_weather
        description: Get the current weather in a given location
        input_schema:
          type: object
          properties:
            location:
              type: string
          required:
            - location
    messages:
      - role: user
        content: What is the weather in San Francisco?
    YAML
    fi
    ```

    ```python Python
    # Prüfe, ob die Antwort während der Tool-Nutzung abgeschnitten wurde
    if response.stop_reason == "max_tokens":
        # Prüfe, ob der letzte Content-Block ein unvollständiges tool_use ist
        last_block = response.content[-1]
        if last_block.type == "tool_use":
            # Sende die Anfrage mit höherem max_tokens
            response = client.messages.create(
                model="claude-opus-5-5",
                max_tokens=4096,  # Increased limit
                messages=messages,
                tools=tools,
            )
    ```

    ```typescript TypeScript
    // Prüfe, ob die Antwort während der Tool-Nutzung abgeschnitten wurde
    if (response.stop_reason === "max_tokens") {
      // Prüfe, ob der letzte Content-Block ein unvollständiges tool_use ist
      const lastBlock = response.content[response.content.length - 1];
      if (lastBlock.type === "tool_use") {
        // Sende die Anfrage mit höherem max_tokens
        response = await client.messages.create({
          model: "claude-opus-5-5",
          max_tokens: 4096, // Increased limit
          messages: messages,
          tools: tools
        });
      }
    }
    ```

    ```csharp C#
    using System.Linq;
    using Anthropic;
    using Anthropic.Models.Messages;

    AnthropicClient client = new();

    var parameters = new MessageCreateParams
    {
        Model = Model.ClaudeOpus5_5,
        MaxTokens = 1024,
        Messages = messages,
        Tools = tools
    };

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

    if (response.StopReason == "max_tokens")
    {
        var lastBlock = response.Content.Last();
        if (lastBlock.TryPickToolUse(out _))
        {
            response = await client.Messages.Create(parameters with { MaxTokens = 4096 });
        }
    }
    ```

    ```go Go
    response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
    	Model:     anthropic.ModelClaudeOpus5_5,
    	MaxTokens: 1024,
    	Messages:  messages,
    	Tools:     tools,
    })
    if err != nil {
    	log.Fatal(err)
    }

    if response.StopReason == "max_tokens" {
    	lastBlock := response.Content[len(response.Content)-1]
    	switch lastBlock.AsAny().(type) {
    	case anthropic.ToolUseBlock:
    		response, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
    			Model:     anthropic.ModelClaudeOpus5_5,
    			MaxTokens: 4096,
    			Messages:  messages,
    			Tools:     tools,
    		})
    		if err != nil {
    			log.Fatal(err)
    		}
    	}
    }
    ```

    ```java Java
    // Prüfe, ob die Antwort während der Tool-Nutzung abgeschnitten wurde
    if (response.stopReason().isPresent() && response.stopReason().get().equals(StopReason.MAX_TOKENS)) {
        ContentBlock lastBlock = response.content().get(response.content().size() - 1);
        if (lastBlock.toolUse().isPresent()) {
            // Sende die Anfrage mit höherem max_tokens
            response = client.messages().create(
                MessageCreateParams.builder()
                    .model(Model.CLAUDE_OPUS_5_5)
                    .maxTokens(4096L) // Increased limit
                    .messages(messages)
                    .tools(tools)
                    .build()
            );
        }
    }
    ```

    ```php PHP
    $response = $client->messages->create(
        maxTokens: 1024,
        messages: $messages,
        model: 'claude-opus-5-5',
        tools: $tools,
    );

    if ($response->stopReason === 'max_tokens') {
        $lastBlock = end($response->content);
        if ($lastBlock->type === 'tool_use') {
            $response = $client->messages->create(
                maxTokens: 4096,
                messages: $messages,
                model: 'claude-opus-5-5',
                tools: $tools,
            );
        }
    }
    ```

    ```ruby Ruby
    response = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: messages,
      tools: tools
    )

    if response.stop_reason == :max_tokens
      last_block = response.content.last
      if last_block.type == :tool_use
        response = client.messages.create(
          model: "claude-opus-5-5",
          max_tokens: 4096,
          messages: messages,
          tools: tools
        )
      end
    end
    ```
  </CodeGroup>
</Accordion>

### stop\_sequence

Claude ist auf eine deiner benutzerdefinierten Stop-Sequenzen gestoßen.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "stop_sequences": ["END", "STOP"],
      "messages": [{"role": "user", "content": "Generate text until you say END"}]
    }' | jq '{stop_reason, stop_sequence}'
  ```

  ```bash CLI
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --stop-sequence END --stop-sequence STOP \
    --message '{role: user, content: "Generate text until you say END"}' \
    --format json | jq '{stop_reason, stop_sequence}'
  ```

  ```python Python
  client = anthropic.Anthropic()
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      stop_sequences=["END", "STOP"],
      messages=[{"role": "user", "content": "Generate text until you say END"}],
  )

  if response.stop_reason == "stop_sequence":
      print(f"Stopped at sequence: {response.stop_sequence}")
  ```

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

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    stop_sequences: ["END", "STOP"],
    messages: [{ role: "user", content: "Generate text until you say END" }]
  });

  if (response.stop_reason === "stop_sequence") {
    console.log(`Stopped at sequence: ${response.stop_sequence}`);
  }
  ```

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

  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      StopSequences = ["END", "STOP"],
      Messages = [new() { Role = Role.User, Content = "Generate text until you say END" }]
  });

  if (response.StopReason == "stop_sequence")
  {
      Console.WriteLine($"Stopped at sequence: {response.StopSequence}");
  }
  ```

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

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:         anthropic.ModelClaudeOpus5_5,
  	MaxTokens:     1024,
  	StopSequences: []string{"END", "STOP"},
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Generate text until you say END")),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == "stop_sequence" {
  	fmt.Printf("Stopped at sequence: %s\n", response.StopSequence)
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  Message response = client.messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024L)
          .addStopSequence("END")
          .addStopSequence("STOP")
          .addUserMessage("Generate text until you say END")
          .build()
  );

  if (response.stopReason().map(StopReason.STOP_SEQUENCE::equals).orElse(false)) {
      IO.println("Stopped at sequence: " + response.stopSequence().orElse(""));
  }
  ```

  ```php PHP
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Generate text until you say END']],
      model: 'claude-opus-5-5',
      stopSequences: ['END', 'STOP'],
  );

  if ($response->stopReason === 'stop_sequence') {
      echo "Stopped at sequence: {$response->stopSequence}", PHP_EOL;
  }
  ```

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

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    stop_sequences: ["END", "STOP"],
    messages: [{ role: "user", content: "Generate text until you say END" }]
  )

  if response.stop_reason == :stop_sequence
    puts "Stopped at sequence: #{response.stop_sequence}"
  end
  ```
</CodeGroup>

### tool\_use

Claude ruft ein Tool auf und erwartet, dass du es ausführst.

<Note>
  Verwende für die meisten Implementierungen von „tool use“ (Tool-Nutzung) den [Tool Runner](https://platform.claude.com/docs/de/agents-and-tools/tool-use/tool-runner), der die Tool-Ausführung, die Ergebnisformatierung und die Konversationsverwaltung automatisch übernimmt.
</Note>

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "tools": [{
        "name": "get_weather",
        "description": "Get the current weather in a given location",
        "input_schema": {
          "type": "object",
          "properties": {"location": {"type": "string", "description": "City and state"}},
          "required": ["location"]
        }
      }],
      "messages": [{"role": "user", "content": "What is the weather in San Francisco?"}]
    }' | jq '.stop_reason, (.content[] | select(.type == "tool_use"))'
  ```

  ```bash CLI
  ant messages create --format json <<'YAML' | jq '.stop_reason, (.content[] | select(.type == "tool_use"))'
  model: claude-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content: What is the weather in San Francisco?
  tools:
    - name: get_weather
      description: Get the current weather in a given location
      input_schema:
        type: object
        properties:
          location: {type: string, description: City and state}
        required: [location]
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()
  weather_tool = {
      "name": "get_weather",
      "description": "Get the current weather in a given location",
      "input_schema": {
          "type": "object",
          "properties": {
              "location": {"type": "string", "description": "City and state"},
          },
          "required": ["location"],
      },
  }


  def execute_tool(name, tool_input):
      """Execute a tool and return the result."""
      return f"Weather in {tool_input.get('location', 'unknown')}: 72°F"


  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      tools=[weather_tool],
      messages=[{"role": "user", "content": "What is the weather in San Francisco?"}],
  )

  if response.stop_reason == "tool_use":
      # Tool extrahieren und ausführen
      for block in response.content:
          if block.type == "tool_use":
              result = execute_tool(block.name, block.input)
              # Ergebnis für die finale Antwort an Claude zurückgeben
  ```

  ```typescript TypeScript
  const client = new Anthropic();
  const weatherTool: Anthropic.Tool = {
    name: "get_weather",
    description: "Get the current weather in a given location",
    input_schema: {
      type: "object",
      properties: {
        location: { type: "string", description: "City and state" }
      },
      required: ["location"]
    }
  };

  function executeTool(name: string, input: Record<string, string>): string {
    return `Weather in ${input.location ?? "unknown"}: 72°F`;
  }

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    tools: [weatherTool],
    messages: [{ role: "user", content: "What is the weather in San Francisco?" }]
  });

  if (response.stop_reason === "tool_use") {
    // Extrahiere und führe das Tool aus
    for (const block of response.content) {
      if (block.type === "tool_use") {
        const result = executeTool(block.name, block.input as Record<string, string>);
        // Gib das Ergebnis für die finale Antwort an Claude zurück
      }
    }
  }
  ```

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

  var weatherTool = new Tool
  {
      Name = "get_weather",
      Description = "Get the current weather in a given location",
      InputSchema = new InputSchema
      {
          Properties = new Dictionary<string, JsonElement>
          {
              ["location"] = JsonSerializer.SerializeToElement(
                  new { type = "string", description = "City and state" }
              ),
          },
          Required = ["location"]
      }
  };

  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Tools = [weatherTool],
      Messages = [new() { Role = Role.User, Content = "What is the weather in San Francisco?" }]
  });

  if (response.StopReason == "tool_use")
  {
      // Tool extrahieren und ausführen
      foreach (var block in response.Content)
      {
          if (block.TryPickToolUse(out var toolUse))
          {
              // Führe toolUse.Name mit toolUse.Input aus und gib das Ergebnis an Claude zurück
          }
      }
  }
  ```

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

  weatherTool := anthropic.ToolParam{
  	Name:        "get_weather",
  	Description: anthropic.String("Get the current weather in a given location"),
  	InputSchema: anthropic.ToolInputSchemaParam{
  		Properties: map[string]any{
  			"location": map[string]string{"type": "string", "description": "City and state"},
  		},
  		Required: []string{"location"},
  	},
  }

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Tools:     []anthropic.ToolUnionParam{{OfTool: &weatherTool}},
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("What is the weather in San Francisco?")),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == "tool_use" {
  	// Extrahiere und führe das Tool aus
  	for _, block := range response.Content {
  		if toolUse, ok := block.AsAny().(anthropic.ToolUseBlock); ok {
  			fmt.Println(toolUse.Name, toolUse.Input)
  			// Gib das Ergebnis für die finale Antwort an Claude zurück
  		}
  	}
  }
  ```

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

      Tool weatherTool = Tool.builder()
          .name("get_weather")
          .description("Get the current weather in a given location")
          .inputSchema(Tool.InputSchema.builder()
              .properties(JsonValue.from(Map.of(
                  "location", Map.of("type", "string", "description", "City and state")
              )))
              .putAdditionalProperty("required", JsonValue.from(List.of("location")))
              .build())
          .build();

      Message response = client.messages().create(
          MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .addTool(weatherTool)
              .addUserMessage("What is the weather in San Francisco?")
              .build()
      );

      if (response.stopReason().map(StopReason.TOOL_USE::equals).orElse(false)) {
          // Extrahiere und führe das Tool aus
          for (ContentBlock block : response.content()) {
              block.toolUse().ifPresent(toolUse -> {
                  // Führe toolUse.name() mit toolUse.input() aus und gib das Ergebnis an Claude zurück
              });
          }
      }
  ```

  ```php PHP
  $client = new Client();

  $weatherTool = [
      'name' => 'get_weather',
      'description' => 'Get the current weather in a given location',
      'input_schema' => [
          'type' => 'object',
          'properties' => [
              'location' => ['type' => 'string', 'description' => 'City and state'],
          ],
          'required' => ['location'],
      ],
  ];

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'What is the weather in San Francisco?']],
      model: 'claude-opus-5-5',
      tools: [$weatherTool],
  );

  if ($response->stopReason === 'tool_use') {
      // Extrahiere und führe das Tool aus
      foreach ($response->content as $block) {
          if ($block->type === 'tool_use') {
              // Führe $block->name mit $block->input aus und gib das Ergebnis an Claude zurück
          }
      }
  }
  ```

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

  weather_tool = {
    name: "get_weather",
    description: "Get the current weather in a given location",
    input_schema: {
      type: "object",
      properties: {
        location: { type: "string", description: "City and state" }
      },
      required: ["location"]
    }
  }

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    tools: [weather_tool],
    messages: [{ role: "user", content: "What is the weather in San Francisco?" }]
  )

  if response.stop_reason == :tool_use
    # Tool extrahieren und ausführen
    response.content.each do |block|
      next unless block.type == :tool_use
      # Führe block.name mit block.input aus und gib das Ergebnis an Claude zurück
    end
  end
  ```
</CodeGroup>

Eine `tool_use`-Antwort kann auch einen `server_tool_use`-Block enthalten, dessen `id` keinen passenden Ergebnisblock hat. Dieser Server-Tool-Aufruf ist nicht abgeschlossen, und diese Antwort enthält sein Ergebnis nicht. Im häufigsten Fall ruft Claude ein [Server-Tool](https://platform.claude.com/docs/de/agents-and-tools/tool-use/server-tools) und eines deiner Client-Tools in derselben Gruppe paralleler Tool-Aufrufe auf: Die API kehrt zurück, ohne das Server-Tool auszuführen, damit du zuerst die Client-Tools ausführen kannst. Es gibt keine andere Markierung für diesen Zustand; erkenne ihn, indem du für die `id` jedes `server_tool_use`- oder `mcp_tool_use`-Blocks prüfst, ob ein passender Ergebnisblock vorhanden ist.

<Note>
  Beim [programmatischen Tool-Aufruf](https://platform.claude.com/docs/de/agents-and-tools/tool-use/programmatic-tool-calling) bedeutet dieselbe Antwortform etwas anderes. Der Client-`tool_use`-Block stammt von Code, der im `code_execution`-Tool läuft, und nicht direkt von Claude, und sein Feld `caller` benennt den `code_execution`-Block, der ihn aufgerufen hat. Dieser Code hat bereits begonnen: Er ist pausiert und wartet auf deine `tool_result`-Blöcke, und das Senden dieser Blöcke setzt die Ausführung fort, anstatt ein aufgeschobenes Tool zu starten. Der eigene Ergebnisblock des `code_execution`-Blocks kommt an, sobald der Code fertig ist, was mehr als eine Runde von Tool-Ergebnissen dauern kann. Die nachfolgende User-Nachricht selbst ist in beiden Fällen dieselbe; beim programmatischen Tool-Aufruf gibst du zusätzlich die `id` aus dem Feld `container` der Antwort zurück, wie auf jener Seite gezeigt.
</Note>

```json A mixed tool_use response
{
  "stop_reason": "tool_use",
  "content": [
    {
      "type": "server_tool_use",
      "id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
      "name": "web_search",
      "input": { "query": "example article" }
    },
    {
      "type": "tool_use",
      "id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
      "name": "run_command",
      "input": { "command": "uname -a" }
    }
  ]
}
```

Die Fortsetzung ist eine User-Nachricht aus `tool_result`-Blöcken, einer für jeden `tool_use`-Block in der Antwort (siehe [Tool-Aufrufe behandeln](https://platform.claude.com/docs/de/agents-and-tools/tool-use/handle-tool-calls)), mit zwei zusätzlichen Regeln: Diese Nachricht darf nichts außer den `tool_result`-Blöcken enthalten, und die Anfrage muss dasselbe `tools`-Array beibehalten. Eine Fortsetzungsanfrage, die das wartende Server-Tool nicht mehr definiert, schlägt mit einem 400 fehl, dessen Meldung mit ``but no `web_search` tool was provided`` endet. Die API hängt deine Ergebnisse an den noch offenen Assistant-Turn an, führt das aufgeschobene Server-Tool aus (bei pausierter Code-Ausführung setzt sie diese fort) und setzt den Turn fort. Bei einem Server-Tool, das Claude direkt aufgerufen hat, beginnt der `content` der nächsten Antwort mit dem Ergebnisblock, der die `server_tool_use`-`id` der vorherigen Antwort beantwortet.

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

Wenn du in dieser User-Nachricht nach den `tool_result`-Blöcken irgendetwas hinzufügst, etwa Text, beendet das den Assistant-Turn; bei einem Server-Tool, das Claude direkt aufgerufen hat, schlägt die Anfrage dann mit einem 400 `invalid_request_error` fehl, der das nicht aufgelöste Server-Tool benennt:

```text wrap
`web_search` tool use with id `srvtoolu_01HxbWnMRmbWyMfUtJKC45rA` was found without a corresponding `web_search_tool_result` block
```

Das Weglassen eines `tool_result` oder das Platzieren eines solchen nach anderem Inhalt schlägt stattdessen früher mit dem Standardfehler `tool_use ids were found without tool_result blocks immediately after` fehl. Um Claude weitere Eingaben zu geben, sende sie als separate User-Nachricht, nachdem der Turn abgeschlossen ist.

### pause\_turn

Wird zurückgegeben, wenn die serverseitige Sampling-Schleife ihr Iterationslimit erreicht, während sie [Server-Tools](https://platform.claude.com/docs/de/agents-and-tools/tool-use/server-tools) wie die Websuche ausführt. Das Standardlimit beträgt 10 Iterationen pro Anfrage.

Wenn dies geschieht, kann die Antwort einen `server_tool_use`-Block ohne zugehörigen Ergebnisblock enthalten. Damit Claude die Verarbeitung abschließen kann, setze die Konversation fort, indem du die Antwort unverändert zurücksendest. Eine Antwort, die einen Client-`tool_use`-Block auf dich warten lässt, hat niemals den `stop_reason` `pause_turn`: Wenn Claude stoppt, um deine Tools aufzurufen, ist `stop_reason` [`tool_use`](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#tool-use), und du setzt sie fort, indem du die Client-`tool_result`-Blöcke anstelle der Antwort selbst sendest.

<CodeGroup>
  ```bash cURL
  # Die SDKs übernehmen die Fortsetzung direkt. Prüfe bei cURL stop_reason
  # in der Antwort und sende erneut per POST, mit angehängtem Assistant-Inhalt.
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 4096,
      "tools": [{"type": "web_search_20250305", "name": "web_search"}],
      "messages": [{"role": "user", "content": "Search for latest AI news"}]
    }' | jq '{stop_reason, content}'
  ```

  ```bash CLI
  # Prüfe stop_reason; bei pause_turn erneut ausführen, mit der Assistant-
  # Antwort an --message angehängt.
  ant messages create --format json <<'YAML' | jq '{stop_reason, content}'
  model: claude-opus-5-5
  max_tokens: 4096
  tools:
    - {type: web_search_20250305, name: web_search}
  messages:
    - {role: user, content: "Search for latest AI news"}
  YAML
  ```

  ```python Python
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=4096,
      tools=[{"type": "web_search_20250305", "name": "web_search"}],
      messages=[{"role": "user", "content": "Search for latest AI news"}],
  )

  if response.stop_reason == "pause_turn":
      # Setze die Unterhaltung fort, indem du die Antwort zurücksendest
      messages = [
          {"role": "user", "content": "Search for latest AI news"},
          {"role": "assistant", "content": response.content},
      ]
      continuation = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=4096,
          messages=messages,
          tools=[{"type": "web_search_20250305", "name": "web_search"}],
      )
  ```

  ```typescript TypeScript
  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 4096,
    tools: [{ type: "web_search_20250305", name: "web_search" }],
    messages: [{ role: "user", content: "Search for latest AI news" }]
  });

  if (response.stop_reason === "pause_turn") {
    // Setze die Unterhaltung fort, indem du die Antwort zurücksendest
    const continuation = await client.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 4096,
      tools: [{ type: "web_search_20250305", name: "web_search" }],
      messages: [
        { role: "user", content: "Search for latest AI news" },
        { role: "assistant", content: response.content }
      ]
    });
  }
  ```

  ```csharp C#
  List<ToolUnion> tools = [new ToolUnion(new WebSearchTool20250305())];
  MessageParam userMessage = new() { Role = Role.User, Content = "Search for latest AI news" };

  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 4096,
      Tools = tools,
      Messages = [userMessage]
  });

  if (response.StopReason == "pause_turn")
  {
      // Setze die Unterhaltung fort, indem du die Antwort zurücksendest
      var continuation = await client.Messages.Create(new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 4096,
          Tools = tools,
          Messages =
          [
              userMessage,
              new()
              {
                  Role = Role.Assistant,
                  Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              }
          ]
      });
  }
  ```

  ```go Go
  tools := []anthropic.ToolUnionParam{
  	{OfWebSearchTool20250305: &anthropic.WebSearchTool20250305Param{}},
  }
  userMessage := anthropic.NewUserMessage(anthropic.NewTextBlock("Search for latest AI news"))

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 4096,
  	Tools:     tools,
  	Messages:  []anthropic.MessageParam{userMessage},
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == "pause_turn" {
  	// Setze die Unterhaltung fort, indem du die Antwort zurücksendest
  	var contentParams []anthropic.ContentBlockParamUnion
  	for _, block := range response.Content {
  		contentParams = append(contentParams, block.ToParam())
  	}
  	continuation, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 4096,
  		Tools:     tools,
  		Messages:  []anthropic.MessageParam{userMessage, anthropic.NewAssistantMessage(contentParams...)},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	_ = continuation
  }
  ```

  ```java Java
  Message response = client.messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(4096L)
          .addTool(WebSearchTool20250305.builder().build())
          .addUserMessage("Search for latest AI news")
          .build()
  );

  if (response.stopReason().map(StopReason.PAUSE_TURN::equals).orElse(false)) {
      // Setze die Unterhaltung fort, indem du die Antwort zurücksendest
      Message continuation = client.messages().create(
          MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(4096L)
              .addTool(WebSearchTool20250305.builder().build())
              .addUserMessage("Search for latest AI news")
              .addMessage(response)
              .build()
      );
  }
  ```

  ```php PHP
  $tools = [['type' => 'web_search_20250305', 'name' => 'web_search']];
  $userMessage = ['role' => 'user', 'content' => 'Search for latest AI news'];

  $response = $client->messages->create(
      maxTokens: 4096,
      messages: [$userMessage],
      model: 'claude-opus-5-5',
      tools: $tools,
  );

  if ($response->stopReason === 'pause_turn') {
      // Setze die Unterhaltung fort, indem du die Antwort zurücksendest
      $continuation = $client->messages->create(
          maxTokens: 4096,
          messages: [
              $userMessage,
              ['role' => 'assistant', 'content' => $response->content],
          ],
          model: 'claude-opus-5-5',
          tools: $tools,
      );
  }
  ```

  ```ruby Ruby
  tools = [{ type: "web_search_20250305", name: "web_search" }]
  user_message = { role: "user", content: "Search for latest AI news" }

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 4096,
    tools: tools,
    messages: [user_message]
  )

  if response.stop_reason == :pause_turn
    # Setze die Unterhaltung fort, indem du die Antwort zurücksendest
    continuation = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 4096,
      tools: tools,
      messages: [user_message, { role: "assistant", content: response.content }]
    )
  end
  ```
</CodeGroup>

<Note>
  Deine Anwendung sollte `pause_turn` in jeder Agentenschleife behandeln, die Server-Tools verwendet. Füge die Antwort des Assistants zu deinem Messages-Array hinzu und stelle eine weitere API-Anfrage, damit Claude fortfahren kann.
</Note>

### refusal

Claude hat es abgelehnt, eine Antwort zu generieren. Sicherheitsklassifikatoren geben diesen Stop-Grund als normale HTTP-200-Antwort zurück, nicht als Fehler.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [{"role": "user", "content": "[Unsafe request]"}]
    }' | jq '{stop_reason, stop_details}'
  ```

  ```bash CLI
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "[Unsafe request]"}' \
    --format json | jq '{stop_reason, stop_details}'
  ```

  ```python Python
  client = anthropic.Anthropic()
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "[Unsafe request]"}],
  )

  if response.stop_reason == "refusal":
      # Claude hat eine Antwort abgelehnt
      print("Claude was unable to process this request")
      # Formuliere die Anfrage ggf. um oder passe sie an
  ```

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

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "[Unsafe request]" }]
  });

  if (response.stop_reason === "refusal") {
    // Claude hat eine Antwort abgelehnt
    console.log("Claude was unable to process this request");
    // Formuliere die Anfrage ggf. um oder passe sie an
  }
  ```

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

  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [new() { Role = Role.User, Content = "[Unsafe request]" }]
  });

  if (response.StopReason == "refusal")
  {
      // Claude hat eine Antwort abgelehnt
      Console.WriteLine("Claude was unable to process this request");
      // Formuliere die Anfrage ggf. um oder passe sie an
  }
  ```

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

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("[Unsafe request]")),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == "refusal" {
  	// Claude hat eine Antwort abgelehnt
  	fmt.Println("Claude was unable to process this request")
  	// Formuliere die Anfrage ggf. um oder passe sie an
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  Message response = client.messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024L)
          .addUserMessage("[Unsafe request]")
          .build()
  );

  if (response.stopReason().map(StopReason.REFUSAL::equals).orElse(false)) {
      // Claude hat eine Antwort abgelehnt
      IO.println("Claude was unable to process this request");
      // Formuliere die Anfrage ggf. um oder passe sie an
  }
  ```

  ```php PHP
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => '[Unsafe request]']],
      model: 'claude-opus-5-5',
  );

  if ($response->stopReason === 'refusal') {
      // Claude hat die Antwort verweigert
      echo 'Claude was unable to process this request', PHP_EOL;
      // Formuliere die Anfrage ggf. um oder passe sie an
  }
  ```

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

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "[Unsafe request]" }]
  )

  if response.stop_reason == :refusal
    # Claude hat eine Antwort abgelehnt
    puts "Claude was unable to process this request"
    # Formuliere die Anfrage ggf. um oder passe sie an
  end
  ```
</CodeGroup>

<Tip>
  Wenn du bei der Verwendung von Claude Sonnet 4.5 ([abgekündigt](https://platform.claude.com/docs/de/about-claude/model-deprecations)) oder Claude Opus 4.1 (letzteres [eingestellt, außer auf Bedrock und Google Cloud](https://platform.claude.com/docs/de/about-claude/model-deprecations)) häufig auf den Stop-Grund `refusal` stößt, kannst du versuchen, deine API-Aufrufe auf Haiku 4.5 (`claude-haiku-4-5-20251001`) umzustellen, das andere Nutzungsbeschränkungen hat. Erfahre mehr über [die API-Sicherheitsfilter von Sonnet 4.5](https://support.claude.com/en/articles/12449294-understanding-sonnet-4-5-s-api-safety-filters).
</Tip>

Bei einer Ablehnung identifiziert das Objekt `stop_details` die Richtlinienkategorie, die sie ausgelöst hat. Die Kategorien und die vollständige Form der Ablehnungsantwort werden unter [Ablehnungen und Fallback](https://platform.claude.com/docs/de/build-with-claude/refusals-and-fallback#refusal-response) behandelt. `stop_details` ist für alle Stop-Gründe außer `refusal` `null`.

Eine abgelehnte Anfrage an Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 oder Claude Haiku 5.5 kann in der Regel durch einen erneuten Versuch mit einem anderen Claude-Modell bedient werden. [Ablehnungen und Fallback](https://platform.claude.com/docs/de/build-with-claude/refusals-and-fallback) zeigt, wie du diesen erneuten Versuch einrichtest, serverseitig oder in deinem Client. Claude Haiku 5.5 hat keinen serverseitigen Fallback, richte den erneuten Versuch daher [in deinem Client](https://platform.claude.com/docs/de/build-with-claude/refusals-and-fallback#client-side-fallback) ein. Wenn du den erneuten Versuch von Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5 oder Claude Sonnet 5.5 aus selbst aufbaust, erklärt [Fallback-Gutschrift](https://platform.claude.com/docs/de/build-with-claude/fallback-credit), wie du vermeidest, die Prompt-Cache-Kosten doppelt zu bezahlen.

### model\_context\_window\_exceeded

Claude hat gestoppt, weil es das Limit des „context window“ (Kontextfenster) des Modells erreicht hat. Dadurch kannst du die maximal möglichen Token anfordern, ohne die genaue Eingabegröße zu kennen.

<Note>
  Dieser Stop-Grund ist derzeit nur im `beta` (csharp, go: `Beta`; java: `beta()`)-Namespace des SDK typisiert, daher rufen die folgenden Beispiele `client.beta.messages` (csharp, go: `client.Beta.Messages`; java: `client.beta().messages()`; php: `$client->beta->messages`) auf und verwenden die Typen mit dem Präfix `Beta`. Bei Sonnet 4.5 (abgekündigt) und neueren Modellen gibt die API diesen Wert ohne Beta-Header zurück. Füge für ältere Modelle den Beta-Header `model-context-window-exceeded-2025-08-26` hinzu, um ihn zu aktivieren.
</Note>

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 20000,
      "messages": [{"role": "user", "content": "Large input that uses most of context window..."}]
    }' | jq '.stop_reason'
  ```

  ```bash CLI
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 20000 \
    --message '{role: user, content: "Large input that uses most of context window..."}' \
    --format json | jq '.stop_reason'
  ```

  ```python Python
  # Anfrage mit maximaler Token-Anzahl, um so viel wie möglich zu erhalten
  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=20000,  # Python SDK requires streaming for max_tokens above ~21k
      messages=[
          {"role": "user", "content": "Large input that uses most of context window..."}
      ],
  )

  if response.stop_reason == "model_context_window_exceeded":
      # Antwort hat das Limit des Kontextfensters vor max_tokens erreicht
      print("Response reached model's context window limit")
      # Die Antwort ist weiterhin gültig, wurde aber durch das Kontextfenster begrenzt
  ```

  ```typescript TypeScript
  // Anfrage mit maximaler Token-Anzahl, um möglichst viel zu erhalten
  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 20000,
    messages: [{ role: "user", content: "Large input that uses most of context window..." }]
  });

  if (response.stop_reason === "model_context_window_exceeded") {
    // Antwort hat das Limit des Kontextfensters vor max_tokens erreicht
    console.log("Response reached model's context window limit");
    // Die Antwort ist weiterhin gültig, wurde aber durch das Kontextfenster begrenzt
  }
  ```

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

  // Anfrage mit maximaler Token-Anzahl, um so viel wie möglich zu erhalten
  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 20000,
      Messages = [new() { Role = Role.User, Content = "Large input that uses most of context window..." }]
  });

  if (response.StopReason?.Value() == BetaStopReason.ModelContextWindowExceeded)
  {
      // Antwort hat das Limit des Kontextfensters vor max_tokens erreicht
      Console.WriteLine("Response reached model's context window limit");
      // Die Antwort ist weiterhin gültig, wurde aber durch das Kontextfenster begrenzt
  }
  ```

  ```go Go
  // Anfrage mit maximaler Tokenanzahl, um möglichst viel zu erhalten
  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 20000,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Large input that uses most of context window...")),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == anthropic.BetaStopReasonModelContextWindowExceeded {
  	// Antwort hat das Limit des Kontextfensters vor max_tokens erreicht
  	fmt.Println("Response reached model's context window limit")
  	// Die Antwort ist weiterhin gültig, wurde aber durch das Kontextfenster begrenzt
  }
  ```

  ```java Java
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaStopReason;
  import com.anthropic.models.beta.messages.MessageCreateParams;

  // Anfrage mit maximaler Token-Anzahl, um möglichst viel zu erhalten
  BetaMessage response = client.beta().messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(20000L)
          .addUserMessage("Large input that uses most of context window...")
          .build()
  );

  if (response.stopReason().map(BetaStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED::equals).orElse(false)) {
      // Antwort hat das Limit des Kontextfensters vor max_tokens erreicht
      IO.println("Response reached model's context window limit");
      // Die Antwort ist weiterhin gültig, wurde aber durch das Kontextfenster begrenzt
  }
  ```

  ```php PHP
  // Anfrage mit maximaler Token-Anzahl, um so viel wie möglich zu erhalten
  $response = $client->beta->messages->create(
      maxTokens: 20000,
      messages: [['role' => 'user', 'content' => 'Large input that uses most of context window...']],
      model: 'claude-opus-5-5',
  );

  if ($response->stopReason === 'model_context_window_exceeded') {
      // Antwort hat das Limit des Kontextfensters vor max_tokens erreicht
      echo 'Response reached model\'s context window limit', PHP_EOL;
      // Die Antwort ist weiterhin gültig, wurde aber durch das Kontextfenster begrenzt
  }
  ```

  ```ruby Ruby
  # Anfrage mit maximaler Token-Anzahl, um so viel wie möglich zu erhalten
  response = client.beta.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 20000,
    messages: [{ role: "user", content: "Large input that uses most of context window..." }]
  )

  if response.stop_reason == :model_context_window_exceeded
    # Antwort hat das Limit des Kontextfensters vor max_tokens erreicht
    puts "Response reached model's context window limit"
    # Die Antwort ist weiterhin gültig, wurde aber durch das Kontextfenster begrenzt
  end
  ```
</CodeGroup>

## Best Practices für den Umgang mit Stop-Gründen

### Prüfe immer stop\_reason

Mache es dir zur Gewohnheit, den `stop_reason` in deiner Antwortverarbeitungslogik zu prüfen:

<CodeGroup exclude="shell">
  ```python Python
  def handle_response(response):
      match response.stop_reason:
          case "tool_use":
              return handle_tool_use(response)
          case "max_tokens":
              return handle_truncation(response)
          case "model_context_window_exceeded":
              return handle_context_limit(response)
          case "pause_turn":
              return handle_pause(response)
          case "refusal":
              return handle_refusal(response)
          case _:
              # Behandle end_turn und andere Fälle
              return next(
                  (block.text for block in response.content if block.type == "text"),
                  "",
              )
  ```

  ```typescript TypeScript
  function handleResponse(response: Anthropic.Beta.BetaMessage): string {
    switch (response.stop_reason) {
      case "tool_use":
        return handleToolUse(response);
      case "max_tokens":
        return handleTruncation(response);
      case "model_context_window_exceeded":
        return handleContextLimit(response);
      case "pause_turn":
        return handlePause(response);
      case "refusal":
        return handleRefusal(response);
      default: {
        // end_turn und andere Fälle behandeln
        const textBlock = response.content.find(
          (block): block is Anthropic.Beta.BetaTextBlock => block.type === "text"
        );
        return textBlock?.text ?? "";
      }
    }
  }
  ```

  ```csharp C#
  static string HandleResponse(BetaMessage response)
  {
      return response.StopReason?.Value() switch
      {
          BetaStopReason.ToolUse => HandleToolUse(response),
          BetaStopReason.MaxTokens => HandleTruncation(response),
          BetaStopReason.ModelContextWindowExceeded => HandleContextLimit(response),
          BetaStopReason.PauseTurn => HandlePause(response),
          BetaStopReason.Refusal => HandleRefusal(response),
          // end_turn und andere Fälle behandeln
          _ => response.Content.Select(b => b.Value).OfType<BetaTextBlock>().FirstOrDefault()?.Text ?? "",
      };
  }
  ```

  ```go Go
  func handleResponse(response *anthropic.BetaMessage) string {
  	switch response.StopReason {
  	case anthropic.BetaStopReasonToolUse:
  		return handleToolUse(response)
  	case anthropic.BetaStopReasonMaxTokens:
  		return handleTruncation(response)
  	case anthropic.BetaStopReasonModelContextWindowExceeded:
  		return handleContextLimit(response)
  	case anthropic.BetaStopReasonPauseTurn:
  		return handlePause(response)
  	case anthropic.BetaStopReasonRefusal:
  		return handleRefusal(response)
  	default:
  		// end_turn und andere Fälle behandeln
  		for _, block := range response.Content {
  			if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  				return textBlock.Text
  			}
  		}
  		return ""
  	}
  }
  ```

  ```java Java
  static String handleResponse(BetaMessage response) {
      BetaStopReason reason = response.stopReason().orElse(BetaStopReason.END_TURN);
      if (reason.equals(BetaStopReason.TOOL_USE)) {
          return handleToolUse(response);
      } else if (reason.equals(BetaStopReason.MAX_TOKENS)) {
          return handleTruncation(response);
      } else if (reason.equals(BetaStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED)) {
          return handleContextLimit(response);
      } else if (reason.equals(BetaStopReason.PAUSE_TURN)) {
          return handlePause(response);
      } else if (reason.equals(BetaStopReason.REFUSAL)) {
          return handleRefusal(response);
      }
      // end_turn und andere Fälle behandeln
      return response.content().stream()
          .filter(BetaContentBlock::isText)
          .findFirst()
          .map(block -> block.asText().text())
          .orElse("");
  }
  ```

  ```php PHP
  function handle_response($response): string
  {
      return match ($response->stopReason) {
          'tool_use' => handle_tool_use($response),
          'max_tokens' => handle_truncation($response),
          'model_context_window_exceeded' => handle_context_limit($response),
          'pause_turn' => handle_pause($response),
          'refusal' => handle_refusal($response),
          // end_turn und andere Fälle behandeln
          default => array_find($response->content, static fn ($block): bool => $block->type === 'text')?->text ?? '',
      };
  }
  ```

  ```ruby Ruby
  def handle_response(response)
    case response.stop_reason
    when :tool_use then handle_tool_use(response)
    when :max_tokens then handle_truncation(response)
    when :model_context_window_exceeded then handle_context_limit(response)
    when :pause_turn then handle_pause(response)
    when :refusal then handle_refusal(response)
    else
      # end_turn und andere Fälle behandeln
      response.content.find { it.type == :text }&.text
    end
  end
  ```
</CodeGroup>

### Behandle abgeschnittene Antworten elegant

Wenn eine Antwort aufgrund von Token-Limits oder des Kontextfensters abgeschnitten wird, hänge einen Hinweis an, damit der Leser weiß, dass die Ausgabe unvollständig ist. Um stattdessen die Generierung dort fortzusetzen, wo die Antwort aufgehört hat, siehe [Vollständige Antworten sicherstellen](https://platform.claude.com/docs/de/build-with-claude/handling-stop-reasons#ensuring-complete-responses).

<CodeGroup exclude="shell">
  ```python Python
  def handle_truncated_response(response):
      text = next((block.text for block in response.content if block.type == "text"), "")
      if response.stop_reason in ["max_tokens", "model_context_window_exceeded"]:
          if response.stop_reason == "max_tokens":
              note = "[Response truncated due to max_tokens limit]"
          else:
              note = "[Response truncated due to context window limit]"
          return f"{text}\n\n{note}"
      return text
  ```

  ```typescript TypeScript
  function handleTruncatedResponse(response: Anthropic.Beta.BetaMessage): string {
    const textBlock = response.content.find(
      (block): block is Anthropic.Beta.BetaTextBlock => block.type === "text"
    );
    const text = textBlock?.text ?? "";

    if (
      response.stop_reason === "max_tokens" ||
      response.stop_reason === "model_context_window_exceeded"
    ) {
      const note =
        response.stop_reason === "max_tokens"
          ? "[Response truncated due to max_tokens limit]"
          : "[Response truncated due to context window limit]";
      return `${text}\n\n${note}`;
    }
    return text;
  }
  ```

  ```csharp C#
  static string HandleTruncatedResponse(BetaMessage response)
  {
      var text = response.Content.Select(b => b.Value).OfType<BetaTextBlock>().FirstOrDefault()?.Text ?? "";
      var reason = response.StopReason?.Value();

      if (reason is BetaStopReason.MaxTokens or BetaStopReason.ModelContextWindowExceeded)
      {
          var note = reason == BetaStopReason.MaxTokens
              ? "[Response truncated due to max_tokens limit]"
              : "[Response truncated due to context window limit]";
          return $"{text}\n\n{note}";
      }
      return text;
  }
  ```

  ```go Go
  func handleTruncatedResponse(response *anthropic.BetaMessage) string {
  	text := ""
  	for _, block := range response.Content {
  		if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  			text = textBlock.Text
  			break
  		}
  	}

  	if response.StopReason == anthropic.BetaStopReasonMaxTokens ||
  		response.StopReason == anthropic.BetaStopReasonModelContextWindowExceeded {
  		note := "[Response truncated due to context window limit]"
  		if response.StopReason == anthropic.BetaStopReasonMaxTokens {
  			note = "[Response truncated due to max_tokens limit]"
  		}
  		return text + "\n\n" + note
  	}
  	return text
  }
  ```

  ```java Java
  static String handleTruncatedResponse(BetaMessage response) {
      String text = response.content().stream()
          .filter(BetaContentBlock::isText)
          .findFirst()
          .map(block -> block.asText().text())
          .orElse("");
      BetaStopReason reason = response.stopReason().orElse(BetaStopReason.END_TURN);

      if (reason.equals(BetaStopReason.MAX_TOKENS)
              || reason.equals(BetaStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED)) {
          String note = reason.equals(BetaStopReason.MAX_TOKENS)
              ? "[Response truncated due to max_tokens limit]"
              : "[Response truncated due to context window limit]";
          return text + "\n\n" + note;
      }
      return text;
  }
  ```

  ```php PHP
  function handle_truncated_response($response): string
  {
      $text = array_find($response->content, static fn ($block): bool => $block->type === 'text')?->text ?? '';

      if (in_array($response->stopReason, ['max_tokens', 'model_context_window_exceeded'], true)) {
          $note = $response->stopReason === 'max_tokens'
              ? '[Response truncated due to max_tokens limit]'
              : '[Response truncated due to context window limit]';
          return "{$text}\n\n{$note}";
      }
      return $text;
  }
  ```

  ```ruby Ruby
  def handle_truncated_response(response)
    text = response.content.find { it.type == :text }&.text

    if [:max_tokens, :model_context_window_exceeded].include?(response.stop_reason)
      note = if response.stop_reason == :max_tokens
        "[Response truncated due to max_tokens limit]"
      else
        "[Response truncated due to context window limit]"
      end
      return "#{text}\n\n#{note}"
    end
    text
  end
  ```
</CodeGroup>

### Implementiere Retry-Logik für pause\_turn

Bei der Verwendung von [Server-Tools](https://platform.claude.com/docs/de/agents-and-tools/tool-use/server-tools) kann die API `pause_turn` zurückgeben, wenn die serverseitige Sampling-Schleife ihr Iterationslimit (standardmäßig 10) erreicht. Behandle dies, indem du die Konversation fortsetzt:

<CodeGroup exclude="shell">
  ```python Python
  def handle_server_tool_conversation(client, user_query, tools, max_continuations=5):
      """
      Handle server tool conversations that may require multiple continuations.

      The server runs a sampling loop when executing server tools. If the loop
      reaches its iteration limit, the API returns pause_turn. Continue the
      conversation by sending the response back to let Claude finish.
      """
      messages = [{"role": "user", "content": user_query}]

      for _ in range(max_continuations):
          response = client.messages.create(
              model="claude-opus-5-5",
              max_tokens=4096,
              messages=messages,
              tools=tools,
          )

          if response.stop_reason != "pause_turn":
              # Claude ist mit der Verarbeitung fertig – gib die finale Antwort zurück
              return response

          # pause_turn: Ersetze die gesamte Nachrichtenliste, damit die Rollen weiter abwechseln
          messages = [
              {"role": "user", "content": user_query},
              {"role": "assistant", "content": response.content},
          ]

      # Maximale Anzahl an Fortsetzungen erreicht – gib die letzte Antwort zurück
      return response
  ```

  ```typescript TypeScript
  async function handleServerToolConversation(
    client: Anthropic,
    userQuery: string,
    tools: Anthropic.ToolUnion[],
    maxContinuations = 5
  ): Promise<Anthropic.Message> {
    let messages: Anthropic.MessageParam[] = [{ role: "user", content: userQuery }];
    let response: Anthropic.Message;

    for (let i = 0; i < maxContinuations; i++) {
      response = await client.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 4096,
        messages,
        tools
      });

      if (response.stop_reason !== "pause_turn") {
        // Claude ist mit der Verarbeitung fertig – gib die finale Antwort zurück
        return response;
      }

      // pause_turn: ersetze die gesamte Nachrichtenliste, damit die Rollen weiter abwechseln
      messages = [
        { role: "user", content: userQuery },
        { role: "assistant", content: response.content }
      ];
    }

    // Maximale Anzahl an Fortsetzungen erreicht – gib die letzte Antwort zurück
    return response!;
  }
  ```

  ```csharp C#
  static async Task<Message> HandleServerToolConversation(
      AnthropicClient client,
      string userQuery,
      List<ToolUnion> tools,
      int maxContinuations = 5)
  {
      List<MessageParam> messages = [new() { Role = Role.User, Content = userQuery }];
      Message response = null!;

      for (var i = 0; i < maxContinuations; i++)
      {
          response = await client.Messages.Create(new MessageCreateParams
          {
              Model = Model.ClaudeOpus5_5,
              MaxTokens = 4096,
              Messages = messages,
              Tools = tools
          });

          if (response.StopReason != "pause_turn")
          {
              // Claude ist mit der Verarbeitung fertig – gib die finale Antwort zurück
              return response;
          }

          // pause_turn: Ersetze die gesamte Nachrichtenliste, damit die Rollen weiterhin abwechseln
          messages =
          [
              new() { Role = Role.User, Content = userQuery },
              new()
              {
                  Role = Role.Assistant,
                  Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              }
          ];
      }

      // Maximale Anzahl an Fortsetzungen erreicht – gib die letzte Antwort zurück
      return response;
  }
  ```

  ```go Go
  func handleServerToolConversation(
  	client anthropic.Client,
  	userQuery string,
  	tools []anthropic.ToolUnionParam,
  	maxContinuations int,
  ) (*anthropic.Message, error) {
  	messages := []anthropic.MessageParam{anthropic.NewUserMessage(anthropic.NewTextBlock(userQuery))}
  	var response *anthropic.Message
  	var err error

  	for range maxContinuations {
  		response, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  			Model:     anthropic.ModelClaudeOpus5_5,
  			MaxTokens: 4096,
  			Messages:  messages,
  			Tools:     tools,
  		})
  		if err != nil {
  			return nil, err
  		}

  		if response.StopReason != "pause_turn" {
  			// Claude ist mit der Verarbeitung fertig – gib die finale Antwort zurück
  			return response, nil
  		}

  		// pause_turn: Ersetze die gesamte Nachrichtenliste, damit sich die Rollen weiter abwechseln
  		var contentParams []anthropic.ContentBlockParamUnion
  		for _, block := range response.Content {
  			contentParams = append(contentParams, block.ToParam())
  		}
  		messages = []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock(userQuery)),
  			anthropic.NewAssistantMessage(contentParams...),
  		}
  	}

  	// Maximale Anzahl an Fortsetzungen erreicht – gib die letzte Antwort zurück
  	return response, nil
  }
  ```

  ```java Java
  static Message handleServerToolConversation(
      AnthropicClient client,
      String userQuery,
      List<Tool> tools,
      int maxContinuations
  ) {
      Message response = null;

      for (int i = 0; i < maxContinuations; i++) {
          // Baue die Parameter in jeder Iteration neu auf, damit sich keine Nachrichten ansammeln
          MessageCreateParams.Builder params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(4096L)
              .addUserMessage(userQuery);
          tools.forEach(params::addTool);
          if (response != null) {
              params.addMessage(response);
          }

          response = client.messages().create(params.build());

          if (!response.stopReason().map(StopReason.PAUSE_TURN::equals).orElse(false)) {
              // Claude ist mit der Verarbeitung fertig – gib die finale Antwort zurück
              return response;
          }
          // pause_turn: Schleife erneut durchlaufen und die Antwort zurücksenden
      }

      // Maximale Anzahl an Fortsetzungen erreicht – gib die letzte Antwort zurück
      return response;
  }
  ```

  ```php PHP
  function handle_server_tool_conversation(
      Client $client,
      string $userQuery,
      array $tools,
      int $maxContinuations = 5
  ) {
      $messages = [['role' => 'user', 'content' => $userQuery]];
      $response = null;

      for ($i = 0; $i < $maxContinuations; $i++) {
          $response = $client->messages->create(
              maxTokens: 4096,
              messages: $messages,
              model: 'claude-opus-5-5',
              tools: $tools,
          );

          if ($response->stopReason !== 'pause_turn') {
              // Claude ist mit der Verarbeitung fertig – gib die finale Antwort zurück
              return $response;
          }

          // pause_turn: Ersetze die gesamte Nachrichtenliste, damit die Rollen weiter abwechseln
          $messages = [
              ['role' => 'user', 'content' => $userQuery],
              ['role' => 'assistant', 'content' => $response->content],
          ];
      }

      // Maximale Anzahl an Fortsetzungen erreicht – gib die letzte Antwort zurück
      return $response;
  }
  ```

  ```ruby Ruby
  def handle_server_tool_conversation(client, user_query, tools, max_continuations: 5)
    messages = [{ role: "user", content: user_query }]
    response = nil

    max_continuations.times do
      response = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 4096,
        messages: messages,
        tools: tools
      )

      # Claude ist fertig – gib die finale Antwort zurück
      return response unless response.stop_reason == :pause_turn

      # pause_turn: ersetze die gesamte Nachrichtenliste, damit die Rollen abwechselnd bleiben
      messages = [
        { role: "user", content: user_query },
        { role: "assistant", content: response.content }
      ]
    end

    # Maximale Anzahl an Fortsetzungen erreicht – gib die letzte Antwort zurück
    response
  end
  ```
</CodeGroup>

## Stop-Gründe vs. Fehler

Es ist wichtig, zwischen `stop_reason`-Werten und tatsächlichen Fehlern zu unterscheiden:

### Stop-Gründe (erfolgreiche Antworten)

* Teil des Antwort-Bodys
* Zeigen an, warum die Generierung normal gestoppt hat
* Antwort enthält gültigen Inhalt

### Fehler (fehlgeschlagene Anfragen)

* HTTP-Statuscodes 4xx oder 5xx
* Zeigen Fehler bei der Anfrageverarbeitung an
* Antwort enthält Fehlerdetails

<CodeGroup>
  ```bash cURL
  # cURL beendet sich bei HTTP-Fehlern mit --fail-with-body mit Nicht-Null-Code; prüfe
  # $? auf Fehler und stop_reason bei erfolgreichen Antworten.
  curl --fail-with-body -sS https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [{"role": "user", "content": "Hello!"}]
    }' | jq '.stop_reason'
  ```

  ```bash CLI
  # Die CLI endet bei API-Fehlern mit einem Exit-Code ungleich null; stop_reason erscheint bei Erfolg.
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "Hello!"}' \
    --format json | jq '.stop_reason'
  ```

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

  try:
      response = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=1024,
          messages=[{"role": "user", "content": "Hello!"}],
      )

      # Erfolgreiche Antwort mit stop_reason verarbeiten
      if response.stop_reason == "max_tokens":
          print("Response was truncated")

  except anthropic.APIStatusError as e:
      # Tatsächliche Fehler behandeln
      match e.status_code:
          case 429:
              print("Rate limit exceeded")
          case 500:
              print("Server error")
  ```

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

  try {
    const response = await client.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [{ role: "user", content: "Hello!" }]
    });

    // Verarbeite erfolgreiche Antwort mit stop_reason
    if (response.stop_reason === "max_tokens") {
      console.log("Response was truncated");
    }
  } catch (err) {
    // Verarbeite tatsächliche Fehler
    if (err instanceof Anthropic.APIError) {
      switch (err.status) {
        case 429:
          console.log("Rate limit exceeded");
          break;
        case 500:
          console.log("Server error");
          break;
      }
    } else {
      throw err;
    }
  }
  ```

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

  try
  {
      var response = await client.Messages.Create(new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [new() { Role = Role.User, Content = "Hello!" }]
      });

      // Erfolgreiche Antwort mit stop_reason verarbeiten
      if (response.StopReason == "max_tokens")
      {
          Console.WriteLine("Response was truncated");
      }
  }
  catch (AnthropicRateLimitException)
  {
      // Tatsächliche Fehler behandeln
      Console.WriteLine("Rate limit exceeded");
  }
  catch (Anthropic5xxException)
  {
      Console.WriteLine("Server error");
  }
  ```

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

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Hello!")),
  	},
  })
  if err != nil {
  	// Behandle tatsächliche Fehler
  	var apiErr *anthropic.Error
  	if errors.As(err, &apiErr) {
  		switch apiErr.StatusCode {
  		case 429:
  			fmt.Println("Rate limit exceeded")
  		case 500:
  			fmt.Println("Server error")
  		}
  	}
  	log.Fatal(err)
  }

  // Behandle erfolgreiche Antwort mit stop_reason
  if response.StopReason == "max_tokens" {
  	fmt.Println("Response was truncated")
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  try {
      Message response = client.messages().create(
          MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .addUserMessage("Hello!")
              .build()
      );

      // Verarbeite erfolgreiche Antwort mit stop_reason
      if (response.stopReason().map(StopReason.MAX_TOKENS::equals).orElse(false)) {
          IO.println("Response was truncated");
      }
  } catch (RateLimitException e) {
      // Behandle tatsächliche Fehler
      IO.println("Rate limit exceeded");
  } catch (AnthropicServiceException e) {
      if (e.statusCode() == 500) {
          IO.println("Server error");
      }
  }
  ```

  ```php PHP
  $client = new Client();

  try {
      $response = $client->messages->create(
          maxTokens: 1024,
          messages: [['role' => 'user', 'content' => 'Hello!']],
          model: 'claude-opus-5-5',
      );

      // Erfolgreiche Antwort mit stop_reason verarbeiten
      if ($response->stopReason === 'max_tokens') {
          echo 'Response was truncated', PHP_EOL;
      }
  } catch (RateLimitException $e) {
      // Tatsächliche Fehler behandeln
      echo 'Rate limit exceeded', PHP_EOL;
  } catch (InternalServerException $e) {
      echo 'Server error', PHP_EOL;
  }
  ```

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

  begin
    response = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [{ role: "user", content: "Hello!" }]
    )

    # Erfolgreiche Antwort mit stop_reason verarbeiten
    if response.stop_reason == :max_tokens
      puts "Response was truncated"
    end
  rescue Anthropic::Errors::RateLimitError
    # Tatsächliche Fehler behandeln
    puts "Rate limit exceeded"
  rescue Anthropic::Errors::APIStatusError => e
    puts "Server error" if e.status == 500
  end
  ```
</CodeGroup>

## Überlegungen zum Streaming

Bei der Verwendung von Streaming ist `stop_reason`:

* `null` im initialen `message_start`-Event
* Im `message_delta`-Event enthalten
* In keinem anderen Event enthalten

<CodeGroup>
  ```bash cURL
  # Das message_delta-Event im SSE-Stream enthält stop_reason.
  curl --no-buffer https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "stream": true,
      "messages": [{"role": "user", "content": "Hello!"}]
    }'
  ```

  ```bash CLI
  # stop_reason erscheint im message_delta-Event.
  ant messages create --stream --format jsonl \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "Hello!"}' |
    jq -c 'select(.type == "message_delta") | .delta.stop_reason'
  ```

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

  with client.messages.stream(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Hello!"}],
  ) as stream:
      for event in stream:
          if event.type == "message_delta":
              stop_reason = event.delta.stop_reason
              if stop_reason:
                  print(f"Stream ended with: {stop_reason}")
  ```

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

  const stream = client.messages.stream({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello!" }]
  });

  for await (const event of stream) {
    if (event.type === "message_delta" && event.delta.stop_reason) {
      console.log(`Stream ended with: ${event.delta.stop_reason}`);
    }
  }
  ```

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

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [new() { Role = Role.User, Content = "Hello!" }]
  };

  await foreach (var streamEvent in client.Messages.CreateStreaming(parameters))
  {
      switch (streamEvent.Value)
      {
          case RawMessageDeltaEvent deltaEvent when deltaEvent.Delta.StopReason is not null:
              Console.WriteLine($"Stream ended with: {deltaEvent.Delta.StopReason}");
              break;
      }
  }
  ```

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

  stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Hello!")),
  	},
  })

  // Sammle die Events in der finalen Message, die stop_reason enthält.
  message := anthropic.Message{}
  for stream.Next() {
  	if err := message.Accumulate(stream.Current()); err != nil {
  		log.Fatal(err)
  	}
  }
  if err := stream.Err(); err != nil {
  	log.Fatal(err)
  }

  if message.StopReason != "" {
  	fmt.Printf("Stream ended with: %s\n", message.StopReason)
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  MessageCreateParams params = MessageCreateParams.builder()
      .model(Model.CLAUDE_OPUS_5_5)
      .maxTokens(1024L)
      .addUserMessage("Hello!")
      .build();

  // Sammle die Events in der finalen Message, die stop_reason enthält.
  MessageAccumulator accumulator = MessageAccumulator.create();
  try (StreamResponse<RawMessageStreamEvent> streamResponse =
          client.messages().createStreaming(params)) {
      streamResponse.stream().forEach(accumulator::accumulate);
  }

  accumulator.message().stopReason().ifPresent(stopReason ->
      IO.println("Stream ended with: " + stopReason)
  );
  ```

  ```php PHP
  $client = new Client();

  $stream = $client->messages->createStream(
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello!']],
      model: 'claude-opus-5-5',
  );

  foreach ($stream as $event) {
      if ($event instanceof \Anthropic\Messages\RawMessageDeltaEvent && $event->delta->stopReason !== null) {
          echo "Stream ended with: {$event->delta->stopReason}", PHP_EOL;
      }
  }
  ```

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

  stream = client.messages.stream(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello!" }]
  )

  stream.each do |event|
    next unless event.type == :message_delta
    stop_reason = event.delta.stop_reason
    puts "Stream ended with: #{stop_reason}" if stop_reason
  end
  ```
</CodeGroup>

## Häufige Muster

### Umgang mit Tool-Use-Workflows

<Tip>
  **Einfacher mit dem Tool Runner:** Das folgende Beispiel zeigt die manuelle Tool-Behandlung. Für die meisten Anwendungsfälle übernimmt der [Tool Runner](https://platform.claude.com/docs/de/agents-and-tools/tool-use/tool-runner) die Tool-Ausführung automatisch mit deutlich weniger Code.
</Tip>

<CodeGroup exclude="shell">
  ```python Python
  def complete_tool_workflow(client, user_query, tools):
      messages = [{"role": "user", "content": user_query}]

      while True:
          response = client.messages.create(
              model="claude-opus-5-5",
              max_tokens=1024,
              messages=messages,
              tools=tools,
          )

          if response.stop_reason == "tool_use":
              # Tools ausführen und fortfahren
              tool_results = execute_tools(response.content)
              messages.append({"role": "assistant", "content": response.content})
              messages.append({"role": "user", "content": tool_results})
          else:
              # Endgültige Antwort
              return response
  ```

  ```typescript TypeScript
  async function completeToolWorkflow(
    client: Anthropic,
    userQuery: string,
    tools: Anthropic.ToolUnion[]
  ): Promise<Anthropic.Message> {
    const messages: Anthropic.MessageParam[] = [{ role: "user", content: userQuery }];

    while (true) {
      const response = await client.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages,
        tools
      });

      if (response.stop_reason === "tool_use") {
        // Tools ausführen und fortfahren
        const toolResults = executeTools(response.content);
        messages.push({ role: "assistant", content: response.content });
        messages.push({ role: "user", content: toolResults });
      } else {
        // Endgültige Antwort
        return response;
      }
    }
  }
  ```

  ```csharp C#
  static async Task<Message> CompleteToolWorkflow(
      AnthropicClient client,
      string userQuery,
      List<ToolUnion> tools)
  {
      List<MessageParam> messages = [new() { Role = Role.User, Content = userQuery }];

      while (true)
      {
          var response = await client.Messages.Create(new MessageCreateParams
          {
              Model = Model.ClaudeOpus5_5,
              MaxTokens = 1024,
              Messages = messages,
              Tools = tools
          });

          if (response.StopReason == "tool_use")
          {
              // Tools ausführen und fortfahren
              var toolResults = ExecuteTools(response.Content);
              messages.Add(new()
              {
                  Role = Role.Assistant,
                  Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              });
              messages.Add(new() { Role = Role.User, Content = toolResults });
          }
          else
          {
              // Endgültige Antwort
              return response;
          }
      }
  }
  ```

  ```go Go
  func completeToolWorkflow(
  	client anthropic.Client,
  	userQuery string,
  	tools []anthropic.ToolUnionParam,
  ) (*anthropic.Message, error) {
  	messages := []anthropic.MessageParam{anthropic.NewUserMessage(anthropic.NewTextBlock(userQuery))}

  	for {
  		response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  			Model:     anthropic.ModelClaudeOpus5_5,
  			MaxTokens: 1024,
  			Messages:  messages,
  			Tools:     tools,
  		})
  		if err != nil {
  			return nil, err
  		}

  		if response.StopReason != "tool_use" {
  			// Endgültige Antwort
  			return response, nil
  		}

  		// Tools ausführen und fortfahren
  		toolResults := executeTools(response.Content)
  		var contentParams []anthropic.ContentBlockParamUnion
  		for _, block := range response.Content {
  			contentParams = append(contentParams, block.ToParam())
  		}
  		messages = append(messages, anthropic.NewAssistantMessage(contentParams...))
  		messages = append(messages, anthropic.NewUserMessage(toolResults...))
  	}
  }
  ```

  ```java Java
  static Message completeToolWorkflow(
      AnthropicClient client,
      String userQuery,
      List<Tool> tools
  ) {
      List<MessageParam> messages = new ArrayList<>();
      messages.add(MessageParam.builder().role(MessageParam.Role.USER).content(userQuery).build());

      while (true) {
          MessageCreateParams.Builder params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .messages(messages);
          tools.forEach(params::addTool);

          Message response = client.messages().create(params.build());

          if (!response.stopReason().map(StopReason.TOOL_USE::equals).orElse(false)) {
              // Endgültige Antwort
              return response;
          }

          // Tools ausführen und fortfahren
          List<ToolResultBlockParam> toolResults = executeTools(response.content());
          messages.add(response.toParam());
          messages.add(MessageParam.builder()
              .role(MessageParam.Role.USER)
              .contentOfBlockParams(toolResults.stream().map(ContentBlockParam::ofToolResult).toList())
              .build());
      }
  }
  ```

  ```php PHP
  function complete_tool_workflow(Client $client, string $userQuery, array $tools)
  {
      $messages = [['role' => 'user', 'content' => $userQuery]];

      while (true) {
          $response = $client->messages->create(
              maxTokens: 1024,
              messages: $messages,
              model: 'claude-opus-5-5',
              tools: $tools,
          );

          if ($response->stopReason !== 'tool_use') {
              // Endgültige Antwort
              return $response;
          }

          // Tools ausführen und fortfahren
          $toolResults = execute_tools($response->content);
          $messages[] = ['role' => 'assistant', 'content' => $response->content];
          $messages[] = ['role' => 'user', 'content' => $toolResults];
      }
  }
  ```

  ```ruby Ruby
  def complete_tool_workflow(client, user_query, tools)
    messages = [{ role: "user", content: user_query }]

    loop do
      response = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages: messages,
        tools: tools
      )

      # Finale Antwort
      return response unless response.stop_reason == :tool_use

      # Tools ausführen und fortfahren
      tool_results = execute_tools(response.content)
      messages << { role: "assistant", content: response.content }
      messages << { role: "user", content: tool_results }
    end
  end
  ```
</CodeGroup>

### Vollständige Antworten sicherstellen

<CodeGroup exclude="shell">
  ```python Python
  def get_complete_response(client, prompt, max_attempts=3):
      messages = [{"role": "user", "content": prompt}]
      full_response = ""

      for _ in range(max_attempts):
          response = client.messages.create(
              model="claude-opus-5-5", messages=messages, max_tokens=4096
          )

          full_response += next(
              (block.text for block in response.content if block.type == "text"), ""
          )

          if response.stop_reason != "max_tokens":
              break

          # Mach dort weiter, wo es aufgehört hat
          messages = [
              {"role": "user", "content": prompt},
              {"role": "assistant", "content": full_response},
              {"role": "user", "content": "Please continue from where you left off."},
          ]

      return full_response
  ```

  ```typescript TypeScript
  async function getCompleteResponse(
    client: Anthropic,
    prompt: string,
    maxAttempts = 3
  ): Promise<string> {
    let messages: Anthropic.MessageParam[] = [{ role: "user", content: prompt }];
    let fullResponse = "";

    for (let i = 0; i < maxAttempts; i++) {
      const response = await client.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 4096,
        messages
      });

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

      if (response.stop_reason !== "max_tokens") {
        break;
      }

      // Mach dort weiter, wo es aufgehört hat
      messages = [
        { role: "user", content: prompt },
        { role: "assistant", content: fullResponse },
        { role: "user", content: "Please continue from where you left off." }
      ];
    }

    return fullResponse;
  }
  ```

  ```csharp C#
  static async Task<string> GetCompleteResponse(AnthropicClient client, string prompt, int maxAttempts = 3)
  {
      List<MessageParam> messages = [new() { Role = Role.User, Content = prompt }];
      var fullResponse = "";

      for (var i = 0; i < maxAttempts; i++)
      {
          var response = await client.Messages.Create(new MessageCreateParams
          {
              Model = Model.ClaudeOpus5_5,
              MaxTokens = 4096,
              Messages = messages
          });

          foreach (var block in response.Content)
          {
              if (block.TryPickText(out var textBlock))
              {
                  fullResponse += textBlock.Text;
                  break;
              }
          }

          if (response.StopReason != "max_tokens")
          {
              break;
          }

          // Mach dort weiter, wo es aufgehört hat
          messages =
          [
              new() { Role = Role.User, Content = prompt },
              new() { Role = Role.Assistant, Content = fullResponse },
              new() { Role = Role.User, Content = "Please continue from where you left off." }
          ];
      }

      return fullResponse;
  }
  ```

  ```go Go
  func getCompleteResponse(client anthropic.Client, prompt string, maxAttempts int) (string, error) {
  	messages := []anthropic.MessageParam{anthropic.NewUserMessage(anthropic.NewTextBlock(prompt))}
  	fullResponse := ""

  	for range maxAttempts {
  		response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  			Model:     anthropic.ModelClaudeOpus5_5,
  			MaxTokens: 4096,
  			Messages:  messages,
  		})
  		if err != nil {
  			return "", err
  		}

  		for _, block := range response.Content {
  			if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  				fullResponse += textBlock.Text
  				break
  			}
  		}

  		if response.StopReason != "max_tokens" {
  			break
  		}

  		// Setze dort fort, wo es aufgehört hat
  		messages = []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock(prompt)),
  			anthropic.NewAssistantMessage(anthropic.NewTextBlock(fullResponse)),
  			anthropic.NewUserMessage(anthropic.NewTextBlock("Please continue from where you left off.")),
  		}
  	}

  	return fullResponse, nil
  }
  ```

  ```java Java
  static String getCompleteResponse(AnthropicClient client, String prompt, int maxAttempts) {
      List<MessageParam> messages = List.of(
          MessageParam.builder().role(MessageParam.Role.USER).content(prompt).build()
      );
      StringBuilder fullResponse = new StringBuilder();

      for (int i = 0; i < maxAttempts; i++) {
          Message response = client.messages().create(
              MessageCreateParams.builder()
                  .model(Model.CLAUDE_OPUS_5_5)
                  .maxTokens(4096L)
                  .messages(messages)
                  .build()
          );

          response.content().stream()
              .filter(ContentBlock::isText)
              .findFirst()
              .ifPresent(block -> fullResponse.append(block.asText().text()));

          if (!response.stopReason().map(StopReason.MAX_TOKENS::equals).orElse(false)) {
              break;
          }

          // Setze dort fort, wo es aufgehört hat
          messages = List.of(
              MessageParam.builder().role(MessageParam.Role.USER).content(prompt).build(),
              MessageParam.builder().role(MessageParam.Role.ASSISTANT).content(fullResponse.toString()).build(),
              MessageParam.builder().role(MessageParam.Role.USER).content("Please continue from where you left off.").build()
          );
      }

      return fullResponse.toString();
  }
  ```

  ```php PHP
  function get_complete_response(Client $client, string $prompt, int $maxAttempts = 3): string
  {
      $messages = [['role' => 'user', 'content' => $prompt]];
      $fullResponse = '';

      for ($i = 0; $i < $maxAttempts; $i++) {
          $response = $client->messages->create(
              maxTokens: 4096,
              messages: $messages,
              model: 'claude-opus-5-5',
          );

          $fullResponse .= array_find($response->content, static fn ($block): bool => $block->type === 'text')?->text ?? '';

          if ($response->stopReason !== 'max_tokens') {
              break;
          }

          // Dort weitermachen, wo es aufgehört hat
          $messages = [
              ['role' => 'user', 'content' => $prompt],
              ['role' => 'assistant', 'content' => $fullResponse],
              ['role' => 'user', 'content' => 'Please continue from where you left off.'],
          ];
      }

      return $fullResponse;
  }
  ```

  ```ruby Ruby
  def get_complete_response(client, prompt, max_attempts: 3)
    messages = [{ role: "user", content: prompt }]
    full_response = +""

    max_attempts.times do
      response = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 4096,
        messages: messages
      )

      full_response << response.content.find { it.type == :text }&.text.to_s

      break unless response.stop_reason == :max_tokens

      # Setze dort fort, wo es aufgehört hat
      messages = [
        { role: "user", content: prompt },
        { role: "assistant", content: full_response },
        { role: "user", content: "Please continue from where you left off." }
      ]
    end

    full_response
  end
  ```
</CodeGroup>

### Maximale Token erhalten, ohne die Eingabegröße zu kennen

Mit dem Stop-Grund `model_context_window_exceeded` kannst du die maximal möglichen Token anfordern, ohne die Eingabegröße zu berechnen:

<CodeGroup exclude="shell">
  ```python Python
  def get_max_possible_tokens(client, prompt):
      """
      Get as many tokens as possible within the model's context window
      without needing to calculate input token count
      """
      response = client.beta.messages.create(
          model="claude-opus-5-5",
          messages=[{"role": "user", "content": prompt}],
          max_tokens=20000,  # Python SDK requires streaming for max_tokens above ~21k
      )

      match response.stop_reason:
          case "model_context_window_exceeded":
              # Maximal mögliche Anzahl an Tokens für die Eingabegröße erhalten
              print(
                  f"Generated {response.usage.output_tokens} tokens (context limit reached)"
              )
          case "max_tokens":
              # Genau die angeforderte Anzahl an Tokens erhalten
              print(
                  f"Generated {response.usage.output_tokens} tokens (max_tokens reached)"
              )
          case _:
              # Natürlicher Abschluss
              print(
                  f"Generated {response.usage.output_tokens} tokens (natural completion)"
              )

      return next((block.text for block in response.content if block.type == "text"), "")
  ```

  ```typescript TypeScript
  async function getMaxPossibleTokens(client: Anthropic, prompt: string): Promise<string> {
    const response = await client.beta.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 20000,
      messages: [{ role: "user", content: prompt }]
    });

    const tokens = response.usage.output_tokens;
    switch (response.stop_reason) {
      case "model_context_window_exceeded":
        // Maximal mögliche Anzahl an Tokens für die Eingabegröße erhalten
        console.log(`Generated ${tokens} tokens (context limit reached)`);
        break;
      case "max_tokens":
        // Genau die angeforderte Anzahl an Tokens erhalten
        console.log(`Generated ${tokens} tokens (max_tokens reached)`);
        break;
      default:
        // Natürlicher Abschluss
        console.log(`Generated ${tokens} tokens (natural completion)`);
    }

    const textBlock = response.content.find(
      (block): block is Anthropic.Beta.BetaTextBlock => block.type === "text"
    );
    return textBlock?.text ?? "";
  }
  ```

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

  static async Task<string> GetMaxPossibleTokens(AnthropicClient client, string prompt)
  {
      var response = await client.Beta.Messages.Create(new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 20000,
          Messages = [new() { Role = Role.User, Content = prompt }]
      });

      var tokens = response.Usage.OutputTokens;
      var reason = response.StopReason?.Value();
      if (reason == BetaStopReason.ModelContextWindowExceeded)
      {
          // Maximal mögliche Anzahl an Tokens für die Eingabegröße erhalten
          Console.WriteLine($"Generated {tokens} tokens (context limit reached)");
      }
      else if (reason == BetaStopReason.MaxTokens)
      {
          // Genau die angeforderte Anzahl an Tokens erhalten
          Console.WriteLine($"Generated {tokens} tokens (max_tokens reached)");
      }
      else
      {
          // Natürlicher Abschluss
          Console.WriteLine($"Generated {tokens} tokens (natural completion)");
      }

      return response.Content.Select(b => b.Value).OfType<BetaTextBlock>().FirstOrDefault()?.Text ?? "";
  }
  ```

  ```go Go
  func getMaxPossibleTokens(client anthropic.Client, prompt string) (string, error) {
  	response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 20000,
  		Messages: []anthropic.BetaMessageParam{
  			anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(prompt)),
  		},
  	})
  	if err != nil {
  		return "", err
  	}

  	tokens := response.Usage.OutputTokens
  	switch response.StopReason {
  	case anthropic.BetaStopReasonModelContextWindowExceeded:
  		// Maximal mögliche Token-Anzahl für die Eingabegröße erhalten
  		fmt.Printf("Generated %d tokens (context limit reached)\n", tokens)
  	case anthropic.BetaStopReasonMaxTokens:
  		// Genau die angeforderte Token-Anzahl erhalten
  		fmt.Printf("Generated %d tokens (max_tokens reached)\n", tokens)
  	default:
  		// Natürlicher Abschluss
  		fmt.Printf("Generated %d tokens (natural completion)\n", tokens)
  	}

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

  ```java Java
  import com.anthropic.models.beta.messages.BetaContentBlock;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaStopReason;
  import com.anthropic.models.beta.messages.MessageCreateParams;

  static String getMaxPossibleTokens(AnthropicClient client, String prompt) {
      BetaMessage response = client.beta().messages().create(
          MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(20000L)
              .addUserMessage(prompt)
              .build()
      );

      long tokens = response.usage().outputTokens();
      BetaStopReason reason = response.stopReason().orElse(BetaStopReason.END_TURN);
      if (reason.equals(BetaStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED)) {
          // Maximal mögliche Anzahl an Tokens für die Eingabegröße erhalten
          IO.println("Generated " + tokens + " tokens (context limit reached)");
      } else if (reason.equals(BetaStopReason.MAX_TOKENS)) {
          // Genau die angeforderte Anzahl an Tokens erhalten
          IO.println("Generated " + tokens + " tokens (max_tokens reached)");
      } else {
          // Natürlicher Abschluss
          IO.println("Generated " + tokens + " tokens (natural completion)");
      }

      return response.content().stream()
          .filter(BetaContentBlock::isText)
          .findFirst()
          .map(block -> block.asText().text())
          .orElse("");
  }
  ```

  ```php PHP
  function get_max_possible_tokens(Client $client, string $prompt): string
  {
      $response = $client->beta->messages->create(
          maxTokens: 20000,
          messages: [['role' => 'user', 'content' => $prompt]],
          model: 'claude-opus-5-5',
      );

      $tokens = $response->usage->outputTokens;
      echo match ($response->stopReason) {
          // Maximal mögliche Anzahl an Tokens für die Eingabegröße erhalten
          'model_context_window_exceeded' => "Generated {$tokens} tokens (context limit reached)",
          // Genau die angeforderte Anzahl an Tokens erhalten
          'max_tokens' => "Generated {$tokens} tokens (max_tokens reached)",
          // Natürlicher Abschluss
          default => "Generated {$tokens} tokens (natural completion)",
      }, PHP_EOL;

      return array_find($response->content, static fn ($block): bool => $block->type === 'text')?->text ?? '';
  }
  ```

  ```ruby Ruby
  def get_max_possible_tokens(client, prompt)
    response = client.beta.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 20000,
      messages: [{ role: "user", content: prompt }]
    )

    tokens = response.usage.output_tokens
    case response.stop_reason
    when :model_context_window_exceeded
      # Maximal mögliche Tokens für die Eingabegröße erhalten
      puts "Generated #{tokens} tokens (context limit reached)"
    when :max_tokens
      # Genau die angeforderten Tokens erhalten
      puts "Generated #{tokens} tokens (max_tokens reached)"
    else
      # Natürlicher Abschluss
      puts "Generated #{tokens} tokens (natural completion)"
    end

    response.content.find { it.type == :text }.text
  end
  ```
</CodeGroup>

## Nächste Schritte

<CardGroup cols={2}>
  <Card title="Ablehnungen und Fallback" icon="arrows-clockwise" href="https://platform.claude.com/docs/de/build-with-claude/refusals-and-fallback">
    Versuche abgelehnte Anfragen auf einem Fallback-Modell erneut, serverseitig oder in deinem Client.
  </Card>

  <Card title="Tool Runner (SDK)" icon="wrench" href="https://platform.claude.com/docs/de/agents-and-tools/tool-use/tool-runner">
    Lass das SDK die `tool_use`-Schleife, die Ergebnisformatierung und erneute Versuche für dich verwalten.
  </Card>

  <Card title="Streaming von Nachrichten" icon="lightning" href="https://platform.claude.com/docs/de/build-with-claude/streaming">
    Lies `stop_reason` beim Streaming aus dem `message_delta`-Event.
  </Card>

  <Card title="Fehler" icon="info" href="https://platform.claude.com/docs/de/api/errors">
    Behandle 4xx- und 5xx-HTTP-Fehler, die sich von Stop-Gründen unterscheiden.
  </Card>
</CardGroup>
