Đội càng lớn, quản lý thông tin và ngân sách càng quan trọng
Khi có 4 agent chạy qua nhiều task, hai vấn đề nảy sinh: (1) thông tin bị trôi — agent quên ràng buộc từ task trước; (2) chi phí phình to — mỗi lượt gọi nhồi cả lịch sử dài. Bài này bàn cách xây bộ nhớ chung gọn và kiểm soát token.
Ba tầng thông tin
Tách rõ thông tin thành ba tầng, chỉ nạp đúng thứ mỗi agent cần:
- Bất biến (project memory): quy ước code, kiến trúc, tiêu chuẩn bảo mật. Ngắn, ổn định, đưa vào system prompt.
- Trạng thái task (shared board): task nào xong, diff hiện tại, issue mở. Dạng cấu trúc, cập nhật liên tục.
- Ngữ cảnh tức thời: chỉ diff + issue của task đang làm. Vứt bỏ sau khi xong.
{
"project_memory": {"lang":"python","style":"pep8","rule":"no plaintext secret"},
"board": {
"T1": {"status":"done"},
"T2": {"status":"in_review","open_issues":1}
}
}
Nguyên tắc chống trôi context
- Không truyền toàn bộ lịch sử chat. Truyền bản tóm tắt trạng thái từ board.
- Tóm tắt sau mỗi task: ghi lại quyết định quan trọng ("đã chọn hash bằng bcrypt") vào memory để task sau không mâu thuẫn.
- Neo lại ràng buộc trong mỗi prompt quan trọng (nhắc lại 2-3 rule cốt lõi), vì agent dễ quên khi context dài.
Các bước xây bộ nhớ chung
- Tạo một "board" dạng JSON/DB lưu trạng thái mọi task.
- Viết hàm
context_for(role, task)chỉ trả về đúng thông tin vai trò cần. - Sau mỗi task, chạy một bước tóm tắt: cập nhật memory bằng quyết định mới.
- Đặt ngân sách token cho mỗi task; nếu vượt, dừng và escalate.
- Đo và log token theo từng vai trò để biết ai "ngốn" nhất.
def context_for(role, task, board, memory):
base = memory["project_memory"]
if role == "coder":
return {"rules": base, "task": task, "feedback": task.get("issues")}
if role == "reviewer":
return {"rules": base, "task": task, "diff": board[task["id"]]["diff"]}
...
Kiểm soát chi phí
- Dùng model rẻ cho vai trò dễ, model mạnh cho vai trò khó: ví dụ Reviewer/Planner cần suy luận sâu dùng model mạnh; định dạng/tóm tắt dùng model rẻ.
- Cache phần bất biến: project memory giống nhau mọi lượt → tận dụng prompt caching.
- Giới hạn độ dài diff truyền đi; nếu quá lớn, đó là dấu hiệu task chia chưa đủ nhỏ (quay lại Bài 4).
Khung tư duy: "Agent này cần biết TỐI THIỂU những gì?"
Với mỗi lượt gọi, liệt kê thông tin thật sự cần để hành động, rồi cắt phần còn lại. Context tối thiểu = rẻ hơn, nhanh hơn, ít trôi hơn.
Sai lầm thường gặp
- Nhồi toàn bộ lịch sử vào mỗi lượt gọi: chi phí bùng nổ, chất lượng giảm vì nhiễu.
- Không tóm tắt quyết định: task sau mâu thuẫn task trước (task 2 dùng bcrypt, task 5 lại dùng md5).
- Dùng model mạnh nhất cho mọi vai trò: đốt tiền vô ích ở việc dễ.
- Không đo token theo vai trò: không biết tối ưu ở đâu.
- Diff quá lớn: dấu hiệu Planner chia task chưa đạt, cần quay lại sửa gốc.
Trôi context: dấu hiệu nhận ra trước khi nó gây hại
Trôi context không thông báo. Bốn dấu hiệu cụ thể:
| Dấu hiệu | Ví dụ |
|---|---|
| Agent mâu thuẫn quyết định cũ | Task 2 dùng bcrypt, task 5 dùng md5 |
| Agent hỏi lại điều đã được trả lời | "Dự án dùng framework nào?" ở task thứ tám |
| Chất lượng giảm khi task về sau | Task 1–3 tốt, task 7–9 lệch quy ước |
| Chi phí mỗi task tăng dần | Dấu hiệu lịch sử đang bị nhồi vào mỗi lượt |
Sổ quyết định: cấu trúc tối thiểu
"Tóm tắt sau mỗi task" cần một hình thức cố định, kẻo nó thành một khối văn bản không ai đọc được. Bốn cột:
| Cột | Ví dụ |
|---|---|
| Quyết định | Băm mật khẩu bằng bcrypt, cost 12 |
| Vì sao | Chuẩn của đội; argon2 chưa có trong môi trường |
| Phạm vi ràng buộc | Mọi chỗ xử lý mật khẩu |
| Task nào quyết | T-02 |
Sổ này nên ngắn và có giới hạn cứng — ví dụ tối đa 30 dòng. Khi đầy, phải hợp nhất, không được nối thêm. Một sổ quyết định 300 dòng bằng với không có sổ, vì nó không vào được prompt.
Chọn model theo vai trò: bảng cụ thể
| Vai trò | Model | Vì sao |
|---|---|---|
| Planner, Reviewer | Mạnh | Suy luận nhiều bước, đánh đổi kiến trúc |
| Coder | Trung–mạnh | Cần đúng, nhưng có test làm lưới |
| Tester | Trung | Sinh test theo mẫu |
| Định tuyến, phân loại, tóm tắt | Rẻ | Việc cơ học, có thể kiểm bằng cấu trúc |
Diff quá lớn là một tín hiệu về Planner
Nhấn lại ý ở cuối bài vì nó là ý dễ bỏ: nếu diff của một task lớn tới mức phải cắt bớt khi truyền đi, vấn đề không ở tầng ngữ cảnh. Nó ở Planner — task chia chưa đủ nhỏ.
Đặt một ngưỡng cứng và coi việc vượt ngưỡng là lỗi của bước lập kế hoạch: "Task nào cho diff trên 300 dòng được trả về Planner để chia lại, không được xử lý bằng cách nén ngữ cảnh." Nén ngữ cảnh ở đây là chữa triệu chứng, và nó làm Reviewer đánh giá trên thông tin thiếu. <!--/les-append-->