DESIGN.md là gì cho Coding Agents?

Ashley Innocent

Ashley Innocent

21 tháng 5 2026

DESIGN.md là gì cho Coding Agents?

Apidog cho doanh nghiệp

Triển khai tại chỗ

SSO & RBAC

Tuân thủ SOC 2

Khám phá Apidog Enterprise

Các tác nhân mã hóa (coding agents) tự tin, nhanh chóng và không biết gì về kiến trúc cơ sở mã của bạn cho đến khi bạn cho chúng biết điều đó. Giao cho Claude Code hoặc Codex một yêu cầu mơ hồ và nó sẽ vui vẻ viết mã biên dịch được, vượt qua một bài kiểm tra nhanh, và âm thầm vi phạm ranh giới giữa tầng miền (domain layer) và tầng HTTP của bạn. Tác nhân không đọc tài liệu thiết kế của bạn. Nó đọc các tệp mà nó có thể thấy, khớp mẫu (pattern-matched) và đoán. Một tệp DESIGN.md khắc phục vấn đề đoán mò bằng cách ghi lại ý định kiến trúc của bạn vào một nơi mà tác nhân luôn tìm kiếm: chính kho lưu trữ (repository) đó.

TÓM TẮT

DESIGN.md là một tệp kho lưu trữ theo quy ước cộng đồng ghi lại ý định kiến trúc, các ràng buộc và quyết định thiết kế của cơ sở mã bằng Markdown thuần túy để các tác nhân mã hóa (Claude Code, Codex, Cursor) tạo ra mã phù hợp với hệ thống thay vì xung đột với nó. Nó trả lời câu hỏi “tại sao mã lại có hình dạng như vậy,” trong khi AGENTS.md trả lời “làm thế nào để xây dựng và kiểm thử.”

button

Giới thiệu

Đây là chế độ lỗi mà mọi nhóm áp dụng tác nhân mã hóa đều gặp phải trong vòng một tuần. Bạn yêu cầu một tác nhân thêm một điểm cuối hoàn tiền vào dịch vụ thanh toán. Nó trả về một trình xử lý hoạt động, gọi trực tiếp cơ sở dữ liệu từ bộ điều khiển, nuốt chửng lỗi cổng thanh toán và tạo ra một loại tiền mới vì nó không nhận thấy rằng bạn đã có một loại tiền tương tự. Bản cập nhật sạch sẽ. Các thử nghiệm vượt qua. Nó cũng sai ba cách mà chỉ một người đánh giá biết kiến trúc mới có thể nhận ra. Tác nhân không kém trong việc viết mã; nó mù tịt trước những quyết định nằm trong đầu bạn, trong một trang Notion, hoặc trong một chuỗi Slack từ tám tháng trước.

DESIGN.md là câu trả lời mà ngày càng nhiều đội đã đạt được sự đồng thuận. Đó là một tệp Markdown duy nhất, được cam kết vào thư mục gốc của kho lưu trữ, thông báo cho bất kỳ tác nhân nào về các sự thật cốt lõi của hệ thống: các quy tắc phân lớp, các bất biến không bao giờ được phá vỡ, các mẫu bạn cố ý chọn và những mẫu bạn đã từ chối. Nó không phải là một đặc tả của nhà cung cấp và không có ủy ban nào sở hữu nó; đó là một quy ước, giống như ARCHITECTURE.mdCONTRIBUTING.md là các quy ước. Nhưng nó kết hợp tự nhiên với các tệp hướng dẫn dành riêng cho công cụ mà các tác nhân đã đọc, và đối với công việc API và backend, đây là một trong những tài liệu có giá trị cao nhất mà bạn có thể viết.

DESIGN.md thực sự là gì

DESIGN.md là một bản ghi văn bản thuần túy về lý do mã của bạn có hình dạng như vậy. Không phải là nó làm gì (đó là README), không phải là cách chạy nó (đó là AGENTS.md), mà là lý do mà một kỹ sư cấp cao sẽ giải thích cho một nhân viên mới vào ngày đầu tiên trước khi cho phép họ chạm vào bất cứ thứ gì quan trọng.

