---
title: Recusas e fallback
url: https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback
description: Como os modelos Claude Fable, os modelos Claude Opus, o Claude Sonnet 5.5 e o Claude Haiku 5.5 retornam recusas de classificadores e como tentar novamente solicitações recusadas em um modelo de fallback.
---

Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 e Claude Haiku 5.5 incluem "safety classifiers" (classificadores de segurança) que podem recusar uma solicitação. Quando isso acontece, você recebe uma resposta normal, não um erro, com `stop_reason: "refusal"`. O `stop_details.category` dessa resposta indica a área de política (consulte [Como é uma recusa](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#refusal-response)). Normalmente, você ainda pode obter uma resposta enviando a mesma solicitação para outro modelo Claude. Esta página mostra como reconhecer uma "refusal" (recusa) e como configurar essa nova tentativa.

Leia esta página quando você desenvolver sobre qualquer um desses modelos e quiser que requisições recusadas passem automaticamente para outro modelo. Ela também se aplica quando você viu `"refusal"` em uma resposta e quer saber o que fazer em seguida.

Páginas relacionadas:

* [Motivos de parada e fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/handling-stop-reasons): a lista completa de valores de `stop_reason`.
* [Crédito de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit): como evitar pagar o custo do cache de prompt duas vezes quando você mesmo constrói a nova tentativa.
* [Middleware do SDK](https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/middleware): o helper do SDK que encapsula tudo isso.
* [Cookbook de fallback e cobrança](https://platform.claude.com/cookbook/fable-5-fallback-billing-guide): um exemplo completo de ponta a ponta.

A configuração mais simples, em beta na Claude API: defina `fallbacks` como `"default"`, e a API repete uma requisição recusada no modelo de "fallback" (modelo alternativo) que a Anthropic recomenda para a categoria da recusa. Para categorias sem fallback recomendado, a recusa permanece. O Claude Haiku 5.5 não tem fallback do lado do servidor, então, para ele, use [fallback do lado do cliente com o middleware do SDK](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#client-side-fallback) ou [escreva você mesmo a nova tentativa](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#manual-retry).

<CodeGroup>
  ```bash cURL
  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 "anthropic-beta: server-side-fallback-2026-07-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5",
      "max_tokens": 1024,
      "fallbacks": "default",
      "messages": [{"role": "user", "content": "Hello, Claude"}]
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --model claude-fable-5 \
    --max-tokens 1024 \
    --message '{"role":"user","content":"Hello, Claude"}' \
    --fallbacks default \
    --beta server-side-fallback-2026-07-01
  ```

  ```python Python
  client = Anthropic()

  response = client.beta.messages.create(
      model="claude-fable-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Hello, Claude"}],
      fallbacks="default",
      betas=["server-side-fallback-2026-07-01"],
  )
  print(response.model)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello, Claude" }],
    fallbacks: "default",
    betas: ["server-side-fallback-2026-07-01"]
  });
  console.log(response.model);
  ```

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

  BetaMessage response = await client.Beta.Messages.Create(
      new()
      {
          Model = Messages::Model.ClaudeFable5,
          MaxTokens = 1024,
          Messages = [new() { Content = "Hello, Claude", Role = Role.User }],
          Fallbacks = new Default(),
          Betas = [AnthropicBeta.ServerSideFallback2026_07_01],
      }
  );

  Console.WriteLine(response.Model.Raw());
  ```

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

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5,
  	MaxTokens: 1024,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  	},
  	Fallbacks: anthropic.BetaFallbacksParamOfDefault(),
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaServerSideFallback2026_07_01},
  })
  if err != nil {
  	panic(err)
  }

  fmt.Println(response.Model)
  ```

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

  BetaMessage response = client.beta().messages().create(MessageCreateParams.builder()
      .model(Model.CLAUDE_FABLE_5)
      .maxTokens(1024L)
      .addUserMessage("Hello, Claude")
      .fallbacksDefault()
      .addBeta(AnthropicBeta.SERVER_SIDE_FALLBACK_2026_07_01)
      .build());

  IO.println(response.model().asString());
  ```

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

  $response = $client->beta->messages->create(
      model: 'claude-fable-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      fallbacks: 'default',
      betas: ['server-side-fallback-2026-07-01'],
  );

  echo $response->model, PHP_EOL;
  ```

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

  response = client.beta.messages.create(
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}],
    fallbacks: :default,
    betas: ["server-side-fallback-2026-07-01"]
  )

  puts response.model
  ```
</CodeGroup>

As seções a seguir abordam o que uma resposta de recusa contém, quando usar fallback do lado do servidor ou do lado do cliente, e como cada um é cobrado.

## Como é uma recusa

Uma recusa é uma resposta HTTP 200 bem-sucedida com `stop_reason: "refusal"`:

```json
{
  "id": "msg_01XFUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "model": "claude-fable-5",
  "content": [],
  "stop_reason": "refusal",
  "stop_details": {
    "type": "refusal",
    "category": "cyber",
    "explanation": "This request was declined because it could enable cyber harm."
  },
  "usage": {
    "input_tokens": 412,
    "output_tokens": 0
  }
}
```

O objeto `stop_details` explica a recusa:

* **`category`:** nomeia a área de política que acionou o classificador.
* **`explanation`:** uma descrição legível por humanos. O texto não é estável, portanto exiba-o em vez de analisá-lo.
* **`recommended_model`:** presente apenas em requisições que definem `fallbacks` ([fallback do lado do servidor](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#server-side-fallback), beta). Ele nomeia um modelo para repetir diretamente quando a API pulou a tentativa de fallback (por exemplo, o modelo de fallback estava com limite de taxa atingido), e é `null` caso contrário. É uma sugestão, não uma garantia.
* `category` e `explanation` são ambos `null` quando a recusa não corresponde a uma categoria nomeada. Esse `null` é um valor normal e permanente, não um placeholder.
* O próprio `stop_details` é `null` para todos os motivos de parada que não sejam `refusal`.

| `category`               | O que significa                                                                                                                                                                                                                                                                                                                                                                                                      | Cobrado antes de qualquer saída |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| `"cyber"`                | A requisição poderia viabilizar danos cibernéticos, como desenvolvimento de malware ou exploits. Trabalho benigno de cibersegurança também pode acionar esta categoria.                                                                                                                                                                                                                                              | Não                             |
| `"bio"`                  | A requisição poderia viabilizar danos biológicos, como métodos laboratoriais perigosos. Trabalho benéfico em ciências da vida também pode acionar esta categoria.                                                                                                                                                                                                                                                    | Sim                             |
| `"frontier_llm"`         | A requisição poderia auxiliar o desenvolvimento de modelos de IA concorrentes, o que é restrito pelos [termos comerciais da Anthropic](https://www.anthropic.com/legal/commercial-terms). Trabalho benigno de aprendizado de máquina também pode acionar esta categoria.                                                                                                                                             | Sim                             |
| `"reasoning_extraction"` | A requisição pede que o modelo reproduza seu raciocínio interno no texto da resposta. Para obter o raciocínio em formato estruturado, use o [pensamento adaptativo](https://platform.claude.com/docs/pt-BR/build-with-claude/thinking). Consulte [Mantenha o raciocínio nos blocos de pensamento](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks). | Sim                             |
| `"general_harms"`        | A requisição se enquadra em uma área da política de uso fora das quatro categorias nomeadas. Trabalho benigno também pode acionar esta categoria.                                                                                                                                                                                                                                                                    | Não                             |

Uma recusa pode chegar antes de qualquer saída, ou no meio do stream após saída parcial. Em ambos os casos, trate qualquer saída parcial como incompleta e descarte-a.

### Mantenha o raciocínio nos blocos de pensamento

Uma recusa `reasoning_extraction` geralmente vem de um prompt que pede ao modelo para colocar seu pensamento ou raciocínio na saída, seja literalmente ou em um formato fixo. Exemplos comuns:

* Uma seção `<thinking>`, `<reasoning>` ou de rascunho que o modelo preenche antes de responder
* Um campo `reasoning`, `thinking` ou `trace` na saída JSON ou em uma entrada de ferramenta
* As anotações privadas do modelo ou um registro contínuo do seu raciocínio
* Raciocínio solicitado literalmente ou na íntegra

Essa redação pode estar em um prompt do sistema, em uma skill ou na descrição de uma ferramenta, então verifique esses pontos também.

Você ainda pode pedir ao Claude que explique sua resposta. Peça uma explicação curta, as evidências por trás de um resultado ou um resumo das ações que ele executou. Para ver como o modelo raciocinou, defina `display: "summarized"` e leia os [blocos `thinking`](https://platform.claude.com/docs/pt-BR/build-with-claude/thinking#summarized-thinking). Esta categoria não tem modelo de fallback recomendado, então altere o prompt em vez de tentar a requisição novamente. Se uma requisição reformulada ainda for recusada, [entre em contato com o suporte](https://support.claude.com/en/articles/9015913-how-to-get-support) e inclua o [ID da solicitação](https://platform.claude.com/docs/pt-BR/api/errors#request-id).

## Como as recusas são cobradas

Estas regras de cobrança se aplicam a todas as plataformas: Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud e Microsoft Foundry.

**Recusas antes de qualquer saída:** para dificultar tentativas de contornar as salvaguardas da Anthropic em escala, uma recusa que chega antes de qualquer saída é cobrada quando seu `stop_details.category` é `"bio"`, `"frontier_llm"` ou `"reasoning_extraction"`. Essas são as categorias em que a Anthropic mede baixos volumes de falsos positivos, em setembro de 2026. Essas recusas são cobradas como qualquer outra requisição, às taxas do modelo que a executou. Uma recusa antes de qualquer saída em qualquer outra categoria, ou com categoria `null`, não é cobrada. Em ambos os casos, `content` está vazio e as contagens de tokens aparecem em `usage`. A requisição ainda conta para seus limites de taxa.

**Recusas no meio do stream:** uma recusa no meio do stream cobra os tokens de entrada e a saída já transmitida via streaming às taxas normais.

**Fallback:** quando você usa fallback, a recusa que o acionou é cobrada, além da requisição de fallback, quando chegou no meio do stream ou está em uma das categorias cobradas. O [crédito de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit) compensa a falha de cache de prompt da requisição de fallback, para que você não pague para armazenar a conversa em cache duas vezes. Uma recusa do Claude Haiku 5.5 não gera crédito de fallback, então um fallback após ela paga o custo total de gravar o cache de prompt do modelo de fallback. Para saber como o fallback do lado do servidor relata cada tentativa, consulte [Cobrança e limites de taxa](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#billing-and-rate-limits).

As categorias cobradas podem mudar à medida que a Anthropic continua medindo e refinando as taxas de falsos positivos de suas salvaguardas. A coluna **Cobrado antes de qualquer saída** na [tabela de categorias de recusa](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#refusal-response) lista as categorias cobradas.

## Escolhendo uma abordagem de fallback

Há três maneiras de repetir uma requisição recusada em outro modelo. A correta depende de onde você está executando e de quanto controle você precisa.

| Sua situação                                        | Use                                                                                                                                                                                                                          | Por quê                                                                      |
| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Claude API, configuração mais simples               | [Fallback do lado do servidor](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#server-side-fallback)                                                                                          | Uma requisição, uma resposta. A API cuida da nova tentativa.                 |
| Qualquer plataforma, usando um SDK da Anthropic     | [O middleware do SDK](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#client-side-fallback)                                                                                                   | Configure uma vez no cliente. As novas tentativas acontecem automaticamente. |
| HTTP puro ou lógica de nova tentativa personalizada | [Uma nova tentativa manual](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#manual-retry) com [crédito de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit) | Controle total. O crédito de fallback mantém o custo baixo.                  |

O fallback do lado do servidor e o middleware do SDK aplicam o crédito de fallback para você. Você só precisa da página [Crédito de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit) quando você mesmo cria a nova tentativa. O Claude Haiku 5.5 não tem fallback do lado do servidor nem crédito de fallback, então use o middleware do SDK ou uma nova tentativa manual.

## Fallback do lado do servidor

O fallback do lado do servidor repete uma requisição recusada dentro de uma única chamada de API. No modo padrão, quando o modelo primário recusa e a categoria de recusa tem um fallback recomendado, a API executa a mesma requisição no modelo que a Anthropic recomenda para essa categoria. Em vez disso, você pode [nomear até três modelos de fallback próprios](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#naming-your-own-fallback-models). De qualquer forma, você recebe de volta uma resposta que nomeia o modelo que respondeu, de modo que seu usuário obtém uma resposta em uma única ida e volta.

<Note>
  O fallback do lado do servidor está em beta na Claude API. O parâmetro `fallbacks` não é suportado na [Message Batches API](https://platform.claude.com/docs/pt-BR/build-with-claude/batch-processing) (um item de lote que o inclui retorna como resultado com erro) e não está disponível no Amazon Bedrock, Google Cloud ou Microsoft Foundry. Nessas plataformas, use o [fallback do lado do cliente com o middleware do SDK](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#client-side-fallback). O Claude Haiku 5.5 não tem fallback do lado do servidor: com `fallbacks: "default"`, uma requisição recusada permanece recusada, e uma lista de modelos de fallback retorna um erro 400.
</Note>

### Fazendo a requisição

Defina o parâmetro `fallbacks` como a string `"default"` e envie o cabeçalho beta `server-side-fallback-2026-07-01`. A API então aplica o roteamento padrão definido pelo servidor para o modelo solicitado, que seleciona um modelo de fallback recomendado com base na categoria de recusa que o classificador reporta, de modo que requisições recusadas sejam atendidas sem que você precise manter uma lista de modelos à medida que as recomendações mudam.

O roteamento padrão nunca provoca a [rejeição antecipada de imagem superdimensionada](https://platform.claude.com/docs/pt-BR/build-with-claude/vision-coordinates#oversized-image-error) para modelos que você não escolheu: um modelo roteado que redimensionaria uma imagem marcada com `"oversized_image": "error"` é removido do roteamento, de modo que uma imagem marcada nunca é servida redimensionada.

<CodeGroup>
  ```bash cURL
  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 "anthropic-beta: server-side-fallback-2026-07-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5",
      "max_tokens": 1024,
      "fallbacks": "default",
      "messages": [{"role": "user", "content": "Hello, Claude"}]
    }' |
    jq -c '{
      stop_reason,
      model,
      # Uma entrada fallback_message em usage.iterations indica que um modelo de fallback foi executado;
      # combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
      served_by_fallback: (
        any(.usage.iterations[]?; .type == "fallback_message")
        and .stop_reason != "refusal"
      )
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --model claude-fable-5 \
    --max-tokens 1024 \
    --message '{"role":"user","content":"Hello, Claude"}' \
    --fallbacks default \
    --beta server-side-fallback-2026-07-01 \
    --format json |
    jq -c '{
      stop_reason,
      model,
      # Uma entrada fallback_message em usage.iterations indica que um modelo de fallback foi executado;
      # combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
      served_by_fallback: (
        any(.usage.iterations[]?; .type == "fallback_message")
        and .stop_reason != "refusal"
      )
    }'
  ```

  ```python Python
  client = Anthropic()

  response = client.beta.messages.create(
      model="claude-fable-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Hello, Claude"}],
      fallbacks="default",
      betas=["server-side-fallback-2026-07-01"],
  )

  # Uma entrada fallback_message em usage.iterations indica que um modelo de fallback foi executado;
  # combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
  fallback_ran = any(
      iteration.type == "fallback_message"
      for iteration in response.usage.iterations or []
  )
  served_by_fallback = fallback_ran and response.stop_reason != "refusal"

  print(
      json.dumps(
          {
              "stop_reason": response.stop_reason,
              "model": response.model,
              "served_by_fallback": served_by_fallback,
          }
      )
  )
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello, Claude" }],
    fallbacks: "default",
    betas: ["server-side-fallback-2026-07-01"]
  });

  // Uma entrada fallback_message em usage.iterations indica que um modelo de fallback foi executado;
  // combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
  const { stop_reason, model, usage } = response;
  const servedByFallback =
    (usage.iterations ?? []).some((entry) => entry.type === "fallback_message") &&
    stop_reason !== "refusal";

  console.log(
    JSON.stringify({
      stop_reason,
      model,
      served_by_fallback: servedByFallback
    })
  );
  ```

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

  var response = await client.Beta.Messages.Create(
      new()
      {
          Model = Messages::Model.ClaudeFable5,
          MaxTokens = 1024,
          Messages =
          [
              new() { Content = "Hello, Claude", Role = Role.User },
          ],
          Fallbacks = new Default(),
          Betas = [AnthropicBeta.ServerSideFallback2026_07_01],
      }
  );

  // Uma entrada fallback_message em usage.iterations indica que um modelo de fallback foi executado;
  // combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
  bool fallbackRan = (response.Usage.Iterations ?? []).Any(iteration =>
      iteration.TryPickBetaFallbackMessageIterationUsage(out _)
  );
  bool servedByFallback =
      fallbackRan && response.StopReason?.Value() != BetaStopReason.Refusal;

  Console.WriteLine(
      JsonSerializer.Serialize(
          new
          {
              stop_reason = response.StopReason?.Raw(),
              model = response.Model.Raw(),
              served_by_fallback = servedByFallback,
          }
      )
  );
  ```

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

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5,
  	MaxTokens: 1024,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  	},
  	Fallbacks: anthropic.BetaFallbacksParamOfDefault(),
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaServerSideFallback2026_07_01},
  })
  if err != nil {
  	panic(err)
  }

  // Uma entrada fallback_message em usage.iterations indica que um modelo de fallback foi executado;
  // combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
  fallbackRan := slices.ContainsFunc(
  	response.Usage.Iterations,
  	func(iteration anthropic.BetaIterationsUsageItemUnion) bool {
  		_, isFallback := iteration.AsAny().(anthropic.BetaFallbackMessageIterationUsage)
  		return isFallback
  	},
  )
  servedByFallback := fallbackRan && response.StopReason != anthropic.BetaStopReasonRefusal

  summary, err := json.Marshal(struct {
  	StopReason       anthropic.BetaStopReason `json:"stop_reason"`
  	Model            anthropic.Model          `json:"model"`
  	ServedByFallback bool                     `json:"served_by_fallback"`
  }{response.StopReason, response.Model, servedByFallback})
  if err != nil {
  	panic(err)
  }
  fmt.Println(string(summary))
  ```

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

  BetaMessage response = client.beta().messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5)
          .maxTokens(1024L)
          .addUserMessage("Hello, Claude")
          .fallbacksDefault()
          .addBeta(AnthropicBeta.SERVER_SIDE_FALLBACK_2026_07_01)
          .build()
  );

  // Uma entrada de uso fallback_message significa que um modelo de fallback produziu a
  // resposta; um stop_reason de recusa significa que nenhum modelo a atendeu.
  List<BetaUsage.Iteration> iterations =
      response.usage().iterations().orElse(List.of());
  boolean servedByFallback =
      iterations.stream().anyMatch(BetaUsage.Iteration::isFallbackMessage)
          && response.stopReason().filter(BetaStopReason.REFUSAL::equals).isEmpty();

  IO.println("""
      {"stop_reason":"%s","model":"%s","served_by_fallback":%b}\
      """.formatted(
          response.stopReason().map(BetaStopReason::asString).orElse("null"),
          response.model().asString(),
          servedByFallback));
  ```

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

  $response = $client->beta->messages->create(
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      model: 'claude-fable-5',
      fallbacks: 'default',
      betas: ['server-side-fallback-2026-07-01'],
  );

  // Uma entrada fallback_message em usage.iterations significa que um modelo de fallback foi executado;
  // combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
  $iterations = $response->usage->iterations ?? [];
  $servedByFallback = array_any($iterations, fn($entry) => $entry->type === 'fallback_message')
      && $response->stopReason !== 'refusal';

  echo json_encode([
      'stop_reason' => $response->stopReason,
      'model' => $response->model,
      'served_by_fallback' => $servedByFallback,
  ]), PHP_EOL;
  ```

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

  response = client.beta.messages.create(
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}],
    fallbacks: :default,
    betas: ["server-side-fallback-2026-07-01"]
  )

  # Uma entrada fallback_message em usage.iterations indica que um modelo de fallback foi executado;
  # combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
  iterations = response.usage.iterations || []
  served_by_fallback = iterations.any? { it.type == :fallback_message } &&
    response.stop_reason != :refusal

  stop_reason = response.stop_reason
  model = response.model
  puts JSON.generate({stop_reason:, model:, served_by_fallback:})
  ```
