AIDive

Spotify giảm 90% token Claude Code? Tôi dựng lại và đo thật

Bởi AIDive · Đăng ngày

Coding agentMô hình AI

Chín mươi phần trăm, và câu nói đã bán được nó

Setup Spotify Claude Code là một bài blog của Dimitri Mazmanov, product manager tại Spotify, kèm mã nguồn trên GitHub: anh cho biết cấu hình mà nhóm anh đang dùng đã giảm 90% lượng token Claude Code của anh. Câu đầu tiên của bài gánh trọn lập luận: phần lớn việc một AI coding agent làm không phải là suy nghĩ, mà là I/O. Đọc năm file để trả lời một câu hỏi về một method, hay viết file test thứ hai mươi mốt sao chép hai mươi file bên cạnh, đốt hàng nghìn token mà gần như không có chút suy luận nào.

Một tweet đã đưa bài viết lên một triệu rưỡi lượt xem chỉ bằng một câu: luật viết ra chỉ là gợi ý, chặn thì không. Hacker News đưa nó lên trang nhất, 271 điểm và 173 bình luận, và một nửa số bình luận hỏi cùng một câu: 90% của cái gì? Từ hạn định của chính Spotify là "bulk read". Bài viết này dựng lại setup đó bên trong Claude Code thuần, rồi đo nó, để bạn biết chính xác từ hạn định ấy mang lại cho bạn điều gì.

Portal thực sự là gì (và vì sao bạn không chạy được)

Portal không phải là một router. Đó là cổng lập trình viên nội bộ của Spotify, xây trên Backstage, nền tảng lập trình viên mà Spotify đã mở mã nguồn. Tính năng liên quan bên trong nó tên là Modes: theo định nghĩa của Spotify, một mode là một agent khai báo chạy trên một runtime tạm thời, đại khái là AWS Lambda dành cho agent. Bạn viết hướng dẫn, chọn model, đặt temperature, gắn tool. Mazmanov đã dựng hai mode như vậy, một bulk reader và một code writer, cả hai đều chạy Gemini Flash ở temperature 0.2, nên cả hai đều rẻ và nhàm chán một cách có chủ đích.

Phần định tuyến nằm trong một plugin Claude Code tên là Shunt. Nó công khai trên GitHub và cài bằng hai lệnh. Nhưng bước hai xác thực dòng lệnh Portal với instance Portal của bạn, mà bạn thì không có. Plugin thì công khai; thứ nó ủy quyền cho thì không.

Vì vậy nước đi hữu ích là quên plugin đi và giữ lấy mô hình. Nó có ba lớp, theo chính lời anh: hook, script, skill. Mỗi lớp đều có một tương đương trong Claude Code thuần, và đó là thứ phần còn lại của bài viết này dựng lên và đo.

Lớp một: hook chặn thay vì hỏi

Phiên bản 1 của setup là một khối luật định tuyến trong file hướng dẫn của dự án. Theo lời Mazmanov, nó "kiểu như có hoạt động": các luật chỉ mang tính khuyến nghị, không được cưỡng chế, Claude có thể bỏ qua chúng, và mỗi dự án lại cần một bản sao riêng. Phiên bản 2 chuyển quyết định ra khỏi prompt và đưa vào lớp tool bằng hai hook, cả hai đều kích hoạt trước một lời gọi tool. Một hook theo dõi mọi lần đọc file, hook kia theo dõi shell.

Hook đọc là 33 dòng bash. Nó đọc một ngưỡng từ biến môi trường, mặc định 350 dòng, rồi cho ba trường hợp đi qua:

  • Một lần đọc có offset hoặc limit, vì Claude đã biết mình cần gì.
  • Một file không tồn tại.
  • Một file bằng hoặc dưới ngưỡng, vì ủy quyền một thứ nhỏ tốn hơn là tự đọc.

Mọi thứ còn lại bị chặn, kèm một thông điệp Claude đọc thay cho file: file này dài chừng ấy dòng, hãy dùng skill bulk reader, và nếu cần nội dung chính xác để sửa, hãy đọc lại đúng đoạn đó. Hook shell bắt cat, head, tail, less và more trên một file lớn. Lệnh có pipe được đi qua, vì pipe vào grep là một lần đọc có mục tiêu.

Luận điểm của Mazmanov về việc xếp lớp là điểm quan trọng: kể cả khi Claude không bao giờ đọc mô tả skill, hook vẫn chặn lần đọc đắt đỏ. Skill làm cho việc chuyển hướng mượt hơn; cú chặn làm cho nó thành thật. Một chi tiết sẽ quan trọng về sau: script trả lời bằng một quyết định ở cấp cao nhất tên là "block". Hãy nhớ từ đó.

Lớp hai và ba: các worker và con số của họ

