Prompt Caching Là Tất Cả Khi Xây Claude Code
Điểm chính
- Claude Code được thiết kế quanh prompt caching từ đầu, nên thứ bạn làm với thứ tự prompt, tool và message ảnh hưởng trực tiếp tới latency lẫn cost.
- Cache là prefix match: chỉ cần đổi một phần trong prefix là bạn có thể làm vỡ toàn bộ phần cache phía sau.
- Các thao tác như đổi model, đổi tool giữa session, hay compact context đều cần được thiết kế theo cách cache-safe.
Nghe thì có vẻ như prompt caching chỉ là một tối ưu kỹ thuật nhỏ. Nhưng với một agent sản phẩm như Claude Code, nó gần như là nền móng của cả hệ thống.
Prompt caching giúp Claude Code tái sử dụng computation từ các lượt gọi trước, nhờ đó giảm đáng kể độ trễ và chi phí. Quan trọng hơn, cache hit rate cao còn cho phép hệ thống tạo ra rate limit thoải mái hơn cho các gói subscription. Vì thế, đội ngũ Claude Code theo dõi cache hit rate như một chỉ số vận hành thật sự, và xem cache break như một sự cố cần chú ý.
Sắp xếp prompt để cache hoạt động tốt nhất
Prompt caching dựa trên prefix matching. API sẽ cache mọi thứ từ đầu request cho tới từng điểm ngắt cache_control. Điều đó có nghĩa là thứ tự bạn đặt nội dung trong prompt quan trọng hơn rất nhiều so với nhiều người vẫn nghĩ.
Cách tốt nhất là để nội dung tĩnh ở trước, nội dung động ở sau. Với Claude Code, thứ tự lý tưởng trông như thế này:
- System prompt tĩnh và tools, được cache toàn cục
CLAUDE.md, được cache trong phạm vi project- Session context, được cache trong phạm vi session
- Conversation messages
Cách này giúp nhiều session khác nhau dùng chung cache hit tối đa có thể.
Nhưng nó cũng rất dễ bị phá. Claude Code đã từng làm vỡ thứ tự này vì nhiều lý do tưởng nhỏ mà hóa ra rất đắt, như: đưa timestamp quá chi tiết vào system prompt tĩnh, sắp xếp định nghĩa tool theo thứ tự không ổn định, hoặc cập nhật tham số của tool, ví dụ danh sách agent mà Agent tool có thể gọi.
Dùng messages để cập nhật thay vì sửa prompt
Có những lúc thông tin trong prompt đã lỗi thời. Ví dụ, thời gian đã đổi, hoặc người dùng vừa sửa một file. Phản xạ tự nhiên là cập nhật luôn prompt. Nhưng làm vậy sẽ tạo cache miss và có thể khiến người dùng tốn thêm chi phí không cần thiết.
Thay vào đó, hãy xem liệu bạn có thể đẩy thông tin đó vào messages của lượt tiếp theo hay không. Trong Claude Code, nhóm phát triển thêm thẻ <system-reminder> vào user message kế tiếp hoặc tool result để truyền thông tin cập nhật cho model, nhưng vẫn giữ được cache.
Đừng đổi model giữa session
Prompt cache là riêng theo từng model, nên toán học của caching trở nên khá phản trực giác.
Ví dụ, nếu bạn đã đi 100k token vào một conversation với Opus và muốn hỏi một câu khá dễ, thì đổi sang Haiku thực ra có thể đắt hơn để Opus trả lời luôn. Lý do là bạn phải xây lại prompt cache cho Haiku từ đầu.
Nếu thật sự cần đổi model, cách tốt nhất là dùng subagent. Cụ thể, bạn có thể để Opus chuẩn bị một “hand-off” message cho model khác về task cần làm. Claude Code làm điều này khá thường xuyên với Explore agents, vốn dùng Haiku.
Không bao giờ thêm hoặc bớt tool giữa session
Thay đổi bộ tool trong giữa một conversation là một trong những cách phổ biến nhất làm vỡ prompt caching. Về trực giác, bạn có thể nghĩ rằng model chỉ nên thấy những tool nó cần ngay lúc đó. Nhưng vì tool là một phần của cached prefix, nên chỉ cần thêm hoặc bỏ một tool là cả conversation có thể mất cache.
Dùng Plan Mode để thiết kế quanh cache
Plan Mode là một ví dụ rất hay về việc thiết kế tính năng xoay quanh ràng buộc caching.
Cách làm trực giác có thể là: khi người dùng vào plan mode thì đổi bộ tool sang chỉ còn các read-only tools. Nhưng như vậy sẽ làm vỡ cache.
Thay vào đó, Claude Code giữ toàn bộ tool trong request mọi lúc và dùng EnterPlanMode và ExitPlanMode như chính các tool. Khi người dùng bật Plan Mode, agent nhận một system message giải thích rằng nó đang ở Plan Mode, cần khám phá codebase, không được sửa file, và phải gọi ExitPlanMode khi xong kế hoạch. Định nghĩa tool không bao giờ đổi.
Điểm cộng nữa là vì EnterPlanMode là một tool mà model có thể tự gọi, nó có thể tự chuyển sang plan mode khi nhận ra một vấn đề khó, mà không cần làm vỡ cache.
Dùng tool search để defer thay vì remove
Nguyên tắc tương tự cũng áp dụng cho tool search của Claude Code. Hệ thống có thể load hàng chục MCP tool, và nếu đưa tất cả vào mỗi request thì sẽ rất tốn. Nhưng nếu bỏ bớt tool giữa conversation, cache sẽ bị phá.
Giải pháp là defer_loading. Thay vì remove tool, hệ thống gửi các stub nhẹ — chỉ gồm tên tool và defer_loading: true — để model có thể “khám phá” bằng tool search khi cần. Schema đầy đủ chỉ được load khi model chọn tool đó. Như vậy cached prefix vẫn ổn định vì các stub luôn xuất hiện theo cùng một thứ tự.
Bạn cũng có thể dùng tool search qua API để đơn giản hóa cách này.
Compaction mà không làm vỡ cache
Khi context window đầy, Claude Code fork một cached call để tóm tắt conversation, rồi tiếp tục bằng summary thay cho các message cũ.
Compaction là chuyện xảy ra khi bạn chạm trần context window. Hệ thống sẽ tóm tắt phần hội thoại đã có rồi tiếp tục một session mới với bản tóm tắt đó.
Nhưng compaction rất dễ bị làm sai nếu bạn không để ý tới prompt caching. Để compact một conversation, bạn phải gửi toàn bộ conversation lên model để nó viết summary. Cách đơn giản nhất là gọi một API riêng với system prompt khác, kiểu “summarize this”, và không gắn tool nào. Vấn đề là đó lại chính là cái bẫy chi phí. Prompt caching chỉ áp dụng khi prefix của request khớp byte-for-byte với phần đã cache từ trước. Conversation chính của bạn được cache dưới một system prompt và một bộ tool; còn lời gọi tóm tắt lại dùng system prompt khác và không có tool, nên prefix diverge ngay từ token đầu tiên và không có cache nào được dùng lại. Kết quả là bạn phải trả full uncached input rate cho cả conversation dài mà mình đang gửi vào — và càng dài, tức là càng cần compaction, thì lần gọi đó càng đắt.
Cách giải là cache-safe forking
Khi chạy compaction, Claude Code dùng đúng cùng system prompt, user context, system context và tool definitions như conversation cha. Hệ thống prepend toàn bộ message của parent rồi append compaction prompt như một user message mới ở cuối.
Từ góc nhìn của API, request này gần như giống hệt request cuối của parent: cùng prefix, cùng tools, cùng lịch sử. Vì vậy cached prefix được tái sử dụng, và token mới chỉ là phần compaction prompt.
Điều đó cũng có nghĩa là cần giữ một “compaction buffer” để đảm bảo còn đủ chỗ trong context window cho compact message và các token output của bản tóm tắt.
Compaction là phần khó, nhưng may là bạn không cần tự học hết từ đầu. Dựa trên những gì Claude Code học được, phần này đã được đưa thẳng vào API, để bạn có thể áp dụng các pattern đó trong ứng dụng của mình.
Những bài học rút ra
Đội ngũ Claude Code đúc kết vài pattern rất hữu ích khi tối ưu prompt caching cho agent:
- Prompt caching là prefix match. Chỉ cần đổi bất kỳ chỗ nào trong prefix là mọi thứ phía sau đều mất cache. Hãy thiết kế toàn bộ hệ thống xoay quanh ràng buộc này.
- Dùng messages thay vì sửa system prompt. Những việc như vào plan mode hay cập nhật ngày tháng nên được đưa vào messages trong conversation thay vì sửa trực tiếp system prompt.
- Đừng đổi tool hoặc model giữa conversation. Hãy dùng tool để biểu diễn state transition, và defer loading tool thay vì remove chúng.
- Theo dõi cache hit rate giống như theo dõi uptime. Cache break nên được xem như incident, vì chỉ vài phần trăm cache miss cũng có thể kéo cost và latency lên rất mạnh.
- Các thao tác fork cần dùng cùng prefix với parent. Nếu cần chạy một tính toán phụ như compaction, summarization hay skill execution, hãy giữ tham số cache-safe giống nhau để còn ăn cache từ parent.
Claude Code được xây quanh prompt caching ngay từ ngày đầu. Nếu bạn đang xây agent, đây cũng nên là cách bạn thiết kế hệ thống của mình.
Kết luận
Prompt caching không phải chi tiết phụ. Với agent dài hơi, nó là thứ quyết định liệu sản phẩm có đủ nhanh, đủ rẻ và đủ ổn định để dùng ở quy mô lớn hay không.
Bài học quan trọng nhất ở đây là: đừng xem cache như một lớp tối ưu gắn thêm sau cùng. Hãy thiết kế prompt, messages, tools, model routing và compaction theo cách cache-safe ngay từ đầu.
Làm đúng điều đó, bạn sẽ tránh được rất nhiều chi phí ẩn — và có một hệ thống agent vừa nhanh hơn, vừa dễ vận hành hơn.
Bình luận