Hãy nghĩ về những cuộc trò chuyện không có trong bất kỳ tệp nào. “Chúng tôi không gọi cổng thanh toán từ luồng yêu cầu; mọi thứ đều thông qua bảng hộp thư đi (outbox table) vì cổng thanh toán bị hết thời gian chờ khi tải.” “Tiền luôn là một số nguyên của các đơn vị nhỏ; chúng tôi đã cấm số thập phân sau sự cố làm tròn.” “Tập hợp Account sở hữu các thay đổi số dư; không có gì khác ghi vào sổ cái.” Đó là những quyết định thiết kế. Chúng vô hình đối với một tác nhân đọc mã nguồn, bởi vì mã nguồn hiển thị kết quả của quyết định, chứ không phải quyết định hay lý do của nó. Một tác nhân có thể thấy rằng Account.debit() tồn tại. Nó không thể thấy rằng bạn đã cố ý biến nó thành đường dẫn ghi duy nhất, vì vậy nó sẽ vui vẻ thêm một đường dẫn thứ hai.

Quy ước này có nguồn gốc từ các thực tiễn lâu đời, đã được thiết lập tốt. Mẫu ARCHITECTURE.md (được phổ biến bởi bài viết được trích dẫn rộng rãi của Alex Kladov) lập luận rằng một kho lưu trữ nên có một bản đồ cấp cao về cơ sở mã giải thích cấu trúc và các bất biến mà không cố gắng đồng bộ hóa từng dòng với mã. Các Hồ sơ Quyết định Kiến trúc (ADRs - Architecture Decision Records) ghi lại các quyết định cá nhân và lý do của chúng theo thời gian. DESIGN.md là những gì bạn nhận được khi bạn viết loại tài liệu đó cho đối tượng bao gồm tác nhân mã hóa: ngắn gọn, mang tính tuyên bố, định hướng quyết định và được đặt ở nơi mà tác nhân thực sự sẽ tải nó.

Hai thuộc tính làm cho nó hoạt động. Nó nằm trong kho lưu trữ, vì vậy tác nhân đọc nó bằng các công cụ tương tự mà nó đọc mã; bạn không cần một plugin hay một lệnh gọi API. Và nó nói về ý định, vì vậy nó vẫn hữu ích ngay cả khi các tệp di chuyển. Đổi tên một gói và ảnh chụp màn hình README của bạn bị hỏng; quy tắc “logic miền không bao giờ nhập khung web” vẫn đúng.

DESIGN.md so với AGENTS.md so với CLAUDE.md so với README

Những tệp này chồng chéo đủ để gây nhầm lẫn và khác biệt đủ để gộp chúng thành một là một sai lầm. Phiên bản ngắn gọn: README dành cho con người khi giới thiệu dự án, AGENTS.md là hợp đồng vận hành cho các tác nhân, CLAUDE.md là tệp hướng dẫn dành riêng cho Claude, và DESIGN.md là lý do kiến trúc mà tất cả chúng đều được hưởng lợi.

AGENTS.md hiện là một định dạng thực tế, được áp dụng rộng rãi; dự án agents.md mô tả nó là “một định dạng đơn giản, mở để hướng dẫn các tác nhân mã hóa,” được sử dụng trên hàng chục nghìn dự án và được quản lý dưới Tổ chức AI Agentic của Linux Foundation. Nhiệm vụ của nó là vận hành: các bước xây dựng, lệnh kiểm thử, phong cách mã, quy ước commit, những thứ bạn sẽ nói với một đồng đội mới để giữ cho họ không bị tắc nghẽn. Theo tài liệu bộ nhớ của Claude Code của Anthropic, CLAUDE.md đóng vai trò hướng dẫn tương tự cho riêng Claude; các tài liệu thậm chí còn khuyến nghị rằng nếu bạn đã có một AGENTS.md, bạn nên tạo một CLAUDE.md nhập nó bằng @AGENTS.md để cả hai công cụ đọc một nguồn sự thật duy nhất.