Các worker là hai prompt. Reader: "bạn là một nhà phân tích mã chính xác, chỉ xuất ra các gạch đầu dòng có cấu trúc, không chào hỏi, không văn xuôi, mở đầu mỗi gạch đầu dòng bằng đúng tên, kiểu hoặc số dòng." Writer: "khớp chính xác các pattern, cách đặt tên và phong cách hiện có; chỉ xuất ra mã, không fence, không giải thích." Thiếu dòng cuối đó, model bọc mọi thứ trong Markdown mà Claude sau đó phải phân tích.

Hai script bao lấy chúng. Bulk-read nhận một câu hỏi và các đường dẫn file rồi gửi đi. Code-write nhận một spec và một file tham chiếu rồi ghi kết quả thẳng xuống đĩa, nên Claude không bao giờ thấy mã được sinh ra. Mỗi lần ủy quyền là one-shot: một câu hỏi tiếp theo sẽ gửi lại các file. Điều đó miễn phí ở chỗ quan trọng, vì kho mã đi tới worker và không bao giờ vào context của Claude.

Lớp ba là một file skill bảo Claude khi nào nên ủy quyền: file trên 350 dòng, câu hỏi trải trên ba file trở lên, diff lớn. Dòng cuối của nó là "kiểm tra số dòng trước khi sửa".

Bảng của Spotify bao gồm một Java monorepo và ba kịch bản đọc. Trường hợp một file giảm từ khoảng 34.000 token xuống dưới 6.000, và mức tiết kiệm trung bình trên ba hàng là 90%.

Benchmark của Spotify Giá trị
Repository 1 Java monorepo
Kịch bản 3, toàn là bulk read
Trường hợp một file, trước ~34.000 token
Trường hợp một file, sau < 6.000 token
Tiết kiệm trung bình 90%
Ước lượng token 4 ký tự mỗi token
Cưỡng chế writer không có (chỉ reader có hook)

Hai lưu ý do chính Spotify in ra: token được ước lượng bốn ký tự mỗi token, và writer hoàn toàn không có cưỡng chế. Vậy nên con số 90% là trung bình của ba hàng bulk read tính bằng input token ước lượng, không có điểm chất lượng và không có con số đô la nào cả. Đó là con số cần kiểm chứng.

Dựng lại, phần một: subagent có trường model

Claude Code có sẵn một subagent Explore tích hợp, và kể từ một bản phát hành gần đây nó kế thừa model chính của bạn, giới hạn tối đa ở Opus, nên "reader rẻ" không còn rẻ nữa. Tài liệu đưa ra cách sửa trong một câu: một subagent của dự án tên là Explore sẽ ghi đè subagent tích hợp và giữ trường model riêng. Một file markdown, một front matter, và dòng model ghi Haiku. Đó là bulk reader. Writer là file thứ hai: model Sonnet, tool chỉ gồm Read và Write, phần thân là chính hướng dẫn của Spotify dán vào.

Nó hoạt động vì mỗi subagent bắt đầu với một context window mới, tách biệt. Những gì nó đọc nằm ở đó, không nằm trong cuộc hội thoại chính. Đó là ủy quyền one-shot của Spotify trừ đi vòng đi về qua mạng.

Rồi đến phần không ai tính trước. Trên Reddit tuần này, Fable được yêu cầu tạo các agent Opus và thay vào đó tạo ra năm agent Fable: 73% hạn mức tuần bay mất trong ba mươi phút. Câu trả lời được bình chọn cao nhất là một hook chạy khi model điều phối một subagent, buộc nó phải chọn model một cách tường minh, và bảo nó chọn model rẻ nhất có thể làm được việc. Đó là hook số ba: nó theo dõi tool Agent, và một lời gọi không có model bị từ chối bằng một câu, "hãy chọn model một cách tường minh".

Skill của Spotify trở thành ba dòng trong file hướng dẫn của dự án: file trên 350 dòng đi tới explorer, boilerplate đi tới writer, mọi lời gọi agent đều đặt model. Lựa chọn thô bạo cũng tồn tại: hai biến môi trường ép một model duy nhất lên mọi subagent. Giới hạn thẳng thắn là reader là một model rẻ hơn, nên những gì nó trả về là tất cả những gì model chính biết. Phần đo đạc sẽ bàn về điều đó.

Dựng lại, phần hai: deny theo định dạng hook hiện hành

Hãy nhớ từ "block". Script của Spotify trả về một quyết định ở cấp cao nhất, nhưng tài liệu Claude Code hiện tại nói khác: một hook PreToolUse trả quyết định của nó bên trong một object output dành riêng cho hook, và trường đó tên là permissionDecision. Nó có bốn kết quả, allow, deny, ask và defer, và kết quả cần ở đây là deny. Bất cứ điều gì hook ghi làm lý do đều được hiển thị cho Claude, và nếu nhiều hook cùng trả lời, deny thắng.

