AIDive

Spotify spart 90 % Claude Code Tokens. Ich habe nachgemessen

Von AIDive · Veröffentlicht am

Coding-AgentsKI-Modelle

Neunzig Prozent, und der Satz, der es verkauft hat

Das Spotify-Setup für Claude Code ist ein Blogpost von Dimitri Mazmanov, Product Manager bei Spotify, mit dem Code auf GitHub: Er sagt, die Konfiguration seines Teams habe seinen Token-Verbrauch in Claude Code um 90 % gesenkt. Sein erster Satz trägt das ganze Argument: Das meiste, was ein KI-Coding-Agent tut, ist kein Denken, sondern I/O. Fünf Dateien lesen, um eine Frage zu einer einzigen Methode zu beantworten, oder die einundzwanzigste Testdatei schreiben, die die zwanzig daneben kopiert, verbrennt Tausende Tokens bei fast null Reasoning.

Ein Tweet brachte den Post mit einem einzigen Satz auf anderthalb Millionen Views: Geschriebene Regeln sind ein Vorschlag, ein Block nicht. Hacker News setzte ihn auf die Titelseite, 271 Punkte und 173 Kommentare, und die Hälfte der Kommentare stellte dieselbe Frage: 90 % wovon? Spotifys eigene Einschränkung lautet "bulk read". Dieser Artikel baut das Setup in reinem Claude Code nach und misst es dann, damit du genau weißt, was diese Einschränkung wert ist.

Was Portal wirklich ist (und warum du es nicht ausführen kannst)

Portal ist kein Router. Es ist Spotifys internes Entwicklerportal, gebaut auf Backstage, der Entwicklerplattform, die Spotify als Open Source veröffentlicht hat. Das relevante Feature darin heißt Modes: Nach Spotifys Definition ist ein Mode ein deklarativer Agent, der auf einer ephemeren Runtime läuft, ungefähr AWS Lambda für Agents. Du schreibst die Anweisungen, wählst ein Modell, setzt eine Temperature, hängst Tools an. Mazmanov hat zwei davon gebaut, einen Bulk Reader und einen Code Writer, beide auf Gemini Flash bei Temperature 0,2, also beide absichtlich billig und langweilig.

Das Routing steckt in einem Claude Code Plugin namens Shunt. Es ist öffentlich auf GitHub und lässt sich mit zwei Befehlen installieren. Schritt zwei authentifiziert jedoch die Portal-Kommandozeile gegen deine Portal-Instanz, und die hast du nicht. Das Plugin ist öffentlich; das, wohin es delegiert, ist es nicht.

Der sinnvolle Schritt ist also, das Plugin zu vergessen und das Muster zu behalten. Es hat drei Schichten, in seinen eigenen Worten: Hooks, Scripts, Skills. Jede davon hat ein Äquivalent in reinem Claude Code, und genau das baut und misst der Rest dieses Artikels.

Schicht eins: der Hook, der blockiert statt zu fragen

Version 1 des Setups war ein Block von Routing-Regeln in der Instruktionsdatei des Projekts. In Mazmanovs Worten hat das "so halbwegs funktioniert": Die Regeln waren Empfehlungen, nicht erzwungen, Claude konnte sie ignorieren, und jedes Projekt brauchte seine eigene Kopie. Version 2 verlagert die Entscheidung aus dem Prompt in die Tool-Schicht, mit zwei Hooks, die beide vor einem Tool-Aufruf feuern. Einer überwacht jeden Datei-Read, der andere die Shell.

Der Read-Hook sind 33 Zeilen Bash. Er liest einen Schwellenwert aus der Umgebung, standardmäßig 350 Zeilen, und lässt dann drei Dinge durch:

  • Einen Read mit Offset oder Limit, weil Claude dann schon weiß, was es braucht.
  • Eine Datei, die nicht existiert.
  • Eine Datei auf oder unter dem Schwellenwert, weil etwas Kleines zu delegieren mehr kostet, als es zu lesen.

