Ablehnungen und Fallback
Wie Claude Fable- und Claude Opus-Modelle Klassifikator-Ablehnungen zurückgeben und wie du abgelehnte Anfragen auf einem Fallback-Modell erneut versuchst.
Claude Fable 5.1, Claude Fable 5 und Claude Opus 5 enthalten Sicherheitsklassifikatoren, die eine Anfrage ablehnen können. Wenn das passiert, erhältst du eine normale Antwort, keinen Fehler, mit stop_reason: "refusal". Ihr stop_details.category benennt den Richtlinienbereich (siehe Wie eine Ablehnung aussieht). In der Regel kannst du trotzdem eine Antwort erhalten, indem du dieselbe Anfrage an ein anderes Claude-Modell sendest. Diese Seite zeigt dir, wie du eine „refusal“ (Ablehnung) erkennst und wie du diesen erneuten Versuch einrichtest.
Lies diese Seite, wenn du auf einem dieser Modelle aufbaust und möchtest, dass abgelehnte Anfragen automatisch an ein anderes Modell weitergereicht werden. Sie gilt auch, wenn du "refusal" in einer Antwort gesehen hast und wissen möchtest, was als Nächstes zu tun ist.
Verwandte Seiten:
- Stop-Reasons und Fallback: die vollständige Liste der
stop_reason-Werte. - Fallback-Guthaben: wie du vermeidest, die Prompt-Cache-Kosten doppelt zu zahlen, wenn du den erneuten Versuch selbst baust.
- SDK-Middleware: der SDK-Helfer, der all dies kapselt.
- Cookbook zu Fallback und Abrechnung: ein durchgearbeitetes End-to-End-Beispiel.
Die einfachste Einrichtung, in Beta auf der Claude API: Setze fallbacks auf "default", und die API versucht eine abgelehnte Anfrage erneut auf dem Fallback-Modell, das Anthropic für ihre Ablehnungskategorie empfiehlt. Bei Kategorien ohne empfohlenen Fallback bleibt die Ablehnung bestehen.
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)Die folgenden Abschnitte behandeln, was eine Ablehnungsantwort enthält, wann du serverseitigen oder clientseitigen Fallback verwenden solltest und wie jeweils abgerechnet wird.
Wie eine Ablehnung aussieht
Eine Ablehnung ist eine erfolgreiche HTTP-200-Antwort mit 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
}
}Das stop_details-Objekt erklärt die Ablehnung:
category: benennt den Richtlinienbereich, der den Klassifikator ausgelöst hat.explanation: eine menschenlesbare Beschreibung. Der Text ist nicht stabil, zeige ihn also an, statt ihn zu parsen.recommended_model: nur bei Anfragen vorhanden, diefallbackssetzen (serverseitiger Fallback, Beta). Es benennt ein Modell, auf dem du direkt erneut versuchen kannst, wenn die API den Fallback-Versuch übersprungen hat (zum Beispiel, weil das Fallback-Modell durch ein Ratenlimit begrenzt war), und ist andernfallsnull. Es ist ein Hinweis, keine Garantie.categoryundexplanationsind beidenull, wenn die Ablehnung keiner benannten Kategorie zugeordnet ist. Diesesnullist ein normaler, dauerhafter Wert, kein Platzhalter.stop_detailsselbst ist für jeden anderen Stop-Reason alsrefusalnull.
category | Bedeutung |
|---|---|
"cyber" | Die Anfrage könnte Cyber-Schaden ermöglichen, etwa die Entwicklung von Malware oder Exploits. Auch harmlose Cybersicherheitsarbeit kann diese Kategorie auslösen. |
"bio" | Die Anfrage könnte biologischen Schaden ermöglichen, etwa gefährliche Labormethoden. Auch nützliche Arbeit in den Lebenswissenschaften kann diese Kategorie auslösen. |
"frontier_llm" | Die Anfrage könnte die Entwicklung konkurrierender KI-Modelle unterstützen, was gemäß Anthropics kommerziellen Bedingungen eingeschränkt ist. Auch harmlose Arbeit im Bereich maschinelles Lernen kann diese Kategorie auslösen. |
"reasoning_extraction" | Die Anfrage fordert das Modell auf, sein internes Reasoning im Antworttext wiederzugeben. Um Reasoning stattdessen in strukturierter Form zu erhalten, verwende adaptives Denken. |
"general_harms" | Die Anfrage fällt in einen Bereich der Nutzungsrichtlinien außerhalb der vier benannten Kategorien. Auch harmlose Arbeit kann diese Kategorie auslösen. |
Eine Ablehnung kann vor jeglicher Ausgabe eintreffen oder mitten im Stream nach teilweiser Ausgabe. Behandle in beiden Fällen jede teilweise Ausgabe als unvollständig und verwirf sie.
Einen Fallback-Ansatz wählen
Es gibt drei Möglichkeiten, eine abgelehnte Anfrage auf einem anderen Modell erneut zu versuchen. Die richtige hängt davon ab, wo du läufst und wie viel Kontrolle du brauchst.
| Deine Situation | Verwende | Warum |
|---|---|---|
| Claude API, einfachste Einrichtung | Serverseitiger Fallback | Eine Anfrage, eine Antwort. Die API übernimmt den erneuten Versuch. |
| Beliebige Plattform, mit einem Anthropic SDK | Die SDK-Middleware | Einmal auf dem Client konfigurieren. Erneute Versuche erfolgen automatisch. |
| Rohes HTTP oder eigene Retry-Logik | Ein manueller erneuter Versuch mit Fallback-Guthaben | Volle Kontrolle. Fallback-Guthaben hält die Kosten niedrig. |
Serverseitiger Fallback und die SDK-Middleware wenden das Fallback-Guthaben für dich an. Du brauchst die Seite Fallback-Guthaben nur, wenn du den erneuten Versuch selbst baust.
Serverseitiger Fallback
Serverseitiger Fallback versucht eine abgelehnte Anfrage innerhalb eines einzigen API-Aufrufs erneut. Im Standardmodus führt die API, wenn das primäre Modell ablehnt und die Ablehnungskategorie einen empfohlenen Fallback hat, dieselbe Anfrage auf dem Modell aus, das Anthropic für diese Kategorie empfiehlt. Du kannst stattdessen bis zu drei eigene Fallback-Modelle benennen. In beiden Fällen erhältst du eine Antwort zurück, die das Modell benennt, das geantwortet hat, sodass dein Nutzer in einem einzigen Roundtrip eine Antwort erhält.
Die Anfrage stellen
Setze den fallbacks-Parameter auf den String "default" und sende den Beta-Header server-side-fallback-2026-07-01. Die API wendet dann das serverseitig definierte Standard-Routing des angefragten Modells an, das basierend auf der vom Klassifikator gemeldeten Ablehnungskategorie ein empfohlenes Fallback-Modell auswählt, sodass abgelehnte Anfragen bedient werden, ohne dass du eine Modellliste pflegen musst, wenn sich Empfehlungen ändern.
Das Standard-Routing löst niemals die vorab erfolgende Ablehnung übergroßer Bilder für Modelle aus, die du nicht gewählt hast: Ein geroutetes Modell, das ein mit "oversized_image": "error" markiertes Bild verkleinern würde, wird stattdessen aus dem Routing entfernt, sodass ein markiertes Bild niemals verkleinert ausgeliefert wird.
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"],
)
# Ein fallback_message-Eintrag in usage.iterations bedeutet, dass ein Fallback-Modell lief;
# kombiniere ihn mit stop_reason, um zu bestätigen, dass das Fallback die Antwort lieferte.
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 legt Schutzmaßnahmen für jedes Modell einzeln und für jede Richtlinienkategorie fest, entsprechend der Fähigkeit des Modells: Je nach Kategorie kann eine markierte Anfrage auf ein weniger leistungsfähiges Modell zurückfallen oder abgelehnt werden. Der Modus "default" kodiert diese modell- und kategoriespezifischen Empfehlungen für dich, sodass eine abgelehnte Anfrage auf dem Modell erneut versucht wird, das Anthropic für diese Kategorie empfiehlt. Fallbacks sind in beiden Fällen sichtbar: Die Antwort benennt das Modell, das sie bedient hat, und der fallback-Content-Block markiert die Übergabe.
Das Routing wird serverseitig angewendet und nicht pro Modell in der Models API veröffentlicht. Um zu sehen, welches Modell eine abgelehnte Anfrage bedient hat, prüfe das model-Feld auf oberster Ebene der Antwort und suche nach einem fallback_message-Eintrag in usage.iterations, wie es die Beispiele auf dieser Seite tun.
Nur eine Ablehnung durch einen Sicherheitsklassifikator löst den Fallback aus. Ein Ratenlimit, eine Überlastung oder ein Serverfehler beim angefragten Modell wird dir unverändert zurückgegeben.
Eigene Fallback-Modelle benennen
Anstelle des Standard-Routings kannst du fallbacks auf eine Liste von bis zu drei Modellen setzen. Wenn das angefragte Modell ablehnt, führt die API das nächste Modell in der Kette mit derselben Anfrage aus. Verwende diese Form, wenn du genau steuern möchtest, welche Modelle abgelehnte Anfragen bedienen, etwa um ein Modell festzulegen, das deine Anwendung qualifiziert hat.
Benannte Fallback-Modelle zählen für die Prüfung auf übergroße Bilder: Eine Anfrage, deren Bild-Block "oversized_image": "error" setzt, wird vorab gegen das angefragte Modell und jeden benannten Fallback geprüft, wird abgelehnt, wenn eines davon dieses Bild verkleinern würde, und das in der Ablehnung gemeldete Skalierungsziel passt für alle.
Die hervorgehobenen Zeilen sind der einzige Unterschied zur Anfrage mit Standard-Routing.
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)Für die fallbacks-Liste gelten einige Regeln:
- Einträge werden der Reihe nach versucht. Jeder muss sich von den anderen Einträgen und vom angefragten Modell unterscheiden.
- Jeder Eintrag muss eines der zulässigen Ziele des angefragten Modells sein. Mit gesetztem Beta-Header wird diese Liste als
allowed_fallback_modelsim Eintrag des Modells in der Models API veröffentlicht. - Jeder Eintrag benennt ein
modelund kannmax_tokens,thinking,output_configundspeednur für diesen Versuch überschreiben. - Die Anfrage muss als direkte Anfrage an jedes benannte Modell gültig sein. Wenn ein Fallback-Modell eine Funktion nicht unterstützt, die die Anfrage verwendet, lehnt die API die Anfrage vorab ab.
- Wie im Standardmodus löst nur eine Ablehnung durch einen Sicherheitsklassifikator den Fallback aus. Ein Ratenlimit, eine Überlastung oder ein Serverfehler beim angefragten Modell wird dir unverändert zurückgegeben.
- Wenn ein Fallback-Modell durch ein Ratenlimit begrenzt oder überlastet ist, wird der Fallback-Versuch nicht unternommen und stattdessen die vorangehende Ablehnung zurückgegeben. Das
stop_details.recommended_modelder Ablehnung benennt dann ein Modell, auf dem du direkt erneut versuchen kannst. Dimensioniere die Ratenlimits des Fallback-Modells für das erwartete Ablehnungsvolumen, sonst degradieren Fallbacks unter Last zu Ablehnungen.
Die Antwort hat in beiden Modi dieselbe Form: Das Modell, das den Turn bedient hat, erscheint im model-Feld auf oberster Ebene, ein fallback-Content-Block markiert die Übergabe, und usage.iterations zeichnet jeden Versuch auf.
Was die Antwort enthält
Die Antwort sieht aus wie jede andere Nachricht, mit zwei Ergänzungen:
- Das
model-Feld auf oberster Ebene meldet das Modell, das die zurückgegebene Nachricht erzeugt hat, ob das nun das angefragte Modell oder ein Fallback ist. - Ein
fallback-Content-Block markiert jede Stelle incontent, an der die Ausgabe eines Modells der des nächsten weicht:{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}.from.modelgibt den Modell-String wieder, den du gesendet hast, wenn der ablehnende Hop das angefragte Modell ist.to.modelist immer die aufgelöste ID des Modells, das fortsetzt.
Bei einer Ablehnung vor jeglicher Ausgabe ist der fallback-Block der erste Content-Block. Zum Beispiel, wenn das Standard-Routing Claude Opus 4.8 für die Kategorie der Ablehnung auswählt:
{
"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
}
]
}
}Das Array usage.iterations zeichnet jeden Versuch auf. Ein Modell, das abgelehnt hat, erscheint als gewöhnlicher message-Eintrag, und das Modell, das den Turn bedient hat, erscheint als fallback_message-Eintrag. Wenn jedes Modell in der Kette ablehnt, ist die Antwort die Ablehnung des letzten Modells, mit einem message-Eintrag für jeden früheren Hop und einem fallback_message-Eintrag für den letzten.
Sticky Routing kann einen späteren Turn direkt an das Fallback-Modell senden. Ein solcher Turn trägt keinen fallback-Content-Block, weil kein Modell diesen Turn abgelehnt hat. Erkenne ihn am fallback_message-Eintrag in usage.iterations, am Fehlen eines message-Eintrags für das angefragte Modell und am model-Feld der Antwort.
Das Gespräch fortsetzen
Sende im nächsten Turn den Assistant-Inhalt so zurück, wie du ihn erhalten hast. Nach einem Fallback mitten in der Ausgabe kann content Block-Typen enthalten, die das ablehnende Modell vor der Übergabe erzeugt hat. Die folgende Tabelle zeigt, welche du behältst und welche du weglässt, wenn du den Turn zurücksendest.
| Block-Typ | Im nächsten Turn |
|---|---|
fallback | Behalte ihn genau dort, wo er erschien. Die API verwendet seine Position, um die Thinking-Blöcke um ihn herum zu validieren, sodass eine Anfrage, die Thinking-Blöcke von beiden Seiten der Grenze zurücksendet, abgelehnt wird, wenn der Block weggelassen oder verschoben wird. |
text | Behalten. |
Jeder Block nach dem letzten fallback-Block | Behalten. |
thinking, redacted_thinking oder connector_text vor dem letzten fallback-Block | Weglassen. |
Clientseitiges tool_use vor dem letzten fallback-Block | Weglassen. |
server_tool_use vor dem letzten fallback-Block | Behalten, wenn mit seinem Ergebnis gepaart. Weglassen, wenn es kein passendes Ergebnis hat. |
Streaming
Bei einer Streaming-Anfrage erfolgt der erneute Versuch auf demselben Stream, und nichts, was du bereits erhalten hast, wird ungültig. Was du siehst, hängt davon ab, wann die Ablehnung erfolgt.
Wenn die Ablehnung vor jeglicher Ausgabe erfolgt:
message_startbenennt das Fallback-Modell, und derfallback-Block ist der erste Content-Block.- Da
message_startauf den Start des Fallback-Versuchs wartet, umfasst die Zeit bis zum ersten Byte den abgelehnten Versuch.
Wenn die Ablehnung mitten in der Ausgabe erfolgt:
- Der offene Content-Block wird geschlossen, und der
fallback-Block (ein gewöhnliches Paar auscontent_block_startundcontent_block_stopohne Deltas) markiert die Grenze. - Das Fallback-Modell setzt ab der teilweisen Ausgabe fort. Nur die
text-Blöcke der teilweisen Ausgabe werden dem Fallback-Modell als Kontext übergeben. Andere Block-Typen verbleiben incontent. message_starthat bereits das angefragte Modell benannt, lies das bedienende Modell also aus demto.modeldesfallback-Blocks und aus demfallback_message-Eintrag inusage.iterationsdes letztenmessage_delta.
Nicht-Streaming-Antworten
Bei einer Nicht-Streaming-Anfrage verhält sich eine Ablehnung mitten in der Ausgabe anders: Die Antwort lässt die teilweise Ausgabe des abgelehnten Modells weg, und das Fallback-Modell antwortet von Grund auf neu. Das Ergebnis sieht aus wie eine Ablehnung vor jeglicher Ausgabe, mit dem fallback-Block an erster Stelle. Der abgelehnte Versuch und seine Output-Token erscheinen dennoch in usage.iterations.
Abrechnung und Ratenlimits
Ein Versuch, der abgelehnt hat, bevor er irgendeine Ausgabe erzeugt hat, wird nicht berechnet: Seine Token werden in seinem usage.iterations-Eintrag gemeldet, aber nicht berechnet. Jeder Versuch, der Ausgabe erzeugt hat, einschließlich eines, der mitten in seiner Antwort abgelehnt hat, wird separat zu den Tarifen des Modells berechnet, das ihn ausgeführt hat. Das Array usage.iterations ist die Aufzeichnung pro Versuch dessen, was dir berechnet wird. Die usage-Zählungen auf oberster Ebene beschreiben nur den Versuch, der die zurückgegebene Nachricht erzeugt hat. Token verschiedener Modelle werden niemals in einem Feld summiert.
Jeder Versuch, der läuft, einschließlich eines abgelehnten, zählt gegen die Ratenlimits seines eigenen Modells.
Sticky Routing
Nachdem ein Gespräch zurückgefallen ist, zeichnet die API auf, welches Modell es bedient hat. Spätere Anfragen für dieses Gespräch, die fallbacks enthalten, gehen direkt an dieses Fallback-Modell, ohne das angefragte Modell auszuführen. Das vermeidet, bei jedem Turn für einen Versuch zu zahlen, der vorhersehbar erneut abgelehnt würde.
Einige Eigenschaften der Routing-Entscheidung:
- Sie wird etwa 1 Stunde lang aufbewahrt und ist auf deine Organisation beschränkt.
- Sie wird als Content-Hash des Gesprächspräfixes plus dem Modell, das es bedient hat, gespeichert. Der Nachrichteninhalt selbst wird nicht gespeichert.
- Sie erfolgt nach bestem Bemühen, daher muss dein Code damit umgehen können, dass das angefragte Modell jederzeit erneut versucht wird.
Sticky Routing gilt sowohl für Streaming- als auch für Nicht-Streaming-Anfragen. Bei einer Streaming-Anfrage wird die Routing-Entscheidung getroffen, bevor der Stream geöffnet wird, sodass das model-Feld des message_start-Events bereits die ID des Fallback-Modells trägt.
Clientseitiger Fallback mit der SDK-Middleware
Jedes Anthropic SDK enthält eine Refusal-Fallback-Middleware. Du konfigurierst sie einmal auf dem Client mit deiner Liste von Fallback-Modellen. Aufrufe über client.beta.messages versuchen abgelehnte Anfragen dann automatisch erneut, auf jeder Plattform. Die Middleware sendet außerdem den Beta-Header fallback-credit-2026-07-01 bei jeder Anfrage, die sie verarbeitet, sodass erneute Versuche ohne Einrichtung pro Anfrage neu bepreist werden.
Einrichtung
Übergib die Middleware an den Client-Konstruktor und teile eine BetaFallbackState-Instanz über die Anfragen eines Gesprächs hinweg.
from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware
# Bei einer Ablehnung wiederholt die Middleware die Anfrage mit dem aufgeführten Fallback-Modell und
# sendet automatisch den Fallback-Credit-Beta-Header bei jeder Anfrage, die sie verarbeitet.
client = Anthropic(
middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
)
state = BetaFallbackState() # pins follow-ups to the model that accepted
# Streaming: Bei einer Ablehnung wiederholt die Middleware die Anfrage mit dem Fallback-Modell und
# fügt dessen Events in den offenen Stream ein.
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}")
# Nicht-Streaming: Die Wiederverwendung des Zustands hält die Konversation fixiert.
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}")Verhalten
- Erneute Versuche durchlaufen deine Fallback-Liste der Reihe nach. Ein Fallback-Modell, das selbst ablehnt, reicht die Anfrage an den nächsten Eintrag weiter.
- Wenn jedes Modell in der Liste abgelehnt hat, gibt die Middleware die letzte Ablehnung (die Ablehnungsantwort des letzten Modells) zurück, statt einen Fehler auszulösen.
- Thinking-Blöcke von Claude Fable 5.1 oder Claude Fable 5 werden unverändert durchgereicht. Jeder erneute Versuch sendet deinen ursprünglichen Anfrage-Body erneut, und die einzigen Blöcke, die die Middleware bei späteren Anfragen aus dem Gesprächsverlauf entfernt, sind die
fallback-Grenzblöcke, die sie selbst hinzugefügt hat. Das Fallback-Modell kann Claude Fable 5.1-Blöcke nicht lesen, die nur für dieses Modell oder ein neueres erhalten bleiben, daher verwirft die API sie. - Über die Middleware bediente Antworten enthalten an jeder Modellgrenze einen
fallback-Content-Block, genau wie Antworten des serverseitigen Fallbacks. Die Middleware verwaltet diese Blöcke bei späteren Anfragen für dich. - Das Modell, das akzeptiert hat, wird in
BetaFallbackStateaufgezeichnet, sodass Folgeanfragen, die den State teilen, daran gebunden bleiben, statt ein Modell erneut zu fragen, das abgelehnt hat.
Den erneuten Versuch selbst schreiben
Über rohes HTTP oder mit eigener Retry-Logik implementierst du das Muster, das die Middleware kapselt:
Die Ablehnung erkennen
Prüfe die Antwort auf
stop_reason: "refusal".Auf einem Fallback-Modell erneut senden
Sende dieselbe Anfrage mit
modelauf ein Fallback-Modell gesetzt, etwa Claude Opus 4.8. Ein anderes Modell kann normalerweise eine Anfrage bedienen, die Claude Fable 5.1 oder Claude Fable 5 ablehnt. Wie du mit dem Gesprächsverlauf umgehst, hängt davon ab, ob du ein Fallback-Guthaben einlöst:- Kein Guthaben einlösen: Du kannst die früheren
thinking- undredacted_thinking-Blöcke an Ort und Stelle lassen oder sie entfernen, um Input-Token zu sparen. Das Fallback-Modell kann sie in beiden Fällen nicht nutzen: Es ignoriert Claude Fable 5-Blöcke, und Claude Fable 5.1-Blöcke bleiben nur für dieses Modell oder ein neueres erhalten, daher verwirft die API sie. - Guthaben einlösen: Sende den Body unverändert, da die Einlösung eine exakte Übereinstimmung erfordert. Der Server kümmert sich bei einer Einlösung um die Thinking-Blöcke des früheren Modells, entferne sie also nicht (siehe Felder, die mit der abgelehnten Anfrage übereinstimmen müssen).
- Kein Guthaben einlösen: Du kannst die früheren
Beim Fallback-Modell bleiben
Verwende bei Multi-Turn-Gesprächen für nachfolgende Turns weiterhin das Fallback-Modell, statt zurückzuwechseln.
Ein manueller erneuter Versuch schreibt den Prompt-Cache des Fallback-Modells von Grund auf neu, was mehr kostet als das Lesen eines bestehenden Caches. Fallback-Guthaben erstattet diese Kosten; löse es bei jedem erneuten Versuch ein, den du selbst baust.
Ablehnungen in Message Batches
Eine abgelehnte Anfrage in einem Message Batch kommt als result.type: "succeeded" mit stop_reason: "refusal" zurück. Batch-Ergebnisse tragen dasselbe stop_details-Objekt wie synchrone Antworten, sodass du Ablehnungen entweder über stop_reason oder stop_details.type erkennen kannst. Ein Unterschied: Batch-Ablehnungen erzeugen keine Fallback-Guthaben, daher enthält stop_details bei einem Batch-Ergebnis niemals ein fallback_credit_token.
Serverseitiger Fallback ist für Batches nicht verfügbar (eine Batch-Anfrage, die fallbacks enthält, erzeugt ein fehlerhaftes Ergebnis pro Element). Um abgelehnte Batch-Elemente erneut zu versuchen:
- Sammle die abgelehnten Elemente aus den Ergebnissen.
- Entferne die Thinking-Blöcke von Claude Fable 5.1 oder Claude Fable 5 aus allen Multi-Turn-Verläufen.
- Reiche sie auf einem Fallback-Modell als neuen Batch oder als direkte Anfragen erneut ein.
Häufige Fallstricke
- Versuche auf einem anderen Modell erneut. Eine abgelehnte Anfrage erneut an dasselbe Modell zu senden, bringt meist eine weitere Ablehnung. Richte den erneuten Versuch auf das Fallback-Modell.
- Budgetiere erneute Versuche pro Anfrage, nicht pro Turn oder pro Sitzung. Ein einzelner Turn kann mehrere Ablehnungen erzeugen, zum Beispiel ein Agent plus seine Sub-Agenten.
- Konfiguriere Fallback auf jedem Anfragepfad. Retry-Handler, Fehlerbehandlungszweige und Hintergrund-Worker brauchen ihn alle. Ein Handler, der eine Anfrage ohne Fallback erneut ausgibt, verliert den Schutz genau bei den Anfragen, die ihn am wahrscheinlichsten brauchen.
- Gib Sub-Agent-Aufrufen ihren eigenen Fallback. Der
fallbacks-Parameter wird nicht in Modellaufrufe weitergegeben, die aus der Tool-Ausführung heraus erfolgen. - Mache Fallback zu einer Eigenschaft der Anfrage, nicht des umgebenden Zustands. Ein geteiltes Flag, ein gecachter Konfigurationswert oder ein globaler Schalter kann aus dem Takt geraten und eine Anfrage stillschweigend ungeschützt lassen. Wenn du nicht bestätigen kannst, dass Fallback aktiv ist, konfiguriere ihn, statt anzunehmen, dass er eingeschaltet ist.
- Instrumentiere Ablehnungen als eigenes Signal. Eine Ablehnung ist ein HTTP 200, daher sieht Monitoring, das auf Fehlerraten oder 5xx-Antworten aufbaut, sie nie. Emittiere ein Event pro Ablehnung und eines pro per Fallback bedienter Antwort (der
fallback_message-Eintrag inusage.iterationsmarkiert Letztere), und alarmiere dann bei der Lücke zwischen den beiden Zählungen. - Verzweige auf
stop_reasonoderstop_details.type, nicht aufcontentoder die innerenstop_details-Felder. Dasstop_details-Objekt ist bei einer Ablehnung immer vorhanden, aber seine Feldercategoryundexplanationkönnennullsein. Prüfe direkt, obstop_reasongleich"refusal"ist.
Nächste Schritte
Vermeide, die Prompt-Cache-Kosten doppelt zu zahlen, wenn du den erneuten Versuch selbst baust.
Jeder stop_reason-Wert und wie du damit umgehst.
Wie SDK-Middleware funktioniert, einschließlich des Refusal-Fallback-Helfers.
Migriere eine bestehende Anwendung zu Claude Fable 5.1.
Was this page helpful?