Startseite / Artikel / Wenn ein Klassifikator still das Modell austauscht: Warum es Header zum ausliefernden Modell braucht

Wenn ein Klassifikator still das Modell austauscht: Warum es Header zum ausliefernden Modell braucht

Ein stiller Fallback auf ein günstigeres Modell hinterlässt weder Fehler noch Logzeile. Wie man die Daten zum tatsächlich antwortenden Modell in Claude-Code-Transkripten liest und warum Anbieter sie in Antworten offenlegen sollten.

1861 Wörter

Als Anthropic am 7. August ankündigte, den Biologie-Sicherheitsklassifikator seines Flaggschiffmodells zu lockern, ordneten die meisten Kommentare das in die alte Debatte über zu viele Ablehnungen ein, ein Thema, das ausgereizt wirkte. Das interessantere Wort in der Ankündigung ist aber Fallback, nicht Ablehnung.

Ein Austausch ohne Signal

Laut Ankündigung stoppt ein auslösender Klassifikator die Anfrage nicht. Er leitet sie an Opus 5 weiter, ein starkes Modell, dem die biologischen Fähigkeiten von Fable 5 fehlen. Nichts wird blockiert oder gefiltert, und es erscheint keine Warnung. Jemand fragt das Topmodell an, ein Klassifikator hält den Prompt für biologienah, und ein anderes Modell antwortet.

Die Modelle kosten unterschiedlich viel. Laut öffentlicher Preisliste verlangt Fable 5 $10 pro Million Input-Token und $50 pro Million Output, Opus 5 dagegen $5 und $25, also jeweils die Hälfte. Wie eine umgeleitete Anfrage abgerechnet wird, sagt der Beitrag nicht, und getestet wurde es nicht, deshalb bleibt die Abrechnung hier außen vor. Fest steht ein Austausch mit dokumentiertem Ziel und veröffentlichtem Preisunterschied.

Die Spezifikationen zählen mehr als der Preis. In der Dokumentation sieht der Vergleich so aus:

  • Positionierung laut Doku: Fable 5 zielt auf lange laufende Agenten, Opus 5 auf anspruchsvolles agentisches Coding und Business-Workloads.
  • Preis pro Million Token, Input und Output: $10 und $50 gegenüber $5 und $25.
  • Kontextfenster: 1M bei beiden.
  • Maximaler Output: 128K bei beiden.
  • Verlässlicher Wissensstand: Januar 2026 bei Fable 5, Mai 2026 bei Opus 5.

Die Kontextgröße ist gleich, die Output-Obergrenze ist gleich, und das Wissen des Ersatzmodells ist vier Monate aktueller. Seine eigene Doku empfiehlt es für anspruchsvolles agentisches Coding sogar an erster Stelle. Die Ankündigung benennt den Preis des Austauschs, nämlich die biologischen Fähigkeiten, und diesen Verlust würde kein Code-Diff zeigen.

Der Austausch sprengt also kein Kontextbudget, reißt kein Token-Limit und sieht bei einer Coding-Aufgabe womöglich gar nicht schlechter aus. Das ist keine Entschärfung. Genau das macht den Austausch unsichtbar.

Die Zahlen genau lesen

Die Schlagzeilenzahl ist ein Rückgang der biologiebezogenen Fallbacks um etwa 85% über alle Produktoberflächen von Anthropic: eine Zahl, auf Biologie beschränkt, über alles aggregiert.

Die Zahlen pro Oberfläche messen etwas anderes und stehen in einer Fußnote über alle Fallbacks, ob Biologie oder nicht. Die Fallbacks insgesamt sollen auf Claude.ai um etwa zwei Drittel sinken (67%), auf Cowork um gut die Hälfte (55%), in Claude Code um 17% und auf der Claude Platform um nur 7%. Sie sind keine Anteile an den 85, und wer beides vermischt, bekommt einen Satz, der sauber, zitierfähig und falsch ist.

Außerdem sind es Rückgänge, keine Raten. Ein Minus von 7% auf der Platform sagt nichts über die absolute Häufigkeit dort, Fallbacks könnten schon immer selten gewesen sein. Die Spreizung zeigt aber, wo die Nachjustierung gewirkt hat: Der Consumer-Chat hat sich etwa zehnmal stärker bewegt als die Entwicklerplattform, und Coding lag mit 17% dazwischen.

Ein Klassifikator, dessen Lockerung ein Chatfenster zehnmal stärker verschiebt als eine API, wurde offensichtlich nicht auf API-Traffic kalibriert. Wer eine Flotte von Subagenten betreibt, saß flussabwärts einer Schutzschranke, die auf einen Menschen abgestimmt war, der eine Frage in ein Textfeld tippt.

Fairerweise braucht es einen Hinweis, und er ist für das Vertrauen wichtig: Nichts wurde geleakt. Anthropic hat die Details beim Ausliefern der Korrektur selbst veröffentlicht, samt Zahl. Der Vorwurf ist nicht Verschleierung. Es geht um die Form des Mechanismus.

