---
title: Rifiuti e fallback
url: https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback
description: Come i modelli Claude Fable, i modelli Claude Opus, Claude Sonnet 5.5 e Claude Haiku 5.5 restituiscono i rifiuti dei classificatori e come ritentare le richieste rifiutate su un modello di fallback.
---

Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 e Claude Haiku 5.5 includono classificatori di sicurezza che possono declinare una richiesta. Quando ciò accade, ricevi una risposta normale, non un errore, con `stop_reason: "refusal"`. Il suo `stop_details.category` indica l'area di policy (vedi [Come appare un rifiuto](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#refusal-response)). Di solito puoi comunque ottenere una risposta inviando la stessa richiesta a un altro modello Claude. Questa pagina mostra come riconoscere un "refusal" (rifiuto) e come configurare quel nuovo tentativo, detto "fallback" (ripiego).

Leggi questa pagina se sviluppi su uno di questi modelli e vuoi che le richieste rifiutate passino automaticamente a un altro modello. È utile anche se hai visto `"refusal"` in una risposta e vuoi sapere come procedere.

Pagine correlate:

* [Motivi di arresto e fallback](https://platform.claude.com/docs/it/build-with-claude/handling-stop-reasons): l'elenco completo dei valori di `stop_reason`.
* [Credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit): come evitare di pagare due volte il costo della cache dei prompt quando implementi tu stesso il nuovo tentativo.
* [Middleware degli SDK](https://platform.claude.com/docs/it/cli-sdks-libraries/middleware): l'helper dell'SDK che incapsula tutto questo.
* [Cookbook su fallback e fatturazione](https://platform.claude.com/cookbook/fable-5-fallback-billing-guide): un esempio completo end-to-end.

La configurazione più semplice, in beta sulla Claude API: imposta `fallbacks` su `"default"` e l'API ritenta una richiesta rifiutata sul modello di fallback che Anthropic raccomanda per la sua categoria di rifiuto. Per le categorie senza un fallback raccomandato, il rifiuto resta valido. Claude Haiku 5.5 non ha un fallback lato server, quindi per questo modello usa il [fallback lato client con il middleware SDK](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#client-side-fallback) oppure [scrivi tu stesso il nuovo tentativo](https://platform.claude.com/docs/it/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>

Le sezioni seguenti descrivono il contenuto di una risposta di rifiuto, quando usare il fallback lato server o lato client e come viene fatturato ciascuno.

## Come appare un rifiuto

Un rifiuto è una risposta HTTP 200 riuscita con `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
  }
}
```

L'oggetto `stop_details` spiega il rifiuto:

* **`category`:** indica l'area di policy che ha attivato il classificatore.
* **`explanation`:** una descrizione leggibile. Il testo non è stabile, quindi visualizzalo anziché analizzarlo.
* **`recommended_model`:** presente solo nelle richieste che impostano `fallbacks` ([fallback lato server](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#server-side-fallback), beta). Indica un modello su cui ritentare direttamente quando l'API ha saltato il tentativo di fallback (ad esempio, il modello di fallback era soggetto a limite di velocità), ed è `null` altrimenti. È un suggerimento, non una garanzia.
* `category` ed `explanation` sono entrambi `null` quando il rifiuto non corrisponde a una categoria denominata. Quel `null` è un valore normale e permanente, non un segnaposto.
* `stop_details` stesso è `null` per ogni motivo di arresto diverso da `refusal`.

| `category`               | Cosa significa                                                                                                                                                                                                                                                                                                                                                                                                                           | Fatturato prima di qualsiasi output |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| `"cyber"`                | La richiesta potrebbe favorire danni informatici, come lo sviluppo di malware o exploit. Anche il lavoro di cybersecurity benigno può attivare questa categoria.                                                                                                                                                                                                                                                                         | No                                  |
| `"bio"`                  | La richiesta potrebbe favorire danni biologici, come metodi di laboratorio pericolosi. Anche il lavoro benefico nelle scienze della vita può attivare questa categoria.                                                                                                                                                                                                                                                                  | Sì                                  |
| `"frontier_llm"`         | La richiesta potrebbe assistere lo sviluppo di modelli di IA concorrenti, il che è limitato dai [termini commerciali di Anthropic](https://www.anthropic.com/legal/commercial-terms). Anche il lavoro benigno di machine learning può attivare questa categoria.                                                                                                                                                                         | Sì                                  |
| `"reasoning_extraction"` | La richiesta chiede al modello di riprodurre il suo ragionamento interno nel testo della risposta. Per ottenere invece il ragionamento in forma strutturata, usa il [ragionamento adattivo](https://platform.claude.com/docs/it/build-with-claude/thinking). Vedi [Mantieni il ragionamento nei blocchi di ragionamento](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks). | Sì                                  |
| `"general_harms"`        | La richiesta rientra in un'area della policy di utilizzo al di fuori delle quattro categorie denominate. Anche il lavoro benigno può attivare questa categoria.                                                                                                                                                                                                                                                                          | No                                  |

Un rifiuto può arrivare prima di qualsiasi output, oppure a metà streaming dopo un output parziale. In entrambi i casi, tratta qualsiasi output parziale come incompleto e scartalo.

### Mantieni il ragionamento nei blocchi di ragionamento

Un rifiuto `reasoning_extraction` deriva di solito da un prompt che chiede al modello di inserire il suo ragionamento nell'output, alla lettera o in un formato fisso. Esempi comuni:

* Una sezione `<thinking>`, `<reasoning>` o di appunti che il modello compila prima di rispondere
* Un campo `reasoning`, `thinking` o `trace` nell'output JSON o nell'input di uno strumento
* Le note private del modello, o un registro continuo del suo ragionamento
* Ragionamento richiesto alla lettera o per intero

La formulazione può trovarsi in un prompt di sistema, in una skill o nella descrizione di uno strumento, quindi controlla anche quelli.

Puoi comunque chiedere a Claude di spiegare la sua risposta. Chiedi una breve spiegazione, le prove alla base di un risultato o un riepilogo delle azioni intraprese. Per vedere come ha ragionato il modello, imposta `display: "summarized"` e leggi i [blocchi `thinking`](https://platform.claude.com/docs/it/build-with-claude/thinking#summarized-thinking). Questa categoria non ha un modello di fallback raccomandato, quindi modifica il prompt anziché ritentare la richiesta. Se una richiesta riformulata viene ancora declinata, [contatta il supporto](https://support.claude.com/en/articles/9015913-how-to-get-support) e includi l'[ID della richiesta](https://platform.claude.com/docs/it/api/errors#request-id).

## Come vengono fatturati i rifiuti

Queste regole di fatturazione si applicano su ogni piattaforma: la Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud e Microsoft Foundry.

**Rifiuti prima di qualsiasi output:** per contrastare i tentativi di aggirare su larga scala le salvaguardie di Anthropic, un rifiuto che arriva prima di qualsiasi output viene fatturato quando il suo `stop_details.category` è `"bio"`, `"frontier_llm"` o `"reasoning_extraction"`. Queste sono le categorie in cui Anthropic misura bassi volumi di falsi positivi, a settembre 2026. Questi rifiuti vengono fatturati come qualsiasi altra richiesta, alle tariffe del modello che l'ha eseguita. Un rifiuto prima di qualsiasi output in qualsiasi altra categoria, o con categoria `null`, non viene fatturato. In ogni caso, `content` è vuoto e i conteggi dei token compaiono in `usage`. La richiesta conta comunque ai fini dei tuoi limiti di velocità.

**Rifiuti a metà streaming:** un rifiuto a metà streaming addebita i token di input e l'output già trasmesso alle tariffe normali.

**Fallback:** quando usi il fallback, il rifiuto che lo ha attivato viene fatturato, in aggiunta alla richiesta di fallback, quando è arrivato a metà streaming o rientra in una delle categorie fatturate. Il [credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit) compensa il mancato riscontro nella cache dei prompt da parte della richiesta di fallback, così non paghi due volte per memorizzare in cache la conversazione. Un rifiuto di Claude Haiku 5.5 non comporta alcun credito di fallback, quindi un fallback successivo paga l'intero costo di scrittura della cache dei prompt del modello di fallback. Per sapere come il fallback lato server riporta ogni tentativo, vedi [Fatturazione e limiti di velocità](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#billing-and-rate-limits).

Le categorie fatturate possono cambiare man mano che Anthropic continua a misurare e perfezionare i tassi di falsi positivi delle proprie salvaguardie. La colonna **Fatturato prima di qualsiasi output** nella [tabella delle categorie di rifiuto](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#refusal-response) elenca le categorie fatturate.

## Scegliere un approccio di fallback

Esistono tre modi per ritentare una richiesta rifiutata su un altro modello. Quello giusto dipende da dove stai eseguendo e da quanto controllo ti serve.

| La tua situazione                              | Usa                                                                                                                                                                                                                     | Perché                                                                       |
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Claude API, configurazione più semplice        | [Fallback lato server](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#server-side-fallback)                                                                                                | Una richiesta, una risposta. L'API gestisce il nuovo tentativo.              |
| Qualsiasi piattaforma, usando un SDK Anthropic | [Il middleware SDK](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#client-side-fallback)                                                                                                   | Configura una volta sul client. I nuovi tentativi avvengono automaticamente. |
| HTTP grezzo o logica di retry personalizzata   | [Un nuovo tentativo manuale](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#manual-retry) con [credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit) | Controllo completo. Il credito di fallback contiene i costi.                 |

Il fallback lato server e il middleware SDK applicano il credito di fallback per te. Ti serve la pagina [Credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit) solo quando costruisci tu stesso il nuovo tentativo. Claude Haiku 5.5 non ha né il fallback lato server né il credito di fallback, quindi usa il middleware SDK o un nuovo tentativo manuale.

## Fallback lato server

Il fallback lato server ritenta una richiesta rifiutata all'interno di una singola chiamata API. Nella modalità predefinita, quando il modello primario declina e la categoria di rifiuto ha un fallback raccomandato, l'API esegue la stessa richiesta sul modello che Anthropic raccomanda per quella categoria. Puoi invece [indicare fino a tre modelli di fallback a tua scelta](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#naming-your-own-fallback-models). In entrambi i casi, ricevi una sola risposta che indica il modello che ha risposto, così il tuo utente ottiene una risposta in un solo round trip.

<Note>
  Il fallback lato server è in beta sulla Claude API. Il parametro `fallbacks` non è supportato sulla [Message Batches API](https://platform.claude.com/docs/it/build-with-claude/batch-processing) (un elemento del batch che lo include restituisce un risultato con errore) e non è disponibile su Amazon Bedrock, Google Cloud o Microsoft Foundry. Su queste piattaforme, usa invece il [fallback lato client con il middleware SDK](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#client-side-fallback). Claude Haiku 5.5 non ha fallback lato server: con `fallbacks: "default"`, una richiesta declinata resta declinata, e un elenco di modelli di fallback restituisce un errore 400.
</Note>

### Effettuare la richiesta

Imposta il parametro `fallbacks` sulla stringa `"default"` e invia l'header beta `server-side-fallback-2026-07-01`. L'API applica quindi il routing predefinito definito dal server per il modello richiesto, che seleziona un modello di fallback raccomandato in base alla categoria di rifiuto riportata dal classificatore, così le richieste rifiutate vengono servite senza che tu debba mantenere un elenco di modelli man mano che le raccomandazioni cambiano.

Il routing predefinito non provoca mai il [rifiuto anticipato per immagine sovradimensionata](https://platform.claude.com/docs/it/build-with-claude/vision-coordinates#oversized-image-error) per modelli che non hai scelto: un modello instradato che ridimensionerebbe un'immagine contrassegnata con `"oversized_image": "error"` viene invece escluso dal routing, così un'immagine contrassegnata non viene mai servita ridimensionata.

<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,
      # Una voce fallback_message in usage.iterations indica che è stato eseguito un modello di fallback;
      # abbinala a stop_reason per confermare che il fallback abbia fornito la risposta.
      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,
      # Una voce fallback_message in usage.iterations indica che è stato eseguito un modello di fallback;
      # abbinala a stop_reason per confermare che il fallback abbia fornito la risposta.
      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"],
  )

  # Una voce fallback_message in usage.iterations indica che è stato eseguito un modello di fallback;
  # abbinala a stop_reason per confermare che il fallback abbia fornito la risposta.
  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"]
  });

  // Una voce fallback_message in usage.iterations indica che è stato eseguito un modello di fallback;
  // abbinala a stop_reason per confermare che il fallback abbia fornito la risposta.
  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],
      }
  );

  // Una voce fallback_message in usage.iterations indica che è stato eseguito un modello di fallback;
  // abbinala a stop_reason per confermare che il fallback abbia fornito la risposta.
  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)
  }

  // Una voce fallback_message in usage.iterations indica che è stato eseguito un modello di fallback;
  // abbinala a stop_reason per confermare che il fallback abbia fornito la risposta.
  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()
  );

  // Una voce di utilizzo fallback_message indica che un modello di fallback ha prodotto la
  // risposta; uno stop reason refusal indica che nessun modello l'ha servita.
  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'],
  );

  // Una voce fallback_message in usage.iterations indica che è stato eseguito un modello di fallback;
  // abbinala a stop_reason per confermare che il fallback abbia fornito la risposta.
  $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"]
  )

  # Una voce fallback_message in usage.iterations indica che è stato eseguito un modello di fallback;
  # abbinala a stop_reason per confermare che il fallback abbia fornito la risposta.
  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>

Anthropic definisce le salvaguardie per ciascun modello individualmente e per ciascuna categoria di policy, in linea con le capacità del modello: a seconda della categoria, una richiesta segnalata può ricadere su un modello meno capace oppure essere declinata. La modalità `"default"` codifica per te queste raccomandazioni per modello e per categoria, così una richiesta rifiutata viene ritentata sul modello che Anthropic raccomanda per quella categoria. I fallback sono visibili in entrambi i casi: la risposta indica il modello che l'ha servita, e il blocco di contenuto `fallback` segna il passaggio di consegne.

Il routing viene applicato lato server e non è pubblicato per modello sulla [Models API](https://platform.claude.com/docs/it/api/models/list). Per vedere quale modello ha servito una richiesta rifiutata, controlla il campo `model` di primo livello della risposta e cerca una voce `fallback_message` in `usage.iterations`, come fanno gli esempi di questa pagina.

Solo un rifiuto del classificatore di sicurezza attiva il fallback. Un limite di velocità, un sovraccarico o un errore del server sul modello richiesto ti viene restituito così com'è.

<Note>
  L'header beta deve riportare esattamente la data `2026-07-01`, che supporta sia `"default"` sia la forma con elenco esplicito, oppure `2026-06-01`, che accetta solo la forma con elenco esplicito. Con qualsiasi altro valore `server-side-fallback-*`, il parametro `fallbacks` viene rifiutato con un errore 400. Se hai sviluppato su un'anteprima precedente di questa funzionalità, aggiorna insieme l'header beta e le forme di richiesta e risposta a quelle di questa pagina.
</Note>

### Indicare i propri modelli di fallback

Invece del routing predefinito, puoi impostare `fallbacks` su un elenco di fino a tre modelli. Quando il modello richiesto declina, l'API esegue il modello successivo nella catena sulla stessa richiesta. Usa questa forma quando vuoi controllare esattamente quali modelli servono le richieste rifiutate, ad esempio fissando un modello che la tua applicazione ha qualificato.

I modelli di fallback indicati contano ai fini del [controllo delle immagini sovradimensionate](https://platform.claude.com/docs/it/build-with-claude/vision-coordinates#oversized-image-error): una richiesta il cui blocco immagine imposta `"oversized_image": "error"` viene controllata in anticipo rispetto al modello richiesto e a ogni fallback indicato, viene rifiutata se uno qualsiasi di essi ridimensionerebbe quell'immagine, e la dimensione di ridimensionamento riportata nel rifiuto è adatta a tutti.

Le righe evidenziate sono l'unica differenza rispetto alla richiesta con routing predefinito.

<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>

All'elenco `fallbacks` si applicano alcune regole:

* Le voci vengono provate in ordine. Ciascuna deve essere diversa dalle altre voci e dal modello richiesto.
* Ogni voce deve essere una delle destinazioni consentite per il modello richiesto. Con l'header beta impostato, quell'elenco è pubblicato come `allowed_fallback_models` nella voce del modello nella [Models API](https://platform.claude.com/docs/it/api/models/list).
* Ogni voce indica un `model` e può sovrascrivere `max_tokens`, `thinking`, `output_config` e `speed` solo per quel tentativo.
* La richiesta deve essere valida come richiesta diretta a ogni modello indicato. Se un modello di fallback non supporta una funzionalità usata dalla richiesta, l'API rifiuta la richiesta in anticipo. Con l'header `2026-07-01`, `thinking: {"type": "between_tools"}` è l'eccezione: quando una richiesta a Claude Sonnet 5.5 ripiega su Claude Sonnet 5, il tentativo di fallback viene eseguito con `thinking: {"type": "disabled"}` e `display: "omitted"`. Con `2026-06-01`, imposta `thinking` nella voce di Claude Sonnet 5, altrimenti la richiesta viene rifiutata in anticipo.
* Come nella modalità predefinita, solo un rifiuto da parte di un classificatore di sicurezza attiva il fallback. Un limite di velocità, un sovraccarico o un errore del server sul modello richiesto ti vengono restituiti così come sono.
* Se un modello di fallback ha raggiunto il limite di velocità o è sovraccarico, il tentativo di fallback non viene effettuato e viene invece restituito il rifiuto precedente. Il campo `stop_details.recommended_model` del rifiuto indica allora un modello da ritentare direttamente. Dimensiona i limiti di velocità del modello di fallback in base al volume di rifiuti che prevedi, altrimenti sotto carico i fallback si riducono a rifiuti.

La risposta ha la stessa forma in entrambe le modalità: il modello che ha servito il turno compare nel campo `model` di primo livello, un blocco di contenuto `fallback` segna il passaggio di consegne, e `usage.iterations` registra ogni tentativo.

### Cosa contiene la risposta

La risposta appare come qualsiasi altro messaggio, con due aggiunte:

* Il campo `model` di primo livello riporta il modello che ha prodotto il messaggio restituito, sia esso il modello richiesto o un fallback.

* Un blocco di contenuto `fallback` segna ogni punto in `content` in cui l'output di un modello cede il passo al successivo: `{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}`.

  * `from.model` riprende la stringa del modello che hai inviato quando l'hop che declina è il modello richiesto.
  * `to.model` è sempre l'ID risolto del modello che prosegue.

In caso di rifiuto prima di qualsiasi output, il blocco `fallback` è il primo blocco di contenuto. Ad esempio, quando il routing predefinito seleziona Claude Opus 4.8 per la categoria del rifiuto:

```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
      }
    ]
  }
}
```

L'array `usage.iterations` registra ogni tentativo. Un modello che ha declinato compare come una normale voce `message`, e il modello che ha servito il turno compare come voce `fallback_message`. Se ogni modello nella catena declina, la risposta è il rifiuto dell'ultimo modello, con una voce `message` per ogni hop precedente e una voce `fallback_message` per l'ultimo.

Il [routing persistente](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#sticky-routing) può inviare un turno successivo direttamente al modello di fallback. Un tale turno non contiene alcun blocco di contenuto `fallback`, perché nessun modello ha declinato quel turno. Identificalo dalla voce `fallback_message` in `usage.iterations`, dall'assenza di una voce `message` per il modello richiesto e dal campo `model` della risposta.

### Continuare la conversazione

Al turno successivo, rimanda il contenuto dell'assistente così come l'hai ricevuto. Dopo un fallback a metà output, `content` può includere tipi di blocco che il modello che ha declinato ha prodotto prima del passaggio di consegne. La tabella seguente indica quali mantenere e quali eliminare quando riproponi il turno.

| Tipo di blocco                                                                         | Al turno successivo                                                                                                                                                                                                                                                   |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fallback`                                                                             | Mantienilo esattamente dove è comparso. L'API usa la sua posizione per validare i blocchi di ragionamento attorno a esso, quindi una richiesta che ripropone blocchi di ragionamento da entrambi i lati del confine viene rifiutata se il blocco è omesso o spostato. |
| `text`                                                                                 | Mantieni.                                                                                                                                                                                                                                                             |
| Qualsiasi blocco dopo l'ultimo blocco `fallback`                                       | Mantieni.                                                                                                                                                                                                                                                             |
| `thinking`, `redacted_thinking` o `connector_text` prima dell'ultimo blocco `fallback` | Elimina.                                                                                                                                                                                                                                                              |
| `tool_use` lato client prima dell'ultimo blocco `fallback`                             | Elimina.                                                                                                                                                                                                                                                              |
| `server_tool_use` prima dell'ultimo blocco `fallback`                                  | Mantieni quando è abbinato al suo risultato. Elimina quando non ha un risultato corrispondente.                                                                                                                                                                       |

<Note>
  Un blocco `connector_text` contiene testo di narrazione che alcune risposte con uso degli strumenti includono tra le chiamate agli strumenti.
</Note>

### Streaming

In una richiesta in streaming, il nuovo tentativo avviene sullo stesso stream, e nulla di ciò che hai già ricevuto viene invalidato. Ciò che vedi dipende da quando avviene il rifiuto.

**Quando il rifiuto avviene prima di qualsiasi output:**

* `message_start` indica il modello di fallback, e il blocco `fallback` è il primo blocco di contenuto.
* Poiché `message_start` attende l'avvio del tentativo di fallback, il tempo al primo byte include il tentativo declinato.

**Quando il rifiuto avviene a metà output:**

* Il blocco di contenuto aperto si chiude, e il blocco `fallback` (una normale coppia `content_block_start` e `content_block_stop` senza delta) segna il confine.
* Il modello di fallback prosegue dall'output parziale. Solo i blocchi `text` dell'output parziale vengono passati al modello di fallback come contesto. Gli altri tipi di blocco rimangono in `content`.
* `message_start` ha già indicato il modello richiesto, quindi leggi il modello che ha servito dal `to.model` del blocco `fallback` e dalla voce `fallback_message` in `usage.iterations` dell'ultimo `message_delta`.

### Risposte non in streaming

In una richiesta non in streaming, un rifiuto a metà output si comporta diversamente: la risposta omette l'output parziale del modello declinato, e il modello di fallback risponde da zero. Il risultato appare come un rifiuto prima di qualsiasi output, con il blocco `fallback` per primo. Il tentativo declinato e i suoi token di output compaiono comunque in `usage.iterations`.

<Note>
  **Rifiuti durante l'uso degli strumenti:** il lavoro degli strumenti completato non blocca il fallback. Quando un rifiuto scatta dopo che gli strumenti server (ad esempio, ricerca web o esecuzione di codice) hanno terminato l'esecuzione all'interno di una richiesta, il tentativo di fallback procede: i risultati degli strumenti completati vengono trasferiti, e il modello di fallback può continuare a invocare strumenti server. L'unico caso che non viene ritentato è un rifiuto in streaming che scatta mentre un blocco di uso degli strumenti di qualsiasi tipo (uno strumento client, uno strumento server o una chiamata a uno strumento MCP) è ancora aperto sullo stream: quel rifiuto viene restituito direttamente, e se l'header `fallback-credit-2026-07-01` è impostato contiene comunque un token di credito riscattabile continuando la risposta parziale. Le richieste non in streaming non sono interessate; l'API cancella il lavoro parziale e ritenta prima di rispondere.
</Note>

### Fatturazione e limiti di velocità

Ogni tentativo segue le regole descritte in [Come vengono fatturati i rifiuti](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#how-refusals-are-billed), alle tariffe del modello che lo ha eseguito. Un tentativo che ha declinato prima di produrre qualsiasi output viene fatturato solo quando la sua categoria di rifiuto è fatturata, e i suoi token sono riportati nella sua voce `usage.iterations` in ogni caso. Ogni tentativo che ha prodotto output, incluso uno che ha declinato a metà della sua risposta, viene fatturato separatamente. L'array `usage.iterations` è il registro per tentativo di ciò che ti viene fatturato. I conteggi `usage` di primo livello descrivono solo il tentativo che ha prodotto il messaggio restituito. I token di modelli diversi non vengono mai sommati in un unico campo.

Ogni tentativo eseguito, incluso uno che ha declinato, conta ai fini dei limiti di velocità del proprio modello.

### Routing persistente

Dopo che una conversazione è passata al fallback, l'API registra quale modello l'ha servita. Le richieste successive per quella conversazione che includono `fallbacks` vanno direttamente a quel modello di fallback, senza eseguire il modello richiesto. Questo evita di pagare a ogni turno un tentativo che verrebbe prevedibilmente declinato di nuovo.

Alcune proprietà della decisione di routing:

* Viene conservata per circa 1 ora ed è limitata alla tua organizzazione.
* Viene memorizzata come hash del contenuto del prefisso della conversazione più il modello che l'ha servita. Il contenuto dei messaggi in sé non viene memorizzato.
* È best-effort, quindi il tuo codice deve gestire il caso in cui il modello richiesto venga provato di nuovo in qualsiasi momento.

Il routing persistente si applica sia alle richieste in streaming sia a quelle non in streaming. In una richiesta in streaming, la decisione di routing viene presa prima dell'apertura dello stream, quindi il campo `model` dell'evento `message_start` contiene già l'ID del modello di fallback.

## Fallback lato client con il middleware SDK

L'SDK include un middleware di fallback per i rifiuti. Lo configuri una volta sul client con il tuo elenco di modelli di fallback. Le chiamate tramite `client.beta.messages` (csharp, go: `client.Beta.Messages`; java: `client.beta().messages()`; php: `$client->beta->messages`) ritentano quindi automaticamente le richieste rifiutate, su qualsiasi piattaforma. Il middleware invia anche l'header beta `fallback-credit-2026-07-01` su ogni richiesta che gestisce, così i nuovi tentativi vengono riprezzati senza configurazione per singola richiesta. Un rifiuto di Claude Haiku 5.5 non comporta alcun credito di fallback, quindi un nuovo tentativo successivo paga l'intero costo di scrittura della cache dei prompt del modello di fallback.

### Configurazione

Passa `BetaRefusalFallbackMiddleware` (typescript: `betaRefusalFallbackMiddleware`; go: `betafallback.BetaRefusalFallbackMiddleware`; csharp: `BetaRefusalFallbackHandler`; java: `BetaRefusalFallbackInterceptor`; php: `RefusalFallbackMiddleware`) al costruttore del client e condividi una singola istanza di `BetaFallbackState` tra le richieste di una conversazione.

<CodeGroup exclude="shell">
  <CodeGroupItem language="cURL">
    Il middleware di fallback per i rifiuti fa parte del Claude SDK, quindi una richiesta cURL non può usarlo. Per eseguire il fallback all'interno di una singola richiesta, usa il [fallback lato server](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#server-side-fallback). Per scrivere tu stesso il nuovo tentativo, vedi [Credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit).
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    La CLI `ant` non include il middleware di fallback per i rifiuti. Per eseguire il fallback all'interno di una singola richiesta, usa il [fallback lato server](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#server-side-fallback). Per scrivere tu stesso il nuovo tentativo, vedi [Credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit).
  </CodeGroupItem>

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

  # In caso di rifiuto, il middleware riprova con il modello di fallback indicato e
  # invia automaticamente l'header beta fallback-credit a ogni richiesta che gestisce.
  client = Anthropic(
      middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
  )

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

  # Streaming: in caso di rifiuto il middleware riprova con il modello di fallback e
  # innesta i suoi eventi nello stream aperto.
  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}")

  # Non-streaming: riutilizzare lo stato mantiene la conversazione fissata.
  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";

  // In caso di rifiuto, il middleware riprova sul modello di fallback elencato e
  // invia automaticamente l'header beta fallback-credit a ogni richiesta che gestisce.
  const client = new Anthropic({
    middleware: [betaRefusalFallbackMiddleware([{ model: "claude-opus-4-8" }])]
  });

  // Condividi un unico stato nella conversazione così le richieste successive restano
  // vincolate al modello che ha accettato.
  const fallbackState = new BetaFallbackState();

  // Streaming: in caso di rifiuto il middleware riprova sul modello di fallback e
  // innesta i suoi eventi sullo stream aperto.
  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);

  // Non-streaming: riutilizzare lo stato mantiene la conversazione vincolata.
  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;

  // In caso di rifiuto, l'handler riprova sul modello di fallback elencato e
  // invia automaticamente l'header beta fallback-credit su ogni richiesta che gestisce.
  AnthropicClient client = new()
  {
      Handlers =
      [
          new BetaRefusalFallbackHandler { Fallbacks = [new(Messages::Model.ClaudeOpus4_8)] },
      ],
  };

  // Vincola le richieste successive che condividono questo stato al modello che ha accettato.
  BetaFallbackState fallbackState = BetaFallbackState.Create();

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

  // Streaming: se lo stream termina con un rifiuto, l'handler innesta gli eventi del modello
  // di fallback sullo stream ancora aperto.
  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()}");

  // Non-streaming: riusare lo stato mantiene la conversazione vincolata al modello che ha accettato.
  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()

  	// Il middleware ritenta una richiesta rifiutata su ciascun modello di fallback
  	// a turno, e iscrive automaticamente le richieste alla beta fallback-credit.
  	client := anthropic.NewClient(
  		option.WithMiddleware(betafallback.BetaRefusalFallbackMiddleware(
  			[]anthropic.BetaFallbackParam{{Model: anthropic.ModelClaudeOpus4_8}},
  		)),
  	)

  	// Uno stato per conversazione: le richieste che lo condividono restano vincolate al
  	// modello che ha accettato, così un follow-up non richiede mai a un modello che ha rifiutato.
  	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: in caso di rifiuto il middleware ritenta sul posto, innestando gli
  	// eventi del modello di fallback sullo stream aperto come un unico messaggio continuo.
  	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)

  	// Non-streaming: lo stato condiviso vincola questo follow-up al modello che
  	// ha servito il turno in 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() {
      // L'interceptor ritenta le richieste rifiutate sul modello di fallback. Aggiunge automaticamente
      // l'header beta fallback-credit a ogni richiesta che gestisce.
      AnthropicClient client = AnthropicOkHttpClient.builder()
          .fromEnv()
          .addInterceptor(BetaRefusalFallbackInterceptor.builder()
              .addFallback(Model.CLAUDE_OPUS_4_8)
              .build())
          .build();

      // Condividi un unico stato tra le richieste così i follow-up restano vincolati al modello che ha accettato.
      BetaFallbackState state = BetaFallbackState.create();

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

      // Streaming: in caso di rifiuto, gli eventi del modello di fallback vengono innestati sullo stream aperto.
      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());

      // Non-streaming: riutilizzare lo stesso stato mantiene la conversazione vincolata.
      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;

  // Configura la catena di fallback una sola volta. In caso di rifiuto, il middleware ritenta la
  // richiesta lungo la catena e invia per te l'header beta fallback-credit.
  $client = new Client(
      requestOptions: [
          'middleware' => [new RefusalFallbackMiddleware([['model' => 'claude-opus-4-8']])],
      ],
  );

  // Condividi un unico stato nella conversazione così le richieste successive restano vincolate
  // al modello che ha accettato.
  $state = new BetaFallbackState();

  // Streaming: in caso di rifiuto il middleware innesta gli eventi del modello di fallback
  // sullo stream ancora aperto. Il modello dell'accumulatore è il modello che serve la richiesta.
  $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";

  // Non-streaming: stesso middleware. Riutilizzare lo stato mantiene la conversazione
  // vincolata al modello che ha accettato.
  $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
  # In caso di rifiuto, il middleware ritenta la richiesta lungo la catena di fallback.
  # Invia l'header beta fallback-credit in ogni richiesta che gestisce.
  client = Anthropic::Client.new(
    middleware: [Anthropic::BetaRefusalFallbackMiddleware.new([{model: "claude-opus-4-8"}])]
  )

  # Condividi un unico stato nella conversazione, così le richieste successive restano
  # vincolate al modello che ha accettato.
  state = Anthropic::BetaFallbackState.new

  # Streaming: in caso di rifiuto il middleware innesta gli eventi del modello di fallback
  # sullo stream ancora aperto.
  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}"

  # Non-streaming: riutilizzare lo stato mantiene la conversazione vincolata al modello che ha accettato.
  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>

### Come si comporta

* I nuovi tentativi scorrono il tuo elenco di fallback in ordine. Un modello di fallback che a sua volta rifiuta passa la richiesta alla voce successiva.
* Quando tutti i modelli dell'elenco hanno rifiutato, il middleware restituisce il rifiuto finale (la risposta di rifiuto dell'ultimo modello) anziché sollevare un errore.
* I blocchi di ragionamento di Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5, Claude Haiku 5.5 o Claude Fable 5 passano invariati. Ogni nuovo tentativo reinvia il corpo della richiesta originale, e gli unici blocchi che il middleware rimuove dalla cronologia della conversazione nelle richieste successive sono i blocchi di confine `fallback` che ha aggiunto esso stesso. Il modello di fallback non può leggere i blocchi di Claude Fable 5.1, che solo [Claude Fable 5.1 e Claude Mythos 5.1 leggono](https://platform.claude.com/docs/it/build-with-claude/thinking#preserved-for-model), quindi l'API li elimina. L'API elimina anche i blocchi di Claude Opus 5.5 per ogni modello di fallback tranne Claude Fable 5.1 e Claude Mythos 5.1 (vedi [Cambiare modello a metà conversazione](https://platform.claude.com/docs/it/build-with-claude/preserved-thinking#switching-models)). Elimina anche i blocchi di Claude Sonnet 5.5, per ogni modello di fallback tranne Claude Opus 5.5 sulla Claude API e su Google Cloud. Claude Opus 5.5 e Claude Sonnet 5.5 leggono i blocchi di Claude Haiku 5.5 sulla Claude API e su Google Cloud, e l'API li elimina per un modello di fallback che non può leggerli.
* Le risposte servite tramite il middleware includono un blocco di contenuto `fallback` a ogni confine tra modelli, come le risposte del fallback lato server. Il middleware gestisce questi blocchi al posto tuo nelle richieste successive.
* Il modello che ha accettato viene registrato in `BetaFallbackState`, quindi le richieste successive che condividono lo stato restano fissate su di esso anziché interrogare di nuovo un modello che ha rifiutato.

<Note>
  Il middleware e il parametro `fallbacks` lato server svolgono lo stesso compito. Configura l'uno o l'altro, mai entrambi sulla stessa richiesta. Per inviare una richiesta `fallbacks` lato server da un'applicazione che installa il middleware, usa un'istanza client separata senza di esso.
</Note>

## Scrivere il nuovo tentativo da soli

Su HTTP grezzo o con logica di retry personalizzata, implementa il pattern che il middleware racchiude:

<Steps>
  <Step title="Rileva il rifiuto">
    Controlla se la risposta contiene `stop_reason: "refusal"`.
  </Step>

  <Step title="Rinvia su un modello di fallback">
    Invia la stessa richiesta con `model` impostato su un modello di fallback, come Claude Opus 4.8. Se la richiesta rifiutata ha inviato `thinking: {"type": "between_tools"}`, modifica prima `thinking`: solo Claude Sonnet 5.5 accetta quel valore, quindi ometti `thinking` o imposta un valore che il modello di fallback accetta. Il [fallback lato server](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#server-side-fallback) con l'header `2026-07-01` effettua questa modifica per te quando ripiega su Claude Sonnet 5. Un altro modello può normalmente servire una richiesta che Claude Fable 5.1 o Claude Fable 5 declina. Il modo in cui gestisci la cronologia della conversazione dipende dal fatto che tu riscatti o meno un [credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit):

    * **Senza riscattare un credito:** puoi lasciare al loro posto i blocchi `thinking` e `redacted_thinking` precedenti oppure rimuoverli per risparmiare token di input. In ogni caso, il modello di fallback normalmente non può usarli: solo Claude Fable 5.1 e Claude Mythos 5.1 [leggono i blocchi di Claude Fable 5.1](https://platform.claude.com/docs/it/build-with-claude/thinking#preserved-for-model), e solo questi due modelli, insieme a Claude Fable 5 e Claude Mythos 5, leggono i blocchi di Claude Fable 5, quindi per qualsiasi altro modello di fallback l'API li elimina. L'API elimina anche i blocchi di Claude Opus 5.5 per ogni modello di fallback tranne Claude Fable 5.1 e Claude Mythos 5.1 (vedi [Cambiare modello a metà conversazione](https://platform.claude.com/docs/it/build-with-claude/preserved-thinking#switching-models)). Elimina anche i blocchi di Claude Sonnet 5.5, per ogni modello di fallback tranne Claude Opus 5.5 sulla Claude API e su Google Cloud. Un nuovo tentativo dopo un rifiuto di Claude Haiku 5.5 rientra sempre in questo caso. Claude Opus 5.5 e Claude Sonnet 5.5 leggono i blocchi di Claude Haiku 5.5 sulla Claude API e su Google Cloud, quindi lascia quei blocchi al loro posto quando passi a uno di questi modelli su tali piattaforme. Per un modello di fallback che non può leggerli, l'API li elimina senza fatturarli.
    * **Riscattando un credito:** invia il corpo invariato, perché il riscatto richiede una corrispondenza esatta. Il server gestisce i blocchi di ragionamento del modello precedente durante un riscatto, quindi non rimuoverli (vedi [Campi che devono corrispondere alla richiesta rifiutata](https://platform.claude.com/docs/it/build-with-claude/fallback-credit#reference)).
  </Step>

  <Step title="Resta sul modello di fallback">
    Per le conversazioni a più turni, continua a usare il modello di fallback per i turni successivi anziché tornare al modello precedente.
  </Step>
</Steps>

Un nuovo tentativo manuale scrive da zero la cache dei prompt del modello di fallback, il che costa più che leggere una cache esistente. Il [credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit) rimborsa quel costo; riscattalo a ogni nuovo tentativo che costruisci tu stesso. Un rifiuto di Claude Haiku 5.5 non comporta alcun credito di fallback, quindi un nuovo tentativo successivo paga l'intero costo di scrittura della cache dei prompt del modello di fallback.

## Rifiuti nei Message Batches

Una richiesta rifiutata in un [Message Batch](https://platform.claude.com/docs/it/build-with-claude/batch-processing) torna come `result.type: "succeeded"` con `stop_reason: "refusal"`. I risultati batch contengono lo stesso oggetto `stop_details` delle risposte sincrone, quindi puoi rilevare i rifiuti tramite `stop_reason` o `stop_details.type`. Una differenza: i rifiuti batch non generano crediti di fallback, quindi `stop_details` su un risultato batch non include mai un `fallback_credit_token`.

Il fallback lato server non è disponibile per i batch (una richiesta batch che include `fallbacks` produce un risultato in errore per elemento). Per ritentare gli elementi batch rifiutati:

1. Raccogli gli elementi rifiutati dai risultati.
2. Lascia al loro posto i blocchi di ragionamento nelle cronologie multi-turno, oppure rimuovili per risparmiare token di input. Per un modello di fallback che non può leggerli, l'API li elimina senza fatturarli, come in [un nuovo tentativo manuale](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#manual-retry).
3. Se un elemento rifiutato ha inviato `thinking: {"type": "between_tools"}`, ometti `thinking` o imposta un valore accettato dal modello di fallback. Solo Claude Sonnet 5.5 accetta `between_tools`.
4. Reinviali su un modello di fallback come nuovo batch o come richieste dirette.

## Errori comuni

* **Ritenta su un modello diverso.** Reinviare una richiesta rifiutata allo stesso modello di solito produce un altro rifiuto. Indirizza il nuovo tentativo al modello di fallback.
* **Prevedi un budget di nuovi tentativi per richiesta, non per turno o per sessione.** Un singolo turno può produrre diversi rifiuti, ad esempio un agente più i suoi sotto-agenti.
* **Configura il fallback su ogni percorso di richiesta.** Gestori di retry, rami di recupero errori e worker in background ne hanno tutti bisogno. Un gestore che riemette una richiesta senza fallback perde la protezione proprio sulle richieste che più probabilmente ne hanno bisogno.
* **Dai alle chiamate dei sotto-agenti il proprio fallback.** Il parametro `fallbacks` non si propaga alle chiamate al modello effettuate dall'interno dell'esecuzione degli strumenti.
* **Rendi il fallback una proprietà della richiesta, non dello stato ambientale.** Un flag condiviso, un valore di configurazione in cache o un interruttore globale possono perdere la sincronizzazione e lasciare silenziosamente una richiesta non protetta. Quando non puoi confermare che il fallback sia attivo, configuralo anziché presumere che sia attivo.
* **Strumenta i rifiuti come segnale a sé.** Un rifiuto è un HTTP 200, quindi il monitoraggio basato sui tassi di errore o sulle risposte 5xx non lo vede mai. Emetti un evento per ogni rifiuto e uno per ogni risposta servita tramite fallback (la voce `fallback_message` in `usage.iterations` contrassegna quest'ultima), quindi imposta un avviso sul divario tra i due conteggi.
* **Dirama su `stop_reason` o `stop_details.type`, non su `content` o sui campi interni di `stop_details`.** L'oggetto `stop_details` è sempre presente in un rifiuto, ma i suoi campi `category` ed `explanation` possono essere `null`. Controlla direttamente che `stop_reason` sia uguale a `"refusal"`.

## Prossimi passi

<CardGroup>
  <Card title="Credito di fallback" icon="scales" href="https://platform.claude.com/docs/it/build-with-claude/fallback-credit">
    Evita di pagare due volte il costo della cache dei prompt quando costruisci tu stesso il nuovo tentativo.
  </Card>

  <Card title="Motivi di arresto e fallback" icon="code" href="https://platform.claude.com/docs/it/build-with-claude/handling-stop-reasons">
    Ogni valore di `stop_reason` e come gestirlo.
  </Card>

  <Card title="Middleware SDK" icon="settings" href="https://platform.claude.com/docs/it/cli-sdks-libraries/middleware">
    Come funziona il middleware SDK, incluso l'helper di fallback per i rifiuti.
  </Card>

  <Card title="Guida alla migrazione" icon="arrow-right" href="https://platform.claude.com/docs/it/models/fable-5-1/migration-guide">
    Sposta un'applicazione esistente su Claude Fable 5.1.
  </Card>
</CardGroup>
