ISMS Copilot
Engineering

Das Modell-ID-Los: dieselbe Anfrage, unterschiedliche Ergebnisse

Hinter einem Multi-Provider-Gateway lieferte dieselbe Modell-ID an einem Tag ein erstes Token nach 312 ms Median ohne Reasoning-Ausgabe und Tage später nach 3.073 ms mit 2.627 Zeichen Reasoning. Die erwartete Routing-Flag, die dies verhindern sollte, funktionierte nicht.

von ISMS Copilot··10 min read
Das Modell-ID-Los: dieselbe Anfrage, unterschiedliche Ergebnisse

Hinter einem Multi-Provider-Gateway spezifiziert eine Modell-ID nicht, was deine Anfrage bedient. Sie benennt eine Menge von Bereitstellungen mit unterschiedlichen Serving-Konfigurationen, und solange du nicht eine davon festlegst, ist jede Anfrage ein Losziehen aus dieser Menge. Wir haben dies auf die harte Tour gemessen: In unserer Evaluation von moonshotai/kimi-k2.5 über OpenRouter (186 Aufrufe, gestartet am 22.04.2026, letzte Runden in den folgenden Tagen) produzierte dieselbe Anfragekonfiguration, dieselbe Modell-ID, derselbe Hinweis provider: { sort: "latency" }, derselbe Satz mit zehn Prompts, in einer Runde einen Median von 312 ms bis zum ersten Token mit null gestreamten Reasoning-Zeichen (10 von 10 Aufrufen) und in einer späteren Runde 3.073 ms mit einem Median von 2.627 Zeichen Reasoning (wiederum 10 von 10 Aufrufen). Ein anderer Provider bediente dieselbe ID mit deutlich anderem Verhalten – ohne dass sich unser Code geändert hätte. Die Antwort-Metadaten nennen zwar den bedienenden Provider, falls man daran denkt, ihn zu loggen; aber nichts weist darauf hin, dass sich das Verhalten geändert hat.

Die schärfere Erkenntnis ist, dass die Routing-Flag, von der wir erwarteten, genau dies zu verhindern, in unseren Läufen nicht funktionierte. Wenn dein Produkt von der Reasoning-Tiefe abhängt, ist die Modell-ID in deiner Konfiguration nicht das, was du ausgeliefert hast. Was du ausgeliefert hast, ist ein Lotterielos, und die Routing-Steuerungen des Gateways sind Hinweise, die zu überprüfen – nicht Verträge, auf die man sich verlassen kann.

Dieselbe Anfrage, zweimal

Wir benchmarkten Kandidatenmodelle für einen Compliance-Assistenten, daher lief jede Konfiguration mit denselben Prompt-Sätzen: zehn Standard-Compliance-Prompts (Erkläre ISO 27001 Anhang A.5.1, DSGVO Artikel 32, SOC 2 CC6.1 usw.) und fünf harte Prompts, die für die Synthese über mehrere Frameworks konzipiert waren – die Art von Frage, bei der die Reasoning-Tiefe wirklich sichtbar wird. Bei jedem Aufruf erfassten wir die Zeit bis zum ersten Token, die Gesamtzeit, die gestreamten Reasoning-Zeichen, die gestreamten Inhaltszeichen sowie das provider-Feld, das OpenRouter in jedem Stream-Chunk zurückgibt.

Mit sort: "latency" leitete eine frühe Runde alle zehn Standard-Prompts an einen Hosting-Provider (BaseTen) weiter: 312 ms Median bis zum ersten Token, null gestreamte Reasoning-Zeichen bei jedem Aufruf. In einer späteren Runde, Tage später, leitete dieselbe Anfragekonfiguration alle zehn Aufrufe an einen anderen Provider (ModelRun) weiter: 3.073 ms Median, 2.627 Reasoning-Zeichen Median. Eine noch spätere Runde leitete zurück zum ersten Provider. Genau das tut sort: "latency" laut Design. Die Dokumentation von OpenRouter zur Provider-Routing (abgerufen am 15.07.2026) besagt, dass bei einem expliziten sort „Load Balancing deaktiviert wird und der Router die Provider der Reihe nach versucht“, geordnet nach gemessener Latenz. Die gemessene Latenz ändert sich, also ändert sich die Reihenfolge – und damit in unseren Läufen auch, ob überhaupt Reasoning-Ausgabe erscheint.

