Một AI agent vạn năng hay chia thành team agent chuyên trách?
Trên máy Ubuntu ở nhà mình hiện có 10 agent, mỗi con một danh tính riêng, một bộ chỉ dẫn riêng, một bộ nhớ riêng. Không có con nào biết làm tất cả mọi việc. Muốn xuất bản một bài blog, việc phải đi qua bốn con: một con ra brief, một con viết, một con soát SEO, một con mở pull request.
Nghe thì rườm rà. Và đúng là nó rườm rà thật — phần cuối bài mình nói kỹ chỗ đó. Nhưng mình vẫn chọn cách này thay vì nhồi tất cả vào một agent vạn năng, và bài này là lý do.
Phần hạ tầng — relay tự host, agent là thành viên có keypair riêng — mình đã viết ở bài về Buzz. Bài này chỉ nói về chuyện chia việc.
Một agent làm tất cả việc thì gãy ở đâu
Ai cũng xuất phát bằng một agent. Mình cũng vậy — mở Claude hoặc ChatGPT ra, giao việc, xong. Không ai dựng cả một team ngay từ đầu, và cũng không nên.
Nỗi đau dễ thấy nhất của cách đó, gói lại trong một câu: một agent thì không có ai phản biện nó.
Ba biểu hiện của cùng một chuyện đó:
Không có review chéo. Nó vừa làm vừa tự chấm bài của chính nó. Người chấm và người bị chấm là một, nên kết quả của việc chấm gần như luôn là “được”.
Không có phản biện. Nó không cãi lại chính nó. Phương án đầu tiên nghĩ ra cũng là phương án cuối cùng, vì không có ai đặt câu hỏi tại sao không làm cách khác.
Không tối ưu được từng khâu. Khi mọi khâu nằm trong cùng một con, bạn chỉnh chỗ này thì lệch chỗ kia. Thêm một dòng để nó viết cẩn thận hơn, thì phần soát lỗi cũng đổi theo. Không cô lập được một khâu ra để mài riêng.
Kết lại là chỗ khó chịu nhất: agent làm thế nào thì mình chấp nhận như thế đó. Không phải vì output tệ — mà vì mình không có cơ sở nào để biết nó tệ hay tốt. Không có con thứ hai nhìn vào.
Chia theo vai và quyền, không chia theo tác vụ
Muốn có phản biện thật thì con soát phải là một con khác thật — khác danh tính, khác bộ nhớ, khác quyền — chứ không phải bảo cùng một agent “giờ đóng vai reviewer, đọc lại bài vừa viết đi”. Nên câu hỏi tiếp theo là chia theo cái gì.
Đây là nguyên tắc mình bám vào. Câu hỏi khi tách một agent mới không phải “việc này có phải một tác vụ riêng không”, mà là “con này được quyền động vào cái gì, và không được động vào cái gì”.
Chia theo tác vụ thì bạn sẽ có agent-viết-mở-bài, agent-viết-kết-bài — vô nghĩa, vì chúng cùng quyền, cùng bối cảnh, chỉ khác đoạn văn.
Chia theo quyền thì khác hẳn. Trong team blog của mình:
- blog-editor được quyền quyết chủ đề, chốt dàn ý, duyệt hoặc bắt sửa. Nhưng nó bị cấm sửa file trong repo. Người ra yêu cầu không phải người thực thi.
- blog-writer chỉ được tạo và sửa file trong
src/content/blog/và ảnh trongpublic/. Không đụng code, không đụng config, không đụng layout. - blog-seo chỉ soát và đề xuất. Nó không tự sửa bài của người khác.
- blog-dev là con duy nhất được
git commit,git push, mở PR và deploy.
Cái hay của ranh giới quyền là nó biến một lỗi tiềm tàng thành một lỗi lộ ra ngay. Nếu blog-writer viết sai frontmatter, nó không thể tự đẩy lên production để rồi build fail trong im lặng — nó phải giao lại cho blog-dev, và blog-dev có checklist riêng cho đúng việc đó.
Một hệ quả mình không lường trước: chia theo quyền làm cho các bản chỉ dẫn ngắn lại. Khi một agent chỉ được đụng vào một thư mục, bạn không cần viết mười dòng cấm nó đụng vào chín thư mục còn lại.
Bản đồ 10 agent hiện tại
Toàn bộ nằm trong một thư mục, mỗi con một folder:
$ ls ~/buzz-relay/agents/
analyst blog-dev blog-editor blog-seo blog-writer
cataloger curator dispatcher sentinel wordsmith
Mỗi con có một bộ skill riêng — skill là quy trình đã viết sẵn cho đúng nghiệp vụ của nó:
| Agent | Skill riêng |
|---|---|
| analyst | kpi-queries |
| blog-dev | ship-post-pr |
| blog-editor | brief-and-review |
| blog-seo | seo-audit-post |
| blog-writer | write-blog-post |
| cataloger | tag-taxonomy |
| curator | review-mockup-batch |
| dispatcher | create-product-gate, enqueue-mockup-job, handle-notify-markers |
| sentinel | final-gate-checklist |
| wordsmith | qa-content-locales |
Bên trong một folder agent trông như thế này:
$ ls -a ~/buzz-relay/agents/blog-writer/
. .. .claude LESSONS.md repo
Ba thứ, mỗi thứ một vai:
.claude/chứa soul (bản chỉ dẫn định nghĩa vai, ranh giới, cách trả lời) vàskills/(quy trình chi tiết cho từng nghiệp vụ).LESSONS.mdlà nơi agent tự ghi bài học mới. Soul và skill là luật, agent không được tự sửa; gặp chuyện mới thì nó append một dòng kèm bằng chứng, để mình xem lại và quyết có nâng thành luật không.repolà symlink trỏ vào repo blog — chỉ các agent blog mới có. analyst thì cóWORK_LOGS/, blog-editor cóPLANS/.
Chú ý dispatcher: nó có ba skill. Chuyên trách không có nghĩa là chỉ làm được một việc — nghĩa là làm mọi việc trong một phạm vi quyền. dispatcher trông giữ hàng đợi job, nên nó cần đủ ba quy trình cho ba tình huống của cùng một phạm vi đó.
Cái giá của kiến trúc multi-agent
Đây là phần các bài ca ngợi multi-agent hay bỏ qua. Chia ra thì phải trả những khoản sau, không có cách nào né:
Phải viết soul cho từng con. Mười agent là mười bản chỉ dẫn phải nghĩ ra, viết, và giữ cho khỏi mâu thuẫn nhau. Đây không phải công việc một lần — sửa ranh giới của một con thường kéo theo phải sửa con đứng cạnh nó trong luồng.
Phải gọi đúng tên đầy đủ. Trong Buzz, mention khớp theo tên hiển thị chính xác của thành viên trong phòng. Mình thử gõ thiếu một chữ để xem chuyện gì xảy ra:
$ echo "test @blog-edito" | buzz messages send --channel <uuid> --content -
{"error":"user_error","message":"mention '@blog-edito' does not match a current channel member; retry with --mention <pubkey>"}
CLI chặn lại, tin nhắn không gửi. Đây là thiết kế đúng — thà hỏng ồn ào còn hơn hỏng im lặng. Nhưng nó vẫn là một khoản phải trả: giao việc cho agent không phải là nói chuyện, mà là gọi đúng một định danh. Sai tên thì việc đơn giản là không tới nơi, và bạn chỉ biết khi quay lại nhìn thấy chưa ai làm gì cả.
Context không tự chia sẻ. Đây là khoản đắt nhất. Mỗi agent là một session riêng; con này không nhìn thấy suy nghĩ của con kia, chỉ thấy những gì được viết ra thành tin nhắn trong phòng. Nên brief phải viết đủ dữ kiện: sai một chi tiết trong brief thì con nhận việc làm sai theo, hoàn toàn tự tin.
Mỗi con một bộ nhớ phải tự bảo trì. Bộ nhớ bền của agent này không giúp gì cho agent kia. Mười agent là mười bộ nhớ phải giữ cho sạch và đúng — quên dọn thì agent hành động theo một trạng thái đã cũ.
Nhiều chặng thì chậm hơn. Một bài blog đi qua bốn agent chắc chắn lâu hơn một agent làm tất, vì mỗi lần bàn giao là một lượt chờ. Đổi lại, mỗi chặng có một con soát bằng con mắt mới. Bạn đang mua chất lượng và khả năng truy vết bằng tốc độ — nếu việc của bạn không cần hai thứ đó thì đây là một vụ mua hớ.
Khi nào đừng chia
Đừng chia khi:
- Việc của bạn không cần ai soát lại. Làm sai thì sửa, sai không mất gì, không có ai khác đọc kết quả ngoài bạn. Đây mới là trường hợp thật sự không cần con thứ hai.
- Các phần việc dùng chung một quyền. Nếu hai “agent” cùng được sửa cùng một thư mục, chúng chỉ là một agent bị tách làm đôi.
- Việc cần đi tới cùng trong một mạch. Bàn giao có giá của nó; một việc ngắn không đủ để bù.
- Bạn chưa viết nổi ranh giới thành câu. Nếu không nói được “con này được đụng vào X, cấm đụng vào Y”, thì bạn chưa hiểu vai đủ rõ để tách.
Ngưỡng mình dùng: chia khi hai phần việc cần hai bộ quyền khác nhau, hoặc khi bạn cần một con khác đọc lại kết quả của con này. Còn khi prompt chỉ đang dài ra mà vẫn nhất quán — đó là dấu hiệu cần cắt bớt chữ, không phải cần thêm agent.
Nói cho gọn: đừng chia vì agent làm nhiều việc. Chia vì nó cần nhiều quyền khác nhau — và vì kết quả của nó cần một con mắt không phải của nó.