Hãy để ý điều gì còn thiếu trong các mô tả đó: lý do kiến trúc sâu sắc. AGENTS.mdCLAUDE.md được điều chỉnh để ngắn gọn. Tài liệu Claude Code khuyến nghị rõ ràng giữ CLAUDE.md dưới 200 dòng vì các tệp dài hơn tiêu thụ ngữ cảnh và giảm độ tin cậy mà mô hình tuân theo. Một giải thích kiến trúc thực sự, các ranh giới, các bất biến, các lựa chọn thay thế bị từ chối, các quy tắc mô hình dữ liệu, sẽ không phù hợp ở đó mà không làm nó phình to. Vì vậy, bạn tham chiếu nó thay thế. DESIGN.md trở thành tài liệu sâu; AGENTS.md / CLAUDE.md chỉ đến nó bằng một dòng duy nhất.

Tệp Đối tượng Trả lời Thời gian tồn tại / Tốc độ thay đổi Độ dài
README.md Con người (người dùng, người đóng góp mới) Đây là gì, làm thế nào để bắt đầu Thay đổi theo tính năng Trung bình
AGENTS.md Bất kỳ tác nhân mã hóa nào Làm thế nào để xây dựng, kiểm thử, kiểm tra lỗi cú pháp, commit tại đây Thay đổi theo công cụ Ngắn (vận hành)
CLAUDE.md Riêng Claude Code Tương tự như AGENTS.md, cộng thêm các quy tắc dành riêng cho Claude Thay đổi theo công cụ Ngắn (dưới ~200 dòng)
DESIGN.md Tác nhân + kỹ sư + người đánh giá Tại sao hệ thống có hình dạng như vậy; điều gì không bao giờ được phá vỡ Thay đổi theo kiến trúc (hiếm khi) Trung bình, dày đặc quyết định

Mối quan hệ này là bổ sung, không cạnh tranh. Một thiết lập sạch sẽ cho cửa hàng Claude + Codex trông như thế này: README.md cho con người; một AGENTS.md với build/test/style; một CLAUDE.md chỉ là @AGENTS.md cộng thêm hai dòng chỉ dành cho Claude; và DESIGN.md chứa kiến trúc, được liên kết từ AGENTS.md để mọi tác nhân tải nó theo yêu cầu. Không trùng lặp, mỗi tệp có một nhiệm vụ. Nếu bạn muốn tìm hiểu sâu hơn về cấu trúc ngữ cảnh của Claude trên các tệp này, quy trình làm việc của Claude Code sẽ hướng dẫn bạn qua mô hình bộ nhớ trong thực tế.

Những gì cần đưa vào DESIGN.md (với một mẫu)

DESIGN.md nên trả lời các câu hỏi mà một tác nhân không thể suy ra từ mã: hình dạng của hệ thống, các quy tắc không xuất hiện trong bất kỳ tệp nào và các quyết định bạn đã đưa ra một cách có chủ ý. Giữ nó mang tính tuyên bố. Mỗi phần nên đọc như một quy tắc mà người đánh giá sẽ thực thi, không phải một bài luận.

Hãy đề cập đến những điều này:

Đây là một mẫu hoàn chỉnh, được viết cho một dịch vụ API thanh toán thực tế. Sao chép nó, xóa những gì không áp dụng, điền vào phần còn lại.

# DESIGN.md: Dịch vụ API Thanh toán

Tệp này ghi lại ý định kiến trúc và các quyết định đằng sau nó.
Hãy đọc cái này trước khi tạo hoặc sửa đổi mã. Nếu một thay đổi xung đột
với một quy tắc ở đây, hãy dừng lại và đánh dấu nó thay vì tìm cách tránh nó.

## Hình dạng hệ thống

Phân lớp, các phụ thuộc chỉ hướng vào trong:

  http (handlers, DTOs)  ->  app (use cases)  ->  domain (entities,
  invariants)  <-  infra (db, gateway clients)