Alles andere wird blockiert, mit einer Nachricht, die Claude statt der Datei liest: Diese Datei hat so viele Zeilen, nimm den Bulk-Reader-Skill, und wenn du für ein Edit den exakten Inhalt brauchst, lies nur diesen Abschnitt erneut. Der Shell-Hook fängt cat, head, tail, less und more auf einer großen Datei ab. Ein Befehl mit Pipe geht durch, weil eine Pipe nach grep ein gezielter Read ist.

Mazmanovs Punkt zur Schichtung ist der wichtige: Selbst wenn Claude die Skill-Beschreibung nie liest, blockiert der Hook trotzdem den teuren Read. Der Skill macht die Umleitung sanfter; der Block macht sie real. Ein Detail zählt später: Das Script antwortet mit einer Top-Level-Entscheidung namens "block". Behalte dieses Wort im Kopf.

Schichten zwei und drei: die Worker und ihre Zahlen

Die Worker sind zwei Prompts. Der Reader: "Du bist ein präziser Code-Analyst, gib nur strukturierte Bullets aus, keine Begrüßung, keine Prosa, beginne jeden Bullet mit dem exakten Namen, Typ oder der Zeilennummer." Der Writer: "Halte dich exakt an die bestehenden Patterns, die Benennung und den Stil; gib nur den Code aus, keine Code-Fences, keine Erklärungen." Ohne diese letzte Zeile packt das Modell alles in Markdown, das Claude dann parsen muss.

Zwei Scripts umhüllen sie. Bulk-read nimmt eine Frage und Dateipfade und schickt sie los. Code-write nimmt eine Spezifikation und eine Referenzdatei und schreibt das Ergebnis direkt auf die Festplatte, sodass Claude den generierten Code nie sieht. Jede Delegation ist ein One-Shot: Eine Nachfrage schickt die Dateien erneut. Das ist dort kostenlos, wo es zählt, weil der Korpus zum Worker geht und nie in Claudes Kontext landet.

Schicht drei ist eine Skill-Datei, die Claude sagt, wann es delegieren soll: Dateien über 350 Zeilen, Fragen über drei oder mehr Dateien, große Diffs. Ihre letzte Zeile lautet "Prüfe die Zeilennummern, bevor du editierst".

Spotifys Tabelle deckt ein Java-Monorepo und drei Read-Szenarien ab. Der Einzeldatei-Fall sinkt von rund 34.000 Tokens auf unter 6.000, und die mittlere Ersparnis über die drei Zeilen beträgt 90 %.

Spotifys Benchmark Wert
Repositories 1 Java monorepo
Szenarien 3, alle Bulk Reads
Einzeldatei-Fall, vorher ~34,000 tokens
Einzeldatei-Fall, nachher < 6,000 tokens
Mittlere Ersparnis 90%
Token-Schätzung 4 Zeichen pro Token
Erzwingung beim Writer keine (nur der Reader hat einen Hook)

Zwei Vorbehalte druckt Spotify selbst ab: Die Tokens sind mit vier Zeichen pro Token geschätzt, und der Writer hat überhaupt keine Erzwingung. Die 90 % sind also der Mittelwert von drei Bulk-Read-Zeilen in geschätzten Input-Tokens, ohne Qualitätsbewertung und ohne eine einzige Dollar-Zahl. Das ist die Zahl, die es zu testen gilt.

Nachbau, Teil eins: ein Subagent mit Modellfeld

Claude Code bringt einen eingebauten Explore-Subagent mit, und seit einem kürzlichen Release erbt er dein Hauptmodell, gedeckelt bei Opus, sodass der "billige Reader" nicht mehr billig ist. Die Dokumentation liefert die Lösung in einem Satz: Ein Projekt-Subagent namens Explore überschreibt den eingebauten und behält sein eigenes Modellfeld. Eine Markdown-Datei, ein Front Matter, und in der Modellzeile steht Haiku. Das ist der Bulk Reader. Der Writer ist eine zweite Datei: Modell Sonnet, Tools nur Read und Write, und der Body sind Spotifys eigene Anweisungen, hineinkopiert.

Es funktioniert, weil jeder Subagent mit einem frischen, isolierten Context Window startet. Was er liest, landet dort, nicht in der Hauptkonversation. Das ist Spotifys One-Shot-Delegation minus den Netzwerk-Roundtrip.