</CodeGroup>

A Anthropic define salvaguardas para cada modelo individualmente e para cada categoria de política, de acordo com a capacidade do modelo: dependendo da categoria, uma requisição sinalizada pode recorrer a um modelo menos capaz ou ser recusada. O modo `"default"` codifica essas recomendações por modelo e por categoria para você, de modo que uma requisição recusada é repetida no modelo que a Anthropic recomenda para essa categoria. Os fallbacks são visíveis de qualquer forma: a resposta nomeia o modelo que a atendeu, e o bloco de conteúdo `fallback` marca a transferência.

O roteamento é aplicado do lado do servidor e não é publicado por modelo na [Models API](https://platform.claude.com/docs/pt-BR/api/models/list). Para ver qual modelo atendeu uma requisição recusada, verifique o campo `model` de nível superior da resposta e procure uma entrada `fallback_message` em `usage.iterations`, como fazem os exemplos desta página.

Apenas uma recusa do classificador de segurança aciona o fallback. Um limite de taxa, sobrecarga ou erro de servidor no modelo solicitado é retornado a você como está.

<Note>
  O cabeçalho beta deve conter exatamente a data `2026-07-01`, que suporta tanto `"default"` quanto a forma de lista explícita, ou `2026-06-01`, que aceita apenas a forma de lista explícita. Sob qualquer outro valor `server-side-fallback-*`, o parâmetro `fallbacks` é rejeitado com um erro 400. Se você desenvolveu com base em uma prévia anterior deste recurso, atualize o cabeçalho beta e os formatos de requisição e resposta juntos para os desta página.
</Note>

### Nomeando seus próprios modelos de fallback

Em vez do roteamento padrão, você pode definir `fallbacks` como uma lista de até três modelos. Quando o modelo solicitado recusa, a API executa o próximo modelo da cadeia na mesma requisição. Use esta forma quando quiser controlar exatamente quais modelos atendem requisições recusadas, como fixar um modelo que sua aplicação qualificou.

Modelos de fallback nomeados contam para a [verificação de imagem superdimensionada](https://platform.claude.com/docs/pt-BR/build-with-claude/vision-coordinates#oversized-image-error): uma requisição cujo bloco de imagem define `"oversized_image": "error"` é verificada antecipadamente em relação ao modelo solicitado e a cada fallback nomeado, é rejeitada se qualquer um deles redimensionaria essa imagem, e o alvo de redimensionamento reportado na rejeição serve para todos eles.

As linhas destacadas são a única diferença em relação à requisição de roteamento padrão.

<CodeGroup>
  ```bash cURL
  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 "anthropic-beta: server-side-fallback-2026-07-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5",
      "max_tokens": 1024,
      "fallbacks": [{"model": "claude-opus-4-8"}],
      "messages": [{"role": "user", "content": "Hello, Claude"}]
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --model claude-fable-5 \
    --max-tokens 1024 \
    --message '{"role":"user","content":"Hello, Claude"}' \
    --fallbacks '[{"model":"claude-opus-4-8"}]' \
    --beta server-side-fallback-2026-07-01
  ```

  ```python Python
  client = Anthropic()

  response = client.beta.messages.create(
      model="claude-fable-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Hello, Claude"}],
      fallbacks=[{"model": "claude-opus-4-8"}],
      betas=["server-side-fallback-2026-07-01"],
  )
  print(response.model)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello, Claude" }],
    fallbacks: [{ model: "claude-opus-4-8" }],
    betas: ["server-side-fallback-2026-07-01"]
  });
  console.log(response.model);
  ```

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

  BetaMessage response = await client.Beta.Messages.Create(
      new()
      {
          Model = Messages::Model.ClaudeFable5,
          MaxTokens = 1024,
          Messages = [new() { Content = "Hello, Claude", Role = Role.User }],
          Fallbacks = new([new(Messages::Model.ClaudeOpus4_8)]),
          Betas = [AnthropicBeta.ServerSideFallback2026_07_01],
      }
  );

  Console.WriteLine(response.Model.Raw());
  ```

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

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5,
  	MaxTokens: 1024,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  	},
  	Fallbacks: anthropic.BetaFallbacksParamUnion{
  		OfBetaFallbackArray: []anthropic.BetaFallbackParam{{Model: anthropic.ModelClaudeOpus4_8}},
  	},
  	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaServerSideFallback2026_07_01},
  })
  if err != nil {
  	panic(err)
  }

  fmt.Println(response.Model)
  ```

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

  BetaMessage response = client.beta().messages().create(MessageCreateParams.builder()
      .model(Model.CLAUDE_FABLE_5)
      .maxTokens(1024L)
      .addUserMessage("Hello, Claude")
      .fallbacksOfFallbackParams(List.of(BetaFallbackParam.builder()
          .model(Model.CLAUDE_OPUS_4_8)
          .build()))
      .addBeta(AnthropicBeta.SERVER_SIDE_FALLBACK_2026_07_01)
      .build());

  IO.println(response.model().asString());
  ```

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

  $response = $client->beta->messages->create(
      model: 'claude-fable-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      fallbacks: [['model' => 'claude-opus-4-8']],
      betas: ['server-side-fallback-2026-07-01'],
  );

  echo $response->model, PHP_EOL;
  ```

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

  response = client.beta.messages.create(
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}],
    fallbacks: [{model: "claude-opus-4-8"}],
    betas: ["server-side-fallback-2026-07-01"]
  )

  puts response.model
  ```
</CodeGroup>

Algumas regras se aplicam à lista `fallbacks`:

* As entradas são tentadas em ordem. Cada uma deve ser diferente das outras entradas e do modelo solicitado.
* Cada entrada deve ser um dos destinos permitidos do modelo solicitado. Com o cabeçalho beta definido, essa lista é publicada como `allowed_fallback_models` na entrada do modelo na [Models API](https://platform.claude.com/docs/pt-BR/api/models/list).
* Cada entrada indica um `model` e pode substituir `max_tokens`, `thinking`, `output_config` e `speed` apenas para aquela tentativa.
* A solicitação deve ser válida como solicitação direta para cada modelo nomeado. Se um modelo de fallback não suportar um recurso que a solicitação usa, a API rejeita a solicitação antecipadamente. Com o cabeçalho `2026-07-01`, `thinking: {"type": "between_tools"}` é a exceção: quando uma solicitação ao Claude Sonnet 5.5 recorre ao Claude Sonnet 5, a tentativa de fallback é executada com `thinking: {"type": "disabled"}` e `display: "omitted"`. Com `2026-06-01`, defina `thinking` na entrada do Claude Sonnet 5, ou a solicitação será rejeitada antecipadamente.
* Assim como no modo padrão, somente uma recusa de um classificador de segurança aciona o fallback. Um limite de taxa, sobrecarga ou erro de servidor no modelo solicitado é retornado a você como está.
* Se um modelo de fallback atingir o limite de taxa ou estiver sobrecarregado, a tentativa de fallback não é feita e a recusa anterior é retornada. O `stop_details.recommended_model` da recusa então indica um modelo para repetir diretamente. Dimensione os limites de taxa do modelo de fallback para o volume de recusas que você espera, ou os fallbacks se degradarão em recusas sob carga.

A resposta tem o mesmo formato em ambos os modos: o modelo que atendeu o turno aparece no campo `model` de nível superior, um bloco de conteúdo `fallback` marca a transferência, e `usage.iterations` registra cada tentativa.

### O que a resposta contém

A resposta se parece com qualquer outra mensagem, com duas adições:

* O campo `model` de nível superior reporta o modelo que produziu a mensagem retornada, seja o modelo solicitado ou um fallback.

* Um bloco de conteúdo `fallback` marca cada ponto em `content` onde a saída de um modelo dá lugar à do próximo: `{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}`.

  * `from.model` ecoa a string de modelo que você enviou quando o salto que recusa é o modelo solicitado.
  * `to.model` é sempre o ID resolvido do modelo que continua.

Em uma recusa antes de qualquer saída, o bloco `fallback` é o primeiro bloco de conteúdo. Por exemplo, quando o roteamento padrão seleciona Claude Opus 4.8 para a categoria da recusa:

```json
{
  "id": "msg_01XFUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-4-8",
  "content": [
    {
      "type": "fallback",
      "from": { "model": "claude-fable-5" },
      "to": { "model": "claude-opus-4-8" }
    },
    { "type": "text", "text": "Hi! How can I help you today?" }
  ],
  "stop_reason": "end_turn",
  "stop_details": null,
  "usage": {
    "input_tokens": 412,
    "output_tokens": 264,
    "cache_read_input_tokens": 0,
    "cache_creation_input_tokens": 0,
    "iterations": [
      {
        "type": "message",
        "model": "claude-fable-5",
        "input_tokens": 535,
        "output_tokens": 0,
        "cache_read_input_tokens": 0,
        "cache_creation_input_tokens": 0
      },
      {
        "type": "fallback_message",
        "model": "claude-opus-4-8",
        "input_tokens": 412,
        "output_tokens": 264,
        "cache_read_input_tokens": 0,
        "cache_creation_input_tokens": 0
      }
    ]
  }
}
```

O array `usage.iterations` registra cada tentativa. Um modelo que recusou aparece como uma entrada `message` comum, e o modelo que atendeu o turno aparece como uma entrada `fallback_message`. Se todos os modelos da cadeia recusarem, a resposta é a recusa do último modelo, com uma entrada `message` para cada salto anterior e uma entrada `fallback_message` para o último.

O [roteamento persistente](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#sticky-routing) pode enviar um turno posterior diretamente para o modelo de fallback. Tal turno não carrega nenhum bloco de conteúdo `fallback`, porque nenhum modelo recusou aquele turno. Identifique-o pela entrada `fallback_message` em `usage.iterations`, pela ausência de uma entrada `message` para o modelo solicitado e pelo campo `model` da resposta.

### Continuando a conversa

No próximo turno, envie o conteúdo do assistente de volta como você o recebeu. Após um fallback no meio da saída, `content` pode incluir tipos de bloco que o modelo que recusou produziu antes da transferência. A tabela a seguir indica quais manter e quais descartar quando você ecoa o turno.

| Tipo de bloco                                                                       | No próximo turno                                                                                                                                                                                                                                  |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fallback`                                                                          | Mantenha-o exatamente onde apareceu. A API usa sua posição para validar os blocos de pensamento ao redor dele, portanto uma requisição que ecoa blocos de pensamento de ambos os lados da fronteira é rejeitada se o bloco for omitido ou movido. |
| `text`                                                                              | Mantenha.                                                                                                                                                                                                                                         |
| Qualquer bloco após o bloco `fallback` final                                        | Mantenha.                                                                                                                                                                                                                                         |
| `thinking`, `redacted_thinking` ou `connector_text` antes do bloco `fallback` final | Descarte.                                                                                                                                                                                                                                         |
| `tool_use` do lado do cliente antes do bloco `fallback` final                       | Descarte.                                                                                                                                                                                                                                         |
| `server_tool_use` antes do bloco `fallback` final                                   | Mantenha quando pareado com seu resultado. Descarte quando não tiver resultado correspondente.                                                                                                                                                    |

