AIDive

वीडियो पैक

Spotify का 90% Claude Code टोकन कटौती दावा, दोबारा बनाकर मापा: hook, subagents

11 मिनट पढ़ें

TL;DR

  • Spotify का "90%" बल्क-रीड वाले परिदृश्यों का औसत है, जिसे एक Java मोनोरेपो पर अनुमानित इनपुट टोकन में मापा गया। पोस्ट में डॉलर का कोई आँकड़ा नहीं है और गुणवत्ता का कोई स्कोर भी नहीं।
  • सादे Claude Code में दोबारा बनाने पर (एक PreToolUse hook, दो सस्ते subagent, तीन पंक्तियों का routing नियम) और Fastify पर चार परिदृश्यों और 16 रन में मापने पर, इस पैटर्न ने मुख्य मॉडल का संदर्भ 59.6% और कुल लागत 33.1% घटाई।
  • मापे गए रनों में deny hooks एक बार भी नहीं चले। बचत CLAUDE.md के routing नियम से आई; hooks उस दिन के लिए सुरक्षा जाल हैं जब मॉडल नियम को अनदेखा कर दे।
  • डेलीगेशन हर बार धीमा रहा, औसतन +65.3% वॉल टाइम। छोटे टेस्ट-लेखन परिदृश्य में यह 2.6% ज़्यादा महँगा पड़ा।
  • दो जाल: hooks subagent के अंदर भी चलते हैं, इसलिए अपने workers को छूट दें, और जो hook सिर्फ cat, head और tail पर नज़र रखता है, उससे sed -n रेंज रीड सीधे निकल जाते हैं।
  • Haiku reader के सारांश में आठ में से दो डेलीगेट किए गए रनों में तथ्य की गलतियाँ थीं। मुख्य मॉडल का verification टर्न बनाए रखें।

मापन क्या कहते हैं

Spotify का plugin, Shunt, बल्क काम को मुख्य मॉडल से दो "modes" के ज़रिए दूर भेजता है: एक bulk-reader और एक code-writer। उदाहरणों में दोनों Gemini 2.5 Flash चलाते हैं, और model फ़ील्ड Portal instance में कॉन्फ़िगर किया गया कोई भी मॉडल स्वीकार करता है s1। routing की तीन परतें हैं। check-file-size hook हर Read पर चलता है और कॉन्फ़िगर करने योग्य पंक्ति सीमा (डिफ़ॉल्ट 350) से बड़ी फ़ाइलों को रोककर मॉडल को bulk-reader skill की ओर भेजता है; check-bash-read hook बड़ी फ़ाइलों पर cat, head, tail, less और more पकड़ता है, जबकि pipe वाले कमांड निकल जाते हैं s1। hook के सोर्स और दोनों skills सार्वजनिक repo में हैं s2, और size चेक अकेले भी पढ़ा जा सकता है s3। modes खुद Portal में रहते हैं, जो Spotify का आंतरिक प्लेटफ़ॉर्म है, इसीलिए plugin को जैसा है वैसा कंपनी के बाहर नहीं चलाया जा सकता s4।

बेंचमार्क का दावा कमज़ोर है। Spotify ने एक Java मोनोरेपो पर चार परिदृश्य परखे, "measuring tokens Claude would consume reading files directly vs. consuming the bulk-reader's summary", और बल्क-रीड की औसत बचत लगभग 90% बताई s1। पोस्ट खुद कहती है कि code-write परिदृश्य को टोकन में मापना कठिन है, worker के सारांश में भरोसेमंद लाइन नंबर नहीं होते इसलिए एडिटिंग डेलीगेट नहीं की जा सकती, worker एक बारीक thread-safety बग चूक गया जिसे मुख्य मॉडल ने पकड़ा, और हर डेलीगेशन 10 से 30 सेकंड जोड़ता है जबकि Portal एक invocation को 30 सेकंड पर सीमित करता है s1। Hacker News थ्रेड ने यही सवाल उठाए कि 90% आख़िर क्या मापता है s7।

दोबारा बनाए गए संस्करण में Portal modes की जगह दो Claude Code subagent हैं जिनकी परिभाषा फ़ाइलें मॉडल पिन करती हैं: Haiku पर Explore reader और Sonnet पर code-writer s6। deny एक PreToolUse hook है जो मौजूदा hook JSON फ़ॉर्मैट में deny निर्णय लौटाता है s5। परखा गया repo fastify/fastify था, commit ac28821d, 294 .js/.ts फ़ाइलें, 78270 पंक्तियाँ, 350 से ज़्यादा पंक्तियों की 63 फ़ाइलें। सेशन JSON के अनुसार मॉडल id: मुख्य बातचीत claude-opus-5[1m], reader claude-haiku-4-5-20251001, writer claude-sonnet-5। हर परिदृश्य प्रति कॉन्फ़िग दो बार चला, कुल 16 मापे गए रन, सिंगल-टर्न claude -p सेशन, सिर्फ़ प्रोजेक्ट सेटिंग्स के साथ ताकि दोनों तरफ़ सिस्टम प्रॉम्प्ट एक जैसा रहे s5।

