Recusas e fallback
Como os modelos Claude Fable e Claude Opus retornam recusas de classificador e como repetir requisições recusadas em um modelo de fallback.
Claude Fable 5.1, Claude Fable 5 e Claude Opus 5 incluem classificadores de segurança que podem recusar uma requisição. Quando isso acontece, você recebe uma resposta normal, não um erro, com stop_reason: "refusal". Seu stop_details.category nomeia a área de política (consulte Como é uma recusa). Normalmente você ainda pode obter uma resposta enviando a mesma requisição para outro modelo Claude. Esta página mostra como reconhecer uma "refusal" (recusa) e como configurar essa nova tentativa.
Leia esta página quando você desenvolver sobre qualquer um desses modelos e quiser que requisições recusadas passem automaticamente para outro modelo. Ela também se aplica quando você viu "refusal" em uma resposta e quer saber o que fazer em seguida.
Páginas relacionadas:
- Motivos de parada e fallback: a lista completa de valores de
stop_reason. - Crédito de fallback: como evitar pagar o custo do cache de prompt duas vezes quando você mesmo constrói a nova tentativa.
- Middleware do SDK: o helper do SDK que encapsula tudo isso.
- Cookbook de fallback e cobrança: um exemplo completo de ponta a ponta.
A configuração mais simples, em beta na Claude API: defina fallbacks como "default", e a API repete uma requisição recusada no modelo de "fallback" (modelo alternativo) que a Anthropic recomenda para sua categoria de recusa. Para categorias sem fallback recomendado, a recusa permanece.
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)As seções a seguir abordam o que uma resposta de recusa contém, quando usar fallback do lado do servidor ou do lado do cliente, e como cada um é cobrado.
Como é uma recusa
Uma recusa é uma resposta HTTP 200 bem-sucedida com stop_reason: "refusal":
{
"id": "msg_01XFUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"model": "claude-fable-5",
"content": [],
"stop_reason": "refusal",
"stop_details": {
"type": "refusal",
"category": "cyber",
"explanation": "This request was declined because it could enable cyber harm."
},
"usage": {
"input_tokens": 412,
"output_tokens": 0
}
}O objeto stop_details explica a recusa:
category: nomeia a área de política que acionou o classificador.explanation: uma descrição legível por humanos. O texto não é estável, portanto exiba-o em vez de analisá-lo.recommended_model: presente apenas em requisições que definemfallbacks(fallback do lado do servidor, beta). Ele nomeia um modelo para repetir diretamente quando a API pulou a tentativa de fallback (por exemplo, o modelo de fallback estava com limite de taxa atingido), e énullcaso contrário. É uma sugestão, não uma garantia.categoryeexplanationsão ambosnullquando a recusa não corresponde a uma categoria nomeada. Essenullé um valor normal e permanente, não um placeholder.- O próprio
stop_detailsénullpara todos os motivos de parada que não sejamrefusal.
category | O que significa |
|---|---|
"cyber" | A requisição poderia viabilizar danos cibernéticos, como desenvolvimento de malware ou exploits. Trabalho benigno de cibersegurança também pode acionar esta categoria. |
"bio" | A requisição poderia viabilizar danos biológicos, como métodos laboratoriais perigosos. Trabalho benéfico em ciências da vida também pode acionar esta categoria. |
"frontier_llm" | A requisição poderia auxiliar o desenvolvimento de modelos de IA concorrentes, o que é restrito pelos termos comerciais da Anthropic. Trabalho benigno de aprendizado de máquina também pode acionar esta categoria. |
"reasoning_extraction" | A requisição pede ao modelo que reproduza seu raciocínio interno no texto da resposta. Para obter o raciocínio em uma forma estruturada, use o pensamento adaptativo. |
"general_harms" | A requisição se enquadra em uma área da política de uso fora das quatro categorias nomeadas. Trabalho benigno também pode acionar esta categoria. |
Uma recusa pode chegar antes de qualquer saída, ou no meio do stream após saída parcial. Em ambos os casos, trate qualquer saída parcial como incompleta e descarte-a.
Escolhendo uma abordagem de fallback
Há três maneiras de repetir uma requisição recusada em outro modelo. A correta depende de onde você está executando e de quanto controle você precisa.
| Sua situação | Use | Por quê |
|---|---|---|
| Claude API, configuração mais simples | Fallback do lado do servidor | Uma requisição, uma resposta. A API cuida da nova tentativa. |
| Qualquer plataforma, usando um SDK da Anthropic | O middleware do SDK | Configure uma vez no cliente. As novas tentativas acontecem automaticamente. |
| HTTP puro ou lógica de nova tentativa personalizada | Uma nova tentativa manual com crédito de fallback | Controle total. O crédito de fallback mantém o custo baixo. |
O fallback do lado do servidor e o middleware do SDK aplicam o crédito de fallback para você. Você só precisa da página Crédito de fallback quando constrói a nova tentativa por conta própria.
Fallback do lado do servidor
O fallback do lado do servidor repete uma requisição recusada dentro de uma única chamada de API. No modo padrão, quando o modelo primário recusa e a categoria de recusa tem um fallback recomendado, a API executa a mesma requisição no modelo que a Anthropic recomenda para essa categoria. Em vez disso, você pode nomear até três modelos de fallback próprios. De qualquer forma, você recebe de volta uma resposta que nomeia o modelo que respondeu, de modo que seu usuário obtém uma resposta em uma única ida e volta.
Fazendo a requisição
Defina o parâmetro fallbacks como a string "default" e envie o cabeçalho beta server-side-fallback-2026-07-01. A API então aplica o roteamento padrão definido pelo servidor para o modelo solicitado, que seleciona um modelo de fallback recomendado com base na categoria de recusa que o classificador reporta, de modo que requisições recusadas sejam atendidas sem que você precise manter uma lista de modelos à medida que as recomendações mudam.
O roteamento padrão nunca provoca a rejeição antecipada de imagem superdimensionada para modelos que você não escolheu: um modelo roteado que redimensionaria uma imagem marcada com "oversized_image": "error" é removido do roteamento, de modo que uma imagem marcada nunca é servida redimensionada.
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks="default",
betas=["server-side-fallback-2026-07-01"],
)
# Uma entrada fallback_message em usage.iterations indica que um modelo de fallback foi executado;
# combine-a com stop_reason para confirmar que o fallback forneceu a resposta.
fallback_ran = any(
iteration.type == "fallback_message"
for iteration in response.usage.iterations or []
)
served_by_fallback = fallback_ran and response.stop_reason != "refusal"
print(
json.dumps(
{
"stop_reason": response.stop_reason,
"model": response.model,
"served_by_fallback": served_by_fallback,
}
)
)A Anthropic define salvaguardas para cada modelo individualmente e para cada categoria de política, de acordo com a capacidade do modelo: dependendo da categoria, uma requisição sinalizada pode recorrer a um modelo menos capaz ou ser recusada. O modo "default" codifica essas recomendações por modelo e por categoria para você, de modo que uma requisição recusada é repetida no modelo que a Anthropic recomenda para essa categoria. Os fallbacks são visíveis de qualquer forma: a resposta nomeia o modelo que a atendeu, e o bloco de conteúdo fallback marca a transferência.
O roteamento é aplicado do lado do servidor e não é publicado por modelo na Models API. Para ver qual modelo atendeu uma requisição recusada, verifique o campo model de nível superior da resposta e procure uma entrada fallback_message em usage.iterations, como fazem os exemplos desta página.
Apenas uma recusa do classificador de segurança aciona o fallback. Um limite de taxa, sobrecarga ou erro de servidor no modelo solicitado é retornado a você como está.
Nomeando seus próprios modelos de fallback
Em vez do roteamento padrão, você pode definir fallbacks como uma lista de até três modelos. Quando o modelo solicitado recusa, a API executa o próximo modelo da cadeia na mesma requisição. Use esta forma quando quiser controlar exatamente quais modelos atendem requisições recusadas, como fixar um modelo que sua aplicação qualificou.
Modelos de fallback nomeados contam para a verificação de imagem superdimensionada: uma requisição cujo bloco de imagem define "oversized_image": "error" é verificada antecipadamente em relação ao modelo solicitado e a cada fallback nomeado, é rejeitada se qualquer um deles redimensionaria essa imagem, e o alvo de redimensionamento reportado na rejeição serve para todos eles.
As linhas destacadas são a única diferença em relação à requisição de roteamento padrão.
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)Algumas regras se aplicam à lista fallbacks:
- As entradas são tentadas em ordem. Cada uma deve ser distinta das outras entradas e do modelo solicitado.
- Cada entrada deve ser um dos alvos permitidos do modelo solicitado. Com o cabeçalho beta definido, essa lista é publicada como
allowed_fallback_modelsna entrada do modelo na Models API. - Cada entrada nomeia um
modele pode sobrescrevermax_tokens,thinking,output_configespeedapenas para aquela tentativa. - A requisição deve ser válida como uma requisição direta para cada modelo nomeado. Se um modelo de fallback não suporta um recurso que a requisição usa, a API rejeita a requisição antecipadamente.
- Assim como no modo padrão, apenas uma recusa do classificador de segurança aciona o fallback. Um limite de taxa, sobrecarga ou erro de servidor no modelo solicitado é retornado a você como está.
- Se um modelo de fallback está com limite de taxa atingido ou sobrecarregado, a tentativa de fallback não é feita e a recusa anterior é retornada em seu lugar. O
stop_details.recommended_modelda recusa então nomeia um modelo para repetir diretamente. Dimensione os limites de taxa do modelo de fallback para o volume de recusas que você espera, ou os fallbacks se degradam em recusas sob carga.
A resposta tem o mesmo formato em ambos os modos: o modelo que atendeu o turno aparece no campo model de nível superior, um bloco de conteúdo fallback marca a transferência, e usage.iterations registra cada tentativa.
O que a resposta contém
A resposta se parece com qualquer outra mensagem, com duas adições:
- O campo
modelde nível superior reporta o modelo que produziu a mensagem retornada, seja o modelo solicitado ou um fallback. - Um bloco de conteúdo
fallbackmarca cada ponto emcontentonde a saída de um modelo dá lugar à do próximo:{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}.from.modelecoa a string de modelo que você enviou quando o salto que recusa é o modelo solicitado.to.modelé sempre o ID resolvido do modelo que continua.
Em uma recusa antes de qualquer saída, o bloco fallback é o primeiro bloco de conteúdo. Por exemplo, quando o roteamento padrão seleciona Claude Opus 4.8 para a categoria da recusa:
{
"id": "msg_01XFUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"model": "claude-opus-4-8",
"content": [
{
"type": "fallback",
"from": { "model": "claude-fable-5" },
"to": { "model": "claude-opus-4-8" }
},
{ "type": "text", "text": "Hi! How can I help you today?" }
],
"stop_reason": "end_turn",
"stop_details": null,
"usage": {
"input_tokens": 412,
"output_tokens": 264,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0,
"iterations": [
{
"type": "message",
"model": "claude-fable-5",
"input_tokens": 535,
"output_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
},
{
"type": "fallback_message",
"model": "claude-opus-4-8",
"input_tokens": 412,
"output_tokens": 264,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
}
]
}
}O array usage.iterations registra cada tentativa. Um modelo que recusou aparece como uma entrada message comum, e o modelo que atendeu o turno aparece como uma entrada fallback_message. Se todos os modelos da cadeia recusarem, a resposta é a recusa do último modelo, com uma entrada message para cada salto anterior e uma entrada fallback_message para o último.
O roteamento persistente pode enviar um turno posterior diretamente para o modelo de fallback. Tal turno não carrega nenhum bloco de conteúdo fallback, porque nenhum modelo recusou aquele turno. Identifique-o pela entrada fallback_message em usage.iterations, pela ausência de uma entrada message para o modelo solicitado e pelo campo model da resposta.
Continuando a conversa
No próximo turno, envie o conteúdo do assistente de volta como você o recebeu. Após um fallback no meio da saída, content pode incluir tipos de bloco que o modelo que recusou produziu antes da transferência. A tabela a seguir indica quais manter e quais descartar quando você ecoa o turno.
| Tipo de bloco | No próximo turno |
|---|---|
fallback | Mantenha-o exatamente onde apareceu. A API usa sua posição para validar os blocos de pensamento ao redor dele, portanto uma requisição que ecoa blocos de pensamento de ambos os lados da fronteira é rejeitada se o bloco for omitido ou movido. |
text | Mantenha. |
Qualquer bloco após o bloco fallback final | Mantenha. |
thinking, redacted_thinking ou connector_text antes do bloco fallback final | Descarte. |
tool_use do lado do cliente antes do bloco fallback final | Descarte. |
server_tool_use antes do bloco fallback final | Mantenha quando pareado com seu resultado. Descarte quando não tiver resultado correspondente. |
Streaming
Em uma requisição com streaming, a nova tentativa acontece no mesmo stream, e nada do que você já recebeu é invalidado. O que você vê depende de quando a recusa acontece.
Quando a recusa acontece antes de qualquer saída:
message_startnomeia o modelo de fallback, e o blocofallbacké o primeiro bloco de conteúdo.- Como
message_startaguarda o início da tentativa de fallback, o tempo até o primeiro byte inclui a tentativa recusada.
Quando a recusa acontece no meio da saída:
- O bloco de conteúdo aberto é fechado, e o bloco
fallback(um par comum decontent_block_startecontent_block_stopsem deltas) marca a fronteira. - O modelo de fallback continua a partir da saída parcial. Apenas os blocos
textda saída parcial são passados ao modelo de fallback como contexto. Outros tipos de bloco permanecem emcontent. message_startjá nomeou o modelo solicitado, portanto leia o modelo que atendeu a partir doto.modeldo blocofallbacke da entradafallback_messageemusage.iterationsdomessage_deltafinal.
Respostas sem streaming
Em uma requisição sem streaming, uma recusa no meio da saída se comporta de forma diferente: a resposta omite a saída parcial do modelo que recusou, e o modelo de fallback responde do zero. O resultado se parece com uma recusa antes de qualquer saída, com o bloco fallback primeiro. A tentativa recusada e seus tokens de saída ainda aparecem em usage.iterations.
Cobrança e limites de taxa
Uma tentativa que recusou antes de produzir qualquer saída não é cobrada: seus tokens são reportados em sua entrada de usage.iterations, mas não cobrados. Cada tentativa que produziu saída, incluindo uma que recusou no meio de sua resposta, é cobrada separadamente às taxas do modelo que a executou. O array usage.iterations é o registro por tentativa do que é cobrado de você. As contagens de usage de nível superior descrevem apenas a tentativa que produziu a mensagem retornada. Tokens de modelos diferentes nunca são somados em um único campo.
Cada tentativa executada, incluindo uma que recusou, conta para os limites de taxa de seu próprio modelo.
Roteamento persistente
Depois que uma conversa recorre ao fallback, a API registra qual modelo a atendeu. Requisições posteriores para essa conversa que incluem fallbacks vão diretamente para esse modelo de fallback, sem executar o modelo solicitado. Isso evita pagar por uma tentativa que previsivelmente seria recusada novamente a cada turno.
Algumas propriedades da decisão de "sticky routing" (roteamento persistente):
- Ela é retida por aproximadamente 1 hora e tem escopo na sua organização.
- Ela é armazenada como um hash de conteúdo do prefixo da conversa mais o modelo que a atendeu. O conteúdo da mensagem em si não é armazenado.
- Ela é de melhor esforço, portanto seu código deve lidar com o modelo solicitado sendo tentado novamente a qualquer momento.
O roteamento persistente se aplica tanto a requisições com streaming quanto sem streaming. Em uma requisição com streaming, a decisão de roteamento é tomada antes de o stream abrir, portanto o campo model do evento message_start já carrega o ID do modelo de fallback.
Fallback do lado do cliente com o middleware do SDK
Todo SDK da Anthropic inclui um middleware de fallback de recusa. Você o configura uma vez no cliente com sua lista de modelos de fallback. Chamadas através de client.beta.messages então repetem requisições recusadas automaticamente, em qualquer plataforma. O middleware também envia o cabeçalho beta fallback-credit-2026-07-01 em cada requisição que ele trata, de modo que as novas tentativas são reprecificadas sem configuração por requisição.
Configurando
Passe o middleware ao construtor do cliente e compartilhe uma instância de BetaFallbackState entre as requisições de uma conversa.
from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware
# Em caso de recusa, o middleware tenta novamente no modelo de fallback listado e
# envia automaticamente o cabeçalho beta fallback-credit em cada requisição que processa.
client = Anthropic(
middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
)
state = BetaFallbackState() # pins follow-ups to the model that accepted
# Streaming: em caso de recusa, o middleware tenta novamente no modelo de fallback e
# insere seus eventos no stream aberto.
with (
state,
client.beta.messages.stream(
max_tokens=1024,
model="claude-fable-5",
messages=[{"role": "user", "content": "Hello, Claude"}],
) as stream,
):
for text in stream.text_stream:
print(text, end="", flush=True)
final_message = stream.get_final_message()
print(f"\nserved by: {final_message.model}")
# Sem streaming: reutilizar o estado mantém a conversa fixada.
with state:
message = client.beta.messages.create(
max_tokens=1024,
model="claude-fable-5",
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(f"served by: {message.model}")Como ele se comporta
- As novas tentativas percorrem sua lista de fallback em ordem. Um modelo de fallback que ele próprio recusa passa a requisição para a próxima entrada.
- Quando todos os modelos da lista recusaram, o middleware retorna a recusa final (a resposta de recusa do último modelo) em vez de lançar um erro.
- Blocos de pensamento do Claude Fable 5.1 ou Claude Fable 5 passam inalterados. Cada nova tentativa reenvia o corpo original da sua requisição, e os únicos blocos que o middleware remove do histórico da conversa em requisições posteriores são os blocos de fronteira
fallbackque ele mesmo adicionou. O modelo de fallback não consegue ler blocos do Claude Fable 5.1, que são preservados apenas para esse modelo ou um mais novo, portanto a API os descarta. - Respostas atendidas através do middleware incluem um bloco de conteúdo
fallbackem cada fronteira de modelo, da mesma forma que as respostas de fallback do lado do servidor. O middleware gerencia esses blocos para você em requisições posteriores. - O modelo que aceitou é registrado em
BetaFallbackState, de modo que requisições subsequentes que compartilham o estado permanecem fixadas nele em vez de perguntar novamente a um modelo que recusou.
Escrevendo a nova tentativa por conta própria
Sobre HTTP puro ou com lógica de nova tentativa personalizada, implemente o padrão que o middleware encapsula:
Detecte a recusa
Verifique a resposta em busca de
stop_reason: "refusal".Reenvie em um modelo de fallback
Envie a mesma requisição com
modeldefinido como um modelo de fallback, como Claude Opus 4.8. Outro modelo normalmente pode atender uma requisição que Claude Fable 5.1 ou Claude Fable 5 recusa. Como você lida com o histórico da conversa depende de você resgatar ou não um crédito de fallback:- Sem resgatar um crédito: você pode deixar os blocos
thinkingeredacted_thinkinganteriores no lugar ou removê-los para economizar tokens de entrada. O modelo de fallback não pode usá-los de qualquer forma: ele ignora blocos do Claude Fable 5, e blocos do Claude Fable 5.1 são preservados apenas para esse modelo ou um mais novo, portanto a API os descarta. - Resgatando um crédito: envie o corpo inalterado, porque o resgate exige uma correspondência exata. O servidor lida com os blocos de pensamento do modelo anterior em um resgate, portanto não os remova (consulte Campos que devem corresponder à requisição recusada).
- Sem resgatar um crédito: você pode deixar os blocos
Permaneça no modelo de fallback
Para conversas de múltiplos turnos, continue usando o modelo de fallback nos turnos subsequentes em vez de voltar ao anterior.
Uma nova tentativa manual grava o cache de prompt do modelo de fallback do zero, o que custa mais do que ler um cache existente. O crédito de fallback reembolsa esse custo; resgate-o em cada nova tentativa que você mesmo construir.
Recusas em Message Batches
Uma requisição recusada em um Message Batch retorna como result.type: "succeeded" com stop_reason: "refusal". Os resultados de lote carregam o mesmo objeto stop_details que as respostas síncronas, portanto você pode detectar recusas através de stop_reason ou de stop_details.type. Uma diferença: recusas em lote não geram créditos de fallback, portanto stop_details em um resultado de lote nunca inclui um fallback_credit_token.
O fallback do lado do servidor não está disponível para lotes (uma requisição de lote que inclui fallbacks produz um resultado com erro por item). Para repetir itens de lote recusados:
- Colete os itens recusados dos resultados.
- Remova os blocos de pensamento do Claude Fable 5.1 ou Claude Fable 5 de quaisquer históricos de múltiplos turnos.
- Reenvie-os em um modelo de fallback como um novo lote ou como requisições diretas.
Armadilhas comuns
- Repita em um modelo diferente. Reenviar uma requisição recusada para o mesmo modelo geralmente resulta em outra recusa. Direcione a nova tentativa para o modelo de fallback.
- Orce novas tentativas por requisição, não por turno ou por sessão. Um único turno pode produzir várias recusas, por exemplo um agente mais seus subagentes.
- Configure o fallback em todos os caminhos de requisição. Handlers de nova tentativa, ramificações de recuperação de erro e workers em segundo plano todos precisam dele. Um handler que reemite uma requisição sem fallback perde a proteção exatamente nas requisições com maior probabilidade de precisar dela.
- Dê às chamadas de subagentes seu próprio fallback. O parâmetro
fallbacksnão se propaga para chamadas de modelo feitas de dentro da execução de ferramentas. - Torne o fallback uma propriedade da requisição, não do estado ambiente. Uma flag compartilhada, um valor de configuração em cache ou um toggle global podem ficar fora de sincronia e silenciosamente deixar uma requisição desprotegida. Quando você não puder confirmar que o fallback está ativo, configure-o em vez de presumir que está ligado.
- Instrumente recusas como um sinal próprio. Uma recusa é um HTTP 200, portanto monitoramento baseado em taxas de erro ou respostas 5xx nunca a vê. Emita um evento por recusa e um por resposta atendida por fallback (a entrada
fallback_messageemusage.iterationsmarca esta última), e então alerte sobre a diferença entre as duas contagens. - Ramifique com base em
stop_reasonoustop_details.type, não emcontentou nos campos internos destop_details. O objetostop_detailsestá sempre presente em uma recusa, mas seus camposcategoryeexplanationpodem sernull. Verifique diretamente sestop_reasoné igual a"refusal".
Próximos passos
Evite pagar o custo do cache de prompt duas vezes quando você mesmo constrói a nova tentativa.
Cada valor de stop_reason e como lidar com ele.
Como o middleware do SDK funciona, incluindo o helper de fallback de recusa.
Mova uma aplicação existente para o Claude Fable 5.1.
Was this page helpful?