Dann kommt der Teil, den niemand einplant. Auf Reddit wurde diese Woche Fable angewiesen, Opus-Agents zu starten, und startete stattdessen fünf Fable-Agents: 73 % eines Wochenlimits in dreißig Minuten weg. Die Top-Antwort war ein Hook, der läuft, wenn das Modell einen Subagent losschickt, es zwingt, das Modell explizit zu wählen, und ihm sagt, das billigste zu nehmen, das die Aufgabe schafft. Das ist Hook Nummer drei: Er überwacht das Agent-Tool, und ein Aufruf ohne Modell wird mit einem Satz abgelehnt, "wähle das Modell explizit".

Spotifys Skill wird zu drei Zeilen in der Instruktionsdatei des Projekts: Dateien über 350 Zeilen gehen an den Explorer, Boilerplate geht an den Writer, jeder Agent-Aufruf setzt ein Modell. Die grobe Option gibt es auch: zwei Umgebungsvariablen, die jedem Subagent ein einziges Modell aufzwingen. Die ehrliche Grenze ist, dass der Reader ein billigeres Modell ist, also ist das, was er zurückgibt, alles, was das Hauptmodell weiß. Der Abschnitt zur Messung geht darauf ein.

Nachbau, Teil zwei: das Deny im heutigen Hook-Format

Erinnere dich an das Wort "block". Spotifys Script gibt eine Top-Level-Entscheidung zurück, aber die aktuelle Claude Code Dokumentation sagt etwas anderes: Ein PreToolUse-Hook gibt seine Entscheidung in einem hook-spezifischen Output-Objekt zurück, und das Feld heißt permissionDecision. Es hat vier Ausgänge, allow, deny, ask und defer, und der hier gewünschte ist deny. Was der Hook als Begründung schreibt, wird Claude angezeigt, und wenn mehrere Hooks antworten, gewinnt deny.

Der nachgebaute Read-Hook behält denselben Schwellenwert von 350 und dieselben drei Ausnahmen und gibt statt "block" ein deny mit einer Begründung zurück, die den Explore-Subagent und das zu verwendende Modell nennt. Eine Falle, die die Docs klar benennen: Hooks aus deinen Settings laufen auch innerhalb von Subagents. Ohne Ausnahme wird dem Haiku-Reader sein eigener Read verweigert, und er kann seine Arbeit nie erledigen, also prüft das Script, wer aufruft, und lässt die beiden Worker durch.

Die Verdrahtung ist eine Settings-Datei mit drei Matchern, Read, Bash und Agent, die jeweils auf ihr Script zeigen, und der Schwellenwert als Umgebungsvariable. In der Praxis kommt ein Read auf eine Datei mit 1.090 Zeilen als Fehler mit dem geschriebenen Satz zurück: Delegiere diesen Read an den Explorer, Modell Haiku. Dann folgt die Delegation: Das Hauptmodell zählt zuerst die Zeilen, ruft den Explorer mit dem Modell Haiku auf, und die Bullets kommen zurück, jeder mit einer Zeilennummer. Drei Turns, 44 Sekunden.

Spotifys Satz hält: Die Schichtung bedeutet, dass das System kontrolliert degradiert. Die Instruktion übernimmt das Routing, der Hook ist das Netz. Das Netz hat allerdings ein Loch. Ein Modell, das die ganze Datei will, kann sie mit Offset und Limit stückeln, was durchgeht, oder sie über die Shell mit einem sed-Bereich ausgeben, was dieser Hook nicht abfängt. Die Messung zählt beides mit.

Die Messung

Das Test-Repository ist Fastify, das Node-Webframework: 294 Dateien, 63 davon über dem Schwellenwert. Zwei identische Klone, der einzige Unterschied ist der .claude-Ordner und die Regeldatei. Hauptmodell Opus, der CLI-Standard; Reader Haiku; Writer Sonnet. Sessions mit einem einzigen Prompt, keine Nachfragen, jedes Szenario zweimal pro Konfiguration, sechzehn Läufe insgesamt. Die vier Szenarien sind dieselben wie bei Spotify: die Exports einer großen Datei, drei Dateien und wie sie sich gegenseitig aufrufen, eine Quelldatei gegen ihren Test, und eine neue Testdatei, die aus einer bestehenden auf die Festplatte geschrieben wird.