Eine Verzehnfachung der Latenz ist ärgerlich. Dass sich das Verhalten unter einer stabilen Modell-ID ändert, ist ein Problem anderer Art, weil es nichts gibt, das dich warnt. Jede Antwort war ein HTTP 200 mit flüssigem Inhalt und plausibler Token-Abrechnung.

Die Flag, von der wir erwarteten, dass sie es abfängt

Wir haben das Ergebnis mit null Reasoning-Zeichen nicht einfach hingenommen. Wir versuchten, Reasoning auf dem schnellen Pfad mit jedem Parameter zu erzwingen, den die API anbietet: reasoning: { enabled: true }, reasoning: { effort: "high" }, reasoning: { max_tokens: 1024 }. Null gestreamte Reasoning-Zeichen, jedes Mal, wenn die Anfrage von diesem Provider bedient wurde.

Dann griffen wir zur Routing-Steuerung. OpenRouters Dokumentation beschreibt require_parameters wie folgt: „Wenn du require_parameters auf true setzt, wird die Anfrage nicht einmal an diesen Provider weitergeleitet“, bezogen auf Provider, die nicht alle Parameter in deiner Anfrage unterstützen (Dokumentation zum Provider-Routing, abgerufen am 15.07.2026). Wir setzten require_parameters: true zusammen mit reasoning: { effort: "high" }. Die Anfrage wurde trotzdem an denselben Provider weitergeleitet, und die Antwort enthielt erneut keinen Reasoning-Text.

Bevor wir Schlüsse zogen, überprüften wir unser Parameterformat an bekannten gut funktionierenden Bereitstellungen, denn „das Modell kann nicht Reasoning“ und „dieser Endpunkt unterstützt kein Reasoning“ sehen von außen identisch aus. Festgelegt auf DeepInfra produzierte dieselbe Modell-ID 3.116 Reasoning-Zeichen ohne Flag und 3.807 mit reasoning: { enabled: true }. Festgelegt auf Novita: 3.460 Zeichen. Diese Läufe beantworten die entscheidende Frage: Die Modellfamilie kann Reasoning, unsere Anfragesyntax war gültig, und die bedienende Endpunkt – nicht das Modell – war die Variable.

Um präzise zu sein, was dies zeigt und was nicht: require_parameters ist als Filter für Provider nach Parameterunterstützung dokumentiert, und allein aus den Antworten können wir nicht erkennen, ob unsere Ergebnisse mit null Reasoning-Zeichen die Fähigkeitsmetadaten des Endpunkts, die Parameterbehandlung des Providers oder eine Serving-Konfiguration widerspiegeln, die einfach keinen Reasoning-Text ausgibt. Ein Endpunkt, der keinen Reasoning-Text ausgibt, kann eine bewusste und legitime Serving-Entscheidung sein; 312 ms bis zum ersten Token ist ein echtes Produkt, das angeboten werden kann, und null gestreamte Reasoning-Zeichen beweist nur, dass uns kein Reasoning ausgegeben wurde – nicht, dass keine Berechnung stattfand. Was wir sagen können, ist enger und nützlicher: In unseren Läufen im April 2026 führte das Deklarieren des Reasoning-Parameters als erforderlich nicht dazu, dass wir an einen Endpunkt weitergeleitet wurden, dessen Antworten Reasoning-Ausgabe enthielten. Was auch immer der Mechanismus war, der praktische Vertrag, von dem wir dachten, wir hätten ihn, hielt nicht, und nur die Messung des Outputs hat uns gewarnt.

Warum ein Compliance-Produkt es bemerkt – und warum deins vielleicht nicht

