Refus et repli
Comment les modèles Claude Fable, les modèles Claude Opus, Claude Sonnet 5.5 et Claude Haiku 5.5 renvoient des refus de classificateur et comment relancer les requêtes refusées sur un modèle de repli.
Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 et Claude Haiku 5.5 incluent des « safety classifiers » (classificateurs de sécurité) qui peuvent décliner une requête. Lorsque cela se produit, vous recevez une réponse normale, et non une erreur, avec stop_reason: "refusal". Son champ stop_details.category nomme le domaine de politique concerné (voir À quoi ressemble un refus). Vous pouvez généralement obtenir malgré tout une réponse en envoyant la même requête à un autre modèle Claude. Cette page vous montre comment reconnaître un refus et comment mettre en place cette nouvelle tentative.
Lisez cette page lorsque vous développez sur l'un de ces modèles et souhaitez que les requêtes déclinées basculent automatiquement vers un autre modèle. Elle s'applique également lorsque vous avez vu "refusal" dans une réponse et souhaitez savoir quoi faire ensuite.
Pages connexes :
- Raisons d'arrêt et repli : la liste complète des valeurs de
stop_reason. - Crédit de repli : comment éviter de payer deux fois le coût de la mise en cache des prompts lorsque vous construisez vous-même la nouvelle tentative.
- Middleware SDK : l'utilitaire SDK qui encapsule tout cela.
- Cookbook sur le repli et la facturation : un exemple complet de bout en bout.
La configuration la plus simple, en bêta sur l'API Claude : définissez fallbacks sur "default", et l'API relance une requête déclinée sur le « fallback model » (modèle de repli) qu'Anthropic recommande pour sa catégorie de refus. Pour les catégories sans repli recommandé, le refus est maintenu. Claude Haiku 5.5 ne dispose pas de repli côté serveur ; pour ce modèle, utilisez donc le repli côté client avec le middleware SDK ou écrivez vous-même la nouvelle tentative.
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)Les sections suivantes décrivent ce que contient une réponse de refus, quand utiliser le repli côté serveur ou côté client, et comment chacun est facturé.
À quoi ressemble un refus
Un refus est une réponse HTTP 200 réussie avec 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'objet stop_details explique le refus :
category: nomme le domaine de politique qui a déclenché le classificateur.explanation: une description lisible par un humain. Le texte n'est pas stable, affichez-le donc plutôt que de l'analyser.recommended_model: présent uniquement sur les requêtes qui définissentfallbacks(repli côté serveur, bêta). Il nomme un modèle sur lequel relancer directement lorsque l'API a ignoré la tentative de repli (par exemple, le modèle de repli était soumis à une limite de débit), et vautnullsinon. C'est une indication, pas une garantie.categoryetexplanationvalent tous deuxnulllorsque le refus ne correspond à aucune catégorie nommée. Cenullest une valeur normale et permanente, pas un espace réservé.stop_detailslui-même vautnullpour toute raison d'arrêt autre querefusal.
category | Signification | Facturé avant toute sortie |
|---|---|---|
"cyber" | La requête pourrait permettre un préjudice cyber, comme le développement de logiciels malveillants ou d'exploits. Un travail de cybersécurité bénin peut également déclencher cette catégorie. | Non |
"bio" | La requête pourrait permettre un préjudice biologique, comme des méthodes de laboratoire dangereuses. Un travail bénéfique en sciences de la vie peut également déclencher cette catégorie. | Oui |
"frontier_llm" | La requête pourrait aider au développement de modèles d'IA concurrents, ce qui est restreint par les conditions commerciales d'Anthropic. Un travail bénin en apprentissage automatique peut également déclencher cette catégorie. | Oui |
"reasoning_extraction" | La requête demande au modèle de reproduire son raisonnement interne dans le texte de la réponse. Pour obtenir le raisonnement sous une forme structurée, utilisez plutôt la réflexion adaptative. Voir Conserver le raisonnement dans les blocs de réflexion. | Oui |
"general_harms" | La requête relève d'un domaine de la politique d'utilisation en dehors des quatre catégories nommées. Un travail bénin peut également déclencher cette catégorie. | Non |
Un refus peut arriver avant toute sortie, ou en cours de streaming après une sortie partielle. Dans les deux cas, considérez toute sortie partielle comme incomplète et écartez-la.
Conserver le raisonnement dans les blocs de réflexion
Un refus reasoning_extraction provient généralement d'un prompt qui demande au modèle de placer sa réflexion ou son raisonnement dans la sortie, soit mot pour mot, soit dans un format fixe. Exemples courants :
- Une section
<thinking>,<reasoning>ou de brouillon que le modèle remplit avant de répondre - Un champ
reasoning,thinkingoutracedans une sortie JSON ou dans une entrée d'outil - Les notes privées du modèle, ou un journal continu de son raisonnement
- Un raisonnement demandé mot pour mot ou dans son intégralité
La formulation peut se trouver dans une invite système, une skill ou une description d'outil, vérifiez donc également ces éléments.
Vous pouvez toujours demander à Claude d'expliquer sa réponse. Demandez une brève explication, les éléments justifiant un résultat, ou un résumé des actions qu'il a effectuées. Pour voir comment le modèle a raisonné, définissez display: "summarized" et lisez les blocs thinking. Cette catégorie n'a pas de modèle de repli recommandé, modifiez donc le prompt plutôt que de relancer la requête. Si une requête reformulée est toujours déclinée, contactez le support et incluez l'ID de requête.
Facturation des refus
Ces règles de facturation s'appliquent sur toutes les plateformes : l'API Claude, Amazon Bedrock, Claude Platform on AWS, Google Cloud et Microsoft Foundry.
Refus avant toute sortie : afin d'entraver les tentatives de contournement à grande échelle des garde-fous d'Anthropic, un refus survenant avant toute sortie est facturé lorsque son stop_details.category vaut "bio", "frontier_llm" ou "reasoning_extraction". Ce sont les catégories pour lesquelles, en septembre 2026, Anthropic mesure de faibles volumes de faux positifs. Ces refus sont facturés comme toute autre requête, aux tarifs du modèle qui l'a exécutée. Un refus avant toute sortie dans toute autre catégorie, ou avec une catégorie null, n'est pas facturé. Dans tous les cas, content est vide, et les décomptes de tokens apparaissent dans usage. La requête compte tout de même dans vos limites de débit.
Refus en cours de streaming : un refus en cours de streaming facture les tokens d'entrée et la sortie déjà diffusée aux tarifs normaux.
Repli : lorsque vous utilisez le repli, le refus qui l'a déclenché est facturé, en plus de la requête de repli, lorsqu'il est survenu en cours de streaming ou qu'il appartient à l'une des catégories facturées. Le crédit de repli compense l'échec du cache de prompts pour la requête de repli, afin que vous ne payiez pas deux fois la mise en cache de la conversation. Un refus de Claude Haiku 5.5 ne donne droit à aucun crédit de repli ; un repli après un tel refus paie donc le coût complet de l'écriture du cache de prompts du modèle de repli. Pour savoir comment le repli côté serveur rend compte de chaque tentative, consultez Facturation et limites de débit.
Les catégories facturées peuvent évoluer à mesure qu'Anthropic continue de mesurer et d'affiner les taux de faux positifs de ses garde-fous. La colonne Facturé avant toute sortie du tableau des catégories de refus répertorie les catégories facturées.
Choisir une approche de repli
Il existe trois façons de relancer une requête refusée sur un autre modèle. La bonne dépend de l'endroit où vous exécutez votre code et du niveau de contrôle dont vous avez besoin.
| Votre situation | Utilisez | Pourquoi |
|---|---|---|
| API Claude, configuration la plus simple | Repli côté serveur | Une requête, une réponse. L'API gère la nouvelle tentative. |
| Toute plateforme, avec un SDK Anthropic | Le middleware SDK | Configurez une fois sur le client. Les nouvelles tentatives se font automatiquement. |
| HTTP brut ou logique de nouvelle tentative personnalisée | Une nouvelle tentative manuelle avec crédit de repli | Contrôle total. Le crédit de repli limite le coût. |
Le repli côté serveur et le middleware SDK appliquent le crédit de repli pour vous. Vous n'avez besoin de la page Crédit de repli que lorsque vous implémentez vous-même la nouvelle tentative. Claude Haiku 5.5 ne dispose ni du repli côté serveur ni du crédit de repli ; utilisez donc le middleware SDK ou une nouvelle tentative manuelle.
Repli côté serveur
Le repli côté serveur relance une requête refusée au sein d'un seul appel API. Dans le mode par défaut, lorsque le modèle principal décline et que la catégorie de refus dispose d'un repli recommandé, l'API exécute la même requête sur le modèle qu'Anthropic recommande pour cette catégorie. Vous pouvez à la place nommer jusqu'à trois modèles de repli de votre choix. Dans les deux cas, vous recevez une seule réponse qui nomme le modèle ayant répondu, de sorte que votre utilisateur obtient une réponse en un seul aller-retour.
Effectuer la requête
Définissez le paramètre fallbacks sur la chaîne "default" et envoyez l'en-tête bêta server-side-fallback-2026-07-01. L'API applique alors le routage par défaut défini côté serveur pour le modèle demandé, qui sélectionne un modèle de repli recommandé en fonction de la catégorie de refus signalée par le classificateur, de sorte que les requêtes refusées sont servies sans que vous ayez à maintenir une liste de modèles au fil de l'évolution des recommandations.
Le routage par défaut ne déclenche jamais le rejet préalable pour image surdimensionnée pour des modèles que vous n'avez pas choisis : un modèle routé qui redimensionnerait une image marquée "oversized_image": "error" est plutôt retiré du routage, de sorte qu'une image marquée n'est jamais servie redimensionnée.
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"],
)
# Une entrée fallback_message dans usage.iterations signifie qu'un modèle de repli a été exécuté ;
# associez-la à stop_reason pour confirmer que le repli a fourni la réponse.
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 définit des garde-fous pour chaque modèle individuellement et pour chaque catégorie de politique, en fonction des capacités du modèle : selon la catégorie, une requête signalée peut se replier sur un modèle moins performant ou être déclinée. Le mode "default" encode pour vous ces recommandations par modèle et par catégorie, de sorte qu'une requête refusée est relancée sur le modèle qu'Anthropic recommande pour cette catégorie. Les replis sont visibles dans tous les cas : la réponse nomme le modèle qui l'a servie, et le bloc de contenu fallback marque le passage de relais.
Le routage est appliqué côté serveur et n'est pas publié par modèle sur l'API Models. Pour voir quel modèle a servi une requête refusée, vérifiez le champ model de premier niveau de la réponse et recherchez une entrée fallback_message dans usage.iterations, comme le font les exemples de cette page.
Seul un refus du classificateur de sécurité déclenche le repli. Une limite de débit, une surcharge ou une erreur serveur sur le modèle demandé vous est renvoyée telle quelle.
Nommer vos propres modèles de repli
Au lieu du routage par défaut, vous pouvez définir fallbacks sur une liste de trois modèles au maximum. Lorsque le modèle demandé décline, l'API exécute le modèle suivant de la chaîne sur la même requête. Utilisez cette forme lorsque vous souhaitez contrôler exactement quels modèles servent les requêtes refusées, par exemple pour épingler un modèle que votre application a qualifié.
Les modèles de repli nommés comptent pour la vérification d'image surdimensionnée : une requête dont le bloc image définit "oversized_image": "error" est vérifiée au préalable par rapport au modèle demandé et à chaque repli nommé, est rejetée si l'un d'eux redimensionnerait cette image, et la cible de redimensionnement indiquée dans le rejet convient à tous.
Les lignes surlignées sont la seule différence avec la requête à routage par défaut.
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)Quelques règles s'appliquent à la liste fallbacks :
- Les entrées sont essayées dans l'ordre. Chacune doit être distincte des autres entrées et du modèle demandé.
- Chaque entrée doit faire partie des cibles autorisées du modèle demandé. Lorsque l'en-tête bêta est défini, cette liste est publiée sous la forme
allowed_fallback_modelsdans l'entrée du modèle de l'API Models. - Chaque entrée désigne un
modelet peut remplacermax_tokens,thinking,output_configetspeedpour cette tentative uniquement. - La requête doit être valide en tant que requête directe vers chaque modèle nommé. Si un modèle de repli ne prend pas en charge une fonctionnalité utilisée par la requête, l'API rejette la requête en amont. Avec l'en-tête
2026-07-01,thinking: {"type": "between_tools"}fait exception : lorsqu'une requête Claude Sonnet 5.5 bascule vers Claude Sonnet 5, la tentative de repli s'exécute avecthinking: {"type": "disabled"}etdisplay: "omitted". Avec2026-06-01, définissezthinkingsur l'entrée Claude Sonnet 5, sinon la requête est rejetée en amont. - Comme pour le mode par défaut, seul un refus d'un classificateur de sécurité déclenche le repli. Une limite de débit, une surcharge ou une erreur serveur sur le modèle demandé vous est renvoyée telle quelle.
- Si un modèle de repli a atteint sa limite de débit ou est surchargé, la tentative de repli n'est pas effectuée et le refus précédent est renvoyé à la place. Le champ
stop_details.recommended_modeldu refus indique alors un modèle à relancer directement. Dimensionnez les limites de débit du modèle de repli en fonction du volume de refus attendu, sinon les replis se transforment en refus sous charge.
La réponse a la même forme dans les deux modes : le modèle qui a servi le tour apparaît dans le champ model de premier niveau, un bloc de contenu fallback marque le passage de relais, et usage.iterations enregistre chaque tentative.
Ce que contient la réponse
La réponse ressemble à n'importe quel autre message, avec deux ajouts :
- Le champ
modelde premier niveau indique le modèle qui a produit le message renvoyé, qu'il s'agisse du modèle demandé ou d'un repli. - Un bloc de contenu
fallbackmarque chaque point danscontentoù la sortie d'un modèle cède la place au suivant :{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}.from.modelreprend la chaîne de modèle que vous avez envoyée lorsque l'étape qui décline est le modèle demandé.to.modelest toujours l'identifiant résolu du modèle qui poursuit.
Lors d'un refus avant toute sortie, le bloc fallback est le premier bloc de contenu. Par exemple, lorsque le routage par défaut sélectionne Claude Opus 4.8 pour la catégorie du refus :
{
"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
}
]
}
}Le tableau usage.iterations enregistre chaque tentative. Un modèle qui a décliné apparaît comme une entrée message ordinaire, et le modèle qui a servi le tour apparaît comme une entrée fallback_message. Si tous les modèles de la chaîne déclinent, la réponse est le refus du dernier modèle, avec une entrée message pour chaque étape précédente et une entrée fallback_message pour la dernière.
Le routage persistant peut envoyer un tour ultérieur directement au modèle de repli. Un tel tour ne porte aucun bloc de contenu fallback, car aucun modèle n'a décliné ce tour. Identifiez-le par l'entrée fallback_message dans usage.iterations, l'absence d'entrée message pour le modèle demandé, et le champ model de la réponse.
Poursuivre la conversation
Au tour suivant, renvoyez le contenu de l'assistant tel que vous l'avez reçu. Après un repli en cours de sortie, content peut inclure des types de blocs que le modèle ayant décliné a produits avant le passage de relais. Le tableau suivant indique lesquels conserver et lesquels supprimer lorsque vous renvoyez le tour.
| Type de bloc | Au tour suivant |
|---|---|
fallback | Conservez-le exactement là où il apparaissait. L'API utilise sa position pour valider les blocs de réflexion qui l'entourent, de sorte qu'une requête qui renvoie des blocs de réflexion des deux côtés de la frontière est rejetée si le bloc est omis ou déplacé. |
text | Conserver. |
Tout bloc après le dernier bloc fallback | Conserver. |
thinking, redacted_thinking ou connector_text avant le dernier bloc fallback | Supprimer. |
tool_use côté client avant le dernier bloc fallback | Supprimer. |
server_tool_use avant le dernier bloc fallback | Conserver lorsqu'il est associé à son résultat. Supprimer lorsqu'il n'a pas de résultat correspondant. |
Streaming
Sur une requête en streaming, la nouvelle tentative se produit sur le même flux, et rien de ce que vous avez déjà reçu n'est invalidé. Ce que vous voyez dépend du moment où le refus se produit.
Lorsque le refus se produit avant toute sortie :
message_startnomme le modèle de repli, et le blocfallbackest le premier bloc de contenu.- Comme
message_startattend que la tentative de repli démarre, le délai jusqu'au premier octet inclut la tentative déclinée.
Lorsque le refus se produit en cours de sortie :
- Le bloc de contenu ouvert se ferme, et le bloc
fallback(une paire ordinairecontent_block_startetcontent_block_stopsans deltas) marque la frontière. - Le modèle de repli poursuit à partir de la sortie partielle. Seuls les blocs
textde la sortie partielle sont transmis au modèle de repli comme contexte. Les autres types de blocs restent danscontent. message_starta déjà nommé le modèle demandé, lisez donc le modèle servant dans le champto.modeldu blocfallbacket dans l'entréefallback_messageduusage.iterationsdu derniermessage_delta.
Réponses sans streaming
Sur une requête sans streaming, un refus en cours de sortie se comporte différemment : la réponse omet la sortie partielle du modèle ayant décliné, et le modèle de repli répond à partir de zéro. Le résultat ressemble à un refus avant toute sortie, avec le bloc fallback en premier. La tentative déclinée et ses tokens de sortie apparaissent toujours dans usage.iterations.
Facturation et limites de débit
Chaque tentative suit les règles de la section Facturation des refus, aux tarifs du modèle qui l'a exécutée. Une tentative qui a décliné avant de produire la moindre sortie n'est facturée que si sa catégorie de refus est facturée, et ses tokens sont indiqués dans son entrée usage.iterations dans tous les cas. Chaque tentative ayant produit une sortie, y compris une tentative qui a décliné en cours de réponse, est facturée séparément. Le tableau usage.iterations est le relevé par tentative de ce qui vous est facturé. Les décomptes usage de premier niveau décrivent uniquement la tentative qui a produit le message renvoyé. Les tokens de modèles différents ne sont jamais additionnés dans un même champ.
Chaque tentative exécutée, y compris une tentative qui a décliné, compte dans les limites de débit de son propre modèle.
Routage persistant
Après qu'une conversation s'est repliée, l'API enregistre quel modèle l'a servie. Les requêtes ultérieures pour cette conversation qui incluent fallbacks vont directement à ce modèle de repli, sans exécuter le modèle demandé. Cela évite de payer à chaque tour une tentative qui serait de manière prévisible déclinée à nouveau.
Quelques propriétés de la décision de routage :
- Elle est conservée pendant environ 1 heure et est limitée à votre organisation.
- Elle est stockée sous forme de hachage de contenu du préfixe de conversation plus le modèle qui l'a servie. Le contenu des messages lui-même n'est pas stocké.
- Elle est fournie au mieux, votre code doit donc gérer le fait que le modèle demandé soit réessayé à tout moment.
Le routage persistant s'applique aux requêtes avec et sans streaming. Sur une requête en streaming, la décision de routage est prise avant l'ouverture du flux, de sorte que le champ model de l'événement message_start porte déjà l'identifiant du modèle de repli.
Repli côté client avec le middleware SDK
Le SDK inclut un middleware de repli en cas de refus. Vous le configurez une seule fois sur le client avec votre liste de modèles de repli. Les appels effectués via client.beta.messages relancent alors automatiquement les requêtes refusées, sur n'importe quelle plateforme. Le middleware envoie également l'en-tête bêta fallback-credit-2026-07-01 sur chaque requête qu'il traite, de sorte que les nouvelles tentatives sont retarifées sans configuration par requête. Un refus de Claude Haiku 5.5 ne donne droit à aucun crédit de repli ; une nouvelle tentative après un tel refus paie donc le coût complet de l'écriture du cache de prompts du modèle de repli.
Configuration
Passez BetaRefusalFallbackMiddleware au constructeur du client, et partagez une seule instance de BetaFallbackState entre les requêtes d'une conversation.
from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware
# En cas de refus, le middleware réessaie sur le modèle de repli indiqué et
# envoie automatiquement l'en-tête bêta fallback-credit à chaque requête qu'il traite.
client = Anthropic(
middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
)
state = BetaFallbackState() # pins follow-ups to the model that accepted
# Streaming : en cas de refus, le middleware réessaie sur le modèle de repli et
# raccorde ses événements au flux ouvert.
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}")
# Sans streaming : réutiliser l'état maintient la conversation épinglée.
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}")Comportement
- Les nouvelles tentatives parcourent votre liste de replis dans l'ordre. Un modèle de repli qui refuse lui-même transmet la requête à l'entrée suivante.
- Lorsque tous les modèles de la liste ont décliné, le middleware renvoie le refus final (la réponse de refus du dernier modèle) plutôt que de lever une erreur.
- Les blocs de réflexion de Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5, Claude Haiku 5.5 ou Claude Fable 5 sont transmis sans modification. Chaque nouvelle tentative renvoie le corps de votre requête d'origine, et les seuls blocs que le middleware retire de l'historique de conversation lors des requêtes ultérieures sont les blocs de frontière
fallbackqu'il a lui-même ajoutés. Le modèle de repli ne peut pas lire les blocs de Claude Fable 5.1, que seuls Claude Fable 5.1 et Claude Mythos 5.1 lisent ; l'API les supprime donc. L'API supprime également les blocs de Claude Opus 5.5 pour tous les modèles de repli sauf Claude Fable 5.1 et Claude Mythos 5.1 (voir Changer de modèle en cours de conversation). Elle supprime aussi les blocs de Claude Sonnet 5.5, pour tous les modèles de repli sauf Claude Opus 5.5 sur l'API Claude et Google Cloud. Claude Opus 5.5 et Claude Sonnet 5.5 lisent les blocs de Claude Haiku 5.5 sur l'API Claude et Google Cloud, et l'API les supprime pour un modèle de repli qui ne peut pas les lire. - Les réponses servies via le middleware incluent un bloc de contenu
fallbackà chaque limite entre modèles, comme les réponses du repli côté serveur. Le middleware gère ces blocs pour vous lors des requêtes ultérieures. - Le modèle qui a accepté est enregistré dans
BetaFallbackState, de sorte que les requêtes suivantes qui partagent cet état restent épinglées sur lui plutôt que de solliciter à nouveau un modèle qui a refusé.
Écrire vous-même la nouvelle tentative
En HTTP brut ou avec une logique de nouvelle tentative personnalisée, implémentez le modèle que le middleware encapsule :
Détecter le refus
Vérifiez si la réponse contient
stop_reason: "refusal".Renvoyer sur un modèle de repli
Envoyez la même requête avec
modeldéfini sur un modèle de repli, comme Claude Opus 4.8. Si la requête refusée envoyaitthinking: {"type": "between_tools"}, modifiez d'abordthinking: seul Claude Sonnet 5.5 accepte cette valeur, omettez doncthinkingou définissez une valeur acceptée par le modèle de repli. Le repli côté serveur avec l'en-tête2026-07-01effectue cette modification pour vous lorsqu'il bascule vers Claude Sonnet 5. Un autre modèle peut normalement servir une requête que Claude Fable 5.1 ou Claude Fable 5 décline. La façon dont vous gérez l'historique de conversation dépend de l'utilisation ou non d'un crédit de repli :- Sans utiliser de crédit : vous pouvez laisser en place les blocs
thinkingetredacted_thinkingantérieurs ou les retirer pour économiser des tokens d'entrée. Le modèle de repli ne peut normalement pas les utiliser dans un cas comme dans l'autre : seuls Claude Fable 5.1 et Claude Mythos 5.1 lisent les blocs de Claude Fable 5.1, et seuls ces deux modèles ainsi que Claude Fable 5 et Claude Mythos 5 lisent les blocs de Claude Fable 5 ; pour tout autre modèle de repli, l'API les supprime donc. L'API supprime également les blocs de Claude Opus 5.5 pour tous les modèles de repli sauf Claude Fable 5.1 et Claude Mythos 5.1 (voir Changer de modèle en cours de conversation). Elle supprime aussi les blocs de Claude Sonnet 5.5, pour tous les modèles de repli sauf Claude Opus 5.5 sur l'API Claude et Google Cloud. Une nouvelle tentative après un refus de Claude Haiku 5.5 relève toujours de ce cas. Claude Opus 5.5 et Claude Sonnet 5.5 lisent les blocs de Claude Haiku 5.5 sur l'API Claude et Google Cloud ; laissez donc ces blocs en place lorsque vous basculez vers l'un de ces modèles sur ces plateformes. Pour un modèle de repli qui ne peut pas les lire, l'API les supprime sans les facturer. - En utilisant un crédit : envoyez le corps sans modification, car l'utilisation du crédit exige une correspondance exacte. Le serveur gère les blocs de réflexion du modèle précédent lors de l'utilisation d'un crédit, ne les supprimez donc pas (consultez Champs qui doivent correspondre à la requête refusée).
- Sans utiliser de crédit : vous pouvez laisser en place les blocs
Rester sur le modèle de repli
Pour les conversations à plusieurs tours, continuez à utiliser le modèle de repli pour les tours suivants plutôt que de revenir au modèle initial.
Une nouvelle tentative manuelle écrit le cache de prompts du modèle de repli à partir de zéro, ce qui coûte plus cher que la lecture d'un cache existant. Le crédit de repli rembourse ce coût ; utilisez-le pour chaque nouvelle tentative que vous implémentez vous-même. Un refus de Claude Haiku 5.5 ne donne droit à aucun crédit de repli ; une nouvelle tentative après un tel refus paie donc le coût complet de l'écriture du cache de prompts du modèle de repli.
Refus dans les Message Batches
Une requête refusée dans un Message Batch revient avec result.type: "succeeded" et stop_reason: "refusal". Les résultats de lot portent le même objet stop_details que les réponses synchrones, vous pouvez donc détecter les refus via stop_reason ou stop_details.type. Une différence : les refus de lot ne génèrent pas de crédits de repli, de sorte que stop_details sur un résultat de lot n'inclut jamais de fallback_credit_token.
Le repli côté serveur n'est pas disponible pour les lots (une requête de lot qui inclut fallbacks produit un résultat en erreur par élément). Pour relancer les éléments de lot refusés :
- Collectez les éléments refusés dans les résultats.
- Laissez en place les blocs de réflexion dans les historiques à plusieurs tours, ou retirez-les pour économiser des tokens d'entrée. Pour un modèle de repli qui ne peut pas les lire, l'API les supprime sans les facturer, comme pour une nouvelle tentative manuelle.
- Si un élément refusé envoyait
thinking: {"type": "between_tools"}, omettezthinkingou définissez une valeur acceptée par le modèle de repli. Seul Claude Sonnet 5.5 acceptebetween_tools. - Soumettez-les à nouveau sur un modèle de repli, sous forme de nouveau lot ou de requêtes directes.
Pièges courants
- Relancez sur un modèle différent. Renvoyer une requête refusée au même modèle entraîne généralement un autre refus. Dirigez la nouvelle tentative vers le modèle de repli.
- Budgétez les nouvelles tentatives par requête, et non par tour ou par session. Un seul tour peut produire plusieurs refus, par exemple un agent plus ses sous-agents.
- Configurez le repli sur chaque chemin de requête. Les gestionnaires de nouvelle tentative, les branches de récupération d'erreur et les workers en arrière-plan en ont tous besoin. Un gestionnaire qui réémet une requête sans repli perd la protection précisément sur les requêtes les plus susceptibles d'en avoir besoin.
- Donnez aux appels de sous-agents leur propre repli. Le paramètre
fallbacksne se propage pas aux appels de modèle effectués depuis l'intérieur de l'exécution d'outils. - Faites du repli une propriété de la requête, et non d'un état ambiant. Un indicateur partagé, une valeur de configuration en cache ou une bascule globale peut se désynchroniser et laisser silencieusement une requête sans protection. Lorsque vous ne pouvez pas confirmer que le repli est actif, configurez-le plutôt que de supposer qu'il est activé.
- Instrumentez les refus comme un signal à part entière. Un refus est un HTTP 200, de sorte qu'une surveillance fondée sur les taux d'erreur ou les réponses 5xx ne le voit jamais. Émettez un événement par refus et un par réponse servie par repli (l'entrée
fallback_messagedansusage.iterationsmarque cette dernière), puis alertez sur l'écart entre les deux décomptes. - Branchez sur
stop_reasonoustop_details.type, et non surcontentou les champs internes destop_details. L'objetstop_detailsest toujours présent sur un refus, mais ses champscategoryetexplanationpeuvent valoirnull. Vérifiez directement questop_reasonest égal à"refusal".
Étapes suivantes
Évitez de payer deux fois le coût de la mise en cache des prompts lorsque vous construisez vous-même la nouvelle tentative.
Chaque valeur de stop_reason et comment la gérer.
Comment fonctionne le middleware SDK, y compris l'utilitaire de repli sur refus.
Migrez une application existante vers Claude Fable 5.1.
Was this page helpful?