Hook đọc dựng lại giữ nguyên ngưỡng 350 và ba ngoại lệ, và thay vì "block" trả về một deny với lý do nêu tên subagent Explore và model cần dùng. Một bẫy mà tài liệu nói rõ: hook trong settings của bạn cũng chạy bên trong subagent. Không có lối thoát, reader Haiku bị từ chối chính những lần đọc của nó và không bao giờ làm được việc, nên script kiểm tra ai đang gọi và cho hai worker đi qua.

Phần đấu nối là một file settings với ba matcher, Read, Bash và Agent, mỗi cái trỏ tới script của mình, và ngưỡng được đặt làm biến môi trường. Trên thực tế, một lần đọc file 1.090 dòng trả về một lỗi kèm câu đã viết: hãy ủy quyền lần đọc này cho explorer, model Haiku. Việc ủy quyền diễn ra tiếp theo: model chính đếm số dòng trước, gọi explorer với model đặt là Haiku, và các gạch đầu dòng trả về, mỗi dòng kèm một số dòng. Ba lượt, 44 giây.

Câu của Spotify vẫn đúng: việc xếp lớp có nghĩa là hệ thống suy giảm một cách nhẹ nhàng. Hướng dẫn làm việc định tuyến, hook là tấm lưới. Nhưng tấm lưới có lỗ. Một model muốn cả file có thể chia nhỏ nó bằng offset và limit, thứ được đi qua, hoặc đổ nó qua shell bằng một dải sed, thứ hook này không bắt. Phần đo đạc tính cả hai.

Phần đo đạc

Kho mã thử nghiệm là Fastify, web framework của Node: 294 file, 63 trong số đó vượt ngưỡng. Hai bản clone giống hệt nhau, khác biệt duy nhất là thư mục .claude và file luật. Model chính Opus, mặc định của CLI; reader Haiku; writer Sonnet. Phiên một prompt, không có câu hỏi tiếp theo, mỗi kịch bản chạy hai lần cho mỗi cấu hình, tổng cộng mười sáu lần chạy. Bốn kịch bản giống của Spotify: các export của một file lớn, ba file và cách chúng gọi nhau, một file nguồn đối chiếu với test của nó, và một file test mới ghi xuống đĩa từ một file có sẵn.

Kịch bản Context chính, không có Context chính, có Thay đổi Tổng chi phí, không có Tổng chi phí, có Thay đổi Thời gian, không có Thời gian, có Thay đổi
Một file lớn 88.693 51.552 -41,9% $0,139 $0,087 -37,8% 22 s 44 s +100,8%
Ba file 357.166 73.440 -79,4% $0,581 $0,218 -62,4% 52 s 129 s +149,9%
Nguồn với test 303.808 114.136 -62,4% $0,451 $0,374 -17,1% 93 s 125 s +33,6%
File test mới 143.432 121.818 -15,1% $0,295 $0,302 +2,6% 66 s 87 s +32,2%
Cả bốn 223.274 90.236 -59,6% $0,366 $0,245 -33,1% 58 s 96 s +65,3%

Context chính, tức số token mà model đắt tiền thực sự nhìn thấy, là cột đầu tiên đáng quan tâm. Ở câu hỏi ba file nó giảm 79%, và trên cả bốn kịch bản giảm 59,6%. Hóa đơn giảm ít hơn, một phần ba tính chung, vì token của chính reader không miễn phí, và ở tác vụ viết test nhỏ hóa đơn tăng 2,6%. Thời gian đi theo hướng ngược lại: trung bình 58 giây khi không có setup, 96 giây khi có. Ủy quyền lần nào cũng chậm hơn.

Chất lượng là nơi hai cấu hình khác nhau nhiều nhất. Không có setup, model chính đổ file qua shell không có số dòng và tự đếm bằng tay, tạo ra số dòng sai xuyên suốt: một hàm được báo ở dòng 149 thực ra nằm ở dòng 156. Có setup, một trong bốn lần chạy tin ngay tóm tắt của reader và mang theo ba khẳng định sai, một trong số đó là một hàm mà reader nói file route không bao giờ gọi, trong khi nó có gọi, ở dòng 553. Cả bốn file test được sinh ra đều pass, và các hook deny không kích hoạt lần nào trong mười sáu lần chạy: khi có file luật, model chính kiểm tra số dòng và tự ủy quyền lần nào cũng vậy.

Thêm một điều từ các trace: không có luật, model chính không bao giờ dùng tool Read. Nó đọc mọi thứ qua shell, và một lần đọc theo dải qua shell tốn cùng số token và lọt qua hook. Vậy nên bảng của Spotify nói 90; bảng này nói 60 về context và một phần ba về hóa đơn.

