Để AI agent viết cả một dự án thì bắt đầu rất dễ, nhưng nhìn lại để đánh giá thì khó. Câu hỏi có ích không phải là code có chạy không, mà là phần nào của quy trình để lại một bản ghi mà sáu tháng sau bạn vẫn tin được. Bài này nhìn lại một website nhỏ mình làm bằng coding agent theo BMAD Method, bản 6 ở thời điểm tháng 4/2026. Ở bản đó, đây là một quy trình dẫn agent đi từ brainstorming tới PRD, kiến trúc, epic và story, rồi code và review từng story. Cuối bài là một orchestrator nhỏ mình viết sau đó để chạy vòng lặp này mà không cần mình ngồi trông.
Website là một trang catalogue tĩnh cho một xưởng đồ gỗ nhỏ: Astro, kèm một CMS dựa trên Git để chủ xưởng tự thêm sản phẩm mà không cần đụng tới code. Phần lên kế hoạch mất hai ngày vào tháng 4/2026, phần code mất bốn ngày. Mọi thứ bên dưới lấy từ các file mà quy trình để lại trong repo, không phải từ trí nhớ.
Giai đoạn lên kế hoạch tạo ra những gì
BMAD chạy như một chuỗi "workflow" của agent, mỗi workflow viết một file Markdown để workflow sau đọc. Với trang này, chuỗi đó là:
| Tài liệu | Số từ |
|---|---|
| Buổi brainstorming | 4.120 |
| Product brief | 3.721 |
| PRD | 4.200 |
| Đặc tả thiết kế UX | 9.897 |
| Kiến trúc | 6.250 |
| Epic và story | 6.033 |
| Báo cáo sẵn sàng triển khai | 4.452 |
| Project context cho agent | 1.837 |
Tổng cộng khoảng 40.500 từ (đếm bằng wc -w), chưa kể một tài liệu nghiên cứu thị trường, cho một trang có 31 story chia trong 8 epic. Báo cáo sẵn sàng triển khai là bước một agent kiểm xem mọi yêu cầu trong PRD đều thuộc một epic nào đó, và đặc tả UX khớp với kiến trúc. Báo cáo kết thúc bằng kết luận đạt (pass).
Đó là rất nhiều chữ cho một trang catalogue, và phần lớn chưa từng được người đọc lại lần nào. Hai file liên tục chứng minh giá trị lại là hai file ngắn nhất: project context và các file story riêng lẻ.
File project context là trang có ích nhất
project-context.md là danh sách quy tắc viết cho agent, không phải cho người: 95 quy tắc, chia theo stack, ngôn ngữ, framework, test, phong cách code, quy trình và một danh sách "đừng bỏ sót". Đó là những chi tiết agent dễ làm sai nhất vì dữ liệu huấn luyện của nó nói khác:
- **Framework:** Astro 6 (SSG-only — no runtime backend, no SSR, no API routes)
- **Content Validation:** Zod 4 (NOT Zod 3 — breaking API differences) schemas in `content.config.ts`
- **Interactive Islands:** Svelte (only ImageGallery component, ~4KB JS — zero-JS-by-default principle)
22 trên 31 file story dẫn nó làm nguồn trong phần Dev Notes. Đây cũng là ý tưởng của file AGENTS.md: một danh sách ngắn các quyết định không hiển nhiên từ code có ích hơn một tài liệu dài giải thích chúng. Chỉ một dòng "Zod 4, không phải Zod 3" đã chặn được cả một nhóm lỗi; phần bàn luận lý do trong tài liệu kiến trúc thì không.
File story mang ngữ cảnh từ story này sang story sau
File story nào cũng cùng một khuôn: user story, tiêu chí chấp nhận, danh sách task, rồi Dev Notes viết lúc tạo story, cuối cùng là bản ghi do agent code story đó điền vào. Hai mục trong Dev Notes làm phần lớn công việc:
- "Previous Story Intelligence": những gì các story trước trong cùng epic đã chốt, để agent không phải suy ra lại hay làm ngược lại. Ví dụ story về deploy mở đầu bằng một mục đối chiếu với story dựng server ngay trước nó.
- "Anti-Patterns": những gì không được làm trong story này, nói thẳng.
Vì mỗi story bắt đầu một phiên agent mới, các ghi chú này là trí nhớ duy nhất của agent. Chúng cũng là tài liệu tốt nhất của dự án: một năm sau, file story giải thích vì sao một component tồn tại rõ hơn chính code của nó.
Cái giá là lịch sử nằm ở đó chứ không nằm trong git. 19 trên 56 commit của tháng 4 có tên feat: story, phần lớn nối tiếp nhau. git log không nói gì cả; bạn phải biết cần mở file story nào.
Review bắt được lỗi thật
Sau khi code xong một story, một workflow review riêng đọc diff và ghi các phát hiện ngược vào file story, xếp mức cao, trung bình hoặc thấp. Định dạng mỗi story một kiểu (checklist, bảng, dòng "Fixed N issues") và không phải story nào cũng có phần review. Vì vậy mình không đưa ra tổng chính xác: trên các story có hàng chục phát hiện, phần lớn đã được sửa. Một số là chuyện văn phong code, nhưng một số là lỗi lẽ ra đã lên production:
- URL ảnh Open Graph và JSON-LD bị ghép thừa một đoạn
./, nên link chia sẻ và dữ liệu có cấu trúc trỏ tới ảnh không tồn tại. - Một race condition trong lightbox xem ảnh, được sửa bằng cách thay một mẹo dùng
requestAnimationFramebằng$effectcủa Svelte. - Nhãn danh mục bị lặp ở ba component; lần sửa đầu bỏ sót một chỗ, và vòng review thứ hai bắt được.
Một lượt review ở phiên riêng, không có trí nhớ về việc viết code, sẽ thấy những thứ khác với người viết. Điều đó đúng với agent cũng như với người.
Những mục bị hoãn trở thành vĩnh viễn
Checklist review có một lối thoát: một mục có thể được hoãn, thường vì sửa nó nằm ngoài phạm vi của story. Rốt cuộc có khoảng một chục mục bị hoãn hoặc được ghi rõ là không sửa. Mục quan trọng nhất được xếp mức cao (rút gọn từ file story, vốn viết lẫn tiếng Việt và tiếng Anh):
Migrate images schema
z.string()→z.image()to enable Astro<Image>component, responsive srcset, WebP/AVIF conversion, LQIP blur. (Breaking change, deferred to dedicated story.)
Story riêng đó không bao giờ được tạo. Project context mình duyệt hứa ảnh WebP/AVIF tạo lúc build, srcset theo kích thước màn hình và ảnh mờ giữ chỗ, còn schema mình đưa lên lại khai báo ảnh là z.string(), nên lời hứa đó vẫn đang chờ story của nó. Đây là mục đầu tiên trong kế hoạch cho giai đoạn tiếp theo của trang. Hoãn một mục là đẩy quyết định ra khỏi story, và không có bước nào trong quy trình đưa nó quay lại, trừ khi có người biến các mục hoãn thành story.
Chuyện tương tự xảy ra ở quy mô lớn hơn. Epic nào cũng kết thúc bằng một buổi retrospective tuỳ chọn. Mình bỏ qua cả tám, và chúng vẫn ghi optional trong file sprint, nên bài học của epic này không bao giờ chảy sang epic sau.
Kế hoạch đổi, tài liệu thì không
Hai phần của kiến trúc không trụ được khi gặp thiết lập thật:
- Đăng nhập CMS đổi cách làm giữa chừng, khi hoá ra backend GitHub của CMS cần một luồng OAuth riêng. File story của cách làm ban đầu vẫn ghi đã xong; project context vẫn mô tả cách cũ.
- Deploy được thiết kế là một pipeline riêng cho đúng trang này. Sáu tháng sau mình chuyển nó sang cùng kiểu image build trên CI như các dự án khác, còn các story mô tả pipeline ban đầu vẫn đọc như thể đang đúng.
Cả hai thay đổi đều không phải lỗi của agent. Kế hoạch thì luôn đổi. Nhưng 40.500 chữ kế hoạch chỉ là tài sản khi chúng còn đúng, và quy trình không có bước nào cập nhật chúng về sau. Tài liệu kế hoạch do agent viết cũ đi y như tài liệu do người viết, chỉ nhanh hơn, vì có nhiều hơn.
Chạy vòng lặp mà không cần mình
Với một dự án sau đó, một app quản lý thời gian kiểu local-first, mình viết một orchestrator nhỏ. Nó đọc file trạng thái sprint và chạy workflow kế tiếp cho từng story qua CLI của opencode (bản rút gọn):
const DISPATCH: Record<string, Action> = {
backlog: { name: "create-story", prompt: (k) => `load skill bmad-create-story and create story for ${k} from epics` },
"ready-for-dev": { name: "dev-story", prompt: (k) => `load skill bmad-dev-story and implement story ${k} from its story file ...` },
// "in-progress" resumes the same story
review: {
name: "review",
prompt: (k) => `load skill bmad-code-review and review story ${k}. YOLO MODE: set yolo=true. ... Do not HALT or wait for user input. Auto-apply all patches. Auto-resolve decision-needed to defer. ...`,
},
};
Mỗi lần chạy có timeout một giờ, và một lần chạy kết thúc mà trạng thái story không tiến lên thì bị đánh dấu thất bại và không chạy lại. Config có tham số maxRetry, nhưng chưa có đoạn code nào đọc nó. Quy tắc cuối đó quan trọng: agent có thể báo đã xong mà chưa làm, và file trạng thái là phép kiểm mà nó không "nói khéo" để qua được.
Prompt review cho thấy rõ sự đánh đổi. Muốn chạy không người trông thì review không bao giờ được dừng lại để hỏi, nên mọi quyết định cần đến người đều được giải quyết bằng "hoãn". Tự động hoá gạt con người ra khỏi đúng những quyết định cần con người. Danh sách mục còn mở của dự án đầu cho thấy những quyết định đó rốt cuộc nằm ở đâu: trong một checklist không ai mở lại.
Giữ gì, đổi gì
- Giữ file project context, và giữ cho nó ngắn. Đó là phần rẻ nhất mà hiệu quả nhất.
- Giữ file story có ghi chú về các story trước. Đó là trí nhớ của agent và là tài liệu của dự án.
- Giữ một lượt review riêng. Nó tìm ra lỗi mà phiên code không thấy.
- Đổi mục bị hoãn thành story một cách tự động, hoặc không cho đóng epic khi còn mục mức cao chưa xử lý.
- Đổi commit message để ghi mã story, cho
git logvà file story trỏ được tới nhau. - Cắt phần kế hoạch xuống còn những gì sẽ được đọc lại. Với một trang cỡ này, mình sẽ bắt đầu từ PRD và epic, và chỉ viết đặc tả UX 9.900 chữ nếu các story liên tục cần tới nó.
Tóm tắt
| Phần của quy trình | Đánh giá |
|---|---|
| Quy tắc project context cho agent | Có ích nhất tính trên mỗi chữ |
| File story có ghi chú về story trước | Trí nhớ tốt giữa các phiên, tài liệu tốt |
| Workflow review riêng | Bắt được lỗi thật |
| Mục review bị hoãn | Không bao giờ quay lại nếu không có người |
| Retrospective để tuỳ chọn | Không bao giờ chạy |
| Tài liệu kế hoạch lớn | Đúng lúc đầu, lỗi thời sau thay đổi đầu tiên |
| Điều phối không người trông | Chạy được, nhưng biến mọi quyết định cần cân nhắc thành một mục hoãn |
Nếu bạn từng cho agent chạy theo một quy trình có cấu trúc như thế này, mình rất muốn được trao đổi xem bạn đã giữ lại và bỏ đi những gì. Email của mình ở trang chủ.