Warum ein Downgrade schlimmer ist als eine Ablehnung

Eine Ablehnung ist eine gute Art des Scheiterns. Sie ist typisiert, hat einen Statuscode, taucht im Dashboard auf, löst einen Alert aus, nimmt einen Retry-Pfad und ist erkennbar die Schuld eines anderen.

Ein Downgrade bietet keinen dieser Ansatzpunkte. Es kommt kein Fehler, kein Statuscode, kein Logeintrag. Zurück kommt eine gültige, sauber formatierte Antwort, die nur etwas schlechter ist: ein Patch, dem ein Randfall fehlt, ein Test, der als flaky abgetan wird, eine Zusammenfassung ohne den entscheidenden Vorbehalt.

Ein schwaches Subagenten-Ergebnis bringt normalerweise niemanden dazu, dem Anbieter die Schuld zu geben. Schuld ist der Prompt, denn er ist das, was man direkt kontrolliert, und meistens liegt der Fehler auch dort. Also wird umformuliert, die Ergebnisse werden besser, und die Theorie scheint bestätigt. Aber eine neue Formulierung ist für den Klassifikator auch ein anderer Input. Das übliche Mittel gegen eine schlechte Antwort stört genau das, was den Austausch ausgelöst haben könnte, also scheint die Reparatur zu wirken, und die falsche Diagnose bleibt hängen. Wenn eine einzige Änderung sowohl einen vagen Prompt repariert als auch einen, der einen Filter ausgelöst hat, kann niemand sagen, welches Problem bestand.

Monatelang mittelmäßiger Subagenten-Output könnte aufs Prompting geschoben worden sein, obwohl ein Teil davon ein Austausch war, und herausfinden lässt sich das nicht, weil niemand festgehalten hat, welches Modell geantwortet hat.

Die Daten waren immer da

Hier fehlte nichts. Das Antwortobjekt der Messages API hat ein Feld model neben id, content, stop_reason, stop_details und usage. Jede jemals zurückgegebene Antwort hat das Modell genannt, das sie erzeugt hat. Kaum jemand liest das Feld, weil es wie ein Echo der Anfrage aussieht.

Das SDK stellt es immer noch als Echo der Anfrage dar: Der Doc-Kommentar zu model im Antworttyp beschreibt es als das Modell, das den Prompt vervollständigen wird. Futur, bei einem Feld in einer bereits abgeschlossenen Antwort. Jahrelang stimmte diese Formulierung, jetzt nicht mehr. Welches Modell einen Aufruf bedient hat, entscheidet sich zur Laufzeit, und der einzige maßgebliche Beleg dafür ist die Antwort, die der meiste Code wegwirft.

Wer Claude Code nutzt, hat das bereits auf der Platte. Jeder Assistenten-Turn wird an ein JSONL-Transkript unter ~/.claude/projects/ angehängt, mit dem vollständigen API-Nachrichtenobjekt. Der naheliegende Einzeiler zählt Modell-Strings:

grep -ho '"model":"[^"]*"' *.jsonl | sort | uniq -c | sort -rn

Die Zählung über die zwölf neuesten Transkripte in einem Projektordner ergab: claude-opus-5 beantwortete 4,691 Turns, claude-opus-4-8 1,231, sechs Turns waren als synthetisch markiert, und eine letzte Gruppe von 133 Zeilen nannte nur sonnet, haiku oder opus.

Diese 133 sind keine ausliefernden Modelle. Sie stehen unter message.content.input.model, wo die Startparameter von Subagenten liegen: das für einen Subagenten angeforderte Modell, festgehalten in einem Tool-Aufruf. Das ausliefernde Modell steht unter message.model. Gleicher Schlüsselname, anderer Pfad, gegenteilige Bedeutung. Wer nach Pfad filtert, lässt den Rest verschwinden:

jq -r 'select(.type=="assistant") | .message.model' *.jsonl | sort | uniq -c | sort -rn

Der erste Versuch lag daneben, und die Art des Fehlers ist die Lektion. Eine Datei speichert angefordertes und ausgeliefertes Modell unter identischem Schlüssel, und nur der Pfad unterscheidet sie. Ein simples grep liefert eine Zahl, aber nicht die Unterscheidung, auf die es ankommt.

Beide vollständigen IDs wurden bewusst gewählt, in Sessions über einen Versionssprung hinweg, daher zeigen diese Summen keinen Austausch durch den Klassifikator; in diesen Logs ist keiner aufgetaucht. Was existiert, ist ein Messinstrument, kein Befund. Die Einträge enthalten außerdem isSidechain, das Subagenten-Traffic markiert, sowie eine requestId. Angefordertes und ausgeliefertes Modell pro Subagent zu vergleichen ist also ein Nachmittagsprojekt über Dateien, die schon auf der Platte liegen. So simple Infrastruktur sollten Nutzer nicht selbst schreiben müssen.