Giữ cú chặn. Đừng mong hóa đơn giảm chín mươi.

Ba thứ đáng giữ: một subagent Explore của dự án chạy Haiku, một luật ba dòng trong file hướng dẫn, và hook đọc làm lưới an toàn. Kết quả đo được là giảm 60% context chính, bớt một phần ba hóa đơn, và thêm hai phần ba thời gian chạy.

Trước khi tin hook, hãy sửa hai thứ. Hook chạy bên trong subagent, nên hãy miễn trừ các worker của bạn. Và lỗ hổng shell: hook bash bắt cat, head và tail, nhưng một lần đọc theo dải lọt qua, và model chính đã dùng đúng cách đó khi không có luật.

Những giới hạn của chính Spotify vẫn đứng vững. Bạn không thể ủy quyền việc sửa và không thể ủy quyền việc suy luận; worker đã bỏ sót một lỗi thread-safety mà Claude bắt được trong vài giây, và mỗi lần ủy quyền là một vòng đi về. Những người hoài nghi trên Hacker News cũng đúng ở một điểm: input token không phải là hóa đơn. Output token đắt hơn, và setup này chẳng làm gì cho chúng.

Ai tiết kiệm được phụ thuộc vào cách bạn trả tiền. Trên API, bớt một phần ba. Trên gói Pro hay Max, cùng setup ấy dịch chuyển cửa sổ năm giờ và cửa sổ tuần của bạn, chứ không phải đô la. Cũng hãy để ý ngưỡng: dưới ngưỡng, ủy quyền tốn hơn là tiết kiệm, và trường hợp test 45 dòng là bằng chứng với mức cộng 2,6%. Cuối cùng, trong hai trên tám lần chạy, tóm tắt của reader chứa lỗi, và lượt kiểm chứng của model chính đã bắt được chúng. Bỏ qua lượt đó và những sai sót ấy sẽ đi vào phần sửa của bạn.

Nguồn

Câu hỏi thường gặp

Spotify có thực sự giảm 90% lượng token Claude Code không?
Con số 90% của Spotify là trung bình của ba kịch bản bulk read trong một Java monorepo, tính bằng input token ước lượng bốn ký tự mỗi token, không có điểm chất lượng và không có con số đô la. Dựng lại bằng Claude Code thuần trên Fastify, cùng ý tưởng ấy giảm 59,6% context của model chính và 33% tổng chi phí.
Portal của Spotify là gì và tôi có dùng được nó với Claude Code không?
Portal là cổng lập trình viên nội bộ của Spotify xây trên Backstage; tính năng Modes của nó chạy các agent khai báo trên một runtime tạm thời. Plugin Shunt định tuyến Claude Code tới các agent đó công khai trên GitHub, nhưng nó xác thực với một instance Portal mà bạn không có, nên bạn chỉ có thể sao chép mô hình chứ không chạy được plugin.
Làm sao để Claude Code ủy quyền việc đọc file lớn cho một model rẻ hơn?
Tạo một subagent của dự án tên là Explore với trường model đặt là Haiku, nó sẽ ghi đè agent Explore tích hợp vốn giờ đây kế thừa model chính của bạn. Thêm một luật ba dòng vào file hướng dẫn của dự án (file trên 350 dòng đi tới explorer, boilerplate đi tới writer, mọi lời gọi agent đều đặt model) và một hook PreToolUse trên Read từ chối những lần đọc lớn với lý do nêu tên subagent đó.
Hook PreToolUse chặn một lời gọi tool trong Claude Code hiện nay như thế nào?
Hook trả quyết định của nó bên trong object hookSpecificOutput, trong một trường tên là permissionDecision, với bốn giá trị có thể: allow, deny, ask và defer. Chuỗi lý do được hiển thị cho Claude, và khi nhiều hook cùng trả lời, deny thắng. Script của Spotify dùng một quyết định ở cấp cao nhất kiểu cũ tên là block.
Ủy quyền việc đọc cho một subagent Haiku có làm Claude Code rẻ hơn không?
Trên API, nó bớt một phần ba hóa đơn trên bốn kịch bản, nhưng token của chính reader không miễn phí: ở một tác vụ viết test 45 dòng, tổng chi phí tăng 2,6%. Trên gói Pro hay Max, khoản tiết kiệm thể hiện dưới dạng hạn mức trong cửa sổ năm giờ và cửa sổ tuần chứ không phải đô la, và output token không hề thay đổi.
Vì sao hook của Claude Code lại chạy bên trong subagent?
Hook định nghĩa trong settings của bạn chạy cho mọi agent, kể cả các subagent bạn điều phối. Vì vậy một hook chặn đọc sẽ từ chối chính những lần đọc của reader Haiku, trừ khi script kiểm tra ai đang gọi và cho các worker agent đi qua.

Video liên quan