<Note>
  Um bloco `connector_text` carrega texto de narração que algumas respostas com uso de ferramentas incluem entre chamadas de ferramentas.
</Note>

### Streaming

Em uma requisição com streaming, a nova tentativa acontece no mesmo stream, e nada do que você já recebeu é invalidado. O que você vê depende de quando a recusa acontece.

**Quando a recusa acontece antes de qualquer saída:**

* `message_start` nomeia o modelo de fallback, e o bloco `fallback` é o primeiro bloco de conteúdo.
* Como `message_start` aguarda o início da tentativa de fallback, o tempo até o primeiro byte inclui a tentativa recusada.

**Quando a recusa acontece no meio da saída:**

* O bloco de conteúdo aberto é fechado, e o bloco `fallback` (um par comum de `content_block_start` e `content_block_stop` sem deltas) marca a fronteira.
* O modelo de fallback continua a partir da saída parcial. Apenas os blocos `text` da saída parcial são passados ao modelo de fallback como contexto. Outros tipos de bloco permanecem em `content`.
* `message_start` já nomeou o modelo solicitado, portanto leia o modelo que atendeu a partir do `to.model` do bloco `fallback` e da entrada `fallback_message` em `usage.iterations` do `message_delta` final.

### Respostas sem streaming

Em uma requisição sem streaming, uma recusa no meio da saída se comporta de forma diferente: a resposta omite a saída parcial do modelo que recusou, e o modelo de fallback responde do zero. O resultado se parece com uma recusa antes de qualquer saída, com o bloco `fallback` primeiro. A tentativa recusada e seus tokens de saída ainda aparecem em `usage.iterations`.