- `domain/` không có import nào từ `http/`, `app/`, hoặc bất kỳ framework nào.
- `infra/` triển khai các interface được khai báo trong `domain/` hoặc `app/`.
- `http/` không bao giờ chạm trực tiếp vào cơ sở dữ liệu hoặc cổng thanh toán.
  Nó gọi một use case trong `app/`.

## Bất biến (luôn phải đúng)

- Một mục sổ cái là bất biến khi đã ghi. Các điều chỉnh là các mục mới
  bù trừ, không bao giờ là cập nhật hoặc xóa.
- Số dư tài khoản được dẫn xuất từ các mục sổ cái, không được lưu trữ như một
  trường có thể thay đổi mà mã có thể đặt trực tiếp.
- Tiền là một số nguyên của các đơn vị nhỏ (cent) cộng với mã tiền tệ ISO-4217.
  Không bao giờ là số thập phân. Không bao giờ trộn lẫn các loại tiền tệ trong một hoạt động.
- Mọi cuộc gọi đến cổng thanh toán bên ngoài đều là bất biến (idempotent), được khóa bằng
  `idempotency_key`. Thử lại không được gây ra việc tính phí hai lần.
- Số dư không bao giờ âm trừ khi một `OverdraftPolicy` rõ ràng
  cho phép điều đó cho tài khoản đó.

## Các quyết định chính và lý do

- **Mẫu Outbox cho các cuộc gọi gateway.** Các handler ghi một hàng ý định
  trong cùng một giao dịch DB với thay đổi nghiệp vụ, sau đó một worker
  gọi gateway. Lý do: gateway hết thời gian chờ khi tải;
  làm nó trực tiếp (inline) khiến độ trễ yêu cầu và xử lý lỗi không được quản lý.
  Không được gọi gateway từ một request handler.
- **Đường dẫn ghi duy nhất cho mỗi aggregate.** Chỉ `Account.post_entry()`
  ghi vào sổ cái. Lý do: một đường dẫn ghi thứ hai đã gây ra
  sự trôi lệch số dư vào tháng 3 năm 2025. Thêm hành vi mới dưới dạng các phương thức trên
  aggregate, không phải các truy vấn mới.
- **Chỉ sử dụng event sourcing cho sổ cái.** Phần còn lại của hệ thống là
  CRUD. Lý do: chúng tôi cần một dấu vết kiểm toán hoàn hảo cho tiền
  và không có gì khác, và event sourcing hoàn chỉnh quá tốn kém ở những nơi khác.

## Các lựa chọn thay thế đã bị từ chối (không được đưa trở lại)

- Lazy-loading của ORM trên các aggregate; gây ra N+1 và ranh giới giao dịch không rõ ràng.
  Repositories trả về các aggregate đã được tải đầy đủ.
- Lưu trữ số dư dưới dạng một cột được cập nhật tại chỗ; xem sự cố trôi lệch số dư.
  Số dư luôn được dẫn xuất.
- Một thư viện `Money` chung được kéo từ registry; chúng tôi có
  `domain/money.py` của riêng mình; hãy sử dụng nó.
- Webhook đồng bộ đến các thương nhân từ luồng yêu cầu; chúng
  gây tắc nghẽn và thất bại âm thầm. Sử dụng hàng đợi thông báo.

## Quy tắc dữ liệu và miền

- Tất cả các dấu thời gian đều là UTC, được lưu trữ dưới dạng timestamptz, được định dạng RFC 3339
  ở rìa. Không có datetime ngây thơ nào vượt qua ranh giới hàm.
- ID là ULID được tạo ở tầng ứng dụng, không bao giờ là tự động tăng của DB.
- Không sử dụng xóa mềm (soft delete). Các bản ghi hoặc là hoạt động hoặc được di chuyển đến một
  bảng lưu trữ bởi một use case rõ ràng.
- Đa người thuê (Multi-tenant): mọi truy vấn đều được giới hạn bởi `tenant_id`. Một phương thức repository
  không có phạm vi người thuê là một lỗi.

## Nguồn sự thật của hợp đồng API

- Đặc tả OpenAPI 3.1 trong `api/openapi.yaml` là có thẩm quyền.
  Các kiểu yêu cầu/phản hồi được tạo từ nó; không sửa thủ công các
  kiểu được tạo trong `http/generated/`.