Szenario Hauptkontext, ohne Hauptkontext, mit Änderung Gesamtkosten, ohne Gesamtkosten, mit Änderung Dauer, ohne Dauer, mit Änderung
Eine große Datei 88,693 51,552 -41.9% $0.139 $0.087 -37.8% 22 s 44 s +100.8%
Drei Dateien 357,166 73,440 -79.4% $0.581 $0.218 -62.4% 52 s 129 s +149.9%
Quelle vs. Test 303,808 114,136 -62.4% $0.451 $0.374 -17.1% 93 s 125 s +33.6%
Neue Testdatei 143,432 121,818 -15.1% $0.295 $0.302 +2.6% 66 s 87 s +32.2%
Alle vier 223,274 90,236 -59.6% $0.366 $0.245 -33.1% 58 s 96 s +65.3%

Der Hauptkontext, also die Tokens, die das teure Modell tatsächlich gesehen hat, ist die erste Spalte, die zählt. Bei der Drei-Dateien-Frage sinkt er um 79 %, über alle vier Szenarien um 59,6 %. Die Rechnung sinkt weniger, insgesamt um ein Drittel, weil die eigenen Tokens des Readers nicht kostenlos sind, und bei der kleinen Testschreib-Aufgabe stieg die Rechnung um 2,6 %. Die Zeit geht in die andere Richtung: 58 Sekunden im Schnitt ohne das Setup, 96 mit. Delegation ist jedes Mal langsamer.

Bei der Qualität unterscheiden sich die beiden Konfigurationen am stärksten. Ohne das Setup hat das Hauptmodell Dateien ohne Zeilennummern über die Shell ausgegeben und von Hand gezählt, mit durchgehend falschen Zeilennummern: Eine Funktion, die bei Zeile 149 gemeldet wurde, stand tatsächlich in Zeile 156. Mit dem Setup nahm einer von vier Läufen die Zusammenfassung des Readers für bare Münze und trug drei falsche Behauptungen weiter, darunter eine Funktion, von der der Reader sagte, die Routendatei rufe sie nie auf, obwohl sie es tut, in Zeile 553. Alle vier generierten Testdateien bestehen, und die Deny-Hooks haben in sechzehn Läufen null Mal gefeuert: Mit vorhandener Regeldatei prüfte das Hauptmodell jedes Mal die Zeilenzahl und delegierte von selbst.

Noch etwas aus den Traces: Ohne die Regel hat das Hauptmodell das Read-Tool nie benutzt. Es hat alles über die Shell gelesen, und ein Shell-Bereichs-Read kostet dieselben Tokens und geht am Hook vorbei. Spotifys Tabelle sagt also 90; diese hier sagt 60 beim Kontext und ein Drittel bei der Rechnung.

Behalte den Block. Erwarte nicht, dass die Rechnung um neunzig fällt.

Drei Dinge lohnt es sich zu behalten: einen Projekt-Explore-Subagent auf Haiku, eine Drei-Zeilen-Regel in der Instruktionsdatei und den Read-Hook als Sicherheitsnetz. Das gemessene Ergebnis sind 60 % weniger Hauptkontext, ein Drittel weniger auf der Rechnung und zwei Drittel mehr Laufzeit.

Bevor du dem Hook vertraust, behebe zwei Dinge. Hooks laufen innerhalb von Subagents, also nimm deine Worker aus. Und das Shell-Loch: Der Bash-Hook fängt cat, head und tail ab, aber ein Bereichs-Read geht durch, und genau den hat das Hauptmodell benutzt, als es keine Regel hatte.

Spotifys eigene Grenzen bleiben bestehen. Editieren lässt sich nicht delegieren und Reasoning auch nicht; der Worker hat einen Thread-Safety-Bug übersehen, den Claude in Sekunden gefunden hat, und jede Delegation ist ein Roundtrip. Die Skeptiker auf Hacker News hatten in einem Punkt ebenfalls recht: Input-Tokens sind nicht die Rechnung. Output-Tokens kosten mehr, und dieses Setup tut nichts für sie.