Hier kommt der unangenehme Teil, ganz klar formuliert: Bei unseren fünf harten Prompts sah die Konfiguration mit null Reasoning-Zeichen immer noch kompetent aus. Gefragt, Kontrollüberschneidungen und einen Konflikt zwischen ISO 27001, DSGVO Artikel 32 und PCI DSS für ein 50-Personen-SaaS-Unternehmen zu finden, produzierte es strukturierte Analysen mit spezifischen Klauselverweisen, wie in unseren Laufnotizen festgehalten: ISO 27001 Anhang A Kontrollen A.9.1 bis A.9.4, DSGVO Art. 32(1)(a), PCI DSS Anforderungen 3.4 und 4.1. Der Haken im Flüssigen: A.9.x ist die Nummerierung der überholten ISO/IEC 27001:2013-Ausgabe; die Revision von 2022 reorganisierte Anhang A. Die Antwort las sich autoritativ und trug eine editionsbedingte Veraltetheit, die nichts in der Antwort kennzeichnet – wir haben es nur bemerkt, weil wir die Nummerierung mit der Revision von 2022 abgeglichen haben. Das ist die Fehlerform im Kleinen: flüssig, strukturiert, spezifisch und leise nicht das Verhalten, das du konfiguriert hattest. Wenn unsere Evaluation „ein paar Antworten kurz angeschaut auf offensichtliche Fehler“ gewesen wäre, wäre der Verlust der Reasoning-Ausgabe unsichtbar geblieben. Er trat zutage, weil wir Reasoning-Zeichen pro Aufruf als Metrik erster Klasse protokollierten und die Spalte auf null ging.

Der Rest des Scans der kimi-Familie zeigte, wie unterschiedlich jeder Pfad scheitert. Die dedizierte Thinking-Variante (moonshotai/kimi-k2-thinking) produzierte bei jedem harten Prompt Reasoning-Ausgabe (Median 4.103 Zeichen), erreichte aber bei einem tiefen Reasoning-Prompt 178.618 ms bis zum ersten Token – drei Minuten starrer Blick auf einen Ladebalken. Festgelegt auf kimi-k2.5 bei einem Provider mit Reasoning-Fähigkeit (Inceptron) produzierte es echtes Reasoning, scheiterte aber bei 2 von 5 harten Prompts komplett: Die Antwort verbrauchte das gesamte 2.048-Token-Budget für Reasoning und gab null Inhalt aus. Schnell ohne Reasoning-Ausgabe, Reasoning ohne begrenzte Latenz oder Reasoning, das die Antwort aushungert. Drei Fehlerformen innerhalb einer Modellfamilie – und keine davon ist in den IDs sichtbar. Wir sind von jedem dieser Pfade für die Produktion zurückgetreten.

Für einen Compliance-Assistenten sind die Einsätze spezifisch: Die Antwort fließt in eine Risikobewertung oder eine Prüfungsantwort ein, und eine Antwort kann sich autoritativ lesen, während sie genau die Veraltetheit trägt, nach der ein Prüfer sucht. „Flüssig, aber nicht das Verhalten, das du konfiguriert hast“ ist die schlimmste Fehlerform in diesem Bereich, weil nichts in der Antwort sie als Fehler kennzeichnet. Der eigene Engineering-Blog von OpenRouter räumt die qualitative Seite dieser Varianz ein: „Einige Provider bedienen stärker quantisierte Varianten eines Modells, die unterperformen im Vergleich zu derselben Modellversion, die woanders gehostet wird“ (Wie das OpenRouter-Modell-Routing funktioniert, veröffentlicht am 12.06.2026). Unsere Daten fügen dieser Darstellung eine verhaltensbezogene Dimension hinzu: Nicht nur dass dasselbe Modell schlechter bedient wird, sondern Reasoning-Ausgabe erscheint oder verschwindet hinter einer stabilen ID.

Das Modell-ID-Los

Das ist die benannte Idee und das mentale Modell, das wir nun auf jede Gateway-Integration anwenden: Wenn eine Modell-ID über Provider mit unterschiedlichen Serving-Konfigurationen load-balanced wird, ist jede Anfrage ein Losziehen, und der gedruckte Name auf dem Los ist das am wenigsten informative Ding daran. Die Modell-ID sagt dir die Modellfamilie. Sie sagt dir nicht die Quantisierung, die Latenzverteilung, ob Reasoning-Ausgabe erscheinen wird oder ob die Parameter, die du als erforderlich markiert hast, im zurückgegebenen Inhalt widergespiegelt werden. Das sind Eigenschaften des Tripels (Modell, Provider, Tag), und zwei der drei Variablen liegen außerhalb deiner Konfigurationsdatei.