- Các điểm cuối mới hoặc thay đổi: cập nhật `api/openapi.yaml` trước, sau đó
  tạo lại, sau đó triển khai. Đặc tả được thiết kế và đánh giá trong
  Apidog trước khi thay đổi mã.
- Các phản hồi lỗi tuân theo RFC 9457 (problem+json). Sử dụng trình trợ giúp
  `problem()` được chia sẻ; không tự tạo ra các hình dạng lỗi tùy tiện.

## Nơi đặt mã mới

- Điểm cuối mới: route trong `http/routes/`, DTO trong `http/dto/`, use
  case trong `app/usecases/`, logic miền trong `domain/`.
- Tích hợp bên ngoài mới: client trong `infra/clients/`, interface
  trong `app/ports/`.
- Vấn đề xuyên suốt (xác thực, ghi nhật ký, bất biến): middleware trong
  `http/middleware/`, không bao giờ trực tiếp trong handlers.

## Ngoài phạm vi / không được chạm vào

- `http/generated/`: được tạo lại từ OpenAPI, các chỉnh sửa sẽ bị mất.
- `legacy/billing_v1/`: đóng băng, đang trong quá trình di chuyển. Không được mở rộng.
- `migrations/`: không bao giờ chỉnh sửa một migration đã áp dụng; hãy thêm một migration mới.

## Khi nghi ngờ

Nếu một thay đổi được yêu cầu đòi hỏi phải phá vỡ một quy tắc trên, hành động đúng đắn
là nói ra và đề xuất giải pháp thay thế nhỏ nhất nhất quán với thiết kế,
chứ không phải âm thầm làm việc tránh quy tắc.

Phần cuối cùng đó quan trọng hơn vẻ bề ngoài của nó. Việc cho một tác nhân biết phải làm gì khi yêu cầu xung đột với thiết kế biến tệp từ tài liệu thụ động thành một rào chắn chủ động. Nếu không có nó, một tác nhân gặp phải ràng buộc có xu hướng vòng qua nó và đưa ra giải pháp thay thế.

Cách các tác nhân mã hóa thực sự sử dụng DESIGN.md

Các tác nhân không có trình phân tích cú pháp DESIGN.md đặc biệt. Chúng sử dụng nó theo cùng một cách mà chúng sử dụng bất kỳ tệp nào: bằng cách đọc nó bằng các công cụ tệp của chúng và coi nội dung là ngữ cảnh. Vì vậy, cơ chế để tải nó có ý nghĩa quan trọng, và chúng hơi khác nhau tùy thuộc vào công cụ.

Mẫu hình đáng tin cậy là tham chiếu DESIGN.md từ tệp hướng dẫn mà mỗi tác nhân đã tải khi khởi động. Đối với Claude Code, đó là CLAUDE.md; tài liệu bộ nhớ mô tả cú pháp nhập @path trong đó @DESIGN.md mở rộng tệp vào ngữ cảnh khi bắt đầu phiên. Đối với hệ sinh thái AGENTS.md, bạn thêm một dòng vào AGENTS.md chỉ vào nó (“Quy tắc kiến trúc và thiết kế: xem DESIGN.md; đọc nó trước khi thay đổi cấu trúc”). Các tác nhân duyệt qua cây thư mục sẽ chọn AGENTS.md gần nhất, thấy con trỏ, và kéo DESIGN.md khi công việc chạm đến kiến trúc. Dù bằng cách nào, bạn cũng không sao chép nội dung; bạn giữ tệp vận hành ngắn gọn và để tệp sâu được sâu.

Ba lưu ý thực tế về cách các công cụ này hoạt động:

Đầu tiên, tác nhân coi tệp là ngữ cảnh, không phải là các quy tắc được thực thi. Tài liệu Claude Code thẳng thừng rằng nội dung CLAUDE.md là hướng dẫn mà mô hình cố gắng tuân theo, không phải là một ràng buộc cứng nhắc. Điều tương tự cũng áp dụng cho bất cứ thứ gì bạn tham chiếu từ đó. Đó là lý do tại sao mẫu trình bày mọi thứ dưới dạng các giá trị tuyệt đối có thể kiểm thử và thêm hướng dẫn rõ ràng “khi nghi ngờ” ; văn xuôi mơ hồ bị bỏ qua khi gặp áp lực, các quy tắc sắc bén thường được tuân thủ hơn.

Thứ hai, độ dài và cấu trúc thay đổi mức độ tuân thủ. Các tiêu đề và dấu đầu dòng tốt hơn các đoạn văn vì mô hình quét cấu trúc theo cách người đọc làm. Một bức tường triết lý kiến trúc dài 3 trang sẽ bị lướt qua; mười bất biến sắc nét dưới một tiêu đề rõ ràng sẽ được sử dụng. Viết để truy xuất, không phải để viết văn.

Thứ ba, tệp thay đổi kinh tế đánh giá, không chỉ tạo. Ngay cả khi tác nhân bỏ qua một phần, người đánh giá có thể chỉ ra quy tắc bị vi phạm và tác nhân khắc phục nó trong một lượt (“điều này phá vỡ quy tắc đường dẫn ghi duy nhất trong DESIGN.md”). Vòng lặp phản hồi đó, dựa trên quyết định đã ghi để sửa lỗi, là nơi tạo ra nhiều giá trị thực sự. Các nhóm xây dựng hệ thống tác nhân của riêng họ dựa vào chính điều này; xem xây dựng Claude Code của riêng bạn để biết cách vòng lặp đó được kết nối vào các luồng tự động.

Chống mẫu và cách ngăn nó bị lỗi thời

Cách nhanh nhất để làm cho DESIGN.md trở nên vô giá trị là viết nó giống như một trang wiki. Một tệp thiết kế bị lỗi thời còn tệ hơn không có gì, bởi vì cả tác nhân và con người đều tin tưởng nó và bị lừa. Tránh những điều sau.

Nhắc lại mã. “Lớp UserService xử lý người dùng” không cho tác nhân biết điều gì mà nó không thể đọc từ user_service.py. Nếu một câu đúng khi đọc tệp, hãy cắt bỏ nó. Chỉ giữ lại những gì mã không thể cho bạn biết: lý do, các bất biến, các đường dẫn bị từ chối.

Phình to hướng dẫn. Hướng dẫn từng bước “cách thêm một tính năng” thuộc về CONTRIBUTING.md hoặc một kỹ năng, không phải ở đây. Ngay khi DESIGN.md có các lệnh shell và đoạn mã sao chép-dán, đó là một tài liệu sai và nó sẽ lỗi thời với tốc độ của công cụ.

Ước vọng là sự thật. Viết “hệ thống sử dụng CQRS” trong khi một nửa trong số đó không làm vậy sẽ huấn luyện các tác nhân tạo ra mã phù hợp với một điều hư cấu. Ghi lại những gì đúng hiện tại cộng với nơi bạn cố ý hướng tới, và dán nhãn sự khác biệt. “Mục tiêu: tất cả các ghi đều thông qua use case. Hiện tại: legacy/ bỏ qua điều này; không mở rộng nó.”

Không có người sở hữu, không có yếu tố kích hoạt đánh giá. Một tệp thiết kế không ai chịu trách nhiệm sẽ bị trôi dạt trong một quý. Hãy gắn nó với một yếu tố kích hoạt: đánh giá DESIGN.md trong bất kỳ PR nào thêm một mô-đun, thay đổi một ranh giới lớp hoặc giới thiệu một phụ thuộc bên ngoài mới. Đặt quy tắc đó vào mẫu PR. Một số nhóm thêm một mục kiểm tra, “thay đổi này có làm thay đổi quyết định nào trong DESIGN.md không? Nếu có, hãy cập nhật nó trong cùng PR.”