पैटर्न जहाँ जीता: S2, lib/route.js (691 पंक्तियाँ), lib/reply.js (1090) और lib/request.js (398) पर तीन-फ़ाइल call-graph सवाल, मुख्य संदर्भ के औसत 357165.5 टोकन से 73440.0 पर आया (-79.4%) और 0.5810500000000001 USD से 0.21823605000000001 USD पर (-62.4%)। जहाँ नहीं जीता: S4, 19 पंक्तियों के संदर्भ के मुक़ाबले 45 पंक्तियों के सोर्स का टेस्ट लिखना, डेलीगेशन के बिना 0.29465575 USD और डेलीगेशन के साथ 0.3022213 USD पड़ा (+2.6%), क्योंकि Sonnet एक दूसरा पूरा संदर्भ है (13004 से 18729 cache-read टोकन) और मुख्य मॉडल ने फिर भी बनी हुई फ़ाइल दोबारा पढ़ी और टेस्ट चलाया s6।

प्रतिशतों से ज़्यादा अहम तीन निष्कर्ष हैं। पहला, 16 मापे गए रनों में hooks शून्य बार चले: CLAUDE.md में routing नियम के साथ मुख्य मॉडल ने खुद wc -l चलाया और डेलीगेट किया। देखा गया एकमात्र deny CLAUDE.md के बिना वाले verification रन से आया, जहाँ मॉडल को Read से इनकार मिला, फिर cat -n से, और उसने Agent टूल को कभी बुलाए बिना सिर्फ़ grep -n से जवाब दिया s5। दूसरा, hooks subagent के अंदर चलते हैं: दो छोड़े गए रनों में Haiku reader खुद size चेक से deny हुआ और chunked offset/limit रीड पर लौट गया। हल है hook की शुरुआत में case "$agent_type" in Explore|code-writer) exit 0 वाला escape, जिसमें फ़ील्ड का नाम लॉग किए गए stdin से पक्का किया जाता है s5। तीसरा, baseline कॉन्फ़िग में मुख्य मॉडल ने Read टूल कभी इस्तेमाल ही नहीं किया। उसने हर फ़ाइल Bash से पढ़ी (cat -n, sed -n '1,200p', sed -n '200,560p'), इसलिए जो hook सिर्फ़ Read देखता है वह कुछ नहीं पकड़ता, और जो Bash hook सिर्फ़ बिना pipe वाले cat, head और tail से मेल खाता है वह sed -n रेंज को निकलने देता है s3।

गुणवत्ता की जाँच सोर्स के विरुद्ध grep से की गई। baseline ने एक S2 रन में गलत लाइन नंबर दिए (उसने फ़ाइलें लाइन नंबर के बिना sed -n से डंप कीं और हाथ से गिनीं)। डेलीगेट वाले कॉन्फ़िग ने दूसरे S2 रन में तीन और एक S3 रन में दो तथ्यात्मक गलतियाँ कीं, जो सब Haiku सारांश को जस का तस मान लेने से आईं: buildRequest/buildReply के गलत callers, एक non-exported constant का export के रूप में दर्ज होना, एक covered iterator का uncovered चिह्नित होना। जहाँ मुख्य मॉडल ने grep से दोबारा जाँचने में output टोकन खर्च किए (S3, 4534 से 4738 output टोकन), वहाँ जवाब सही रहे s6। टेस्ट-लेखन परिदृश्य में बनी हर फ़ाइल पास हुई: 12/12, 6/6, 7/7 और 10/10 टेस्ट। एक Reddit रिपोर्ट इससे जुड़ी विफलता दिखाती है, जहाँ कुछ भी मॉडल पिन न करे तो मुख्य मॉडल गलत मॉडल पर workers खड़े कर देता है s8, और require-model hook तथा agent फ़ाइलों का model: फ़ील्ड इसी से बचाते हैं।

मापन

प्रति सेल 2 रनों का औसत। "Main context" वह input + cache_creation + cache_read टोकन है जो सेशन भर में मुख्य मॉडल पर बिल हुआ, यानी Spotify के "tokens in the main context" से तुलनीय आँकड़ा। A = सादा Claude Code, B = hook + subagents + CLAUDE.md नियम।

