Sử dụng Claude Code: Session management & 1M token context window

Trong các cuộc trao đổi gần đây của tôi với người dùng Claude Code, có một chủ đề liên tục được nhắc đến: 1M token context window là một con dao hai lưỡi.

Nó cho phép Claude Code hoạt động tự chủ lâu hơn và xử lý các tác vụ đáng tin cậy hơn, nhưng đồng thời cũng dẫn đến nguy cơ context pollution nếu bạn không chủ động quản lý các phiên làm việc của mình.

Session management quan trọng hơn bao giờ hết và dường như có rất nhiều câu hỏi xoay quanh vấn đề này. Bạn nên duy trì một phiên mở trong terminal, hay hai phiên? Bắt đầu mới với mỗi câu lệnh? Khi nào bạn nên sử dụng compact, rewind, hoặc subagents? Điều gì dẫn đến một quá trình compact không hiệu quả?

Có một lượng lớn chi tiết kỹ thuật ở đây có thể định hình trải nghiệm của bạn với Claude Code và hầu hết chúng đều xuất phát từ việc quản lý ngữ cảnh của bạn.

Sơ lược về Ngữ cảnh, Compaction & Context rot

Ngữ cảnh là tất cả những gì mô hình có thể “nhìn thấy” tại một thời điểm khi tạo ra phản hồi tiếp theo. Nó bao gồm system prompt của bạn, cuộc hội thoại cho đến hiện tại, mọi tool call và kết quả đầu ra của nó, cùng mọi tệp đã được đọc. Claude Code có cửa sổ ngữ cảnh lên tới một triệu tokens.

Đáng tiếc là việc sử dụng ngữ cảnh đi kèm với một chi phí nhỏ, thường được gọi là Context rot. Context rot là hiện tượng hiệu suất của mô hình bị suy giảm khi ngữ cảnh tăng lên vì sự chú ý bị phân tán qua nhiều tokens hơn, và những nội dung cũ, không còn liên quan bắt đầu làm xao nhãng khỏi tác vụ hiện tại. Đối với mô hình 1MM ngữ cảnh của chúng tôi, chúng tôi thấy một mức độ Context rot nhất định xảy ra ở khoảng ~300-400k tokens, nhưng điều này phụ thuộc nhiều vào tác vụ chứ không phải là một quy tắc cố định.

Cửa sổ ngữ cảnh có một giới hạn cứng, vì vậy khi bạn gần đạt đến giới hạn này, bạn sẽ cần tóm tắt tác vụ đang thực hiện thành một mô tả ngắn hơn và tiếp tục công việc trong một cửa sổ ngữ cảnh mới, chúng tôi gọi đây là compaction. Bạn cũng có thể tự kích hoạt compaction.

Mỗi lượt hội thoại là một điểm rẽ nhánh

Giả sử bạn vừa yêu cầu Claude thực hiện một việc gì đó và nó đã hoàn thành, bây giờ bạn có một số thông tin trong ngữ cảnh (các tool call, kết quả đầu ra, hướng dẫn của bạn) và bạn có rất nhiều lựa chọn cho bước tiếp theo:

  • Continue — gửi một tin nhắn khác trong cùng một phiên
  • /rewind (esc esc) — quay lại tin nhắn trước đó và thử lại từ điểm đó
  • /clear — bắt đầu một phiên mới, thường là với một tóm lược ngắn gọn bạn đã đúc kết từ những gì vừa học được
  • Compact — tóm tắt phiên làm việc hiện tại và tiếp tục dựa trên bản tóm tắt đó
  • Subagents — giao phần việc tiếp theo cho một tác nhân với ngữ cảnh sạch riêng, và chỉ lấy kết quả cuối cùng về

Mặc dù cách tự nhiên nhất là tiếp tục, bốn lựa chọn còn lại tồn tại để giúp bạn quản lý ngữ cảnh của mình.

Khi nào nên bắt đầu một phiên mới

Cửa sổ ngữ cảnh 1M mới có nghĩa là giờ đây bạn có thể thực hiện các tác vụ dài hơn một cách đáng tin cậy hơn, ví dụ như yêu cầu nó xây dựng một full-stack app từ đầu. Nhưng chỉ vì mô hình của bạn chưa hết ngữ cảnh, không có nghĩa là bạn không nên bắt đầu một phiên mới.

Nguyên tắc chung của chúng tôi là khi bạn bắt đầu một tác vụ mới, bạn cũng nên bắt đầu một phiên mới.

Một trường hợp trung gian là khi bạn muốn thực hiện các tác vụ liên quan mà một số phần ngữ cảnh vẫn cần thiết, nhưng không phải tất cả.

Ví dụ, việc viết tài liệu cho một tính năng bạn vừa triển khai. Mặc dù bạn có thể bắt đầu một phiên mới, Claude sẽ phải đọc lại các tệp mà bạn vừa thực hiện, điều này sẽ chậm hơn và tốn kém hơn. Vì viết tài liệu có thể không phải là một tác vụ nhạy cảm về trí tuệ ở mức cao, nên phần ngữ cảnh dư thừa có lẽ xứng đáng với hiệu quả đạt được từ việc không phải đọc lại các tệp liên quan.

Sử dụng Rewind thay vì Sửa lỗi trực tiếp

Nếu tôi phải chọn một thói quen cho thấy khả năng quản lý ngữ cảnh tốt, đó là rewind.