Kịch bản đồng bộ hóa. Đừng cố gắng giữ nó đồng bộ từng dòng với mã; đó là một trò chơi thua cuộc và đó là lý do tài liệu kiến trúc bị bỏ rơi. Giữ nó ở cấp độ các quyết định thay đổi vài lần một năm, không phải chữ ký hàm thay đổi hàng tuần. Hướng dẫn ARCHITECTURE.md của matklad là bản năng đúng ở đây: chỉ ghi lại những gì ít có khả năng thay đổi thường xuyên.

Mâu thuẫn với các tệp hướng dẫn khác. Nếu AGENTS.md nói một điều về xử lý lỗi và DESIGN.md nói một điều khác, các tác nhân sẽ chọn một cách tùy tiện. Giữ các quy tắc vận hành trong AGENTS.md / CLAUDE.md và các quy tắc kiến trúc trong DESIGN.md, và không để chúng chồng chéo. Khi chúng phải tham chiếu lẫn nhau, một cái sẽ chỉ đến cái kia; chúng không cùng khẳng định một sự thật.

Một DESIGN.md lành mạnh thì ngắn gọn, súc tích, mang tính khai báo, có người sở hữu và được đánh giá theo yếu tố kích hoạt. Nếu của bạn dài, mang tính kể chuyện và lần cuối cùng được chạm vào là một năm trước, các tác nhân đang đọc tiểu thuyết.

DESIGN.md cho các cơ sở mã API và backend

Đây là nơi tệp này phát huy giá trị của nó. Các dịch vụ API và backend có chính xác những loại ràng buộc vô hình, chi phí cao mà các tác nhân dở nhất: ranh giới hợp đồng, ngữ nghĩa giao dịch, tính bất biến (idempotency), tính toàn vẹn dữ liệu, phân lớp. Không có điều nào rõ ràng từ một tệp duy nhất, và việc làm sai sẽ tạo ra lỗi và gây thiệt hại tiền bạc.

Đặt những điều đặc thù cho API này vào DESIGN.md và chất lượng đầu ra của tác nhân trên các tác vụ backend sẽ tăng lên:

Đối với công việc backend, lợi ích là cụ thể: ít vi phạm phân lớp hơn, không có các cuộc gọi gateway trực tuyến bất ngờ, hình dạng lỗi và phân trang nhất quán, và các trình xử lý tuân thủ hợp đồng vì tác nhân được chỉ dẫn đến đặc tả OpenAPI thay vì đoán schema. Tác nhân ngừng tự tạo và bắt đầu tuân thủ. Nếu bạn muốn tác nhân cũng thực hiện API mà nó vừa viết, sự kết hợp giữa hợp đồng và thiết kế là điều cho phép các công cụ và tác nhân kiểm thử dựa trên một giao diện đã biết; Tải xuống Apidog cung cấp cho bạn không gian làm việc thiết kế trước, xuất OpenAPI mà DESIGN.md của bạn chỉ đến, và một máy chủ MCP cùng trình gỡ lỗi tác nhân AI để kiểm tra xem các điểm cuối được tạo có thực sự khớp với hợp đồng hay không.

Kết luận

Câu hỏi thường gặp

DESIGN.md có phải là một tiêu chuẩn chính thức như AGENTS.md không?

Không. AGENTS.md là một định dạng được xác định, được áp dụng rộng rãi và hiện được quản lý dưới Tổ chức AI Agentic của Linux Foundation. DESIGN.md là một quy ước cộng đồng không có chủ sở hữu hoặc đặc tả duy nhất, cùng dòng với ARCHITECTURE.md và ADRs. Hãy coi nó là một mẫu hữu ích mà bạn thích nghi, chứ không phải là một tiêu chuẩn mà bạn phải tuân thủ.

Tôi có cần DESIGN.md nếu tôi đã có AGENTS.md hoặc CLAUDE.md không?

Nếu kiến trúc của bạn có những ràng buộc không rõ ràng, thì có. AGENTS.mdCLAUDE.md được tạo ra để giữ ngắn gọn và mang tính vận hành; tài liệu Claude Code khuyến nghị giữ CLAUDE.md dưới khoảng 200 dòng. Lý do kiến trúc sâu sắc không phù hợp ở đó mà không làm nó phình to và ảnh hưởng đến sự tuân thủ, vì vậy bạn đặt nó vào DESIGN.md và tham chiếu nó. Đối với chính tệp vận hành, hãy xem cách viết tệp AGENTS.md.