Die portable Checkliste

Wenn du LLM-Traffic über jedes Multi-Provider-Gateway leitest – nicht nur OpenRouter:

  • Protokolliere verhaltensbezogene Ausgaben als Metriken erster Klasse. Reasoning-Zeichen oder -Tokens pro Aufruf, zusammen mit der Latenz, verknüpft mit dem bedienenden Provider, den die Antwort meldet. Ein Verhalten, das nicht pro Antwort gemessen wird, kann verschwinden, ohne dass es jemand bemerkt. Richte in der Produktion Warnungen für den Zusammenbruch ein, nicht nur in der Evaluation.
  • Behandle Routing- und Parameter-Flags als Hinweise, bis du sie anhand des Outputs bestätigt hast. Sende eine Anfrage, die eine Fähigkeit erfordert, dann prüfe, welcher Provider sie bedient hat und ob die Fähigkeit tatsächlich in der Antwort erschienen ist.
  • Bevor du schlussfolgerst „dieses Modell kann kein X“, pin einen bekannten guten Provider und führe einen A/B-Test mit der Flag durch. Unsere Anfrage war die ganze Zeit gültig; der bedienende Endpunkt war die Variable. Ohne die Pinning-Validierung hätten wir das Modell verantwortlich gemacht.
  • Probe das Routing über Stunden und Tage hinweg, nicht innerhalb einer Session. Zehn von zehn an einen Provider am Dienstag ist eine Stichprobe, kein Merkmal. Unsere Oszillation zeigte sich erst über Runden, die Tage auseinanderlagen.
  • Unterscheide mit harten Prompts und berichte Verteilungen. Unsere zehn einfachen Prompts produzierten Antworten, die wir nicht sinnvoll hätten einordnen können; nur die fünf harten Prompts trennten die Antwortqualität zwischen den Konfigurationen, und Mediane verdeckten den 178-Sekunden-Ausreißer. Die Maximalspalte ist dort, wo die nicht auslieferbaren Konfigurationen liegen.
  • Wenn deterministisches Verhalten wichtig ist, pin den Provider und überprüfe ihn regelmäßig neu. Pinning verzichtet auf Failover und manchmal auf Latenz. Für einen regulierten Bereich ist das oft der richtige Kompromiss.

Grenzen

Dies ist eine Evaluation: 186 Aufrufe, 5 bis 10 Prompts pro Konfiguration, auf unserem Compliance-Prompt-Set, gestartet am 22.04.2026 mit letzten Runden in den folgenden Tagen (wir haben das Evaluationsdatum protokolliert, nicht die Zeitstempel pro Runde). Jede Zahl hier ist unsere eigene Messung auf unseren eigenen Aufgaben in diesem Zeitraum – kein Anspruch auf das aktuelle Verhalten, die Konfiguration oder die Absicht eines Anbieters. Modellbezeichner sind die öffentlichen Gateway-IDs, wie sie zum Zeitpunkt der Anfrage verwendet wurden; wir haben keine zugrundeliegenden Modellrevisionen unabhängig erfasst. Provider-Bereitstellungen, OpenRouters Routing-Logik und die Dokumentation, die wir zitieren (abgerufen am 15.07.2026), können sich seitdem geändert haben. Die Beobachtung zu require_parameters bezieht sich auf ein Modell bei einem Provider-Paar; wir haben sie nicht über den gesamten Katalog hinweg überprüft. Null gestreamte Reasoning-Zeichen bedeutet nur, dass kein Reasoning im Response ausgegeben wurde – nichts weiter. Und die Stichprobengrößen sind entscheidungsrelevant für unsere Auslieferungsentscheidung, richtungsweisend für deine. Worin wir uns sicher sind, ist der Mechanismus: Wenn sich das Serving-Verhalten pro Provider hinter einer stabilen ID unterscheidet, ist die einzige Fähigkeit, die du tatsächlich hast, die, die du am Ausgang misst.

Die Modell-ID in deiner Konfiguration ist ein Name für eine Verteilung. Miss die Ziehungen.

Verwandte Beiträge