Das Harness behandelt Modellwechsel längst als Ereignisse

Claude Code behandelt Fallback seit Monaten, Release für Release, als eigenständiges Konzept. Version 2.1.166 führte die Einstellung fallbackModel ein, die bis zu drei Modelle auflistet, die nacheinander probiert werden, wenn das Hauptmodell überlastet oder nicht erreichbar ist. In 2.1.76 wurden diese Hinweise dauerhaft sichtbar, nicht mehr im Verbose-Modus versteckt, und bekamen lesbare Namen. Release 2.1.183 gibt im Print-Modus eine Warnung auf stderr aus, wenn das angeforderte Modell veraltet ist oder still aktualisiert wurde. In 2.1.233 erzeugt eine unbekannte Modell-ID eine Zeile über ein nicht erkanntes Modell auf stderr. Der neueste Build ergänzt die Hook-Events PreModelSwitch und PostModelSwitch, damit Code einen Wechsel verhindern, bestätigen oder annotieren kann.

Fünf Entscheidungen, eine Schlussfolgerung: Von einem Modellwechsel soll der Betreiber erfahren.

All das regelt Wechsel, die das Harness selbst vornimmt. Ein Austausch, den ein Klassifikator weiter oben vornimmt, kommt ohne Hinweis, ohne Hook-Event, ohne stderr-Ausgabe und ohne typisierten Fehler. Ein Team, das entschieden hat, dass ein Downgrade wegen Verfügbarkeit ein dauerhaftes Banner verdient, liefert ein Downgrade aus Sicherheitsgründen ganz ohne alles aus. Böswilligkeit ist eine unwahrscheinliche Erklärung. Eine Nahtstelle passt besser: Das Harness meldet seine eigenen Aktionen, das Modell seine, und der Austausch passiert im Zwischenraum.

Das gleiche Muster anderswo

Am 19. August stellte OpenAI eine Vorschau auf Private Safety Processing vor, eine Monitoring-Schicht, die Inputs und Outputs mehrerer Unterhaltungen gemeinsam betrachtet, um Missbrauch zu erkennen, der erst sessionübergreifend sichtbar wird. Laut Unternehmen werden keine Kundendaten gespeichert, sondern nur ein eng gefasstes Signal zur Art der Aktivität erzeugt. Es ist eine Antwort auf die 30-tägige Aufbewahrung, die Anthropic im Juli für betroffene Modelle angekündigt hatte, eine Richtlinie, die Unternehmen mit sensiblem Material beunruhigte.

Das als falsch zu bezeichnen wäre unfair. Es lässt sich schlicht nicht überprüfen. Verhalten über Sessions hinweg zu korrelieren und dabei nichts zu speichern, sind Aussagen in sichtbarer Spannung, und um sie aufzulösen, müsste man wissen, was das Signal enthält und wie lange das Korrelationsfenster dauert. Beides ist nicht veröffentlicht.

Die Form entspricht dem Fallback-Fall: eine Eigenschaft des Dienstes, die Kunden erheblich betrifft, die nur der Anbieter beobachten kann und die in der Granularität offengelegt wird, die der Anbieter wählt. Sicherheitsverhalten ist zum Wettbewerbsfeld geworden, und der Wettbewerb läuft über Eigenschaften, für die Kunden kein Messgerät haben.

Was es beheben würde

Niemand verlangt hier eine Rücknahme. Der Biologie-Klassifikator kann bleiben, ebenso die Fallbacks, die der Beitrag für Virologie, Toxikologie und molekulares Design auflistet. Die Bitte ist klein: Sie kostet einen einzigen String.

Der Austausch gehört in den Antwort-Umschlag. Jede dieser Varianten würde reichen: ein Header, ein zusätzliches Feld in usage oder ein Telemetrie-Attribut, das das angeforderte Modell vom antwortenden trennt. Daran ist nichts ungewöhnlich. Anfragen von Subagenten gehen bereits mit den Headern agent-id und parent-agent-id raus, Modellangaben an eine Anfrage zu hängen ist in einer Richtung also gängige Praxis. Gleichzeitig versieht der OpenTelemetry-Export nur eine einzige Metrik (Codezeilen) mit einem Attribut model, und nirgends zeigt ein Signal, dass das antwortende Modell vom angeforderten abwich.

Der Grund muss nicht offengelegt werden. Eine Kategorie genügt, oder sogar nur die Tatsache, dass es passiert ist, geliefert in dem Moment, in dem es passiert, innerhalb der Antwort.

Die Regel, die immer wieder auftaucht, überdauert diesen Anbieter und diesen Monat: Was ein Anbieter nicht in die Antwort schreibt, wird zum Bug des Kunden. Es landet in dessen Fehlerbudget, Code-Review, Postmortem und Einschätzung der eigenen Kompetenz. Die 85% wurden auf der Anbieterseite dieser Linie gemessen. Ein Header würde die nächste Zahl auf die Kundenseite holen.