Jev senkte die Kosten dieses KI-Agenten um 61 %
Im Juli schrieb ich, dass kleine Modelle entscheiden sollten, was große Modelle zu sehen bekommen: Es geht nicht darum, eine Aufgabe an ein günstigeres Modell weiterzuleiten, sondern kleine Modelle neben dem großen einzusetzen, damit sie auswählen, welche Tokens es überhaupt liest. Am Ende des Artikels schrieb ich, die Kosten seien ein Grund zum Experimentieren, aber kein Beweis, und jemand müsse den Test durchführen.
Am 15. September wurde dann Jev veröffentlicht. Es ist das erste System-One-Modell von TypeSafe: Es erzeugt überhaupt keinen Text, sondern liefert kalibrierte Wahrscheinlichkeiten für Antworten, die dein Code vorgibt. Es kostet $0.042 pro Million Eingabe-Tokens und antwortet in wenigen hundert Millisekunden. Mit dieser Kombination lassen sich zwei sehr konkrete Varianten der Juli-Idee günstig genug umsetzen, um sie tatsächlich zu messen.
Also habe ich diese beiden Varianten getestet.
Skills vorab laden. Bekommt ein Agent einen Katalog interner Dokumente, braucht er einen ganzen zusätzlichen Durchlauf, um zu entscheiden, welches er lesen soll, und es dann über ein Tool abzurufen. Jev kann diese Entscheidung vor dem ersten Durchlauf für einen Bruchteil eines Cents treffen. Die Dokumente stehen dann bereits im Prompt.
Tool-Daten filtern. Eine echte API-Antwort enthält größtenteils Felder, mit denen ein Agent nichts anfangen kann. In einem MCP-Setup landen sie trotzdem alle im Kontextfenster und werden in jedem weiteren Durchlauf erneut gesendet. Jev kann jedes Feld einer Antwort bewerten, bevor der Agent sie zu sehen bekommt.
Beides sind Klassifizierungsaufgaben, keine Schreibaufgaben. So fielen die Ergebnisse bei 192 Läufen mit 8 Aufgaben aus, berechnet mit den Preisen für Claude Opus 5:
Ob ein Chat-Titel noch zur Unterhaltung passt, ist eine weitere mögliche Entscheidung für Jev. Ich beschreibe diesen Anwendungsfall in meinem Artikel über das Erstellen von Unterhaltungstiteln. Mit Jev habe ich ihn noch nicht gemessen.
Durchschnittliche Kosten eines Agentenlaufs mit Opus 5
Bei der besten Aufgabe sanken die Kosten um 61%. Der Durchschnitt über alle acht Aufgaben liegt bei 29%, der geringste Wert bei 13%. In jedem Versuchsarm bestanden 99% der Qualitätsprüfungen, auch beim einfachen Agenten. Es musste also nichts aufgegeben werden, um diese Einsparungen zu erzielen.
Das gesamte Experiment kostete $1.17.
Was Jev ist
Jev erzeugt keinen Text. Du übergibst ihm einen state und eine Reihe typisierter Fragen. Zurück kommt eine kalibrierte Wahrscheinlichkeitsverteilung über die Antworten, die dein Code definiert. TypeSafe bezeichnet Jev als System-One-Modell, das mit dem trainiert wurde, was das Unternehmen als Reinforcement Learning für kalibrierte Entscheidungen beschreibt.
| Was | Wert |
|---|---|
| Preis | $0.042 pro Million Eingabe-Tokens, Ausgabe kostenlos |
| Kontext | 32,000 Tokens |
| Latenz, hier gemessen | 300 bis 600 ms, p50, unabhängig von der Batchgröße |
| Endpunkt | POST /api/alpha/decisions auf OpenRouter |
Was dieses Experiment überhaupt erst möglich macht, ist Batch-Verarbeitung. Alle Fragen werden in einem HTTP-Aufruf übermittelt, der state wird nur einmal gesendet. 264 Datenfelder zu bewerten erfordert eine Anfrage, nicht 264.
Mechanismus eins: Skills vorab laden
Vor dem ersten Durchlauf des Agenten liest Jev die Anfrage und die einzeilige Beschreibung jedes Skills. Den Inhalt der Skills sieht Jev nie. Alles mit einem Wert von mindestens 0.55 wird vollständig in den System-Prompt eingefügt.
Schritt 1 · die Nutzeranfrage
Schritt 2 · Jev bewertet alle 11 Skills auf einmal und liest nur die einzeiligen Beschreibungen
Ein HTTP-Aufruf, 11 Fragen, etwa 1,500 Tokens, $0.00006. Beim Schwellenwert von 0.55 wird ein Skill ausgewählt.
Schritt 3 · der Prompt, den der Agent gleich in seinem ersten Durchlauf erhält
Das Tool read_skill bleibt verfügbar. Der Agent kann also weiterhin alles abrufen, was der Router übersehen hat. Das ist wichtig, denn der Router übersieht durchaus Dinge.
Mechanismus zwei: Tool-Payloads filtern
Nachdem ein Tool geantwortet hat und bevor seine Ausgabe den Agenten erreicht, wird jedes Blattfeld der Antwort auf seine Relevanz für die aktuelle Anfrage bewertet. Alles unter 0.35 wird entfernt.
Schritt 1 · Der Agent ruft ein Tool auf, die API antwortet vollständig
Schritt 2 · Was Jev über die Situation erfährt, nicht nur über die Payload
Schritt 3 · Ein Aufruf, ein Wert pro Feld. Unter 0.35 wird das Feld durchgestrichen
In den sechs Durchläufen dieser Aufgabe blieben 58 bis 62 der 124 Felder erhalten. Die drei für die Aufgabe entscheidenden Felder (status, dunning.days_past_due, account.id) blieben in allen sechs erhalten.
Schritt 4 · Was das Kontextfenster des Agenten erreicht
Von 3,181 auf etwa 1,780 Zeichen, eine Kürzung um 44 %. Auch in Durchlauf 3, 4 und 5 wird nichts von den entfernten Feldern erneut gesendet.
Bemerkenswert an diesen Werten: Die Felder, die bei diesem Aufruf wegfallen, liegen bei 0.31 bis 0.34, die erhaltenen bei 0.35 bis 0.37. Der Grenzwert ist also tatsächlich eine Grenze, und einige Felder wechseln zwischen den Durchläufen die Seite. trial_end erzielte in einem Durchlauf 0.34, in einem anderen 0.37. Kein für die Aufgabe benötigtes Feld lag jemals in diesem Bereich.
Woher die Sicherheit tatsächlich kommt
Im dritten Schritt, beim Zustand, fällt die Entscheidung. Derselbe Schwellenwert ist mit einem unvollständigen Zustand gefährlich. Ein umfassenderer Zustand macht die Filterung zugleich sicherer und aggressiver.
Isoliert betrachtet, für das Feld, das bei der Mahnaufgabe entscheidend ist:
| Inhalt des Zustands | account.id | metadata.account_id | Behalten |
|---|---|---|---|
| Anfrage + Tool + Argumente | 0.18 | 0.20 | 51 / 124 |
| + die Richtlinien, denen der Agent folgt | 0.19 | 0.18 | 50 / 124 |
| + die bisherigen Aktionen | 0.33 | 0.25 | 40 / 124 |
| + die noch verfügbaren Tools | 0.73 | 0.76 | 27 / 124 |
Die beiden mittleren Spalten zeigen die Werte für das Feld, von dem die Aufgabe tatsächlich abhängt. Die letzte Spalte gibt an, wie viele der 124 Felder den Schwellenwert von 0.35 überstehen.
Die Skills hinzuzufügen, ändert nichts. Der bisherige Verlauf hilft ein wenig. Entscheidend ist die Liste der noch möglichen Aktionen. Solange der Scorer nicht weiß, dass ein Aufruf von billing_set_account_state(account_id, …) ansteht, ist eine Konto-ID nur eine Zeichenfolge unter vielen.
Die allgemeine Form dieses Prinzips, die sich auch auf andere Setups übertragen lässt:
Ein Feld ist nicht an sich nützlich. Es ist nützlich im Hinblick darauf, was der Agent gleich damit tun wird. Diese Information steckt nicht in der Payload, sondern im Schema der weiterhin verfügbaren Tools.
Wo die Einsparungen entstehen und wo nicht
Die beiden Mechanismen erfassen völlig unterschiedliche Dinge. Für den eigenen Workload ist es wichtiger zu wissen, welcher davon greift, als den Durchschnitt zu kennen.
Vorabladen wirkt bei vermeidbaren DurchläufenNicht bei der Payload-Größe
- Am sinnvollsten bei Aufgaben, die eine Richtlinie benötigen und sonst einen Durchlauf fürs Abrufen aufwenden würden
- Bringt nichts bei Aufgaben, die keinen Skill benötigen
- Kann sich negativ auswirken: Ein falsch geladener Skill wird bei jedem Durchlauf erneut gesendet
Filterung wirkt bei hoher Payload-DichteNicht bei der Aufgabenlänge
- Am sinnvollsten, wenn der Großteil der Bytes aus Text besteht, den niemand liest
- Nahezu wirkungslos, wenn jedes Feld entscheidend ist
- Die Einsparungen summieren sich, da ein entferntes Feld im nächsten Durchlauf nicht erneut gesendet wird
Die Unterschiede sind groß. Bei der Aufgabe, für die sechs Hilfeartikel eingehen und nur updated_at wichtig ist, entfernt die Filterung 84% der Payload und 63% der Eingabetokens. Bei der Incident-Aufgabe, bei der fast jedes Feld verwendet wird, sind es 5%. Derselbe Agent, derselbe Schwellenwert, ein Unterschied um den Faktor 17.
Kosten pro Aufgabe mit Opus 5, einfacher Agent im Vergleich zu beiden Mechanismen:
| Aufgabe | Art | Einfach | Beide | Einsparung |
|---|---|---|---|---|
| veraltete Doku | kurz · sehr dünne Payload | $0.0639 | $0.0252 | −61% |
| Rückerstattung | mittel · gemischt | $0.0419 | $0.0249 | −41% |
| Incident | kurz · dicht | $0.0340 | $0.0241 | −29% |
| Mahnwesen | kurz · gemischt | $0.0187 | $0.0135 | −28% |
| Abfrage | ein Aufruf · dünn | $0.0083 | $0.0068 | −17% |
| DSGVO | mittel · gemischt | $0.0336 | $0.0282 | −16% |
| SLA | lang · gemischt | $0.0442 | $0.0378 | −15% |
| Postmortem | sehr lang · gemischt | $0.0906 | $0.0792 | −13% |
| Durchschnitt | $0.0419 | $0.0299 | −29% |
Ein Opus-5-Agent, der 10,000 Aufgaben pro Monat bearbeitet, kostet statt $419 nur noch $299. Davon entfallen $9 auf Jev.
Ob sich die Filterung lohnt, hängt vom Preis des Hauptmodells ab
Das ist das Ergebnis, das dein Vorgehen ändern sollte.
Das Filtern kostet bei jedem Tool-Aufruf Jev-Tokens. Diese Tokens haben einen festen Preis. Die eingesparten Tokens werden hingegen zum Preis deines Agentenmodells abgerechnet. Entscheidend ist also das Verhältnis, und das kann sich umkehren.
| Agentenmodell | Preis für Eingabe | Agent ohne Filter | Beide Mechanismen | |
|---|---|---|---|---|
| GPT-5.6 Luna | $0.20/M | $0.00182 | $0.00221 | +21% |
| Claude Sonnet 5 | $2.00/M | $0.01676 | $0.01253 | −25% |
| Claude Opus 5 | $5.00/M | $0.04191 | $0.02995 | −29% |
Die Tokenzahlen bleiben gleich. Nur der Preis des Agentenmodells ändert sich. Beim günstigen Modell entfallen 42% der Kosten auf Jev, und das Filtern kostet mehr, als es einspart. Bei Opus 5 sind es 3% der Kosten.
Berechnet man den Kipppunkt anhand der gemessenen Tokenzahlen und der üblichen Preisstruktur, liegt er bei $0.55 pro Million Eingabe-Tokens mit aktivem Prompt-Caching und bei $0.37 ohne. Darunter solltest du nicht filtern, darüber schon.
Skills vorzuladen lohnt sich immer, auch beim günstigsten Modell, denn es kostet fast nichts: etwa 1,500 Jev-Tokens pro Durchlauf, also $0.00006, und spart dafür einen Gesprächsschritt.
Ein weiterer Effekt ist wissenswert: Caching halbiert die Kosten ungefähr und verringert den relativen Nutzen des Filterns, weil das meiste, was beim Filtern entfernt wird, ohnehin günstige Cache-Lesezugriffe gewesen wären. Filtern lohnt sich für einen Einsatz ohne Caching mehr als für einen mit Caching.
Der Fehlermodus
Der Schwellenwert von 0.35 ist nur dank des umfangreichen Zustands sicher. Eine frühere Version ohne diesen Zustand führte zum schlimmsten denkbaren Fehler.
Der Filter entfernte account.id aus einem Stripe-Abonnement und bewertete es mit 0.18. Außerdem entfernte er metadata.account_id, die zweite Kopie. Der Agent nahm den einzigen verbliebenen Bezeichner und tat Folgendes:
Aufruf: billing_set_account_state(account_id="cus_PmT4k9WqLr2XbN", state="read_only")
↑ die Stripe-Kunden-ID, nicht das Konto
Bericht: „Ich habe das zugehörige Konto gemäß der Richtlinie für Tag 10 auf schreibgeschützt gesetzt.“Der richtige Bezeichner war acct_borealis_4c77. Der Agent führte die Aktion am falschen Objekt aus und meldete das selbstbewusst.
Für jeden Einsatz müssen kritische Pfade festgelegt und der Schwellenwert darauf abgestimmt werden. Beim Routing entschieden zwei Hundertstel beim Schwellenwert darüber, ob ein Gesprächsschritt eingespart wurde oder nicht. Beim Filtern war der Unterschied noch deutlich größer.
Was ich daraus mitnehme
Es lohnt sich, an der Effizienz von KI zu arbeiten. Viel Potenzial liegt darin, Modelle unterschiedlicher Größe und Art zu kombinieren. Interessant ist hier, dass sich ein Modell, das überhaupt keinen Text verfassen kann, als guter Beurteiler dafür erweist, was ein textgenerierendes Modell sehen darf.
Hier wurden zwei Ansatzpunkte getestet. Dasselbe Muster könnte an vielen weiteren Stellen greifen: bei der Auswahl der Dateien, die ein Agent öffnet, bei der Entscheidung, wann ein Gespräch komprimiert werden sollte, bei der Bewertung, ob ein abgerufenes Dokument seine Tokens wert ist, oder beim Prüfen eines Schreibvorgangs, bevor er ausgeführt wird. Nichts davon wurde gemessen. Ich würde nicht davon ausgehen, dass es funktioniert, bevor es getestet wurde.
Weiter unten findest du die vollständige Dokumentation: den Testaufbau, jede Aufgabe, jeden Schwellenwert, alle Tabellen und auch, was diese Untersuchung nicht zeigt.
Alle Details
Alles ab hier ist das vollständige Experiment. Es ist absichtlich lang. Wenn du nur das Ergebnis wolltest, hast du es bereits.
Der Versuchsaufbau
Der Agent
Etwa 80 Zeilen. Kein Framework, kein Agent-SDK, keine Orchestrierungsbibliothek. Eine while-Schleife um fetch:
- Sende einen POST-Request an den Chat-Completions-Endpunkt von OpenRouter, mit der Nachrichtenliste und den Tool-Schemas im OpenAI-Format für Funktionsaufrufe.
- Enthält die Antwort
tool_calls, führe jeden Aufruf lokal aus, füge das Ergebnis als Nachricht mitrole: "tool"hinzu und starte die Schleife erneut. - Enthält die Antwort keine
tool_calls, ist dieser Text die endgültige Antwort und die Schleife endet.
| Parameter | Wert | Hinweis |
|---|---|---|
model | openai/gpt-5.6-luna | $0.20/M eingehend, $1.20/M ausgehend, Kontextfenster mit 1,050,000 Token |
tools | 17 Funktions-Schemas | |
tool_choice | auto | Der Agent entscheidet, ob und was aufgerufen wird |
seed | 1000 + Wiederholungsindex | Das Einzige, was zwischen den Wiederholungen variiert |
max_tokens | 2000 | Eine Obergrenze, kein Zielwert |
reasoning / reasoning_effort | nicht festgelegt | Beim Standardwert des Anbieters belassen |
temperature, top_p | nicht festgelegt | Beim Standardwert des Anbieters belassen |
Zum Thema Reasoning: Es wurde nie ein reasoning-Parameter übergeben, das Modell lief also mit dem Standardwert des Anbieters. Ein späterer Kontrollaufruf gibt reasoning_tokens: 0 zurück. Es wurde somit kein separates Reasoning-Budget verbraucht, und keine der Tokenzahlen enthält verborgene Reasoning-Token. Bei einer Wiederholung mit höherem Reasoning-Aufwand wären die absoluten Werte anders.
Zwei Sicherheitsvorkehrungen, denn eine außer Kontrolle geratene Agentenschleife kostet Geld: maximal 8 Durchläufe pro Ausführung und höchstens 6 Tool-Aufrufe pro Durchlauf. Bei den 192 Ausführungen wurde keine der beiden Grenzen erreicht. Eine dritte Vorkehrung summiert die Kosten aller Aufrufe und bricht ab, sobald der festgelegte Grenzwert überschritten wird. Für die Kampagne lag er bei $2.60.
Die Welt
Ein fiktives B2B-SaaS-Unternehmen namens Northwind Analytics, für das der Agent als Betriebsassistent arbeitet.
17 Tools, deren Nutzdaten die tatsächliche Struktur von Stripe, Zendesk, HubSpot, Statuspage, PagerDuty, Slack, Linear und einem Help-Center-CMS nachbilden: gleiche Schlüsselnamen, gleiche Verschachtelung, gleicher Datenballast. Es handelt sich um lokale Funktionen, die Testdaten zurückgeben, daher verlässt nichts den Rechner. Schreibvorgänge werden zur Bewertung protokolliert und mit einer plausiblen Bestätigung quittiert.
| Tool | Nachgebildet nach | Nutzdaten |
|---|---|---|
kb_list_articles | Listen-Endpunkt eines Help-Center-CMS | 28,128 Zeichen |
stripe_list_charges | Stripe GET /v1/charges | 6,993 Zeichen |
kb_get_article | Lese-Endpunkt eines Help-Center-CMS | 4,966 Zeichen |
stripe_get_subscription | Stripe GET /v1/subscriptions/:id | 3,181 Zeichen |
zendesk_get_ticket | Zendesk GET /api/v2/tickets/:id mit zusätzlichen eingebetteten Daten | 2,402 Zeichen |
pagerduty_get_incident | PagerDuty GET /incidents/:id | 1,821 Zeichen |
statuspage_get_incident | Statuspage-Vorfall + Verfügbarkeit | 1,711 Zeichen |
crm_get_account | HubSpot-Unternehmensobjekt | 1,117 Zeichen |
read_skill | intern | 988 Zeichen |
stripe_create_refund | Stripe POST /v1/refunds | 479 Zeichen |
linear_create_issue | Linear issueCreate | 202 Zeichen |
billing_apply_credit | interne Abrechnungs-API | 147 Zeichen |
zendesk_reply | Zendesk PUT /api/v2/tickets/:id | 144 Zeichen |
billing_set_account_state | interne Abrechnungs-API | 134 Zeichen |
slack_post_message | Slack chat.postMessage | 124 Zeichen |
billing_apply_discount | interne Abrechnungs-API | 98 Zeichen |
pagerduty_escalate | PagerDuty-Eskalation | 92 Zeichen |
11 Skills: Markdown-Dateien mit einer einzeiligen description im Frontmatter und einem Textkörper, der die konkreten Grenzwerte, Zahlen und Formate enthält: churn-save-offers, docs-review-cadence, dunning-playbook, enterprise-contract-terms, escalation-matrix, gdpr-data-requests, incident-comms, oncall-handover, refund-policy, release-notes-format, slack-style-guide. Mehrere davon sind für keine der Aufgaben relevant. Sie dienen dem Router als Ablenkung.
8 Aufgaben, ausgewählt entlang zweier unabhängiger Dimensionen: Länge, von einem einzelnen Tool-Aufruf bis zu sieben Durchläufen, und Dichte der Nutzdaten, von „jedes Feld ist wichtig“ bis zu „76 % der Bytes sind Text, den man verwerfen kann“.
Die Aufgaben im Wortlaut
| Aufgabe | Als Nutzernachricht gesendete Eingabe |
|---|---|
T1-refund | ACME Analytics (Konto acct_acme_9f21) hat eine E-Mail geschickt: Dem Unternehmen zufolge wurde die November-Rechnung doppelt abgebucht. Prüfe das und erledige alles vollständig, einschließlich einer Benachrichtigung des Teams. |
T2-sla | Das Zendesk-Ticket 48213 ist ein Antrag auf SLA-Gutschrift von einem Unternehmenskunden wegen Oktober. Ermittle den zustehenden Betrag, verbuche die Gutschrift und antworte dem Kunden. |
T3-dunning | Das Abonnement sub_1QdRvT2eZvKYlo2CkW8pQm4L ist überfällig. Führe den nächsten Schritt gemäß unserem Prozess aus. |
T4-gdpr | Ticket 48377 ist gerade im Datenschutz-Postfach eingegangen. Übernimm den Fall und erledige alles, was der Prozess verlangt. |
T5-incident | Der Vorfall PD-99213 wurde gerade ausgelöst. Kümmere dich um die Eskalation und die Kommunikation. |
T6-stale-docs | Welche unserer veröffentlichten Help-Center-Artikel sind zur Überprüfung überfällig? Erfasse die anstehenden Arbeiten. |
T7-postmortem | Der Vorfall INC-4471 ist behoben. Erledige die Nachbereitung: Wer war betroffen, was steht den Betroffenen zu, und informiere das Unternehmen über den aktuellen Stand. |
T8-lookup | Welchen Tarif hat acct_borealis_4c77, und wer ist der zuständige CSM? |
Bewertung
Deterministisch. 59 Prüfungen über die acht Aufgaben hinweg, jede entweder ein Tool-Aufruf mit exakt vorgegebenen Argumenten, etwa stripe_create_refund(charge="ch_3QRk9X…", amount=14900, reason="duplicate"), oder eine Information, die nur in einem Skill-Dokument vorkommt: die SLA-Stufe von 25 %, die Regel für Tag 10, das Team PRIV und die Frist von 30 Tagen.
Es kommt nirgends ein LLM als Prüfer zum Einsatz. Öffnet eine Ausführung die Skills nicht, scheitert sie automatisch an der zweiten Art von Prüfung. Genau darum geht es: So lässt sich messen, „ob der Agent die Richtlinie tatsächlich vorliegen hatte“, statt darüber zu spekulieren.
Für jede Aufgabe sind außerdem kritische Nutzdatenpfade festgelegt, also die Felder, von denen die Antwort abhängt. Sie werden nie dazu verwendet, den Filter zu steuern. So wird ein übermotivierter Filter im Protokoll sichtbar, selbst wenn die Ausführung trotzdem erfolgreich ist.
Die Varianten
| Variante | Vorab geladene Skills | Gefilterte Payload |
|---|---|---|
0 | nein | nein |
A | ja, Schwellenwert 0.55 | nein |
B | nein | ja, Schwellenwert 0.35, umfangreicher Zustand |
D | ja, Schwellenwert 0.55 | ja, Schwellenwert 0.35, umfangreicher Zustand |
8 Aufgaben × 4 Varianten × 6 Wiederholungen = 192 Durchläufe. Die Wiederholungen unterschieden sich nur durch seed.
Kalibrierung
Beide Schwellenwerte wurden offline getestet, bevor Agent-Tokens verbraucht wurden.
0.55 für das Routing ist der höchste Wert, bei dem der vollständige Recall für die Aufgaben erhalten bleibt, auf die der Wert kalibriert wurde. Bei 0.60 erzielt slack-style-guide bei der Rückerstattungsaufgabe einen Wert von 0.58, und die eingesparte Runde geht verloren. Zwei Hundertstel entscheiden darüber, ob die Zahl der Runden um 15 % sinkt oder gar nicht.
0.35 für die Filterung ist nur dank des oben beschriebenen umfangreichen Zustands vertretbar. Der Kalibrierungslauf kostet etwa $0.004, da dabei Router und Scorer ausgeführt werden, nicht aber der Agent.
Eine allgemeingültige Erkenntnis: Jede Formulierung einer Frage muss eigens kalibriert werden. Ein Schwellenwert lässt sich nicht von einer Formulierung auf eine andere übertragen, selbst wenn beide dieselbe Frage stellen. Für eine aufgabenspezifische und eine aufgabenunabhängige Formulierung wurden Verteilungen mit völlig unterschiedlichen Trägern gemessen. Bei jeder Umformulierung neu kalibrieren.
Summen der Testkampagne
| Messgröße | Gesamt |
|---|---|
| Durchläufe | 192 |
| Agentenrunden | 775 |
| Eingabe-Tokens des Agenten | 2,118,338, davon 1,685,860 (80%) aus dem Cache |
| Ausgabe-Tokens des Agenten | 130,003 |
| Jev-Eingabe-Tokens | 2,065,975 |
| Jev-Aufrufe | 96 Routing + 252 Filterung |
| Tatsächliche Kosten | Agent $0.2977 · Jev $0.0868 |
| Gesamt, einschließlich Kalibrierung und verworfener Varianten | $1.17 |
Gesamtübersicht nach Variante
| Variante | Fehlerfreie Durchläufe | Bestandenene Prüfungen | Runden | Eingabe-Tokens | Verworfene kritische Pfade |
|---|---|---|---|---|---|
0 | 92% | 99% | 4.44 | 12,960 | n/a |
A | 96% | 99% | 3.69 | 11,809 | n/a |
B | 94% | 99% | 4.31 | 9,967 | 0 |
D | 94% | 99% | 3.71 | 9,396 | 1 |
Keine der Techniken hat die Qualität verschlechtert. In allen vier Varianten werden 99% der Prüfungen bestanden. Bei 96 gefilterten Aufrufen in Variante D wurde genau ein als kritisch gekennzeichneter Pfad verworfen, und der betreffende Durchlauf wurde trotzdem bestanden. Die Unterschiede bei den „fehlerfreien“ Durchläufen pro Lauf zwischen 92% und 96% liegen bei n = 48 im Bereich des Zufalls. Belastbare Effekte zeigen sich bei Runden und Tokens.
Durchschnittliche Tokens pro Durchlauf, aufgeschlüsselt nach tatsächlicher Abrechnung:
| Variante | Neue Eingabe | Eingabe aus Cache | Ausgabe | Jev-Eingabe |
|---|---|---|---|---|
0 | 2,941 | 10,020 | 741 | 0 |
A | 2,700 | 9,109 | 615 | 1,517 |
B | 1,873 | 8,093 | 723 | 19,457 |
D | 1,496 | 7,900 | 629 | 22,067 |
Variante D senkt die Zahl der neuen Eingabe-Tokens, der teuren Tokenart, um 49%.
Einsparung bei Eingabe-Tokens pro Technik, von geringster bis höchster
| Technik | Minimum | Maximum | Median |
|---|---|---|---|
A Skills vorab laden | −3% bei der SLA-Aufgabe | +23% bei der DSGVO-Aufgabe | 10% |
B Payload filtern | +2% bei der DSGVO-Aufgabe | +51% bei veralteten Dokumenten | 17% |
D beides | +9% beim Postmortem | +63% bei veralteten Dokumenten | 26% |
Der einzige negative Wert in der gesamten Matrix tritt bei A für die SLA-Aufgabe auf: Der Router lädt einen Skill zu viel, ohne eine Runde einzusparen. Der zusätzliche Skill wird in den System-Prompt aufgenommen und anschließend in jeder Runde erneut gesendet. Außerdem addieren sich die beiden Techniken nicht immer: Bei der SLA-Aufgabe und beim Postmortem spart D weniger Tokens als B allein, genau aus diesem Grund.
So hat der Router tatsächlich abgeschnitten
Mittlere Wahrscheinlichkeit pro Skill und Aufgabe. Als geladen gilt ein Skill ab 0.55.
| Aufgabe | Geladene Skills | Höchste Werte |
|---|---|---|
T1-refund | 2.0 | refund-policy 0.82 · slack-style-guide 0.60 · incident-comms 0.32 |
T2-sla | 2.0 | enterprise-contract-terms 0.95 · refund-policy 0.84 · churn-save-offers 0.13 |
T3-dunning | 1.0 | dunning-playbook 0.95 · churn-save-offers 0.32 · oncall-handover 0.13 |
T4-gdpr | 1.0 | gdpr-data-requests 0.87 · refund-policy 0.27 · escalation-matrix 0.22 |
T5-incident | 3.0 | escalation-matrix 0.93 · incident-comms 0.85 · slack-style-guide 0.69 |
T6-stale-docs | 1.0 | docs-review-cadence 0.93 · slack-style-guide 0.15 · oncall-handover 0.05 |
T7-postmortem | 3.0 | enterprise-contract-terms 0.92 · refund-policy 0.89 · incident-comms 0.58 · slack-style-guide 0.47 |
T8-lookup | 0.0 | slack-style-guide 0.07 · enterprise-contract-terms 0.06 · dunning-playbook 0.04 |
Recall: 132 der 144 benötigten Skills wurden geladen, also 92 %. Ein systematischer Fehltreffer und ein systematischer falsch positiver Treffer, die beide klar benannt werden sollten.
Beim Postmortem wurde slack-style-guide in allen 12 Durchläufen übersehen: Der Wert lag mit 0.47 unter dem Schwellenwert. In der Aufgabe heißt es „dem Unternehmen sagen, wo es steht“, und der Router erkennt darin keine Formatierungsfrage. Der Agent hat den Skill selbst abgerufen, als er ihn brauchte.
Der falsch positive Treffer ist refund-policy bei der SLA-Aufgabe mit 0.84 und beim Postmortem mit 0.89. Eine SLA-Gutschrift sieht wie eine Rückerstattung aus. Genau diese Verwechslung soll refund-policy verhindern, denn das Dokument stellt klar, dass ein Dienstausfall keine Rückerstattung ist. Der Router liegt bei der Form falsch, beim Inhalt aber richtig, und dem Agenten ist dadurch kein Schaden entstanden.
Bei der Lookup-Aufgabe wird richtigerweise nichts geladen. Kein Skill ist dafür relevant, und der höchste Wert liegt bei 0.07.
So hat der Filter tatsächlich funktioniert
Arm D, nach Tool, über 96 gefilterte Aufrufe:
| Tool | Aufrufe | Zeichen vorher → nachher | Änderung | Beibehaltene Schlüssel |
|---|---|---|---|---|
kb_list_articles | 8 | 225,024 → 24,834 | −89% | 605 / 1,808 |
stripe_list_charges | 6 | 41,958 → 12,819 | −69% | 405 / 1,584 |
stripe_get_subscription | 6 | 19,086 → 10,637 | −44% | 359 / 744 |
crm_get_account | 30 | 29,400 → 16,723 | −43% | 384 / 1,002 |
zendesk_get_ticket | 12 | 25,620 → 15,787 | −38% | 328 / 822 |
statuspage_get_incident | 9 | 15,399 → 10,734 | −30% | 311 / 540 |
pagerduty_get_incident | 12 | 21,852 → 16,497 | −25% | 428 / 684 |
stripe_create_refund | 6 | 3,012 → 2,610 | −13% | 60 / 108 |
zendesk_reply | 12 | 8,685 → 9,489 | +9% | 24 / 84 |
linear_create_issue | 18 | 5,287 → 6,734 | +27% | 83 / 138 |
billing_apply_credit | 8 | 1,343 → 2,406 | +79% | 42 / 56 |
Bei den Lese-Tools liegt das größte Einsparpotenzial, und die Unterschiede sind enorm: von −89% bei einer Dokumentenliste bis zu −25% bei einem Vorfall, bei dem fast alles unverzichtbar ist.
Bei den Bestätigungen für Schreibvorgänge geht es in die falsche Richtung. billing_apply_credit gibt 147 Zeichen zurück, und der angehängte Marker _trimmed kostet mehr, als durch die entfernten Felder eingespart wird. Einen kleinen Payload zu filtern, bringt unterm Strich also Nachteile. Eine Implementierung für den Produktionseinsatz sollte alles unter ein paar hundert Zeichen ganz überspringen. Hier blieb es dabei, damit der Effekt in den Daten sichtbar ist.
Jede Aufgabe, jeder Arm
Die Preise zeigen die vollständigen Kosten eines Durchlaufs für Agent plus Jev und basieren auf der gemessenen Aufteilung in frische und zwischengespeicherte Daten. Die Spalten für Sonnet 5 und Opus 5 rechnen den gemessenen Traffic zu den jeweiligen Modellpreisen durch. Jevs Kosten sind in allen drei Spalten identisch.
T1-refund, mittel · gemischter Payload
| Arm | Perfekt | Prüfungen | Durchläufe | Eingabetokens | Payload gekürzt | $ Luna | $ Sonnet 5 | $ Opus 5 | vs. 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 4.5 | 15,369 | n/a | 0.00180 | 0.0167 | 0.0419 | n/a |
A | 100% | 100% | 4.0 | 14,247 (−7%) | n/a | 0.00165 | 0.0150 | 0.0373 | −11% |
B | 100% | 100% | 4.3 | 10,719 (−30%) | 65% | 0.00285 | 0.0141 | 0.0331 | −21% |
D | 100% | 100% | 4.0 | 9,899 (−36%) | 66% | 0.00252 | 0.0108 | 0.0249 | −41% |
T2-sla, lang · gemischter Payload
| Arm | Perfekt | Prüfungen | Durchläufe | Eingabetokens | Payload gekürzt | $ Luna | $ Sonnet 5 | $ Opus 5 | vs. 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 83% | 96% | 6.8 | 18,811 | n/a | 0.00192 | 0.0177 | 0.0442 | n/a |
A | 100% | 100% | 6.2 | 19,359 (+3%) | n/a | 0.00193 | 0.0174 | 0.0433 | −2% |
B | 83% | 96% | 6.5 | 15,528 (−17%) | 30% | 0.00286 | 0.0173 | 0.0417 | −6% |
D | 83% | 96% | 6.0 | 16,533 (−12%) | 72% | 0.00312 | 0.0160 | 0.0378 | −15% |
T3-dunning, kurz · gemischter Payload
| Arm | Perfekt | Prüfungen | Durchläufe | Eingabetokens | Payload gekürzt | $ Luna | $ Sonnet 5 | $ Opus 5 | vs. 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 4.0 | 8,084 | n/a | 0.00080 | 0.0075 | 0.0187 | n/a |
A | 100% | 100% | 3.0 | 6,704 (−17%) | n/a | 0.00079 | 0.0069 | 0.0171 | −9% |
B | 100% | 100% | 4.0 | 7,384 (−9%) | 44% | 0.00129 | 0.0069 | 0.0163 | −13% |
D | 100% | 100% | 3.0 | 6,002 (−26%) | 44% | 0.00123 | 0.0058 | 0.0135 | −28% |
T4-gdpr, mittel · gemischter Payload
| Variante | Perfekt | Prüfungen | Durchläufe | Eingabetoken | Payload gekürzt | $ Luna | $ Sonnet 5 | $ Opus 5 | vs. 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 50% | 94% | 4.2 | 8,344 | n/a | 0.00150 | 0.0134 | 0.0336 | n/a |
A | 100% | 100% | 3.0 | 6,467 (−23%) | n/a | 0.00132 | 0.0114 | 0.0285 | −15% |
B | 83% | 98% | 4.2 | 8,167 (−2%) | 14% | 0.00186 | 0.0129 | 0.0315 | −6% |
D | 83% | 98% | 3.0 | 6,159 (−26%) | 16% | 0.00178 | 0.0116 | 0.0282 | −16% |
T5-incident, kurz · dichter Payload
| Variante | Perfekt | Prüfungen | Durchläufe | Eingabetoken | Payload gekürzt | $ Luna | $ Sonnet 5 | $ Opus 5 | vs. 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 3.8 | 8,647 | n/a | 0.00151 | 0.0136 | 0.0340 | n/a |
A | 67% | 96% | 3.0 | 7,004 (−19%) | n/a | 0.00121 | 0.0104 | 0.0259 | −24% |
B | 83% | 98% | 3.7 | 8,153 (−6%) | 6% | 0.00168 | 0.0127 | 0.0313 | −8% |
D | 83% | 98% | 3.0 | 6,935 (−20%) | 5% | 0.00143 | 0.0099 | 0.0241 | −29% |
T6-stale-docs, kurz · sehr dünner Payload
| Variante | Perfekt | Prüfungen | Durchläufe | Eingabetoken | Payload gekürzt | $ Luna | $ Sonnet 5 | $ Opus 5 | vs. 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 4.0 | 19,821 | n/a | 0.00265 | 0.0256 | 0.0639 | n/a |
A | 100% | 100% | 3.0 | 18,468 (−7%) | n/a | 0.00260 | 0.0246 | 0.0614 | −4% |
B | 100% | 100% | 4.0 | 9,639 (−51%) | 78% | 0.00262 | 0.0139 | 0.0329 | −49% |
D | 100% | 100% | 3.0 | 7,387 (−63%) | 84% | 0.00235 | 0.0109 | 0.0252 | −61% |
T7-postmortem, sehr lang · gemischter Payload
| Variante | Perfekt | Prüfungen | Durchläufe | Eingabetoken | Payload gekürzt | $ Luna | $ Sonnet 5 | $ Opus 5 | vs. 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 6.0 | 21,294 | n/a | 0.00406 | 0.0363 | 0.0906 | n/a |
A | 100% | 100% | 5.3 | 19,224 (−10%) | n/a | 0.00339 | 0.0297 | 0.0743 | −18% |
B | 100% | 100% | 5.7 | 17,064 (−20%) | 34% | 0.00488 | 0.0343 | 0.0841 | −7% |
D | 100% | 100% | 5.7 | 19,430 (−9%) | 33% | 0.00472 | 0.0324 | 0.0792 | −13% |
T8-lookup, ein Aufruf · dünner Payload
| Variante | Perfekt | Prüfungen | Durchläufe | Eingabetoken | Payload gekürzt | $ Luna | $ Sonnet 5 | $ Opus 5 | vs. 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 2.2 | 3,314 | n/a | 0.00036 | 0.0033 | 0.0083 | n/a |
A | 100% | 100% | 2.0 | 3,004 (−9%) | n/a | 0.00038 | 0.0030 | 0.0073 | −12% |
B | 100% | 100% | 2.2 | 3,080 (−7%) | 62% | 0.00047 | 0.0026 | 0.0062 | −24% |
D | 100% | 100% | 2.0 | 2,819 (−15%) | 62% | 0.00056 | 0.0029 | 0.0068 | −17% |
So wurden die Preise berechnet
Einmal messen, dann neu berechnen. Die Tokenzahlen bilden die Grundlage; die Kosten für jedes Modell ergeben sich aus denselben Zahlen, multipliziert mit den jeweiligen Modellsätzen.
Die Abrechnungsformel wurde anhand der Daten rückerschlossen, nicht einfach angenommen. Über alle 192 Durchläufe hinweg entspricht der beobachtete Agentenpreis
fresh_input × $0.25/M + cached_input × $0.02/M + output × $1.20/Meinem medianen relativen Fehler von 0.04%. Daraus ergeben sich zwei Dinge. Prompt-Caching war die ganze Zeit automatisch aktiviert, ohne cache_control-Marker, und 80% der Eingabetoken waren Cache-Lesezugriffe. Außerdem wird jedes nicht gecachte Eingabetoken zum Schreibpreis abgerechnet, also zum 1.25-Fachen des nominalen Eingabepreises. In einer Schleife mit mehreren Durchläufen zahlt man daher praktisch nie den nominalen Satz von $0.20/M.
Ein früheres theoretisches Caching-Modell, bei dem die Lesezugriffe im Durchlauf t dem Präfix aus Durchlauf t−1 entsprechen, unterschätzte die tatsächlichen Cache-Lesezugriffe um 19%. Es wurde zugunsten der gemessenen Aufteilung pro Durchlauf verworfen.
| Modell | Eingabe | Ausgabe | Cache-Lesezugriff | Cache-Schreibzugriff |
|---|---|---|---|---|
openai/gpt-5.6-luna | $0.20/M | $1.20/M | $0.02/M | $0.25/M |
anthropic/claude-sonnet-5 | $2.00/M | $10.00/M | $0.20/M | $2.50/M |
anthropic/claude-opus-5 | $5.00/M | $25.00/M | $0.50/M | $6.25/M |
typesafe/jev-1.13 | $0.042/M | kostenlos | n/a | n/a |
| Variante | Luna | Sonnet 5 | Opus 5 | Anteil von Jev, Opus 5 |
|---|---|---|---|---|
0 | $0.00182 | $0.01676 | $0.04191 | n/a |
A | $0.00166 (−9%) | $0.01479 (−12%) | $0.03688 (−12%) | 0% |
B | $0.00232 (+27%) | $0.01435 (−14%) | $0.03466 (−17%) | 2% |
D | $0.00221 (+21%) | $0.01253 (−25%) | $0.02995 (−29%) | 3% |
Zum Vergleich: dieselben Durchläufe ganz ohne Caching:
| Variante | Luna | Sonnet 5 | Opus 5 |
|---|---|---|---|
0 | $0.00348 | $0.03333 | $0.08332 |
A | $0.00316 | $0.02984 | $0.07450 |
B | $0.00368 | $0.02798 | $0.06874 |
D | $0.00356 | $0.02601 | $0.06362 |
Eine Annahme ist bewusst konservativ statt neutral. OpenAI cached automatisch und berechnet jedes nicht gecachte Eingabetoken zum Schreibpreis, genau das wurde gemessen. Caching bei Anthropic muss ausdrücklich aktiviert werden: Nur Inhalte innerhalb eines cache_control-Breakpoints werden zum Schreibpreis abgerechnet, der Rest zum regulären Eingabepreis. Werden also alle nicht gecachten Token zum Schreibpreis berechnet, fallen die Anthropic-Werte etwas zu hoch aus. Bei einer Neuberechnung mit dem regulären Eingabepreis für nicht gecachte Token sinkt der Opus-5-Mittelwert von $0.04191 → $0.02995 (−29%) auf $0.03823 → $0.02808 (−27%); kein Wert pro Aufgabe verschiebt sich um mehr als 3 Punkte.
Was dies nicht zeigt
- Ein Agentenmodell. Alles wird mit
openai/gpt-5.6-lunabei standardmäßiger Denktiefe gemessen. Die Tokenzahlen sind das Ergebnis, die Preisspalten werden darauf aufbauend berechnet. Ein anderes Modell würde andere Tokenzahlen liefern, nicht nur andere Preise. - n = 6 pro Zelle. Das reicht für die Anzahl der Durchläufe und Tokenzahlen, die nahezu deterministisch sind. Es reicht nicht aus, um eine Qualität von 92 % von 96 % zu unterscheiden.
- Test-Fixtures statt Live-APIs. Die Payload-Strukturen entsprechen den realen. Echte Endpunkte haben Paginierung, Teilausfälle und Ratenbegrenzungen, die dieser Testaufbau nicht abbildet.
- Dieselben Personen haben die Aufgaben und die Skills verfasst. Die Bewertung ist deterministisch, aber die Testumgebung stellt keine adversarialen Bedingungen dar.
- Jevs eigene Kalibrierung wurde nicht geprüft. Gemessen wurde, wie sich Jevs Bewertungen auf einen Agenten auswirken, nicht, ob sie statistisch gesehen gut kalibriert sind.
- Ein Agentenaufbau. Eine
while-Schleife mit Funktionsaufrufen. Unteragenten, parallele Tool-Aufrufe und lang laufende Sitzungen verändern die Berechnung.