Wer spart, hängt davon ab, wie du bezahlst. Über die API ein Drittel weniger. Im Pro- oder Max-Plan verschiebt dasselbe Setup deine Fünf-Stunden- und Wochenfenster, nicht Dollar. Achte auch auf den Schwellenwert: Darunter kostet Delegation mehr, als sie spart, und der 45-Zeilen-Testfall ist der Beweis mit plus 2,6 %. Und schließlich: In zwei von acht Läufen enthielt die Zusammenfassung des Readers Fehler, und der Verifikations-Turn des Hauptmodells hat sie abgefangen. Lass diesen Turn weg, und diese Fehler landen in deinen Edits.

Quellen

Häufige Fragen

Hat Spotify den Token-Verbrauch von Claude Code wirklich um 90 % gesenkt?
Spotifys 90 % sind der Mittelwert von drei Bulk-Read-Szenarien in einem Java-Monorepo, gezählt in geschätzten Input-Tokens mit vier Zeichen pro Token, ohne Qualitätsbewertung und ohne Dollar-Zahl. In reinem Claude Code auf Fastify nachgebaut, hat dieselbe Idee den Kontext des Hauptmodells um 59,6 % und die Gesamtkosten um 33 % gesenkt.
Was ist Spotifys Portal und kann ich es mit Claude Code nutzen?
Portal ist Spotifys internes Entwicklerportal auf Basis von Backstage; sein Feature Modes führt deklarative Agents auf einer ephemeren Runtime aus. Das Shunt-Plugin, das Claude Code an diese Agents weiterleitet, ist öffentlich auf GitHub, authentifiziert sich aber gegen eine Portal-Instanz, die du nicht hast. Du kannst also nur das Muster kopieren, nicht das Plugin ausführen.
Wie bringe ich Claude Code dazu, große Datei-Reads an ein billigeres Modell zu delegieren?
Lege einen Projekt-Subagent namens Explore mit dem Modellfeld Haiku an; er überschreibt den eingebauten Explore-Agent, der inzwischen dein Hauptmodell erbt. Füge der Instruktionsdatei des Projekts eine Drei-Zeilen-Regel hinzu (Dateien über 350 Zeilen gehen an den Explorer, Boilerplate geht an den Writer, jeder Agent-Aufruf setzt ein Modell) sowie einen PreToolUse-Hook auf Read, der große Reads mit einer Begründung verweigert, die diesen Subagent nennt.
Wie blockiert ein PreToolUse-Hook heute einen Tool-Aufruf in Claude Code?
Der Hook gibt seine Entscheidung im Objekt hookSpecificOutput zurück, in einem Feld namens permissionDecision, mit vier möglichen Werten: allow, deny, ask und defer. Der Begründungs-String wird Claude angezeigt, und wenn mehrere Hooks antworten, gewinnt deny. Spotifys Script verwendet eine ältere Top-Level-Entscheidung namens block.
Wird Claude Code billiger, wenn Reads an einen Haiku-Subagent delegiert werden?
Über die API hat es die Rechnung über vier Szenarien um ein Drittel gesenkt, aber die eigenen Tokens des Readers sind nicht kostenlos: Bei einer 45-Zeilen-Testschreib-Aufgabe stiegen die Gesamtkosten um 2,6 %. Im Pro- oder Max-Plan zeigt sich die Ersparnis als Kontingent in den Fünf-Stunden- und Wochenfenstern, nicht als Dollar, und Output-Tokens bleiben unberührt.
Warum feuern Claude Code Hooks innerhalb von Subagents?
Hooks, die in deinen Settings definiert sind, laufen für jeden Agent, auch für die Subagents, die du losschickst. Ein Hook, der Reads blockiert, verweigert dem Haiku-Reader deshalb seine eigenen Reads, es sei denn, das Script prüft, wer aufruft, und lässt die Worker-Agents durch.

Ähnliche Videos