Claude Fable 5 include classificatori di sicurezza che possono rifiutare una richiesta. Quando ciò accade, ricevi una risposta normale, non un errore, con stop_reason: "refusal". Di solito puoi comunque ottenere una risposta inviando la stessa richiesta a un altro modello Claude. Questa pagina mostra come riconoscere un rifiuto e come configurare quel nuovo tentativo.
Leggi questa pagina quando sviluppi con Claude Fable 5 e vuoi che le richieste rifiutate passino automaticamente a un altro modello. Si applica anche quando hai appena visto "refusal" in una risposta e vuoi sapere cosa fare dopo.
L'elenco completo dei valori di stop_reason si trova in Motivi di arresto e fallback. I dettagli su come vengono fatturate le richieste rifiutate, e su come evitare di pagare due volte per la cache dei prompt su un nuovo tentativo, si trovano in Credito di fallback. L'helper dell'SDK che racchiude tutto questo si trova in Middleware SDK. Per un esempio completo end-to-end, consulta il Cookbook su fallback e fatturazione.
La configurazione più semplice: specifica un modello di fallback nella richiesta e l'API gestisce il nuovo tentativo.
await client.beta.messages.create({
model: "claude-fable-5",
max_tokens: 1024,
messages,
betas: ["server-side-fallback-2026-06-01"],
fallbacks: [{ model: "claude-opus-4-8" }]
});Le sezioni seguenti spiegano cosa contiene una risposta di rifiuto, quando usare il fallback lato server o lato client, e come viene fatturato ciascuno.
Un rifiuto è una risposta HTTP 200 riuscita con stop_reason: "refusal":
{
"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. Il suo campo category indica l'area di policy che ha attivato il classificatore. Il suo campo explanation è una descrizione leggibile dall'utente; il testo non è stabile, quindi visualizzalo anziché analizzarlo. Entrambi i campi sono null quando il rifiuto non corrisponde a una categoria denominata, e null è un valore normale e permanente, non un segnaposto. stop_details stesso è null per ogni motivo di arresto diverso da refusal.
category | Cosa significa |
|---|---|
"cyber" | La richiesta potrebbe consentire danni informatici, come lo sviluppo di malware o exploit. Anche il lavoro legittimo di cybersecurity può attivare questa categoria. |
"bio" | La richiesta potrebbe consentire danni biologici, come metodi di laboratorio pericolosi. Anche il lavoro benefico nelle scienze della vita può attivare questa categoria. |
"reasoning_extraction" | La richiesta chiede al modello di riprodurre il proprio ragionamento interno nel testo della risposta. Per ottenere il ragionamento in forma strutturata, usa invece l'adaptive thinking. |
Un rifiuto può arrivare prima di qualsiasi output, oppure a metà dello stream dopo un output parziale. In entrambi i casi, considera qualsiasi output parziale come incompleto e scartalo.
Come vengono fatturati i rifiuti: Un rifiuto prima di qualsiasi output lascia content vuoto e non ti viene addebitato nulla (i conteggi dei token appaiono in usage ma non vengono addebitati, e la richiesta non viene conteggiata ai fini dei limiti di velocità). Un rifiuto a metà dello stream addebita i token di input e l'output già trasmesso in streaming alle tariffe normali.
Ci sono tre modi per riprovare una richiesta rifiutata su un altro modello. Quello giusto dipende da dove stai eseguendo il codice e da quanto controllo ti serve.
| La tua situazione | Usa | Perché |
|---|---|---|
| API Claude o Claude Platform su AWS, configurazione più semplice | Fallback lato server | Una richiesta, una risposta. L'API gestisce il nuovo tentativo. |
| Qualsiasi piattaforma, con l'SDK TypeScript, Python, Go, Java o C# | Il middleware SDK | Configura una volta sul client. I nuovi tentativi avvengono automaticamente. |
| Ruby, PHP, HTTP grezzo o logica di retry personalizzata | Retry manuale con credito di fallback | Controllo completo. Il credito di fallback mantiene basso il costo. |
Il fallback lato server e il middleware SDK applicano il credito di fallback per te, quindi hai bisogno di quella pagina solo quando costruisci tu stesso il retry.
Il fallback lato server riprova una richiesta rifiutata all'interno di una singola chiamata API. Specifichi fino a tre modelli di fallback e, quando Claude Fable 5 rifiuta, l'API esegue il modello successivo nella catena sulla stessa richiesta. Ricevi una sola risposta che indica il modello che ha risposto, così il tuo utente ottiene una risposta in un unico round trip.
Il fallback lato server è in beta sull'API Claude e su Claude Platform su AWS. Il parametro fallbacks viene rifiutato sulla Message Batches API e non è disponibile su Amazon Bedrock, Vertex AI o Microsoft Foundry. Su quelle piattaforme, usa invece il middleware SDK.
Specifica i modelli di fallback nel parametro fallbacks e invia l'header beta server-side-fallback-2026-06-01.
Alcune regole si applicano all'elenco fallbacks:
allowed_fallback_models nella voce del modello nella Models API.model e può sovrascrivere max_tokens e thinking solo per quel tentativo.L'header beta deve contenere esattamente la data 2026-06-01. Con qualsiasi altro valore server-side-fallback-*, il parametro fallbacks viene rifiutato con un errore 400. Se hai sviluppato su una preview precedente di questa funzionalità, aggiorna insieme l'header beta e le forme di richiesta e risposta a quelle presenti in questa pagina.
La risposta è simile a qualsiasi altro messaggio, con due aggiunte:
model di primo livello riporta il modello che ha prodotto il messaggio restituito, che sia il modello richiesto o un fallback.fallback segna ogni punto in content in cui l'output di un modello lascia il posto al successivo: {"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}. from.model riporta la stringa del modello che hai inviato quando il passaggio che rifiuta è il modello richiesto. to.model è sempre l'ID risolto del modello che continua.In caso di rifiuto prima di qualsiasi output, il blocco fallback è il primo blocco di contenuto:
{
"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 rifiutato appare come una voce message ordinaria, e il modello che ha servito il turno appare come una voce fallback_message. Se ogni modello nella catena rifiuta, la risposta è il rifiuto dell'ultimo modello, con una voce message per ogni passaggio precedente e una voce fallback_message per l'ultimo.
Al turno successivo, rinvia 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 rifiutato ha prodotto prima del passaggio di consegne; la tabella seguente indica quali mantenere e quali eliminare quando riporti il turno.
| Tipo di blocco | Al turno successivo |
|---|---|
fallback | Mantienilo esattamente dove è apparso. L'API usa la sua posizione per validare i blocchi di thinking intorno ad esso, quindi una richiesta che riporta blocchi di thinking 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. |
| prima dell'ultimo blocco |
Un blocco connector_text contiene testo di narrazione che alcune risposte che usano strumenti includono tra le chiamate agli strumenti.
In una richiesta in streaming, il nuovo tentativo avviene sullo stesso stream e nulla di ciò che hai già ricevuto viene invalidato. 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 rifiutato. Quando il rifiuto avviene a metà output, il blocco di contenuto aperto si chiude, il blocco fallback (una coppia ordinaria content_block_start e content_block_stop senza delta) segna il confine, e il modello di fallback continua 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. Nel caso a metà output message_start ha già indicato il modello richiesto, quindi leggi il modello che serve dalla proprietà to.model del blocco fallback e dalla voce fallback_message in usage.iterations del message_delta finale.
In una richiesta non in streaming, un rifiuto a metà output si comporta diversamente: la risposta omette l'output parziale del modello che ha rifiutato, 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 rifiutato e i suoi token di output appaiono comunque in usage.iterations.
Quando un rifiuto si attiva dopo che gli strumenti server (ad esempio, ricerca web o esecuzione di codice) sono già stati eseguiti all'interno di una richiesta, l'API restituisce il rifiuto invece di passare a un modello di fallback. Se è impostato anche l'header fallback-credit-2026-06-01, quel rifiuto contiene un token di credito riscattabile continuando la risposta parziale, così il lavoro degli strumenti completato non va perso. Questo si applica solo agli strumenti server che iterano all'interno di una singola richiesta; le conversazioni che usano strumenti lato client eseguono il fallback normalmente.
Gli SDK TypeScript, Python, Go, Java e C# includono 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 riprovano quindi automaticamente le richieste rifiutate, su qualsiasi piattaforma. Il middleware invia anche l'header beta fallback-credit-2026-06-01 su ogni richiesta che gestisce, così i nuovi tentativi vengono ritariffati senza configurazione per richiesta.
L'helper del middleware di fallback per i rifiuti non è ancora disponibile negli SDK Ruby e PHP. Su quegli SDK, implementa direttamente il pattern rileva-e-riprova.
Passa il middleware al costruttore del client e condividi una singola istanza BetaFallbackState tra le richieste di una conversazione.
fallback a ogni confine tra modelli, come le risposte di fallback lato server. Il middleware gestisce quei blocchi per te nelle richieste successive.BetaFallbackState, così le richieste successive che condividono lo stato rimangono ancorate ad esso anziché interrogare di nuovo un modello che ha rifiutato.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.
Una richiesta rifiutata in un Message Batch ritorna come result.type: "succeeded" con stop_reason: "refusal". Il campo stop_details può essere null nei risultati batch, quindi rileva i rifiuti controllando direttamente stop_reason.
Il fallback lato server non è disponibile per i batch (una richiesta batch che include fallbacks produce un risultato di errore per elemento). Per riprovare gli elementi batch rifiutati:
fallbacks non si propaga nelle chiamate al modello effettuate dall'interno dell'esecuzione degli strumenti.fallback_message in segna quest'ultima), poi imposta un alert sulla differenza tra i due conteggi.Evita di pagare due volte il costo della cache dei prompt quando costruisci tu stesso il retry.
Ogni valore di stop_reason e come gestirlo.
Was this page helpful?
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-06-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 ha 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,
}
)
)server_tool_usefallback| Mantieni quando è abbinato al suo risultato. Elimina quando non ha un risultato corrispondente. |
# In caso di rifiuto, il middleware riprova sul modello di fallback indicato e
# invia automaticamente l'header beta fallback-credit su 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 sul modello di fallback e
# inserisce 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 event in stream:
if event.type == "text":
print(event.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 ancorata.
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}")usage.iterationsstop_reason, non su stop_details o content. stop_details è informativo e può essere null su un rifiuto. Controlla direttamente che stop_reason sia uguale a "refusal".Come funziona il middleware SDK, incluso l'helper di fallback per i rifiuti.