Trong Claude Code, việc nhấn đúp Esc (hoặc chạy lệnh /rewind) cho phép bạn nhảy ngược lại bất kỳ tin nhắn nào trước đó và yêu cầu lại từ đó. Các tin nhắn sau điểm đó sẽ bị loại bỏ khỏi ngữ cảnh.

Rewind thường là cách tiếp cận tốt hơn để điều chỉnh. Ví dụ, Claude đọc năm tệp, thử một phương pháp và nó không hiệu quả. Bản năng của bạn có thể là nhập “cách đó không hiệu quả, hãy thử X thay thế.” nhưng bước đi tốt hơn là rewind về ngay sau khi đọc tệp, và yêu cầu lại với những gì bạn đã học được: “Đừng dùng phương pháp A, foo module không hỗ trợ việc đó — hãy chuyển thẳng sang B.”

Bạn cũng có thể sử dụng “summarize from here” để yêu cầu Claude tóm tắt những gì nó học được và tạo ra một tin nhắn bàn giao, giống như một lời nhắn cho phiên bản trước của Claude từ “bản thân tương lai” đã thử một phương án và thất bại.

Compacting so với Fresh Sessions

Khi một phiên làm việc trở nên quá dài, bạn có hai cách để giảm tải: /compact hoặc /clear (và bắt đầu mới). Chúng có vẻ giống nhau nhưng hoạt động rất khác nhau.

Compact yêu cầu mô hình tóm tắt cuộc hội thoại cho đến hiện tại, sau đó thay thế lịch sử bằng bản tóm tắt đó. Quá trình này có sự thất thoát thông tin, bạn đang tin tưởng để Claude quyết định điều gì quan trọng, nhưng bạn không phải tự viết bất cứ điều gì và Claude có thể kỹ lưỡng hơn trong việc đưa vào các bài học hoặc tệp quan trọng. Bạn cũng có thể điều hướng nó bằng cách đưa ra hướng dẫn (/compact focus on the auth refactor, drop the test debugging).

Với /clear, chính bạn sẽ viết ra những gì quan trọng (“chúng ta đang tái cấu trúc auth middleware, ràng buộc là X, các tệp quan trọng là A và B, chúng ta đã loại bỏ phương pháp Y”) và bắt đầu sạch sẽ. Cách này tốn công hơn, nhưng ngữ cảnh kết quả là những gì bạn đã quyết định là có liên quan.

Điều gì gây ra một quá trình compact kém?

Nếu bạn chạy nhiều phiên làm việc dài hạn, bạn có thể đã nhận thấy những lúc việc compact trở nên đặc biệt tệ. Trong trường hợp này, chúng tôi thường thấy rằng các bản compact không tốt có thể xảy ra khi mô hình không thể dự đoán hướng đi của công việc bạn đang làm.

Ví dụ: autocompact kích hoạt sau một phiên gỡ lỗi dài và tóm tắt quá trình điều tra, sau đó tin nhắn tiếp theo của bạn là “bây giờ hãy sửa lỗi cảnh báo khác mà chúng ta thấy trong  bar.ts.”

Nhưng vì phiên làm việc tập trung vào việc gỡ lỗi, nên cảnh báo kia có thể đã bị loại khỏi bản tóm tắt.

Điều này đặc biệt khó khăn, bởi vì do Context rot, mô hình ở trạng thái kém thông minh nhất khi thực hiện compact. Với một triệu ngữ cảnh, bạn có thêm thời gian để /compact một cách chủ động với mô tả về những gì bạn muốn thực hiện.

Subagents & Cửa sổ ngữ cảnh mới

Subagents là một hình thức quản lý ngữ cảnh, hữu ích khi bạn biết trước rằng một phần công việc sẽ tạo ra nhiều kết quả trung gian mà bạn sẽ không cần dùng lại.

Khi Claude khởi tạo một subagent thông qua Agent tool, subagent đó sẽ có cửa sổ ngữ cảnh mới của riêng nó. Nó có thể thực hiện bao nhiêu công việc tùy ý, sau đó tổng hợp kết quả để chỉ báo cáo cuối cùng được gửi lại cho tác nhân cha.

Tiêu chuẩn đánh giá mà chúng tôi sử dụng: tôi sẽ cần đầu ra của công cụ này lần nữa, hay chỉ cần kết luận?

Mặc dù Claude Code sẽ tự động gọi các subagents, bạn có thể muốn yêu cầu nó làm điều này một cách rõ ràng. Ví dụ, bạn có thể muốn nói với nó:

  • “Khởi tạo một subagent để xác minh kết quả của công việc này dựa trên tệp đặc tả sau”
  • “Khởi tạo một subagent để đọc qua codebase khác này và tóm tắt cách nó triển khai luồng xác thực, sau đó tự mình triển khai theo cùng một cách”
  • “Khởi tạo một subagent để viết tài liệu cho tính năng này dựa trên các git changes của tôi”

Tổng kết

Tóm lại, khi Claude kết thúc một lượt hội thoại và bạn sắp gửi một tin nhắn mới, bạn đang đứng trước một điểm ra quyết định.

Theo thời gian, chúng tôi hy vọng Claude sẽ tự giúp bạn xử lý việc này, nhưng hiện tại đây là một trong những cách bạn có thể điều hướng đầu ra của Claude.

Guest