Deine Pipeline braucht keinen Aufsatz. Sie braucht eine Wahrscheinlichkeit.
Arne Kellmann ·
Jeder LLM-Call in einer Pipeline endet gleich. Das Modell schreibt drei Absätze, und eine Regex liest eine Zeile davon. Die Absätze kosten Tokens und Sekunden. Die Regex ist der Teil, der läuft.
TypeSafe hat Jev am 15. September 2026 veröffentlicht, am nächsten Morgen stand es mit 1.800 Punkten oben auf Hacker News. Seitdem lässt man es Schach spielen, einen Browser steuern, Orderbücher handeln und Doom mit zehn Entscheidungen pro Sekunde spielen. Unterhaltsam. Nichts davon sagt dir, ob es in deine CI gehört.
Also habe ich die langweilige Variante gemacht. Ich habe die eine Stelle in meiner autonomen Build-Chain genommen, an der eine Regex die Prosa eines Modells liest, jedes echte Code-Review, das die Chain je erzeugt hat, durch Jev geschickt und die Antwort eingebaut. Das kam dabei heraus.
Wer dahintersteht. Jev ist das erste Modell von TypeSafe AI, einem Labor in San Francisco, das am 15. September 2026 mit einer 40-Millionen-Dollar-Seed-Runde unter Führung von DCVC aus dem Stealth kam. Gründer sind Diogo Almeida, zuvor Forscher bei OpenAI, mit Erik Gafni und Sasha Sheng. Auf X: @typesafeai und @CompleteSkeptic. Ich stehe in keiner Beziehung zur Firma; der API-Key ist ein normaler Early-Access-Key, und jeden Call in diesem Post habe ich selbst bezahlt.
Was Jev zurückgibt, in einem Absatz
Du schickst einen Zustand und eine typisierte Frage. Drei Fragetypen: Noul gibt eine Wahrscheinlichkeit zurück, dass eine Bedingung gilt. Choice gibt eine Option mit Verteilung zurück. Score gibt eine Position auf geordneten Stufen zurück, die du definierst. Mehrere Fragen über denselben Zustand laufen in einem Call, parallel, und das Modell sieht beim Beantworten die anderen Antworten nicht. Das ist die ganze API. Keine Prosa, keine Erklärung, kein JSON-Schema zum Reparieren.
curl -s https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"model":"jev-1.13.0","state":"Help! My payouts have been failing for 3 days.",
"questions":{"is_urgent":{"type":"noul","instructions":"Does this convey urgency?"}}}'
# {"model":"jev-1.13.0","answers":{"is_urgent":{"type":"noul","noul":0.95}},"usage":{"input_tokens":283,"output_tokens":23}}
Der Fall: ein Review sagt „mergeable“ und nennt einen Blocker
Die Chain, die blockquote.io baut, hat eine Review-Routine. Sie liest jeden Draft-PR und beendet ihr Review mit einer Markerzeile, MERGE-VERDICT: mergeable oder MERGE-VERDICT: changes. Ein Gate-Skript liest den Marker per Regex. Die Regex ist das Einzige zwischen diesem Review und dem Merge.
Der Fehlerfall ist offensichtlich, sobald man ihn gesehen hat. Der Reviewer schreibt: „The migration drops a column, which violates the expand-only rule. Must be fixed before merge. MERGE-VERDICT: mergeable.“ Die Regex sieht mergeable. Der Code merged.
Ich habe Jev den Review-Body, das Verdict und ein Noul gegeben:
{
"model": "jev-1.13.0",
"state": {
"verdict": "mergeable",
"review_body": "...",
"context": "A code review on a pull request. The verdict is a machine-read marker the reviewer wrote at the end. mergeable means: the code may merge as is, no open blocker. changes means: not mergeable."
},
"questions": {
"supports": {
"type": "noul",
"instructions": "Does `review_body` support the marker `verdict`? Answer no if the body names an unresolved blocker, a failing check, a missing file or asks for a change before proceeding while the verdict is positive, or if the body finds no problem while the verdict is negative."
}
}
}
74 echte Reviews, jede Zahl wörtlich
Jedes Review mit Merge-Verdict auf einem geschlossenen Pull Request im Repository. Nicht für den Test geschrieben. Je zwei bis sechs Kilobyte, in den letzten fünf Wochen von einem Reasoning-Modell erzeugt. Die, an denen das Modell gezweifelt hat, habe ich gelesen und von Hand gelabelt.
| Menge | Reviews | supports |
|---|---|---|
Verdict mergeable, Prosa stimmt zu |
46 | 0,58 bis 0,98, Median 0,96 |
Verdict changes, Prosa nennt einen Blocker |
25 | 0,61 bis 0,96, Median 0,85 |
| Prosa widerspricht dem Verdict, von Hand gelesen | 3 | 0,32, 0,44, 0,52 |
Die drei Widersprüche sind echt. Zwei Reviews nennen jeden Befund „non-blocking“, sagen wörtlich „nothing blocks“ und schreiben trotzdem changes. Eins ist ein leerer Body mit changes. Jev hat alle drei ganz unten einsortiert, und nichts, was seinem Verdict zustimmt, fiel unter 0,58.
Was es gekostet hat:
| Metrik | Wert |
|---|---|
| Calls | 74 |
| Latenz | 210 bis 959 ms, Mittel 292 ms |
| Input-Tokens, gesamt | 126.142 |
| Preis | 0,0053 $ für alle 74, Output ist kostenlos |
Das ist die Zahl, die man neben ein Reasoning-Modell halten muss, das dieselben 74 Reviews liest. Für eines davon zahle ich mehr.
Ein Vorbehalt, den der Hype überspringt: Der Anbieter nennt 70 bis 500 ms. Meine ersten Einzel-Calls mit curl lagen bei 530 bis 630 ms. In einem Node-Skript mit warmer Verbindung sind es 210 bis 300 ms. Miss dort, wo es später läuft.
Die Regel: eine Wahrscheinlichkeit ist ein Signal, keine Entscheidung
Die Chain hat eine Verfassung. Der Pause-Schalter, der Merge und die Gate-Schwellen sind Code, den ein Mensch editiert und ein Hash festnagelt. Eine Modellantwort geht als ein weiterer Input in diesen Code. Sie ersetzt nie eine Bedingung.
Das Gate macht also drei Dinge mit supports, und die Schwellen kommen aus der Tabelle oben, nicht aus der Doku:
- Unter 0,4: Das Gate wartet. Es postet die Zahl, ein Mensch liest das Review. Ein Treffer in 74.
- 0,4 bis 0,7: Das Gate lässt durch, das Sweep-Log trägt die Zahl. Sechzehn von 74. Ein Kommentar auf jedem wäre Rauschen.
- 0,7 und darüber, oder keine Antwort: unverändert. Die Regex hat schon ja gesagt.
Nichts wird gemerged, weil Jev es gesagt hat. Etwas wartet, weil Jev widersprochen hat. Diese Asymmetrie ist das ganze Design. Ein False Positive kostet einen menschlichen Blick. Ein False Negative kostet, was es vorher gekostet hat, nichts Neues. Wenn die API einen Fehler liefert oder der Key fehlt, verhält sich das Gate wie vor dem Modell. Fail open beim Modell, nie beim Code.
Die ganze Änderung ist ein Client-Modul mit 80 Zeilen, eine reine Funktion, die die Frage baut, ein if pro Gate und ein Fixture-Test, der die Schwellen gegen die 74 Zahlen festnagelt. Wandert der Modell-Pin, läuft das Fixture neu, und der Test sagt mir, ob die Schwellen noch halten.
Wo ich es einsetze, und wo nicht
Sieben Stellen in der Chain waren Kandidaten. Vier haben überlebt:
- Sentry-Ingest. Zwei Nouls pro Fehlergruppe: durch eine Codeänderung behebbar, und Duplikat eines offenen Issues. Heute ist der Dedupe-Schlüssel ein Fingerprint, und ein neuer Fingerprint für einen alten Bug verbraucht einen Build-Slot.
- Copy-Lint. Die Hausregel heißt „no AI slop“: keine Buzzwords, keine unbelegbaren Superlative, keine erfundenen Zahlen, keine falsche Dringlichkeit. Fünf Nouls pro geändertem String-Literal in einem Pull Request.
- Das Gate von oben.
- Injection-Scan. Ein Noul über jeden neuen Issue-Body und Kommentar: Enthält der Text Anweisungen an einen Agenten? Ein Treffer bekommt ein Label, jede Routine überspringt gelabelte Objekte. Die alte Regel war ein Satz im Prompt. Die neue Regel ist ein Test.
Drei nicht:
- Issues nach Scope und Größe vorsortieren. Der Grooming-Schritt ist schon ein Lauf eines Reasoning-Modells. Ein Vorklassifikator dupliziert ihn.
- Wöchentliche Produktsignale. Das sind Schwellenüberschreitungen über Zahlen. Da gibt es keinen Text zu beurteilen.
- Ausfall oder Rauschen bei einem Deploy. Der Judge, der ein Release zurückrollt, ist ein Anker der Chain. Ein Modellsignal dort braucht erst ein Log-Format, und einen Owner-Merge.
Und das Muster hinter den populären Demos: Schach funktioniert, weil die legalen Züge eine Liste sind und jeder Zug ein Choice darüber ist. Der Browser-Agent funktioniert, weil ein LLM plant und Jev den Klick aus einem Snapshot wählt. Der Trading-Bot funktioniert, weil BUY, SELL und HOLD drei Optionen sind. In jedem Fall besitzt der Code die Optionsliste, und das Modell wählt. Nach dieser Form solltest du in deinem eigenen System suchen. Wenn du die Optionen nicht aufschreiben kannst, ist Jev das falsche Werkzeug.
Was die Reviews nicht laut genug sagen
- „Zero hallucinations“ heißt typgültige Ausgabe. Eine falsche Wahrscheinlichkeit ist trotzdem eine falsche Antwort. Die Ausgabe kann nicht kaputt sein. Sie kann falsch sein.
- Kalibrierung ist eine Behauptung. Ob 0,9 auf deinen Daten neun von zehn Mal richtig heißt, misst du selbst. Diese Kurve hat noch niemand veröffentlicht. Meine 74 Reviews sind ein Datenpunkt in einer Domäne.
- Die Benchmark-Labels stammen von anderen Modellen. Die Genauigkeitszahlen des Anbieters nehmen die Übereinstimmung zweier Frontier-Modelle als Ground Truth. Betrachte sie als Obergrenze dessen, was der Anbieter weiß.
Nichts davon ändert das Design oben. Es ist der Grund für das Design oben.
An einem Nachmittag ausprobieren
- Key besorgen. Early Access ist offen, Keys kommen in Wellen.
- Eine Stelle finden, an der eine Regex die Prosa eines Modells liest, oder an der ein Prompt „sei vorsichtig mit X“ sagt.
- Die Frage so schreiben, dass ein Fremder sie allein aus dem Zustand beantworten könnte. Die Bedeutung gehört in die Instructions, nicht in den Schlüsselnamen.
- Jeden echten Fall ziehen, den du hast. Nicht zwanzig selbst geschriebene. Laufen lassen, die lesen, an denen das Modell zweifelt, die von Hand labeln.
- Die Schwellen aus dieser Tabelle setzen. Die Zahl als Input in den Code hängen, der schon entscheidet. Fail open beim Modell.
Die Doku liegt unter docs.typesafe.ai. Hängst du .md an einen Seitenpfad, bekommst du Markdown. Lies zuerst die Confidence-Seite.
Quellen
- Meine eigenen 74 Calls, 17. September 2026, Modell
jev-1.13.0. Fixture und Gate-Änderung in ArneFfm/blockquote #662. - TypeSafe, Introducing System One models and Jev.
- Maxim Saplin, Jev played chess: Elo 243, 0,0015 $ pro Partie.
- Every, Jev judged everything I’ve written in 0.7 seconds: 1.709 Urteile für unter einen Cent.
- Kingy AI, TypeSafe Jev review: die Kritik an Kalibrierung und Label-Herkunft.