DESIGN.md là gì và cách dùng để quản lý AI coding agent
DESIGN.md giúp AI hiểu lý do kiến trúc code tồn tại, ngăn chặn việc tự ý thay đổi cấu trúc hệ thống. Tìm hiểu cách viết file này để tránh lỗi logic khi dùng Claude hay Cursor.
DESIGN.md là gì và những điều AGENTS.md không đề cập
DESIGN.md là một file markdown nằm tại thư mục gốc của repository, giải thích cho AI coding agent lý do tại sao code lại được cấu trúc như hiện tại. AGENTS.md trả lời một câu hỏi khác: cách làm việc tại đây, bao gồm lệnh build, lệnh test, các quy tắc lint bắt buộc phải vượt qua và các đường dẫn cần giữ nguyên. DESIGN.md ghi lại các quyết định đã được chốt và những gì sẽ hỏng nếu một trong số đó bị thay đổi.
Một coding agent, tức là các công cụ như Claude Code hoặc Cursor có khả năng tự đọc và chỉnh sửa repository, mặc định thường rất tự tin. Nó tìm thấy một pattern mà nó không nhận diện được và cố gắng "cải thiện" pattern đó. Một cache tự viết bằng tay có thể bị nó thay thế bằng Redis (một data store chạy trên RAM), vì đó là cách cache thường xuất hiện trong phần lớn code mà model đã học. AGENTS.md không ngăn chặn được việc này vì make test vẫn pass trong cả hai trường hợp. Quy tắc bị phá vỡ vốn chưa từng được ghi lại ở bất kỳ đâu mà agent có thể đọc được.
Nếu bạn chưa viết file đầu tiên, hãy bắt đầu từ đó. AGENTS.md và file HUMAN.md đi kèm bao gồm định dạng và nơi mỗi công cụ tìm kiếm file này. Nội dung dưới đây là chương tiếp theo của phần đó.
Nội dung thực sự bên trong một file DESIGN.md đã xuất bản
Cách nhanh nhất để học định dạng này là đọc các file mà các công ty tự xuất bản về chính họ. Repository official-design-md chỉ theo dõi những file đó. Quy tắc đưa vào của nó chỉ có một dòng, và dòng đó chính là toàn bộ mục đích của bộ sưu tập này:
Every entry here is a DESIGN.md published by the company or project itself — not extracted, not reverse-engineered, not community-made.Tính đến tháng 8 năm 2026, nó liệt kê bảy cái tên: Atlassian, Clerk, Mintlify, Nuxt, Resend, Vercel và VoltAgent. Mỗi file nằm tại một URL công khai ổn định, vì vậy bạn có thể đọc ngay trong terminal.
curl -s https://nuxt.com/design.md | head -n 60
curl -s https://vercel.com/design.md | wc -wCả hai file đó đều là tài liệu về hệ thống thiết kế (design system). Chúng mô tả cách một sản phẩm nên hiển thị: màu sắc, kiểu chữ, khoảng cách, chuyển động. Hãy đọc vượt ra ngoài chủ đề, vì phần hữu ích nằm ở cách viết hơn là nội dung.
File của Nuxt dài khoảng 2.100 từ, và phần lớn trong đó là một quy tắc đi kèm với lý do của nó:
Dark mode is the default theme.
Colors are semantic (`primary`, `neutral`, `error`…) rather than hardcoded hex values in components.
Don't hardcode `#00DC82` in UI code — use `text-primary` or `color="primary"`.File của Vercel dài hơn, khoảng 6.500 từ vào tháng 8 năm 2026, và nó tiến thêm một bước. Một trong các tiêu đề của nó là Reject generated-design reflexes. Bên dưới là danh sách những gì một trình tạo (generator) có năng lực sẽ thực hiện khi không có ai ngăn cản nó:
Hard reject decorative gradients, gradient text, glows, blobs, stripes, textures, grid backgrounds, glass effects, paper simulations, colored side rails, ornamental shadows, and fake depth.Câu đó định nghĩa loại file này. Nó là một danh sách văn bản về các giá trị mặc định mà một model tự tin tạo ra, được xuất bản để model đó ngừng tạo ra chúng. Mọi file DESIGN.md đáng để commit đều là danh sách đó cho một lĩnh vực cụ thể.
Tại sao các công ty lại tự xuất bản file DESIGN.md của riêng họ?
Cộng đồng đã đi trước một bước. awesome-design-md chứa 73 file được reverse-engineer từ các trang web công khai, mỗi file đều được viết theo cùng một định dạng chín phần, nhờ đó một agent có thể được hướng dẫn để tạo ra kết quả gần giống với giao diện đó. Những file này hữu ích nhưng vẫn chỉ là các phỏng đoán. Không ai tại các công ty đó kiểm duyệt chúng.
Một file chính chủ (first-party) khác biệt ở chỗ nó là nguồn gốc thay vì là kết quả đọc từ đầu ra. Khi Vercel thay đổi thang đo kiểu chữ (type scale), vercel.com/design.md cũng thay đổi theo. Một bản copy được thu thập từ tháng Ba vẫn tiếp tục dạy cho agent của bạn thang đo cũ, và không có gì trong repository của bạn báo hiệu rằng bản copy đó đã lỗi thời.
Bảy nhà xuất bản là một con số nhỏ, và bản thân repository cũng đã nêu rõ điều đó: tiêu chuẩn này còn mới và việc áp dụng chính thức đang tăng dần. Cả hai bộ sưu tập đều được duy trì bởi VoltAgent, một framework agent mã nguồn mở cũng tự xuất bản file của riêng mình, vì vậy hãy đọc danh sách này như một công cụ theo dõi thay vì một cuộc điều tra trung lập. Nó vẫn đáng để theo dõi vì danh tính của bảy đơn vị đó. Họ là những công ty có mã front-end được các lập trình viên khác sao chép nhiều nhất, và các file của họ đang trở thành ví dụ điển hình cho việc DESIGN.md là gì. Hãy so sánh với lộ trình mà AGENTS.md đã đi qua: agents.md hiện ghi nhận hơn 60.000 dự án mã nguồn mở sử dụng định dạng này, và quyền quản lý thuộc về Agentic AI Foundation dưới sự bảo trợ của Linux Foundation. Các quy ước cho file mà agent có thể đọc được đang hình thành nhanh chóng, và chúng đang được thiết lập từ trên xuống.
Nội dung của file DESIGN.md khi dự án không có giao diện người dùng
Hầu hết phần mềm chạy trên VPS không có ngôn ngữ hình ảnh để quy định. File này vẫn cần thiết vì cơ chế hoạt động không liên quan đến màu sắc. Nó dùng để ghi lại các ràng buộc mà một người biên tập tự tin có thể vô tình vi phạm.
Các bất biến (Invariants). Mỗi câu một ý, nêu rõ điều gì phải luôn đúng sau bất kỳ chỉnh sửa nào. "Mọi thao tác ghi đều phải thông qua queue.enqueue(). Việc ghi trực tiếp vào database sẽ bỏ qua audit log, trong khi audit log là nguồn dữ liệu cho báo cáo tuân thủ." Một bất biến đi kèm lý do sẽ tồn tại được ngay cả khi bạn gặp phải tác vụ chưa từng dự tính. Một bất biến đứng riêng lẻ chỉ được coi là tùy chọn, và các tùy chọn thường bị tối ưu hóa mất.
Các phương án đã loại bỏ. Phương án hiển nhiên và lý do nó bị loại. "Chúng ta không dùng Redis để cache. Dịch vụ chạy trên một VPS duy nhất, nên in-process map sẽ nhanh hơn và bớt đi một daemon cần duy trì. Hãy xem xét lại khi có server ứng dụng thứ hai." Nếu thiếu đoạn này, một agent được yêu cầu tăng tốc cache sẽ thêm Redis, và nó làm đúng: bạn chưa từng nói cho nó biết ràng buộc đó. Đây là phần giá trị nhất của cả file.
Các ranh giới (Boundaries). Những nơi mà một chỉnh sửa nhỏ có thể gây ảnh hưởng lớn. Schema của database. Tiền tố route công khai mà khách hàng đã viết script dựa vào đó. File cấu hình mà quá trình deploy đọc trước khi ứng dụng khởi động. Cron job giả định rằng chỉ có một bản sao của nó chạy. Hãy liệt kê chúng và nêu rõ chi phí nếu thay đổi từng cái. Nếu agent có thể truy cập Internet, ví dụ thông qua một instance SearXNG tự host được kết nối làm backend tìm kiếm, đó cũng là một ranh giới cần ghi lại. File này nên quy định rõ văn bản nào được phép ảnh hưởng đến code và văn bản nào chỉ được trích dẫn lại cho bạn.
Từ vựng. Nếu code dùng tenant còn team dùng customer, hãy ghi lại bảng ánh xạ. Một agent đoán sai ở đây sẽ tạo ra code đọc thì ổn nhưng lại mô hình hóa sai vấn đề, đây là loại lỗi khó phát hiện nhất khi review.
Một file DESIGN.md bạn có thể sao chép ngay hôm nay
# DESIGN.md
## What this service is
One paragraph. What it does, who calls it, where it runs.
## Invariants
- Every write goes through `queue.enqueue()`. Direct writes skip the audit log.
- Timestamps are stored as UTC integers. Only the display layer converts them.
- One process writes to SQLite. The database is in WAL mode, and a second writer
gets `database is locked` under load.
## Rejected alternatives
- **Redis for caching.** Rejected: one VPS, one process, an in-process map is
enough. Revisit at two application servers.
- **An ORM for the reporting queries.** Rejected: the reports are four hand-tuned
SQL statements. The generated query joined the same table twice.
## Boundaries
- `schema.sql` is append-only. A column rename needs a migration and a deploy window.
- The `/v1/` routes are public. Customers script against them, so the response
shape is frozen.
## Vocabulary
- `tenant` in code is what the docs and the billing system call a customer account.
## Keeping this file honest
Update it in the commit that changes the decision. A stale DESIGN.md is worse
than no DESIGN.md, because the agent believes it.Hãy điền vào hai phần mà bạn có thể viết từ trí nhớ ngay hôm nay, đó là các bất biến (invariants) và các phương án đã bị loại bỏ (rejected alternatives), và để trống các phần còn lại dưới dạng tiêu đề. Một file với bốn dòng trung thực còn hơn một file với bốn mươi dòng phỏng đoán.
Một số công cụ tải mọi file markdown trong thư mục gốc của repository, trong khi một số khác chỉ tải file được chỉ định, vì vậy đừng đưa ra giả định. Hãy thêm một con trỏ đến AGENTS.md:
Read DESIGN.md before editing anything under `src/`. It lists the invariants and
the alternatives that were already rejected.Anti-pattern: file DESIGN.md lặp lại nội dung README
Phiên bản tệ hại phổ biến nhất là loại tài liệu đọc thì trôi chảy nhưng không dạy được gì. Nó mở đầu bằng việc dự án làm gì, liệt kê các tính năng, giải thích cách cài đặt và kết thúc bằng giấy phép. Mọi dòng đó đều đã có trong README, và không dòng nào giải thích tại sao mọi thứ lại được thiết kế như vậy.
Điều này gây tốn kém gấp đôi. Chi phí đầu tiên là ngữ cảnh. Một file mà agent đọc ở đầu mỗi tác vụ sẽ tiêu tốn token cho mọi tác vụ đó, và phần cài đặt bị trùng lặp là chi phí dư thừa thuần túy so với một cửa sổ ngữ cảnh cố định. Việc quản lý cửa sổ đó là một kỹ năng riêng, được đề cập trong quản lý cửa sổ ngữ cảnh trong Claude Code. Tóm tắt ngắn gọn: bất cứ thứ gì được load tự động phải là văn bản có giá trị cao nhất trong repository.
Chi phí thứ hai còn tệ hơn. Hai bản sao của cùng một thông tin sẽ dần sai lệch. README nói service lắng nghe ở cổng 8080, DESIGN.md vẫn ghi 3000, và agent không có cách nào để ưu tiên cái nào hơn, nên nó chọn đại một cái và viết code dựa trên đó. Một file đôi khi sai sẽ bị tham chiếu với cùng mức độ tin cậy như một file luôn đúng.
Bài kiểm tra rất nhanh. Nếu một đoạn văn có thể nằm gọn trong README, hãy cắt nó khỏi DESIGN.md. Những gì còn lại phải là phần bạn sẽ nói thành lời trong buổi code review, phần bắt đầu bằng "chúng ta đã thử cách đó rồi".
Làm sao để biết file đang hoạt động?
Không có linter nào cho việc này. Bạn có thể thực hiện một kiểm tra nhanh trong vòng một phút.
Hãy giao cho agent một tác vụ đi thẳng vào một bất biến (invariant). Ví dụ: "Thêm một background job đánh dấu các hàng cũ là đã hết hạn." Một file đang hoạt động tốt sẽ thể hiện ngay trong câu trả lời trước khi bất kỳ đoạn code nào được viết ra: agent phải cho bạn biết job đó ghi dữ liệu thông qua queue.enqueue(), vì ghi trực tiếp sẽ bỏ qua audit log. Nếu nó mở kết nối database và ghi dữ liệu, thì một trong hai điều sau là đúng. File đó hoàn toàn không được đọc, hoặc bất biến được diễn đạt quá lỏng lẻo để có thể tranh luận.
Hãy theo dõi cả token count, vì file này được load trong mỗi lượt phản hồi. Nếu mức sử dụng context tăng vọt sau khi bạn thêm DESIGN.md mà chất lượng câu trả lời không cải thiện, thì file đó đang chứa những nội dung mà agent vốn đã biết. Đọc bộ đếm token trong Claude Code sẽ chỉ cho bạn biết ngân sách đó được dùng vào việc gì.
Điều này quan trọng nhất khi agent chạy trên server thay vì trên laptop của bạn. Một agent làm việc trong phiên chạy dài, như thiết lập trong một workspace Claude Code trên VPS với tmux, sẽ không ghi nhớ cuộc hội thoại của ngày hôm qua. Repository chính là bộ nhớ. Mọi thứ bạn đã giải thích trong chat mà không commit sẽ mất sạch vào phiên làm việc tiếp theo, và DESIGN.md là nơi lưu trữ những giải thích đó để chúng tồn tại lâu dài.
Bắt đầu với những quyết định bạn thường tranh luận
Phiên bản đầu tiên mất hai mươi phút. Hãy mở vài pull request gần nhất mà người review đã viết "không, chúng ta làm khác ở đây". Mỗi bình luận đó là một quy tắc bất biến chưa từng được ghi lại, và mỗi bình luận là một điểm mà agent sẽ mắc lỗi tương tự, nhanh hơn và thường xuyên hơn con người. Hãy thêm vào file khi nó khiến bạn thất bại, đừng làm theo lịch trình. Nếu bạn vẫn đang tìm hiểu xem agent phù hợp thế nào trong quy trình phát triển thông thường, hướng dẫn năm 2026 về việc học AI agents là điểm dừng tiếp theo hợp lý.
FAQ
DESIGN.md có phải là một tiêu chuẩn chính thức không?
Không giống như cách AGENTS.md được công nhận. AGENTS.md có trang chủ tại agents.md, được hơn 60,000 dự án mã nguồn mở sử dụng và được quản lý bởi Agentic AI Foundation, một thành viên của Linux Foundation. Tính đến tháng 8 năm 2026, DESIGN.md chưa có cơ quan quản lý và chưa có đặc tả kỹ thuật được công bố. Những gì nó có là sự chấp nhận từ các bên đầu tiên: bảy công ty, bao gồm Vercel, Nuxt, Atlassian và Resend, đã xuất bản file này tại một URL công khai, và một bộ sưu tập cộng đồng hiện có thêm 73 file khác được reverse-engineer từ các trang web công cộng. Hãy coi đây là một quy ước mà bạn có thể áp dụng ngay và mở rộng tùy ý, vì không có cơ chế nào kiểm chứng tên các section của bạn cả.
DESIGN.md có nên chỉ là một section của AGENTS.md không?
Với một repository nhỏ thì có. Một file mà agent chắc chắn đọc được sẽ tốt hơn hai file mà một trong số đó bị bỏ qua. Hãy tách chúng ra khi AGENTS.md không còn dễ quét nội dung nữa, hoặc khi bạn nhận thấy hai phần này thay đổi với tốc độ khác nhau. AGENTS.md thay đổi khi bản build thay đổi. DESIGN.md thay đổi khi một quyết định thay đổi, điều này hiếm hơn và mang trọng lượng lớn hơn. Khi tách ra, hãy thêm một dòng vào AGENTS.md yêu cầu agent đọc DESIGN.md trước khi chỉnh sửa code, vì không phải công cụ nào cũng load mọi file markdown trong thư mục root.
DESIGN.md khác gì với một bản ghi quyết định kiến trúc (ADR)?
Một ADR (architecture decision record) là bản ghi có ngày tháng của một quyết định cụ thể, và một dự án lành mạnh sẽ tích lũy hàng chục bản ghi như vậy trong một thư mục. Đó là lịch sử, và lịch sử rất tốn kém để load, vì agent sẽ phải đọc tất cả chúng để xác định xem cái nào vẫn còn hiệu lực. DESIGN.md là trạng thái hiện tại, được viết để đọc toàn bộ trong mỗi tác vụ. Hãy giữ cả hai nếu bạn đã viết ADR. ADR cho biết cái gì đã được quyết định và khi nào. DESIGN.md cho biết cái gì đúng ở thời điểm hiện tại, và đó là file bạn nên trỏ agent vào.
DESIGN.md nên dài bao nhiêu?
Đủ ngắn để load trong mỗi lượt mà không gây lãng phí. Các ví dụ đã công bố thường dài vì chúng quy định toàn bộ ngôn ngữ hình ảnh: file của Nuxt dài khoảng 2,100 từ và file của Vercel dài khoảng 6,500 từ tính đến tháng 8 năm 2026. Một backend service thường cần ít hơn nhiều. Hãy bắt đầu với một trang và chỉ mở rộng nó khi agent làm sai điều gì đó mà một câu đơn có thể ngăn chặn được. Độ dài không phải là thước đo. Mọi dòng trong đó nên là thứ mà nếu không có nó, agent sẽ làm sai.