<Note>
  **Recusas durante o uso de ferramentas:** trabalho de ferramenta concluído não bloqueia o fallback. Quando uma recusa dispara depois que ferramentas de servidor (por exemplo, busca na web ou execução de código) terminaram de executar dentro de uma requisição, a tentativa de fallback prossegue: os resultados de ferramenta concluídos são transferidos, e o modelo de fallback pode continuar invocando ferramentas de servidor. O único caso que não é repetido é uma recusa em streaming que dispara enquanto um bloco de uso de ferramenta de qualquer tipo (uma ferramenta de cliente, uma ferramenta de servidor ou uma chamada de ferramenta MCP) ainda está aberto no stream: essa recusa é retornada diretamente e, se o cabeçalho `fallback-credit-2026-07-01` estiver definido, ela ainda carrega um token de crédito resgatável ao continuar a resposta parcial. Requisições sem streaming não são afetadas; a API limpa o trabalho parcial e repete antes de responder.
</Note>

### Cobrança e limites de taxa

Cada tentativa segue as regras de [Como as recusas são cobradas](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#how-refusals-are-billed), às taxas do modelo que a executou. Uma tentativa que recusou antes de produzir qualquer saída só é cobrada quando sua categoria de recusa é cobrada, e seus tokens são reportados em sua entrada de `usage.iterations` em qualquer caso. Cada tentativa que produziu saída, incluindo uma que recusou no meio de sua resposta, é cobrada separadamente. O array `usage.iterations` é o registro por tentativa do que é cobrado de você. As contagens de `usage` de nível superior descrevem apenas a tentativa que produziu a mensagem retornada. Tokens de modelos diferentes nunca são somados em um único campo.

Cada tentativa executada, incluindo uma que recusou, conta para os limites de taxa de seu próprio modelo.

### Roteamento persistente

Depois que uma conversa recorre ao fallback, a API registra qual modelo a atendeu. Requisições posteriores para essa conversa que incluem `fallbacks` vão diretamente para esse modelo de fallback, sem executar o modelo solicitado. Isso evita pagar por uma tentativa que previsivelmente seria recusada novamente a cada turno.

Algumas propriedades da decisão de "sticky routing" (roteamento persistente):

* Ela é retida por aproximadamente 1 hora e tem escopo na sua organização.
* Ela é armazenada como um hash de conteúdo do prefixo da conversa mais o modelo que a atendeu. O conteúdo da mensagem em si não é armazenado.
* Ela é de melhor esforço, portanto seu código deve lidar com o modelo solicitado sendo tentado novamente a qualquer momento.

O roteamento persistente se aplica tanto a requisições com streaming quanto sem streaming. Em uma requisição com streaming, a decisão de roteamento é tomada antes de o stream abrir, portanto o campo `model` do evento `message_start` já carrega o ID do modelo de fallback.

## Fallback do lado do cliente com o middleware do SDK

O SDK inclui um middleware de fallback de recusa. Você o configura uma vez no cliente com sua lista de modelos de fallback. As chamadas por meio de `client.beta.messages` (csharp, go: `client.Beta.Messages`; java: `client.beta().messages()`; php: `$client->beta->messages`) então repetem automaticamente as requisições recusadas, em qualquer plataforma. O middleware também envia o cabeçalho beta `fallback-credit-2026-07-01` em cada requisição que processa, para que as novas tentativas sejam reprecificadas sem configuração por requisição. Uma recusa do Claude Haiku 5.5 não gera crédito de fallback, então uma nova tentativa após ela paga o custo total de gravar o cache de prompt do modelo de fallback.

### Configurando

Passe `BetaRefusalFallbackMiddleware` (typescript: `betaRefusalFallbackMiddleware`; go: `betafallback.BetaRefusalFallbackMiddleware`; csharp: `BetaRefusalFallbackHandler`; java: `BetaRefusalFallbackInterceptor`; php: `RefusalFallbackMiddleware`) ao construtor do cliente e compartilhe uma instância de `BetaFallbackState` entre as requisições de uma conversa.

<CodeGroup exclude="shell">
  <CodeGroupItem language="cURL">
    O middleware de fallback de recusa faz parte do Claude SDK, então uma requisição cURL não pode usá-lo. Para fazer fallback dentro de uma única requisição, use o [fallback do lado do servidor](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#server-side-fallback). Para escrever você mesmo a nova tentativa, consulte [Crédito de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit).
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    A CLI `ant` não inclui o middleware de fallback de recusa. Para fazer fallback dentro de uma única requisição, use o [fallback do lado do servidor](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#server-side-fallback). Para escrever você mesmo a nova tentativa, consulte [Crédito de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit).
  </CodeGroupItem>

  ```python Python
  from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware

  # Em caso de recusa, o middleware tenta novamente no modelo de fallback listado e
  # envia automaticamente o cabeçalho beta fallback-credit em cada requisição que processa.
  client = Anthropic(
      middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
  )

  state = BetaFallbackState()  # pins follow-ups to the model that accepted

  # Streaming: em caso de recusa, o middleware tenta novamente no modelo de fallback e
  # insere seus eventos no stream aberto.
  with (
      state,
      client.beta.messages.stream(
          max_tokens=1024,
          model="claude-fable-5",
          messages=[{"role": "user", "content": "Hello, Claude"}],
      ) as stream,
  ):
      for text in stream.text_stream:
          print(text, end="", flush=True)
      final_message = stream.get_final_message()
  print(f"\nserved by: {final_message.model}")

  # Sem streaming: reutilizar o estado mantém a conversa fixada.
  with state:
      message = client.beta.messages.create(
          max_tokens=1024,
          model="claude-fable-5",
          messages=[{"role": "user", "content": "Hello, Claude"}],
      )
  print(f"served by: {message.model}")
  ```

  ```typescript TypeScript
  import { BetaFallbackState, betaRefusalFallbackMiddleware } from "@anthropic-ai/sdk";

  // Em caso de recusa, o middleware tenta novamente no modelo de fallback listado e
  // envia automaticamente o cabeçalho beta fallback-credit em cada requisição que processa.
  const client = new Anthropic({
    middleware: [betaRefusalFallbackMiddleware([{ model: "claude-opus-4-8" }])]
  });

  // Compartilhe um único estado ao longo da conversa para que as requisições seguintes permaneçam
  // fixadas no modelo que aceitou.
  const fallbackState = new BetaFallbackState();

  // Streaming: em caso de recusa, o middleware tenta novamente no modelo de fallback e
  // insere seus eventos no stream aberto.
  const stream = client.beta.messages
    .stream(
      {
        max_tokens: 1024,
        model: "claude-fable-5",
        messages: [{ role: "user", content: "Hello, Claude" }]
      },
      { fallbackState }
    )
    .on("text", (text) => process.stdout.write(text));

  const finalMessage = await stream.finalMessage();
  console.log("\nserved by:", finalMessage.model);

  // Sem streaming: reutilizar o estado mantém a conversa fixada.
  const message = await client.beta.messages.create(
    {
      max_tokens: 1024,
      model: "claude-fable-5",
      messages: [{ role: "user", content: "Hello, Claude" }]
    },
    { fallbackState }
  );
  console.log("served by:", message.model);
  ```

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

  // Em caso de recusa, o handler tenta novamente no modelo de fallback listado e
  // envia automaticamente o cabeçalho beta fallback-credit em cada requisição que processa.
  AnthropicClient client = new()
  {
      Handlers =
      [
          new BetaRefusalFallbackHandler { Fallbacks = [new(Messages::Model.ClaudeOpus4_8)] },
      ],
  };

  // Fixa as requisições subsequentes que compartilham este estado no modelo que aceitou.
  BetaFallbackState fallbackState = BetaFallbackState.Create();

  MessageCreateParams parameters = new()
  {
      Model = Messages::Model.ClaudeFable5,
      MaxTokens = 1024,
      Messages = [new() { Content = "Hello, Claude", Role = Role.User }],
  };

  // Streaming: se o stream terminar em recusa, o handler emenda os eventos do modelo
  // de fallback no stream ainda aberto.
  BetaMessageContentAggregator aggregator = new();
  using (fallbackState.Use())
  {
      var responseUpdates = client.Beta.Messages.CreateStreaming(parameters);
      await foreach (BetaRawMessageStreamEvent rawEvent in responseUpdates.CollectAsync(aggregator))
      {
          if (
              rawEvent.TryPickContentBlockDelta(out var deltaEvent)
              && deltaEvent.Delta.TryPickText(out var textDelta)
          )
          {
              Console.Write(textDelta.Text);
          }
      }
  }
  BetaMessage streamedMessage = aggregator.Message();
  Console.WriteLine($"\nserved by: {streamedMessage.Model.Raw()}");

  // Sem streaming: reutilizar o estado mantém a conversa fixada no modelo que aceitou.
  using (fallbackState.Use())
  {
      BetaMessage message = await client.Beta.Messages.Create(parameters);
      Console.WriteLine($"served by: {message.Model.Raw()}");
  }
  ```

  ```go Go
  import (
  // ...
  	"github.com/anthropics/anthropic-sdk-go/lib/betafallback"
  // ...
  )

  func main() {
  	ctx := context.Background()

  	// O middleware tenta novamente uma requisição recusada em cada modelo de fallback,
  	// um por vez, e inclui as requisições no beta de crédito de fallback automaticamente.
  	client := anthropic.NewClient(
  		option.WithMiddleware(betafallback.BetaRefusalFallbackMiddleware(
  			[]anthropic.BetaFallbackParam{{Model: anthropic.ModelClaudeOpus4_8}},
  		)),
  	)

  	// Um estado por conversa: requisições que o compartilham ficam fixadas no
  	// modelo que aceitou, então um follow-up nunca consulta de novo um modelo que recusou.
  	state := &betafallback.BetaFallbackState{}
  	conversation := betafallback.WithBetaFallbackState(state)

  	params := anthropic.BetaMessageNewParams{
  		MaxTokens: 1024,
  		Model:     anthropic.ModelClaudeFable5,
  		Messages: []anthropic.BetaMessageParam{
  			anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  		},
  	}

  	// Streaming: em uma recusa, o middleware tenta novamente no lugar, emendando os
  	// eventos do modelo de fallback no stream aberto como uma única mensagem contínua.
  	stream := client.Beta.Messages.NewStreaming(ctx, params, conversation)
  	defer stream.Close()
  	var streamed anthropic.BetaMessage
  	for stream.Next() {
  		event := stream.Current()
  		if err := streamed.Accumulate(event); err != nil {
  			panic(err)
  		}
  		switch eventVariant := event.AsAny().(type) {
  		case anthropic.BetaRawContentBlockDeltaEvent:
  			if textDelta, ok := eventVariant.Delta.AsAny().(anthropic.BetaTextDelta); ok {
  				fmt.Print(textDelta.Text)
  			}
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  	fmt.Println("\nserved by:", streamed.Model)

  	// Sem streaming: o estado compartilhado fixa este follow-up no modelo que
  	// atendeu o turno transmitido via streaming.
  	message, err := client.Beta.Messages.New(ctx, params, conversation)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println("served by:", message.Model)
  }
  ```

  ```java Java
  import com.anthropic.client.AnthropicClient;
  import com.anthropic.client.okhttp.AnthropicOkHttpClient;
  import com.anthropic.core.RequestOptions;
  import com.anthropic.core.http.StreamResponse;
  import com.anthropic.helpers.BetaFallbackState;
  import com.anthropic.helpers.BetaMessageAccumulator;
  import com.anthropic.helpers.BetaRefusalFallbackInterceptor;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaRawMessageStreamEvent;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  import com.anthropic.models.messages.Model;

  void main() {
      // O interceptor repete requisições recusadas no modelo de fallback. Ele automaticamente
      // adiciona o cabeçalho beta fallback-credit a cada requisição que processa.
      AnthropicClient client = AnthropicOkHttpClient.builder()
          .fromEnv()
          .addInterceptor(BetaRefusalFallbackInterceptor.builder()
              .addFallback(Model.CLAUDE_OPUS_4_8)
              .build())
          .build();

      // Compartilhe um único estado entre requisições para que as continuações fiquem fixadas no modelo que aceitou.
      BetaFallbackState state = BetaFallbackState.create();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5)
          .maxTokens(1024)
          .addUserMessage("Hello, Claude")
          .build();

      // Streaming: em caso de recusa, os eventos do modelo de fallback são inseridos no stream aberto.
      BetaMessageAccumulator accumulator = BetaMessageAccumulator.create();
      try (StreamResponse<BetaRawMessageStreamEvent> streamResponse = client.beta()
              .messages()
              .createStreaming(params, RequestOptions.builder().fallbackState(state).build())) {
          streamResponse.stream()
              .peek(accumulator::accumulate)
              .forEach(event -> event.contentBlockDelta()
                  .flatMap(deltaEvent -> deltaEvent.delta().text())
                  .ifPresent(textDelta -> IO.print(textDelta.text())));
      }
      IO.println("\nserved by: " + accumulator.message().model().asString());

      // Sem streaming: reutilizar o mesmo estado mantém a conversa fixada.
      BetaMessage message = client.beta()
          .messages()
          .create(params, RequestOptions.builder().fallbackState(state).build());
      IO.println("served by: " + message.model().asString());
  }
  ```

  ```php PHP
  use Anthropic\Beta\Messages\BetaRawContentBlockDeltaEvent;
  use Anthropic\Beta\Messages\BetaTextDelta;
  use Anthropic\Client;
  use Anthropic\Lib\Middleware\BetaFallbackState;
  use Anthropic\Lib\Middleware\RefusalFallbackMiddleware;
  use Anthropic\Lib\Streaming\MessageAccumulator;

  // Configure a cadeia de fallback uma vez. Em caso de recusa, o middleware tenta novamente a
  // requisição ao longo da cadeia e envia o cabeçalho beta fallback-credit para você.
  $client = new Client(
      requestOptions: [
          'middleware' => [new RefusalFallbackMiddleware([['model' => 'claude-opus-4-8']])],
      ],
  );

  // Compartilhe um único estado na conversa para que requisições seguintes fiquem fixadas
  // no modelo que aceitou.
  $state = new BetaFallbackState();

  // Streaming: em caso de recusa, o middleware insere os eventos do modelo de fallback
  // no stream ainda aberto. O modelo do acumulador é o modelo que está atendendo.
  $stream = $client->beta->messages->createStream(
      model: 'claude-fable-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      requestOptions: ['fallbackState' => $state],
  );
  $accumulator = MessageAccumulator::forBetaMessages();
  foreach ($stream as $event) {
      $accumulator->accumulate($event);
      if ($event instanceof BetaRawContentBlockDeltaEvent
          && $event->delta instanceof BetaTextDelta) {
          echo $event->delta->text;
      }
  }
  echo "\nserved by: {$accumulator->message()->model}\n";

  // Sem streaming: mesmo middleware. Reutilizar o estado mantém a conversa
  // fixada no modelo que aceitou.
  $message = $client->beta->messages->create(
      model: 'claude-fable-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      requestOptions: ['fallbackState' => $state],
  );
  echo "served by: {$message->model}\n";
  ```

  ```ruby Ruby
  # Em caso de recusa, o middleware tenta novamente a requisição seguindo a cadeia de fallback.
  # Ele envia o cabeçalho beta fallback-credit em cada requisição que processa.
  client = Anthropic::Client.new(
    middleware: [Anthropic::BetaRefusalFallbackMiddleware.new([{model: "claude-opus-4-8"}])]
  )

  # Compartilhe um único estado ao longo da conversa para que as requisições seguintes permaneçam
  # fixadas no modelo que aceitou.
  state = Anthropic::BetaFallbackState.new

  # Streaming: em caso de recusa, o middleware insere os eventos do modelo de fallback
  # no stream ainda aberto.
  stream = client.beta.messages.stream(
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}],
    request_options: {fallback_state: state}
  )
  stream.text.each { print it }
  puts "\nserved by: #{stream.accumulated_message.model}"

  # Sem streaming: reutilizar o estado mantém a conversa fixada no modelo que aceitou.
  message = client.beta.messages.create(
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}],
    request_options: {fallback_state: state}
  )
  puts "served by: #{message.model}"
  ```
</CodeGroup>

### Como ele se comporta

* As novas tentativas percorrem sua lista de fallback em ordem. Um modelo de fallback que também recusa passa a solicitação para a próxima entrada.
* Quando todos os modelos da lista recusaram, o middleware retorna a recusa final (a resposta de recusa do último modelo) em vez de gerar um erro.
* Os blocos de pensamento do Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5, Claude Haiku 5.5 ou Claude Fable 5 passam inalterados. Cada nova tentativa reenvia o corpo da sua solicitação original, e os únicos blocos que o middleware remove do histórico da conversa em solicitações posteriores são os blocos de fronteira `fallback` que ele mesmo adicionou. O modelo de fallback não consegue ler blocos do Claude Fable 5.1, que apenas [o Claude Fable 5.1 e o Claude Mythos 5.1 leem](https://platform.claude.com/docs/pt-BR/build-with-claude/thinking#preserved-for-model), então a API os descarta. A API também descarta blocos do Claude Opus 5.5 para todo modelo de fallback, exceto Claude Fable 5.1 e Claude Mythos 5.1 (consulte [Trocar de modelo no meio da conversa](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking#switching-models)). Ela também descarta blocos do Claude Sonnet 5.5, para todo modelo de fallback, exceto o Claude Opus 5.5 na Claude API e no Google Cloud. O Claude Opus 5.5 e o Claude Sonnet 5.5 leem blocos do Claude Haiku 5.5 na Claude API e no Google Cloud, e a API os descarta para um modelo de fallback que não consegue lê-los.
* As respostas atendidas por meio do middleware incluem um bloco de conteúdo `fallback` em cada fronteira entre modelos, assim como as respostas de fallback no lado do servidor. O middleware gerencia esses blocos para você em solicitações posteriores.
* O modelo que aceitou é registrado em `BetaFallbackState`, de modo que as solicitações seguintes que compartilham o estado permanecem fixadas nele, em vez de consultar novamente um modelo que recusou.

<Note>
  O middleware e o parâmetro `fallbacks` do lado do servidor fazem o mesmo trabalho. Configure um ou outro, nunca ambos na mesma requisição. Para enviar uma requisição `fallbacks` do lado do servidor a partir de uma aplicação que instala o middleware, use uma instância de cliente separada sem ele.
</Note>

## Escrevendo a nova tentativa por conta própria

Sobre HTTP puro ou com lógica de nova tentativa personalizada, implemente o padrão que o middleware encapsula:

<Steps>
  <Step title="Detecte a recusa">
    Verifique se a resposta contém `stop_reason: "refusal"`.
  </Step>

  <Step title="Reenvie para um modelo de fallback">
    Envie a mesma solicitação com `model` definido como um modelo de fallback, como o Claude Opus 4.8. Se a solicitação recusada enviou `thinking: {"type": "between_tools"}`, altere `thinking` primeiro: apenas o Claude Sonnet 5.5 aceita esse valor, então omita `thinking` ou defina um valor que o modelo de fallback aceite. O [fallback no lado do servidor](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#server-side-fallback) com o cabeçalho `2026-07-01` faz essa alteração para você quando recorre ao Claude Sonnet 5. Outro modelo normalmente consegue atender uma solicitação que o Claude Fable 5.1 ou o Claude Fable 5 recusa. A forma como você lida com o histórico da conversa depende de você resgatar ou não um [crédito de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit):

    * **Sem resgatar um crédito:** você pode deixar os blocos `thinking` e `redacted_thinking` anteriores no lugar ou removê-los para economizar tokens de entrada. O modelo de fallback normalmente não consegue usá-los de qualquer forma: apenas o Claude Fable 5.1 e o Claude Mythos 5.1 [leem blocos do Claude Fable 5.1](https://platform.claude.com/docs/pt-BR/build-with-claude/thinking#preserved-for-model), e apenas esses dois modelos, além do Claude Fable 5 e do Claude Mythos 5, leem blocos do Claude Fable 5, então, para qualquer outro modelo de fallback, a API os descarta. A API também descarta blocos do Claude Opus 5.5 para todo modelo de fallback, exceto Claude Fable 5.1 e Claude Mythos 5.1 (consulte [Trocar de modelo no meio da conversa](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking#switching-models)). Ela também descarta blocos do Claude Sonnet 5.5, para todo modelo de fallback, exceto o Claude Opus 5.5 na Claude API e no Google Cloud. Uma nova tentativa após uma recusa do Claude Haiku 5.5 sempre se enquadra neste caso. O Claude Opus 5.5 e o Claude Sonnet 5.5 leem blocos do Claude Haiku 5.5 na Claude API e no Google Cloud, então deixe esses blocos no lugar quando recorrer a qualquer um desses modelos ali. Para um modelo de fallback que não consegue lê-los, a API os descarta sem cobrá-los.
    * **Resgatando um crédito:** envie o corpo inalterado, porque o resgate exige correspondência exata. O servidor lida com os blocos de thinking do modelo anterior em um resgate, então não os remova (consulte [Campos que devem corresponder à solicitação recusada](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit#reference)).
  </Step>

  <Step title="Permaneça no modelo de fallback">
    Em conversas com vários turnos, continue usando o modelo de fallback nos turnos seguintes em vez de voltar ao modelo original.
  </Step>
</Steps>

Uma nova tentativa manual grava o cache de prompt do modelo de fallback do zero, o que custa mais do que ler um cache existente. O [crédito de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit) reembolsa esse custo; resgate-o em cada nova tentativa que você mesmo criar. Uma recusa do Claude Haiku 5.5 não gera crédito de fallback, então uma nova tentativa após ela paga o custo total de gravar o cache de prompt do modelo de fallback.

## Recusas em Message Batches

Uma requisição recusada em um [Message Batch](https://platform.claude.com/docs/pt-BR/build-with-claude/batch-processing) retorna como `result.type: "succeeded"` com `stop_reason: "refusal"`. Os resultados de lote carregam o mesmo objeto `stop_details` que as respostas síncronas, portanto você pode detectar recusas através de `stop_reason` ou de `stop_details.type`. Uma diferença: recusas em lote não geram créditos de fallback, portanto `stop_details` em um resultado de lote nunca inclui um `fallback_credit_token`.

O fallback do lado do servidor não está disponível para lotes (uma requisição de lote que inclui `fallbacks` produz um resultado com erro por item). Para repetir itens de lote recusados:

1. Colete os itens recusados dos resultados.
2. Deixe os blocos de pensamento nos históricos de vários turnos no lugar ou remova-os para economizar tokens de entrada. Para um modelo de fallback que não consegue lê-los, a API os descarta sem cobrá-los, como em [uma nova tentativa manual](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#manual-retry).
3. Se um item recusado enviou `thinking: {"type": "between_tools"}`, omita `thinking` ou defina um valor que o modelo de fallback aceite. Apenas o Claude Sonnet 5.5 aceita `between_tools`.
4. Reenvie-os em um modelo de fallback como um novo lote ou como requisições diretas.

## Armadilhas comuns

* **Repita em um modelo diferente.** Reenviar uma requisição recusada para o mesmo modelo geralmente resulta em outra recusa. Direcione a nova tentativa para o modelo de fallback.
* **Orce novas tentativas por requisição, não por turno ou por sessão.** Um único turno pode produzir várias recusas, por exemplo um agente mais seus subagentes.
* **Configure o fallback em todos os caminhos de requisição.** Handlers de nova tentativa, ramificações de recuperação de erro e workers em segundo plano todos precisam dele. Um handler que reemite uma requisição sem fallback perde a proteção exatamente nas requisições com maior probabilidade de precisar dela.
* **Dê às chamadas de subagentes seu próprio fallback.** O parâmetro `fallbacks` não se propaga para chamadas de modelo feitas de dentro da execução de ferramentas.
* **Torne o fallback uma propriedade da requisição, não do estado ambiente.** Uma flag compartilhada, um valor de configuração em cache ou um toggle global podem ficar fora de sincronia e silenciosamente deixar uma requisição desprotegida. Quando você não puder confirmar que o fallback está ativo, configure-o em vez de presumir que está ligado.
* **Instrumente recusas como um sinal próprio.** Uma recusa é um HTTP 200, portanto monitoramento baseado em taxas de erro ou respostas 5xx nunca a vê. Emita um evento por recusa e um por resposta atendida por fallback (a entrada `fallback_message` em `usage.iterations` marca esta última), e então alerte sobre a diferença entre as duas contagens.
* **Ramifique com base em `stop_reason` ou `stop_details.type`, não em `content` ou nos campos internos de `stop_details`.** O objeto `stop_details` está sempre presente em uma recusa, mas seus campos `category` e `explanation` podem ser `null`. Verifique diretamente se `stop_reason` é igual a `"refusal"`.

## Próximos passos

<CardGroup>
  <Card title="Crédito de fallback" icon="scales" href="https://platform.claude.com/docs/pt-BR/build-with-claude/fallback-credit">
    Evite pagar o custo do cache de prompt duas vezes quando você mesmo constrói a nova tentativa.
  </Card>

  <Card title="Motivos de parada e fallback" icon="code" href="https://platform.claude.com/docs/pt-BR/build-with-claude/handling-stop-reasons">
    Cada valor de `stop_reason` e como lidar com ele.
  </Card>

  <Card title="Middleware do SDK" icon="settings" href="https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/middleware">
    Como o middleware do SDK funciona, incluindo o helper de fallback de recusa.
  </Card>

  <Card title="Guia de migração" icon="arrow-right" href="https://platform.claude.com/docs/pt-BR/models/fable-5-1/migration-guide">
    Mova uma aplicação existente para o Claude Fable 5.1.
  </Card>
</CardGroup>