DESIGN.md khác với ARCHITECTURE.md như thế nào?

Chủ yếu là ý định và đối tượng. ARCHITECTURE.md là quy ước cũ hơn nhằm mục đích giúp những người đóng góp là con người lập bản đồ cơ sở mã. DESIGN.md là cùng một ý tưởng được viết cho đối tượng bao gồm tác nhân mã hóa: mang tính khai báo hơn, tập trung vào quyết định và bất biến, và được tham chiếu rõ ràng từ các tệp hướng dẫn của tác nhân để nó được tải vào ngữ cảnh. Nhiều nhóm sử dụng một tệp và một tên; các nguyên tắc là như nhau.

DESIGN.md nên dài bao nhiêu?

Đủ dài để bao gồm các quyết định mà các tác nhân thường xuyên làm sai, đủ ngắn để mỗi dòng đều có giá trị. Dày đặc quyết định tốt hơn là toàn diện. Nếu nó đọc như một hướng dẫn hoặc nhắc lại mã, hãy cắt bỏ nó. Hai đến bốn trang các bất biến và lý do tập trung tốt hơn một bài tường thuật mười lăm trang mà không tác nhân nào đọc kỹ.

Làm thế nào để tôi khiến tác nhân thực sự đọc nó?

Tham chiếu nó từ tệp mà tác nhân đã tải khi khởi động. Đối với Claude Code, nhập nó từ CLAUDE.md bằng @DESIGN.md. Đối với hệ sinh thái AGENTS.md, thêm một dòng chỉ dẫn vào AGENTS.md yêu cầu các tác nhân đọc DESIGN.md trước khi thay đổi cấu trúc. Đừng dán toàn bộ nội dung vào tệp ngắn; hãy tham chiếu nó để tệp vận hành vẫn ngắn gọn.

Tác nhân sẽ luôn tuân theo DESIGN.md chứ?

Không, và bạn nên thiết kế dựa trên điều đó. Các tệp hướng dẫn của tác nhân là ngữ cảnh mà mô hình cố gắng tuân theo, không phải cấu hình được thực thi. Viết các quy tắc dưới dạng các giá trị tuyệt đối sắc nét, thêm hướng dẫn rõ ràng “đánh dấu các xung đột, đừng vòng tránh chúng,” và dựa vào vòng lặp đánh giá; chỉ ra một quy tắc bị vi phạm trong DESIGN.md sẽ nhận được một bản sửa lỗi nhanh chóng, chính xác ngay cả khi lần đầu tiên bị bỏ qua.

DESIGN.md có giúp ích cụ thể cho các vấn đề hợp đồng API không?

Rất nhiều. Công dụng backend có giá trị cao nhất của nó là nêu rõ rằng đặc tả OpenAPI là có thẩm quyền và đặt tên tệp, để các tác nhân tuân thủ hợp đồng thay vì tự tạo schema hoặc sửa thủ công các kiểu được tạo. Thiết kế hợp đồng đó trước tiên trong một công cụ như Apidog cung cấp cho tác nhân một mục tiêu rõ ràng mà DESIGN.md của bạn có thể chỉ thẳng vào.

DESIGN.md nên đặt ở đâu trong kho lưu trữ?

Thư mục gốc của kho lưu trữ, bên cạnh README.mdAGENTS.md, để các tác nhân và con người tìm thấy nó mà không cần tìm kiếm. Trong một monorepo, một DESIGN.md gốc cho các quy tắc toàn hệ thống cộng với một tệp trên mỗi gói cho kiến trúc cục bộ hoạt động tốt, phản ánh cách các tác nhân đọc AGENTS.md gần nhất trong cây thư mục.

Thực hành thiết kế API trong Apidog

Khám phá cách dễ dàng hơn để xây dựng và sử dụng API

DESIGN.md là gì cho Coding Agents?