Claude Fable 5 e Claude Opus 5 includono 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 ti mostra come riconoscere un "refusal" (rifiuto) e come configurare quel nuovo tentativo.
Leggi questa pagina quando sviluppi su Claude Fable 5 o Claude Opus 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.
Pagine correlate:
stop_reason.La configurazione più semplice, in beta sulla Claude API: imposta fallbacks su "default", e l'API riprova una richiesta rifiutata sul modello di "fallback" (riserva) che Anthropic raccomanda per la sua categoria di rifiuto. Per le categorie senza un fallback raccomandato, il rifiuto rimane.
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)Le sezioni seguenti coprono 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:
category: indica l'area della policy che ha attivato il classificatore.explanation: una descrizione leggibile. Il testo non è stabile, quindi visualizzalo invece di analizzarlo.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 |
|---|---|
"cyber" | La richiesta potrebbe abilitare danni informatici, come lo sviluppo di malware o exploit. Anche il lavoro benigno di cybersecurity può attivare questa categoria. |
"bio" | La richiesta potrebbe abilitare danni biologici, come metodi di laboratorio pericolosi. Anche il lavoro benefico nelle scienze della vita può attivare questa categoria. |
"frontier_llm" | La richiesta potrebbe assistere lo sviluppo di modelli di IA concorrenti, il che è limitato dai termini commerciali di Anthropic. Anche il lavoro benigno di machine learning può attivare questa categoria. |
"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 pensiero adattivo. |
"general_harms" | La richiesta potrebbe essere correlata a un'area determinata come dannosa. Il lavoro benigno potrebbe talvolta attivare questa categoria. |
Un rifiuto può arrivare prima di qualsiasi output o a metà dello stream dopo un output parziale. In entrambi i casi, tratta qualsiasi output parziale come incompleto e scartalo.
Come vengono fatturati i rifiuti: Non ti viene addebitato un rifiuto che arriva prima di qualsiasi output. content è vuoto e i conteggi dei token appaiono in usage ma non vengono addebitati. La richiesta conta comunque ai fini dei tuoi limiti di velocità. Un rifiuto a metà stream fattura 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 e da quanto controllo ti serve.
| La tua situazione | Usa | Perché |
|---|---|---|
| Claude API, configurazione più semplice | Fallback lato server | Una richiesta, una risposta. L'API gestisce il nuovo tentativo. |
| Qualsiasi piattaforma, usando un SDK di Anthropic | Il middleware dell'SDK | Configura una volta sul client. I nuovi tentativi avvengono automaticamente. |
| HTTP grezzo o logica di retry personalizzata | Nuovo tentativo manuale con credito di fallback | Controllo completo. Il credito di fallback mantiene basso il costo. |
Il fallback lato server e il middleware dell'SDK applicano il credito di fallback per te. La pagina Credito di fallback ti serve solo quando costruisci il nuovo tentativo da solo.
Il fallback lato server riprova una richiesta rifiutata all'interno di una singola chiamata API. Nella modalità predefinita, quando il modello primario rifiuta e la categoria di rifiuto ha un fallback raccomandato, l'API esegue la stessa richiesta sul modello che Anthropic raccomanda per quella categoria. In alternativa puoi indicare fino a tre modelli di fallback di tua scelta (sotto). 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.
Il fallback lato server è in beta sulla Claude API. Il parametro fallbacks non è supportato sulla Message Batches API (un elemento del batch che lo include viene restituito come risultato con errore) e non è disponibile su Amazon Bedrock, Google Cloud o Microsoft Foundry. Su quelle piattaforme, usa invece il fallback lato client con il middleware dell'SDK.
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 lato server per il modello richiesto, che seleziona un modello di fallback raccomandato in base alla categoria di rifiuto segnalata dal classificatore, così le richieste rifiutate vengono servite senza che tu debba mantenere un elenco di modelli man mano che le raccomandazioni cambiano.
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 ha servito 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,
}
)
)Anthropic imposta le salvaguardie per ogni modello individualmente e per ogni categoria di policy, in linea con le capacità del modello: a seconda della categoria, una richiesta segnalata può ricadere su un modello meno capace o essere rifiutata. La modalità "default" codifica per te queste raccomandazioni per modello e per categoria, così una richiesta rifiutata viene riprovata 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.
Il routing viene applicato lato server e non è pubblicato per modello sulla Models API. 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'è.
L'header beta deve riportare esattamente la data 2026-07-01, che supporta sia "default" sia la forma con elenco esplicito qui sotto, 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 una preview precedente di questa funzionalità, aggiorna insieme l'header beta e le forme di richiesta e risposta a quelle di questa pagina.
Invece del routing predefinito, puoi impostare fallbacks su un elenco di massimo tre modelli. Quando il modello richiesto rifiuta, 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.
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)Alcune regole si applicano all'elenco fallbacks:
allowed_fallback_models nella voce del modello nella Models API.model e può sovrascrivere max_tokens, thinking, output_config e speed solo per quel tentativo.La forma con elenco esplicito funziona anche con l'header beta server-side-fallback-2026-06-01; la modalità "default" no.
La risposta ha la stessa forma in entrambe le modalità: il modello che ha servito il turno appare nel campo model di primo livello, un blocco di contenuto fallback segna il passaggio e usage.iterations registra ogni tentativo.
La risposta appare come 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 l'hop 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. Ad esempio, quando il routing predefinito seleziona Claude Opus 4.8 per la categoria del rifiuto:
{
"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 normale voce message, 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 hop precedente e una voce fallback_message per l'ultimo.
Al turno successivo, rinvia il contenuto dell'assistente così come lo hai ricevuto. Dopo un fallback a metà output, content può includere tipi di blocco prodotti dal modello che ha rifiutato prima del passaggio; la tabella seguente indica quali mantenere e quali eliminare quando rinvii il turno.
| Tipo di blocco | Al turno successivo |
|---|---|
fallback | Mantienilo esattamente dove è apparso. L'API usa la sua posizione per convalidare i blocchi di thinking intorno ad esso, quindi una richiesta che rinvia blocchi di thinking da entrambi i lati del confine viene rifiutata se il blocco è omesso o spostato. |
text | Mantieni. |
Qualsiasi blocco dopo il blocco fallback finale | Mantieni. |
thinking, redacted_thinking o connector_text prima del blocco fallback finale | Elimina. |
tool_use lato client prima del blocco fallback finale | Elimina. |
server_tool_use prima del blocco fallback finale | Mantieni quando è abbinato al suo risultato. Elimina quando non ha un risultato corrispondente. |
Un blocco connector_text contiene il testo di narrazione che alcune risposte con uso degli 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. 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.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:
fallback (una normale coppia content_block_start e content_block_stop senza delta) segna il confine.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 serve la richiesta dal 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 output token appaiono comunque in usage.iterations.
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, la ricerca web o l'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 riprovato è 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 riprova prima di rispondere.
Ogni SDK di Anthropic include un middleware di refusal-fallback. 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-07-01 su ogni richiesta che gestisce, così i nuovi tentativi vengono riprezzati senza configurazione per richiesta.
Passa il middleware al costruttore del client e condividi una singola istanza di BetaFallbackState tra le richieste di una conversazione.
from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware
# In caso di rifiuto, il middleware riprova sul modello di fallback indicato e
# invia automaticamente l'header beta fallback-credit in 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 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 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}")fallback che ha aggiunto esso stesso.fallback a ogni confine tra modelli, come le risposte del fallback lato server. Il middleware gestisce quei blocchi per te nelle richieste successive.BetaFallbackState, così le richieste successive che condividono lo stato rimangono fissate su di esso invece di 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 viene restituita come result.type: "succeeded" con stop_reason: "refusal". I risultati del 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 nei batch non generano crediti di fallback, quindi stop_details su un risultato di 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 con errore per elemento). Per riprovare gli elementi del batch rifiutati:
fallbacks non si propaga alle chiamate al modello effettuate dall'interno dell'esecuzione degli strumenti.fallback_message in usage.iterations contrassegna quest'ultima), poi imposta un avviso sul divario tra i due conteggi.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".Evita di pagare due volte il costo della cache dei prompt quando costruisci il nuovo tentativo da solo.
Ogni valore di stop_reason e come gestirlo.
Come funziona il middleware dell'SDK, incluso l'helper di refusal-fallback.
Migra un'applicazione esistente a Claude Fable 5.
Was this page helpful?