परिदृश्य मुख्य संदर्भ A मुख्य संदर्भ B बदलाव मुख्य आउटपुट A मुख्य आउटपुट B बदलाव कुल लागत A कुल लागत B बदलाव अवधि A s अवधि B s बदलाव
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%
all 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%

प्रोटोकॉल: fastify/fastify के ac28821d पर दो बाइट-समान shallow clones; repo-shunt सिर्फ़ .claude/ (settings, दो agent फ़ाइलें, तीन hooks) और एक CLAUDE.md routing नियम जोड़ता है, और कुछ नहीं। हर सेशन: claude -p "<prompt>" --output-format json --setting-sources project --strict-mcp-config, खाली MCP कॉन्फ़िग के साथ, बिना --model, 600 s timeout। चार प्रॉम्प्ट, दोनों तरफ़ एक जैसे: S1 lib/reply.js के exports, S2 तीन lib फ़ाइलों में call graph, S3 lib/hooks.js के methods बनाम test/hooks.test.js की coverage, S4 test/noop-set.test.js को आदर्श मानकर test/head-route.test.js लिखना। आँकड़े सेशन JSON के modelUsage और total_cost_usd से बिना राउंड किए लिए गए हैं। जवाब सोर्स के विरुद्ध grep से जाँचे गए; बने हुए टेस्ट node --test से चलाए गए।

सोमवार को यह करें

  • अपने repo पर wc -l चलाएँ और 350 से ज़्यादा पंक्तियों वाली फ़ाइलें गिनें। अगर गिनती लगभग शून्य है तो यहीं रुकें: यह सीमा इसलिए है कि छोटी फ़ाइलों पर डेलीगेशन बचाने से ज़्यादा खर्च कराता है।
  • अपने CLAUDE.md में तीन पंक्तियों का routing नियम जोड़ें: सीमा से बड़ी फ़ाइलें reader subagent को, पैटर्न-अनुसार कोड writer subagent को, debugging और architecture मुख्य मॉडल के पास। मापन में सारा काम इसी नियम ने किया।
  • frontmatter में model: haiku के साथ .claude/agents/Explore.md और model: sonnet के साथ .claude/agents/code-writer.md बनाएँ, ताकि worker का मॉडल फ़ाइल में पिन रहे और orchestrator पर न छूटे।
  • Read पर सुरक्षा जाल के रूप में PreToolUse hook लिखें, जो मौजूदा hook JSON फ़ॉर्मैट में deny निर्णय लौटाए, और उसकी पहली पंक्तियाँ तब exit 0 करें जब agent_type आपके workers में से कोई हो।
  • Bash hook को cat, head और tail से आगे बढ़ाएँ: बड़ी फ़ाइलों पर sed -n रेंज और cat -n से मेल खाएँ, pipe और grep वाले कमांड निकलने दें।
  • एक असली सवाल .claude/ फ़ोल्डर के साथ और उसके बिना चलाएँ, claude -p --output-format json से, और total_cost_usd तथा duration_ms की तुलना करें, सिर्फ़ input कॉलम की नहीं।
  • reader के सारांश पर भरोसा करने से पहले डेलीगेट किए गए दो जवाब सोर्स के विरुद्ध grep से जाँचें; मुख्य मॉडल के verification टर्न को लागत का हिस्सा मानकर बजट में रखें।
  • मल्टी-टर्न सेशन भी मापें: सिंगल-टर्न नतीजे मुख्य संदर्भ को 50k से 119k टोकन पर छोड़ते हैं, जबकि डेलीगेशन के बिना यह 84k से 414k है, इसलिए दूसरा सवाल सस्ता शुरू होना चाहिए, पर यह मापा नहीं गया।

