TL;DR
- "90%" Spotify to średnia ze scenariuszy masowego czytania, mierzona w szacowanych tokenach wejściowych na monorepo w Javie. Post nie podaje ani kwoty w dolarach, ani wyniku jakości.
- Odtworzony w czystym Claude Code (jeden hook PreToolUse, dwa tanie subagenty, reguła routingu w trzech linijkach) i zmierzony na Fastify w czterech scenariuszach i 16 uruchomieniach, ten wzorzec obniżył kontekst głównego modelu o 59.6%, a koszt całkowity o 33.1%.
- Hooki blokujące nie odpaliły ani razu w zmierzonych uruchomieniach. Oszczędność dała reguła routingu w CLAUDE.md; hooki to siatka bezpieczeństwa na dzień, w którym model ją zignoruje.
- Delegowanie było za każdym razem wolniejsze, średnio +65.3% czasu zegarowego. W małym scenariuszu pisania testu kosztowało o 2.6% więcej.
- Dwie pułapki: hooki odpalają też wewnątrz subagentów, więc wyłącz swoich workerów, a odczyty zakresów przez
sed -nprzechodzą bez przeszkód przez hook, który pilnuje tylkocat,headitail. - Podsumowanie readera na Haiku zawierało błędy merytoryczne w dwóch z ośmiu delegowanych uruchomień. Zostaw turę weryfikacji po stronie głównego modelu.
Co pokazują pomiary
Wtyczka Spotify, Shunt, kieruje masową robotę z dala od głównego modelu przez dwa "mode'y": bulk-reader i code-writer, w przykładach oba na Gemini 2.5 Flash, przy czym pole model przyjmuje dowolny model skonfigurowany w instancji Portal s1. Routing ma trzy warstwy. Hook check-file-size odpala przy każdym Read i blokuje pliki powyżej konfigurowalnego progu linii, domyślnie 350, kierując model do skilla bulk-reader; hook check-bash-read łapie cat, head, tail, less i more na dużych plikach, a polecenia z pipe przechodzą s1. Źródła hooków i oba skille są w publicznym repo s2, a sprawdzanie rozmiaru można przeczytać osobno s3. Same mode'y żyją w Portalu, wewnętrznej platformie Spotify, dlatego wtyczki w obecnej postaci nie da się uruchomić poza firmą s4.
Teza benchmarku jest cienka. Spotify przetestowało cztery scenariusze na monorepo w Javie, "measuring tokens Claude would consume reading files directly vs. consuming the bulk-reader's summary", i podaje średnie oszczędności na masowym czytaniu rzędu 90% s1. Sam post przyznaje, że scenariusz zapisu kodu trudniej zmierzyć w tokenach, że podsumowania workerów nie zawierają wiarygodnych numerów linii, więc edycji nie da się delegować, że worker przeoczył subtelny błąd thread safety, który główny model wyłapał, i że każde delegowanie dodaje od 10 do 30 sekund, a Portal ogranicza pojedyncze wywołanie do 30 sekund s1. Wątek na Hacker News zadał te same pytania o to, co właściwie mierzy 90% s7.
Odtworzenie zastępuje mode'y Portala dwoma subagentami Claude Code, których pliki definicji przypinają model: reader Explore na Haiku i code-writer na Sonnecie s6. Blokadą jest hook PreToolUse zwracający decyzję deny w aktualnym formacie JSON hooków s5. Testowane repo to fastify/fastify na commicie ac28821d, 294 pliki .js/.ts, 78270 linii, 63 pliki powyżej 350 linii. ID modeli według JSON-a sesji: główna rozmowa claude-opus-5[1m], reader claude-haiku-4-5-20251001, writer claude-sonnet-5. Każdy scenariusz uruchomiono dwa razy na konfigurację, 16 zmierzonych uruchomień, jednoturowe sesje claude -p z ustawieniami tylko z projektu, żeby obie strony miały identyczny system prompt s5.
Gdzie wzorzec wygrał: S2, pytanie o graf wywołań w trzech plikach, lib/route.js (691 linii), lib/reply.js (1090) i lib/request.js (398), spadło ze średniego głównego kontekstu 357165.5 tokenów do 73440.0 (-79.4%) i z 0.5810500000000001 USD do 0.21823605000000001 USD (-62.4%). Gdzie nie: S4, napisanie testu dla źródła na 45 linii według wzorca na 19 linii, kosztowało 0.29465575 USD bez delegowania i 0.3022213 USD z nim (+2.6%), bo Sonnet to drugi pełny kontekst (od 13004 do 18729 tokenów cache-read), a główny model i tak ponownie przeczytał wygenerowany plik i uruchomił test s6.
Trzy ustalenia znaczą więcej niż procenty. Po pierwsze, hooki nie odpaliły ani razu w 16 zmierzonych uruchomieniach: z regułą routingu w CLAUDE.md główny model sam uruchomił wc -l i zdelegował. Jedyna zaobserwowana blokada pochodziła z uruchomienia weryfikacyjnego bez CLAUDE.md, gdzie modelowi odmówiono Read, potem cat -n, a on odpowiedział samym grep -n, nigdy nie wywołując narzędzia Agent s5. Po drugie, hooki działają wewnątrz subagentów: w dwóch odrzuconych uruchomieniach reader na Haiku został sam zablokowany przez sprawdzanie rozmiaru i przeszedł na fragmentaryczne odczyty offset/limit. Naprawą jest wyjątek case "$agent_type" in Explore|code-writer) exit 0 na początku hooka, z nazwą pola potwierdzoną z zalogowanego stdin s5. Po trzecie, w konfiguracji bazowej główny model w ogóle nie używał narzędzia Read. Czytał każdy plik przez Bash (cat -n, sed -n '1,200p', sed -n '200,560p'), więc hook pilnujący tylko Read nic nie łapie, a hook Bash dopasowujący tylko cat, head i tail bez pipe nadal przepuszcza zakresy sed -n s3.
Jakość sprawdzono względem źródła za pomocą grep. Baseline dał błędne numery linii w jednym uruchomieniu S2 (zrzucił pliki przez sed -n bez numerów linii i liczył ręcznie). Konfiguracja z delegowaniem dała trzy błędy merytoryczne w drugim uruchomieniu S2 i dwa w uruchomieniu S3, wszystkie wynikające z przyjęcia podsumowania Haiku za dobrą monetę: błędni wywołujący buildRequest/buildReply, niewyeksportowana stała wymieniona jako export, pokryty iterator oznaczony jako niepokryty. Tam, gdzie główny model wydał tokeny wyjściowe na ponowną weryfikację przez grep (S3, od 4534 do 4738 tokenów wyjściowych), odpowiedzi się trzymały s6. W scenariuszu pisania testów każdy wygenerowany plik przeszedł: 12/12, 6/6, 7/7 i 10/10 testów. Jedno zgłoszenie na Reddicie pokazuje pokrewny przypadek, gdy główny model odpala workerów na złym modelu, jeśli nic go nie przypina s8, przed czym chronią hook require-model i pole model: w plikach agentów.
Pomiary
Średnie z 2 uruchomień na komórkę. "Główny kontekst" to tokeny input + cache_creation + cache_read naliczone głównemu modelowi w całej sesji, liczba porównywalna z "tokens in the main context" Spotify. A = czysty Claude Code, B = hook + subagenty + reguła w CLAUDE.md.
| scenariusz | główny kontekst A | główny kontekst B | zmiana | główny output A | główny output B | zmiana | koszt całkowity A | koszt całkowity B | zmiana | czas A s | czas B s | zmiana |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| S1 | 88693.0 | 51551.5 | -41.9% | 1424.5 | 1060.5 | -25.6% | 0.13910675 | 0.08653685 | -37.8% | 21.817500000000003 | 43.799499999999995 | +100.8% |
| S2 | 357165.5 | 73440.0 | -79.4% | 3835.0 | 2555.5 | -33.4% | 0.5810500000000001 | 0.21823605000000001 | -62.4% | 51.637 | 129.036 | +149.9% |
| S3 | 303807.5 | 114135.5 | -62.4% | 6192.0 | 4636.0 | -25.1% | 0.451037 | 0.3738534 | -17.1% | 93.321 | 124.64099999999999 | +33.6% |
| S4 | 143431.5 | 121818.0 | -15.1% | 5275.5 | 3340.0 | -36.7% | 0.29465575 | 0.3022213 | +2.6% | 65.7125 | 86.857 | +32.2% |
| wszystkie 4 | 223274.375 | 90236.25 | -59.6% | 4181.75 | 2898.0 | -30.7% | 0.366462375 | 0.2452119 | -33.1% | 58.122 | 96.08337499999999 | +65.3% |
Protokół: dwa bajt w bajt identyczne płytkie klony fastify/fastify na ac28821d; repo-shunt dodaje .claude/ (ustawienia, dwa pliki agentów, trzy hooki) i regułę routingu w CLAUDE.md, nic więcej. Każda sesja: claude -p "<prompt>" --output-format json --setting-sources project --strict-mcp-config z pustą konfiguracją MCP, bez --model, timeout 600 s. Cztery prompty, identyczne po obu stronach: S1 eksporty lib/reply.js, S2 graf wywołań w trzech plikach lib, S3 metody lib/hooks.js kontra pokrycie w test/hooks.test.js, S4 napisanie test/head-route.test.js według test/noop-set.test.js. Liczby pochodzą z modelUsage i total_cost_usd w JSON-ie sesji, bez zaokrągleń. Odpowiedzi sprawdzono względem źródła za pomocą grep; wygenerowane testy uruchomiono przez node --test.
Zrób w poniedziałek
- Uruchom
wc -lna swoim repo i policz pliki powyżej 350 linii. Jeśli wynik jest bliski zeru, zatrzymaj się tutaj: próg istnieje, bo delegowanie kosztuje więcej, niż oszczędza na małych plikach. - Dodaj do CLAUDE.md regułę routingu w trzech linijkach: pliki powyżej progu idą do subagenta readera, kod według wzorca do subagenta writera, debugowanie i architektura zostają przy głównym modelu. W pomiarach cała robota wynikała z tej reguły.
- Utwórz
.claude/agents/Explore.mdzmodel: haikui.claude/agents/code-writer.mdzmodel: sonnetwe frontmatterze, żeby model workera był przypięty w pliku, a nie zostawiony orkiestratorowi. - Napisz hook PreToolUse na Read jako siatkę bezpieczeństwa, zwracający decyzję deny w aktualnym formacie JSON hooków, i niech jego pierwsze linie kończą się exit 0, gdy
agent_typeto jeden z twoich workerów. - Rozszerz hook Bash poza
cat,headitail: dopasuj zakresysed -nicat -nna dużych plikach, przepuść polecenia z pipe i grep. - Uruchom jedno prawdziwe pytanie z folderem
.claude/i bez niego, przezclaude -p --output-format json, i porównajtotal_cost_usdorazduration_ms, a nie samą kolumnę wejścia. - Sprawdź dwie delegowane odpowiedzi względem źródła przez grep, zanim zaufasz podsumowaniu readera; wliczaj turę weryfikacji głównego modelu w koszt.
- Zmierz też sesję wieloturową: wyniki jednoturowe zostawiają główny kontekst na poziomie 50k do 119k tokenów wobec 84k do 414k bez delegowania, więc drugie pytanie powinno startować taniej, ale tego nie mierzono.
Czytaj dalej
- Przeczytaj format hooków i pole
agent_typew oficjalnej dokumentacji, zanim skopiujesz hook z bloga; kształt deny i pola na stdin umożliwiają wyłączenie subagentów s5. - Dokumentacja subagentów opisuje pole frontmattera
modeli ograniczenia narzędzi, dzięki którym reader pozostaje tylko do odczytu i tani s6. - Sekcja "What doesn't work" w poście Spotify to jego najużyteczniejsza część: brak delegowanej edycji (brak wiarygodnych numerów linii w podsumowaniach), brak delegowanego rozumowania (przeoczony błąd thread safety), round trip od 10 do 30 sekund s1.
- README Shunta pokazuje trójwarstwową strukturę (hooki, skrypty, skille) i teksty skilli mówiące modelowi, kiedy delegować; do przerobienia nadaje się proza skilli, nie hook s2.
- Mode'y Portala to warstwa konfiguracji nad modelem plus system promptem; ta sama idea mapuje się na plik agenta Claude Code z polem
models4. - Wątek na Hacker News to miejsce, gdzie pytania o pomiar padły jako pierwsze, i dobra lista kontrolna tego, o co pytać przy każdej deklaracji oszczędności tokenów s7.
- Wątek na Reddicie opisuje orkiestratora, który odpalił pięciu workerów na własnym drogim modelu; przypnij model w pliku agenta, a jeśli chcesz twardej gwarancji, odrzucaj wywołania Agent bez pola
models8.
Źródła
- Portal by Spotify cut my Claude Code token usage by 90%, Spotify Engineering. Dlaczego warto: oryginalna teza, trójwarstwowy projekt i uczciwa sekcja o ograniczeniach, która osłabia nagłówek.
- Shunt plugin (spotify/portal-ai-plugins), GitHub. Dlaczego warto: prawdziwe hooki, skrypty i teksty skilli, na tyle krótkie, że da się przeczytać w całości.
- check-file-size hook source, GitHub. Dlaczego warto: sprawdzenie 350 linii w kilku linijkach shella, wzór na własny deny.
- Portal Modes documentation, Spotify. Dlaczego warto: czym jest "mode", żeby zobaczyć, czemu mapuje się na plik subagenta.
- Claude Code hooks reference, Anthropic. Dlaczego warto: aktualny format deny i pola na stdin, w tym to, które identyfikuje subagenta.
- Claude Code subagents, Anthropic. Dlaczego warto: pole frontmattera
modeli listy dozwolonych narzędzi dla taniego workera tylko do odczytu. - Hacker News discussion of the Spotify post, Hacker News. Dlaczego warto: pytania o to, co mierzy 90%, zadane, zanim ktokolwiek zmierzył ponownie.
- Fable spawned five Fable agents instead of Opus (r/ClaudeCode), Reddit. Dlaczego warto: przypadek awarii, któremu zapobiega przypięte pole
model.
FAQ
Czy liczba 90% jest błędna?
Mierzy jedną rzecz: szacowane tokeny wejściowe w głównym kontekście dla scenariuszy masowego czytania dużych plików Java. Na podobnej metryce odtworzenie dało od 41.9% do 79.4% w scenariuszach czytania. Nie mówi nic o kosztach, czasie ani jakości odpowiedzi, a post tego nie twierdzi.
Czy potrzebuję Portala, żeby to osiągnąć?
Nie. Routing mieści się w regule CLAUDE.md, dwóch plikach agentów z przypiętym modelem i hooku PreToolUse. Portal dostarcza modele workerów w Spotify; jedna linijka model: haiku robi to samo w czystym Claude Code.
Kiedy delegowanie kosztuje więcej?
Gdy pliki są małe. Scenariusz testu na 45 linii kosztował z delegowaniem o 2.6% więcej, bo writer to drugi pełny kontekst, a główny model i tak ponownie przeczytał i przetestował wynik. Każde delegowane uruchomienie było też wolniejsze, średnio +65.3%.
Dlaczego hook nigdy nie odpalił?
Bo reguła routingu w CLAUDE.md sprawiła, że główny model sprawdził wc -l i zdelegował, zanim spróbował czytać. Hook ma znaczenie tylko wtedy, gdy model ignoruje regułę, co zdarzyło się w uruchomieniu weryfikacyjnym bez CLAUDE.md.
AIDive