Claude Platform Docs
MessagesEntwickeln mit Claude

Ablehnungen und Fallback

Wie Claude Fable-Modelle, Claude Opus-Modelle, Claude Sonnet 5.5 und Claude Haiku 5.5 Klassifikator-Ablehnungen zurückgeben und wie du abgelehnte Anfragen auf einem Fallback-Modell wiederholst.

Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 und Claude Haiku 5.5 enthalten „safety classifiers" (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 diese Wiederholung 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:

Die einfachste Einrichtung, in der Beta auf der Claude API: Setze fallbacks auf "default", und die API versucht eine abgelehnte Anfrage erneut auf dem „fallback model" (Fallback-Modell), das Anthropic für die jeweilige Ablehnungskategorie empfiehlt. Für Kategorien ohne empfohlenes Fallback-Modell bleibt die Ablehnung bestehen. Claude Haiku 5.5 hat keinen serverseitigen Fallback, verwende dafür also clientseitigen Fallback mit der SDK-Middleware oder schreibe den erneuten Versuch selbst.

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, die fallbacks setzen (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 andernfalls null. Es ist ein Hinweis, keine Garantie.
  • category und explanation sind beide null, wenn die Ablehnung keiner benannten Kategorie zugeordnet ist. Dieses null ist ein normaler, dauerhafter Wert, kein Platzhalter.
  • stop_details selbst ist für jeden anderen Stop-Reason als refusal null.
categoryBedeutungVor jeglicher Ausgabe abgerechnet
"cyber"Die Anfrage könnte Cyber-Schaden ermöglichen, etwa die Entwicklung von Malware oder Exploits. Auch harmlose Cybersicherheitsarbeit kann diese Kategorie auslösen.Nein
"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.Ja
"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.Ja
"reasoning_extraction"Die Anfrage fordert das Modell auf, sein internes Reasoning im Antworttext wiederzugeben. Um das Reasoning stattdessen in strukturierter Form zu erhalten, verwende adaptives Nachdenken. Siehe Reasoning in Thinking-Blöcken belassen.Ja
"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.Nein

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.

Reasoning in Thinking-Blöcken belassen

Eine reasoning_extraction-Ablehnung entsteht meist durch einen Prompt, der das Modell auffordert, sein Nachdenken oder Reasoning in die Ausgabe zu schreiben, entweder wörtlich oder in einem festen Format. Häufige Beispiele:

  • Ein <thinking>-, <reasoning>- oder Scratchpad-Abschnitt, den das Modell ausfüllt, bevor es antwortet
  • Ein reasoning-, thinking- oder trace-Feld in einer JSON-Ausgabe oder in einer Tool-Eingabe
  • Die privaten Notizen des Modells oder ein fortlaufendes Protokoll seines Reasonings
  • Reasoning, das wörtlich oder vollständig angefordert wird

Die Formulierung kann in einem System-Prompt, einem Skill oder einer Tool-Beschreibung stehen, also prüfe auch diese.

Du kannst Claude weiterhin bitten, seine Antwort zu erklären. Bitte um eine kurze Erklärung, die Belege hinter einem Ergebnis oder eine Zusammenfassung der durchgeführten Aktionen. Um zu sehen, wie das Modell nachgedacht hat, setze display: "summarized" und lies die thinking-Blöcke. Diese Kategorie hat kein empfohlenes Fallback-Modell, also ändere den Prompt, statt die Anfrage zu wiederholen. Wenn eine umformulierte Anfrage weiterhin abgelehnt wird, kontaktiere den Support und gib die Request-ID an.

Wie Ablehnungen berechnet werden

Diese Abrechnungsregeln gelten auf jeder Plattform: der Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud und Microsoft Foundry.

Ablehnungen vor jeglicher Ausgabe: Um Versuche zu erschweren, die Schutzmaßnahmen von Anthropic in großem Umfang zu umgehen, wird eine Ablehnung, die vor jeglicher Ausgabe eintrifft, abgerechnet, wenn ihre stop_details.category den Wert "bio", "frontier_llm" oder "reasoning_extraction" hat. Dies sind die Kategorien, in denen Anthropic, Stand September 2026, wenige Fehlalarme misst. Diese Ablehnungen werden wie jede andere Anfrage abgerechnet, zu den Tarifen des Modells, das sie ausgeführt hat. Eine Ablehnung vor jeglicher Ausgabe in einer anderen Kategorie oder mit der Kategorie null wird nicht abgerechnet. In beiden Fällen ist content leer, und Token-Zählungen erscheinen in usage. Die Anfrage zählt dennoch gegen deine Ratenlimits.

Ablehnungen mitten im Stream: Eine Ablehnung mitten im Stream berechnet die Input-Token und die bereits gestreamte Ausgabe zu normalen Tarifen.

Fallback: Wenn du Fallback verwendest, wird die Ablehnung, die ihn ausgelöst hat, zusätzlich zur Fallback-Anfrage abgerechnet, wenn sie mitten im Stream eintraf oder zu einer der abgerechneten Kategorien gehört. Die Fallback-Gutschrift gleicht den Prompt-Cache-Miss der Fallback-Anfrage aus, sodass du nicht zweimal für das Caching der Konversation bezahlst. Eine Ablehnung durch Claude Haiku 5.5 enthält keine Fallback-Gutschrift, daher zahlt ein Fallback danach die vollen Kosten für das Schreiben des Prompt-Caches des Fallback-Modells. Wie der serverseitige Fallback jeden Versuch meldet, erfährst du unter Abrechnung und Ratenlimits.

Die abgerechneten Kategorien können sich ändern, während Anthropic die Fehlalarmraten seiner Schutzmaßnahmen weiter misst und verfeinert. Die Spalte Vor jeglicher Ausgabe abgerechnet in der Tabelle der Ablehnungskategorien listet die abgerechneten Kategorien auf.

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 SituationVerwendeWarum
Claude API, einfachste EinrichtungServerseitiger FallbackEine Anfrage, eine Antwort. Die API übernimmt den erneuten Versuch.
Beliebige Plattform, mit einem Anthropic SDKDie SDK-MiddlewareEinmal auf dem Client konfigurieren. Erneute Versuche erfolgen automatisch.
Rohes HTTP oder eigene Retry-LogikEin manueller erneuter Versuch mit Fallback-GuthabenVolle Kontrolle. Fallback-Guthaben hält die Kosten niedrig.

Serverseitiger Fallback und die SDK-Middleware wenden die Fallback-Gutschrift für dich an. Die Seite Fallback-Gutschrift brauchst du nur, wenn du den erneuten Versuch selbst baust. Claude Haiku 5.5 hat weder serverseitigen Fallback noch Fallback-Gutschrift, verwende also die SDK-Middleware oder einen manuellen erneuten Versuch.

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. Bei gesetztem Beta-Header wird diese Liste als allowed_fallback_models im Eintrag des Modells in der Models API veröffentlicht.
  • Jeder Eintrag benennt ein model und kann max_tokens, thinking, output_config und speed nur für diesen Versuch überschreiben.
  • Die Anfrage muss als direkte Anfrage an jedes benannte Modell gültig sein. Wenn ein Fallback-Modell eine Funktion, die die Anfrage verwendet, nicht unterstützt, lehnt die API die Anfrage vorab ab. Unter dem Header 2026-07-01 ist thinking: {"type": "between_tools"} die Ausnahme: Wenn eine Claude Sonnet 5.5-Anfrage auf Claude Sonnet 5 zurückfällt, läuft der Fallback-Versuch mit thinking: {"type": "disabled"} und display: "omitted". Unter 2026-06-01 setze thinking im Claude Sonnet 5-Eintrag, sonst wird die Anfrage vorab abgelehnt.
  • 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 unverändert an dich zurückgegeben.
  • Wenn ein Fallback-Modell ratenlimitiert oder überlastet ist, wird der Fallback-Versuch nicht unternommen und stattdessen die vorherige Ablehnung zurückgegeben. stop_details.recommended_model der Ablehnung benennt dann ein Modell, das du direkt erneut versuchen kannst. Dimensioniere die Ratenlimits des Fallback-Modells für das erwartete Ablehnungsvolumen, sonst werden 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 in content, an der die Ausgabe eines Modells der des nächsten weicht: {"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}.
    • from.model gibt den Modell-String wieder, den du gesendet hast, wenn der ablehnende Hop das angefragte Modell ist.
    • to.model ist 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-TypIm nächsten Turn
fallbackBehalte 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.
textBehalten.
Jeder Block nach dem letzten fallback-BlockBehalten.
thinking, redacted_thinking oder connector_text vor dem letzten fallback-BlockWeglassen.
Clientseitiges tool_use vor dem letzten fallback-BlockWeglassen.
server_tool_use vor dem letzten fallback-BlockBehalten, 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_start benennt das Fallback-Modell, und der fallback-Block ist der erste Content-Block.
  • Da message_start auf 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 aus content_block_start und content_block_stop ohne 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 in content.
  • message_start hat bereits das angefragte Modell benannt, lies das bedienende Modell also aus dem to.model des fallback-Blocks und aus dem fallback_message-Eintrag in usage.iterations des letzten message_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

Für jeden Versuch gelten die Regeln unter Wie Ablehnungen berechnet werden, und zwar zu den Tarifen des Modells, das ihn ausgeführt hat. Ein Versuch, der abgelehnt hat, bevor er irgendeine Ausgabe erzeugt hat, wird nur abgerechnet, wenn seine Ablehnungskategorie abgerechnet wird, und seine Token werden in jedem Fall in seinem usage.iterations-Eintrag gemeldet. Jeder Versuch, der Ausgabe erzeugt hat, einschließlich eines, der mitten in seiner Antwort abgelehnt hat, wird separat berechnet. 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

Das 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 bei jeder von ihr verarbeiteten Anfrage den Beta-Header fallback-credit-2026-07-01, sodass erneute Versuche ohne Einrichtung pro Anfrage neu bepreist werden. Eine Ablehnung durch Claude Haiku 5.5 enthält keine Fallback-Gutschrift, daher zahlt ein erneuter Versuch danach die vollen Kosten für das Schreiben des Prompt-Caches des Fallback-Modells.

Einrichtung

Übergib BetaRefusalFallbackMiddleware 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

  • Retries durchlaufen deine Fallback-Liste der Reihe nach. Ein Fallback-Modell, das selbst ablehnt, gibt 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, Claude Opus 5.5, Claude Sonnet 5.5, Claude Haiku 5.5 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 Konversationsverlauf 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 Claude Fable 5.1 und Claude Mythos 5.1 lesen, daher verwirft die API sie. Die API verwirft außerdem Claude Opus 5.5-Blöcke für jedes Fallback-Modell außer Claude Fable 5.1 und Claude Mythos 5.1 (siehe Modellwechsel mitten im Gespräch). Sie verwirft auch Claude Sonnet 5.5-Blöcke, für jedes Fallback-Modell außer Claude Opus 5.5 auf der Claude API und Google Cloud. Claude Opus 5.5 und Claude Sonnet 5.5 lesen Claude Haiku 5.5-Blöcke auf der Claude API und Google Cloud, und die API verwirft sie für ein Fallback-Modell, das sie nicht lesen kann.
  • Ü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 BetaFallbackState aufgezeichnet, sodass Folgeanfragen, die den State teilen, an dieses Modell gebunden bleiben, statt erneut ein Modell 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:

  1. Die Ablehnung erkennen

    Prüfe die Antwort auf stop_reason: "refusal".

  2. Auf einem Fallback-Modell erneut senden

    Sende dieselbe Anfrage mit model auf ein Fallback-Modell gesetzt, etwa Claude Opus 4.8. Wenn die abgelehnte Anfrage thinking: {"type": "between_tools"} gesendet hat, ändere zuerst thinking: Nur Claude Sonnet 5.5 akzeptiert diesen Wert, also lass thinking weg oder setze einen Wert, den das Fallback-Modell akzeptiert. Serverseitiger Fallback unter dem Header 2026-07-01 nimmt diese Änderung für dich vor, wenn er auf Claude Sonnet 5 zurückfällt. Ein anderes Modell kann normalerweise eine Anfrage bedienen, die Claude Fable 5.1 oder Claude Fable 5 ablehnt. Wie du mit dem Konversationsverlauf umgehst, hängt davon ab, ob du eine Fallback-Gutschrift einlöst:

    • Ohne Einlösung einer Gutschrift: Du kannst die früheren thinking- und redacted_thinking-Blöcke an Ort und Stelle lassen oder sie entfernen, um Eingabe-Token zu sparen. Das Fallback-Modell kann sie in beiden Fällen normalerweise nicht nutzen: Nur Claude Fable 5.1 und Claude Mythos 5.1 lesen Claude Fable 5.1-Blöcke, und nur diese beiden Modelle, Claude Fable 5 und Claude Mythos 5 lesen Claude Fable 5-Blöcke, daher verwirft die API sie für jedes andere Fallback-Modell. Die API verwirft außerdem Claude Opus 5.5-Blöcke für jedes Fallback-Modell außer Claude Fable 5.1 und Claude Mythos 5.1 (siehe Modellwechsel mitten im Gespräch). Sie verwirft auch Claude Sonnet 5.5-Blöcke, für jedes Fallback-Modell außer Claude Opus 5.5 auf der Claude API und Google Cloud. Ein erneuter Versuch nach einer Ablehnung durch Claude Haiku 5.5 fällt immer unter diesen Fall. Claude Opus 5.5 und Claude Sonnet 5.5 lesen Claude Haiku 5.5-Blöcke auf der Claude API und Google Cloud, lass diese Blöcke also an Ort und Stelle, wenn du dort auf eines dieser Modelle zurückfällst. Für ein Fallback-Modell, das sie nicht lesen kann, verwirft die API sie, ohne sie abzurechnen.
    • Mit Einlösung einer Gutschrift: Sende den Body unverändert, da die Einlösung eine exakte Übereinstimmung erfordert. Der Server behandelt die Thinking-Blöcke des früheren Modells bei einer Einlösung selbst, also entferne sie nicht (siehe Felder, die mit der abgelehnten Anfrage übereinstimmen müssen).
  3. Beim Fallback-Modell bleiben

    Verwende bei Multi-Turn-Konversationen das Fallback-Modell auch für nachfolgende Turns, 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 vorhandenen Caches. Die Fallback-Gutschrift erstattet diese Kosten; löse sie bei jedem erneuten Versuch ein, den du selbst baust. Eine Ablehnung durch Claude Haiku 5.5 enthält keine Fallback-Gutschrift, daher zahlt ein erneuter Versuch danach die vollen Kosten für das Schreiben des Prompt-Caches des Fallback-Modells.

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:

  1. Sammle die abgelehnten Elemente aus den Ergebnissen.
  2. Lass die Thinking-Blöcke in Verläufen mit mehreren Turns an Ort und Stelle oder entferne sie, um Eingabe-Token zu sparen. Für ein Fallback-Modell, das sie nicht lesen kann, verwirft die API sie, ohne sie abzurechnen, wie bei einem manuellen erneuten Versuch.
  3. Wenn ein abgelehntes Element thinking: {"type": "between_tools"} gesendet hat, lass thinking weg oder setze einen Wert, den das Fallback-Modell akzeptiert. Nur Claude Sonnet 5.5 akzeptiert between_tools.
  4. 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 in usage.iterations markiert Letztere), und alarmiere dann bei der Lücke zwischen den beiden Zählungen.
  • Verzweige auf stop_reason oder stop_details.type, nicht auf content oder die inneren stop_details-Felder. Das stop_details-Objekt ist bei einer Ablehnung immer vorhanden, aber seine Felder category und explanation können null sein. Prüfe direkt, ob stop_reason gleich "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?