और आगे

  • किसी ब्लॉग से hook कॉपी करने से पहले आधिकारिक रेफ़रेंस में hook फ़ॉर्मैट और agent_type फ़ील्ड पढ़ें; deny का आकार और stdin के फ़ील्ड ही subagent छूट को संभव बनाते हैं s5।
  • subagent दस्तावेज़ model frontmatter फ़ील्ड और टूल प्रतिबंध समझाता है, यानी reader को read-only और सस्ता कैसे रखें s6।
  • Spotify का अपना "What doesn't work" भाग पोस्ट का सबसे काम का हिस्सा है: डेलीगेट की गई एडिटिंग नहीं (सारांश में भरोसेमंद लाइन नंबर नहीं), डेलीगेट की गई reasoning नहीं (thread-safety बग छूटा), 10 से 30 सेकंड का राउंड ट्रिप s1।
  • Shunt README तीन परतों की संरचना (hooks, scripts, skills) और वे skill पाठ दिखाता है जो मॉडल को बताते हैं कि कब डेलीगेट करना है; अपनाने लायक हिस्सा skill की भाषा है, hook नहीं s2।
  • Portal modes एक मॉडल और सिस्टम प्रॉम्प्ट के ऊपर कॉन्फ़िगरेशन परत हैं; यही विचार model फ़ील्ड वाली Claude Code agent फ़ाइल पर लागू होता है s4।
  • Hacker News थ्रेड वह जगह है जहाँ मापन के सवाल पहली बार उठे, और किसी भी टोकन-बचत दावे से पूछने लायक बातों की अच्छी चेकलिस्ट है s7।
  • एक Reddit थ्रेड दर्ज करता है कि कैसे एक orchestrator ने पाँच workers अपने ही महँगे मॉडल पर खड़े कर दिए; agent फ़ाइल में मॉडल पिन करें और पक्की गारंटी चाहिए तो बिना model फ़ील्ड वाले Agent कॉल deny करें s8।

स्रोत

  • Portal by Spotify cut my Claude Code token usage by 90%, Spotify Engineering. क्यों पढ़ें: मूल दावा, तीन परतों का डिज़ाइन और एक ईमानदार सीमाओं वाला भाग जो शीर्षक को कमज़ोर करता है।
  • Shunt plugin (spotify/portal-ai-plugins), GitHub. क्यों पढ़ें: असली hooks, scripts और skill पाठ, इतने छोटे कि पूरे पढ़े जा सकें।
  • check-file-size hook source, GitHub. क्यों पढ़ें: कुछ shell पंक्तियों में 350-पंक्ति की जाँच, आपके अपने deny का टेम्पलेट।
  • Portal Modes documentation, Spotify. क्यों पढ़ें: "mode" क्या है, ताकि दिखे कि वह subagent फ़ाइल से क्यों मेल खाता है।
  • Claude Code hooks reference, Anthropic. क्यों पढ़ें: मौजूदा deny फ़ॉर्मैट और stdin फ़ील्ड, जिनमें वह भी जो subagent की पहचान कराता है।
  • Claude Code subagents, Anthropic. क्यों पढ़ें: सस्ते read-only worker के लिए model frontmatter फ़ील्ड और टूल allowlist।
  • Hacker News discussion of the Spotify post, Hacker News. क्यों पढ़ें: 90% क्या मापता है इस पर सवाल, किसी के दोबारा मापने से पहले पूछे गए।
  • Fable spawned five Fable agents instead of Opus (r/ClaudeCode), Reddit. क्यों पढ़ें: वह विफलता जिसे पिन किया हुआ model फ़ील्ड रोकता है।

FAQ

क्या 90% वाला आँकड़ा गलत है?

यह एक ही चीज़ मापता है: बड़ी Java फ़ाइलों पर बल्क-रीड परिदृश्यों में मुख्य संदर्भ के अनुमानित इनपुट टोकन। उसी तरह के मापदंड पर दोबारा बनाए गए संस्करण में रीड परिदृश्यों पर 41.9% से 79.4% दिखा। यह लागत, समय या जवाब की गुणवत्ता के बारे में कुछ नहीं कहता, और पोस्ट भी ऐसा दावा नहीं करती।

क्या यह पाने के लिए मुझे Portal चाहिए?

नहीं। routing CLAUDE.md के एक नियम, पिन किए हुए मॉडल वाली दो agent फ़ाइलों और एक PreToolUse hook में रहती है। Spotify में Portal worker मॉडल देता है; सादे Claude Code में model: haiku की एक पंक्ति वही काम करती है।

डेलीगेशन कब ज़्यादा महँगा पड़ता है?

जब फ़ाइलें छोटी हों। 45 पंक्तियों वाला टेस्ट-लेखन परिदृश्य डेलीगेशन के साथ 2.6% ज़्यादा महँगा रहा, क्योंकि writer एक दूसरा पूरा संदर्भ है और मुख्य मॉडल ने फिर भी नतीजा दोबारा पढ़ा और परखा। हर डेलीगेट किया गया रन धीमा भी था, औसतन +65.3%।

hook कभी क्यों नहीं चला?

क्योंकि CLAUDE.md के routing नियम ने मुख्य मॉडल से पढ़ने की कोशिश से पहले wc -l चलवाया और डेलीगेट करवाया। hook तभी मायने रखता है जब मॉडल नियम को अनदेखा करे, जो CLAUDE.md के बिना वाले verification रन में हुआ।