SSD Nodes Learn 🎉 VPS từ $5.50/tháng
Hướng dẫn Matt ConnorBởi Matt Connor

dox: Tự động cập nhật AGENTS.md theo repository

AGENTS.md sai sau ba tuần vì không gắn với mã nguồn. Dùng dox để tạo lại file từ repository, rồi review diff như review code trước khi commit.

Vì sao AGENTS.md của bạn sai chỉ sau ba tuần

Tệp AGENTS.md trở nên lỗi thời vì không có gì liên kết nó với mã nguồn. Bạn viết tệp một lần, bằng tay, vào thời điểm repository có một trạng thái nhất định. Sau đó test runner thay đổi, một package được đổi tên, một service bị xóa, nhưng tệp vẫn mô tả trạng thái của tháng 6. Không có gì fail vì không bước build nào đọc tệp này.

Agent đọc tệp và tin vào nội dung đó. Đây mới là phần gây tổn thất. Repository không có AGENTS.md sẽ khiến coding agent kiểm tra trước khi thực hiện. Repository có AGENTS.md sai khiến agent không kiểm tra nữa vì nó đã có câu trả lời. Agent chạy command được nêu trong tệp, shell trả về Missing script: "test", rồi agent bắt đầu đoán. Nhiều khi nó chỉnh sửa package.json để thêm script mà tài liệu của bạn đã hứa sẽ có. Tệp lỗi thời không fail một cách im lặng. Nó khiến agent thực hiện một thay đổi mà bạn không muốn.

dox là một cách để giải quyết vấn đề này. Đây là một bộ quy tắc được viết cho agent, yêu cầu cập nhật tài liệu là một phần của việc hoàn tất công việc. Nhờ đó, tệp tài liệu được thay đổi trong cùng commit với phần mã nguồn khiến nó trở nên sai.

dox là gì và không phải là gì

dox là một file Markdown duy nhất. Repository là agent0ai/dox, được cấp phép theo MIT, và tính đến ngày 11 tháng 8 năm 2026, toàn bộ project chỉ gồm một AGENTS.md 3906-byte, một README, một LICENSE và hai image. Không có package nào cần cài đặt và không có runtime.

Điều này quan trọng vì từ “generator” gợi ý rằng có một program phân tích code của bạn. Không có thành phần nào phân tích code của bạn. dox là một contract để coding agent đọc: agent của bạn là generator, còn dox là instruction set cho biết khi nào agent phải đọc tài liệu, khi nào phải viết lại tài liệu và mỗi tài liệu phải có cấu trúc như thế nào.

File này có mười section, trong đó hai section thực hiện phần việc chính. “Read Before Editing” yêu cầu agent đi từ repository root đến mọi path mà agent dự định chỉnh sửa, đồng thời đọc mọi AGENTS.md trên từng route trong session hiện tại, không dựa vào memory. “Update After Editing” quy định rằng mọi thay đổi có ý nghĩa đều cần một DOX pass, tức là phải chạy bước cập nhật tài liệu trước khi task được xem là hoàn tất. Pass này cập nhật tài liệu gần nhất đang sở hữu phần thay đổi khi purpose, structure, workflow, permissions hoặc user preferences thay đổi.

Các phần còn lại quy định cấu trúc. AGENTS.md con có thứ tự section mặc định: Purpose, Ownership, Local Contracts, Work Guidance, Verification và Child DOX Index. File ở root chứa các rule áp dụng trên toàn project cùng Child DOX Index cấp cao nhất. Agent dùng index này để tìm các tài liệu con. “Closeout” là checklist agent chạy khi kết thúc task: kiểm tra lại các path đã thay đổi theo chain, cập nhật tài liệu sở hữu gần nhất, refresh mọi index bị ảnh hưởng, xóa các nội dung mâu thuẫn, chạy bước verification hiện có và báo cáo những tài liệu mà agent cố ý không thay đổi.

Ghim dox vào một commit, không ghim vào main

Repository không có tag và cũng không có release, nên không có version number để ghim. Thay vào đó, hãy ghim commit. AGENTS.md hiện tại là commit f34ec7ad1055d3393887e5a2670e8cb7320c9165, ngày 1 August 2026.

mkdir -p .agent
curl -fsSL -o .agent/dox-f34ec7a.md \
  https://raw.githubusercontent.com/agent0ai/dox/f34ec7ad1055d3393887e5a2670e8cb7320c9165/AGENTS.md
wc -c .agent/dox-f34ec7a.md

wc -c phải in ra 3906. Nếu ra số khác, bạn chưa fetch đúng file mà hướng dẫn này mô tả, vì vậy hãy đọc file trước khi tin tưởng nó. Nếu nhập sai commit hash, -f sẽ khiến curl dừng với curl: (22) The requested URL returned error: 404 và không ghi nội dung nào, sau đó wc -c sẽ in ra 0. File bị cắt ngắn còn tệ hơn không có file, vì agent sẽ làm theo một nửa contract mà không biết phần còn lại.

cp .agent/dox-f34ec7a.md AGENTS.md
git add AGENTS.md .agent/dox-f34ec7a.md
git commit -m "Add DOX rules (agent0ai/dox @ f34ec7a)"

cp dành cho repository chưa có AGENTS.md. Nếu đã có file này, đừng ghi đè. Đặt các section dox ở phía trên nội dung hiện có, giữ các rule của bạn ở bên dưới, rồi đọc lại toàn bộ kết quả từ đầu đến cuối. Hai tài liệu mâu thuẫn nhau sẽ khiến agent làm theo dòng mà nó đọc sau cùng.

Tiếp theo, trong repository, hãy yêu cầu agent thực hiện lượt đầu tiên. README có sẵn câu lệnh chính xác:

Initialize DOX tree for this project now.

Lệnh này tạo các file AGENTS.md con và các index trỏ đến chúng. Hãy kiểm tra kết quả trước khi tin tưởng:

git status --short
find . -name AGENTS.md -not -path './.git/*' | sort

Mọi file trong output find phải xuất hiện ở đâu đó trong Child DOX Index bên trên nó. Một tài liệu con không được index nào nhắc đến là tài liệu agent có thể bỏ sót, vì index là cách agent tìm các tài liệu không nằm trực tiếp trên path mà nó đang duyệt.

Dox có thể thấy gì và không thể biết gì

Agent xây dựng cây của bạn sẽ đọc repository, vì vậy mọi thứ trong repository đều có thể được đưa vào inventory: cấu trúc thư mục, package manifest và lockfile, các script trong package.json hoặc Makefile hoặc pyproject.toml, file workflow của CI, Dockerfile, entry point và CODEOWNERS nếu bạn có. Inventory được xây dựng từ các nguồn này thực sự tự duy trì. Khi một package được chuyển đi, lần chạy tiếp theo sẽ chuyển cả dòng mô tả package đó.

Bạn phải tự nêu mọi nội dung dưới đây, vì chúng không nằm trong repository để agent đọc:

  • lý do một rule tồn tại; đây là yếu tố ngăn agent xóa rule vì cho rằng đó là độ phức tạp không cần thiết
  • trong hai quy trình đang hoạt động, quy trình nào được hỗ trợ và quy trình nào đang chờ xóa
  • mọi thứ nằm ngoài repository, chẳng hạn môi trường staging hoặc lý do một dependency bị ghim lùi hai phiên bản
  • việc bạn dự định làm vào tuần tới; đây là điểm khác biệt giữa một file còn hiện hành và một file thực sự hữu ích

Dox biết rõ những giới hạn này. Các rule của chính nó quy định rằng Work Guidance phải phản ánh các tiêu chuẩn hiện tại của project hoặc hướng dẫn của người dùng, và nếu chưa có tiêu chuẩn nào thì để trống section đó. Verification phải phản ánh một bước kiểm tra đang tồn tại. Vì vậy, nếu repository chưa có test framework, section đó vẫn để trống cho đến khi có framework. Một file được generate nhưng tự bịa ra tiêu chuẩn còn tệ hơn một section trống, vì sau đó agent sẽ thực thi tiêu chuẩn bịa ra đó.

Đừng để mất ý định do con người viết khi tạo inventory

Đây là lỗi khiến nhiều người bỏ cuộc với tài liệu được tạo tự động. Bạn viết một đoạn giải thích rằng hàng đợi job phải luôn chỉ có một consumer. Ba tuần sau, một lần chạy lại ghi đè file, và đoạn văn biến mất trong một diff gồm 40 dòng, phần lớn chỉ sắp xếp lại tên file. Không ai phát hiện ra.

Bạn cần cả hai cơ chế.

Trước hết, chuyển ý định cần duy trì lâu dài sang một file khác. Các quyết định thiết kế và lý do đằng sau chúng thuộc về DESIGN.md do agent viết, còn các ghi chú dành cho con người nên đặt ở nơi bạn tách HUMAN.md khỏi AGENTS.md. Khi đó, AGENTS.md chỉ chứa inventory và các contract cục bộ. Đây chính là phần cần thay đổi khi code thay đổi.

Tiếp theo, đánh dấu rõ phần ý định vẫn phải nằm trong AGENTS.md. Bọc phần đó bằng các marker và coi block này là nội dung do con người quản lý:

## User Preferences

<!-- dox:keep start -->
The jobs queue stays single consumer. Ordering is the reason this service exists.
Deploys ship on Tuesday. A Friday deploy is a human decision, not an agent decision.
<!-- dox:keep end -->

Comment Markdown không hiển thị trên trang, nhưng agent vẫn đọc được. Bây giờ hãy kiểm tra để biết block này còn nguyên, sao cho một lần chạy ghi đè nó sẽ báo lỗi rõ ràng. Chạy lệnh này trong CI (continuous integration) trên mọi pull request:

git fetch -q origin main
sed -n '/dox:keep start/,/dox:keep end/p' AGENTS.md > /tmp/keep.head
git show origin/main:AGENTS.md | sed -n '/dox:keep start/,/dox:keep end/p' > /tmp/keep.base
diff -u /tmp/keep.base /tmp/keep.head

diff không in gì và thoát với mã 0 khi block không thay đổi. Nếu có output, lần chạy đó đã ghi đè nội dung do con người quản lý. Khi đó, một người phải phê duyệt thay đổi hoặc revert nó. Kiểm tra này vẫn có hiệu lực mà không cần ai phải nhớ thực hiện.

Tạo lại khi mở pull request, không chạy theo timer

Thời điểm tốt nhất để cập nhật một tài liệu là ngay trong commit khiến tài liệu đó sai. Đưa bước chạy DOX vào cùng pull request với thay đổi cấu trúc để diff đủ nhỏ và thực sự dễ đọc.

Một check dạng blocking để bắt buộc việc này:

#!/usr/bin/env bash
set -euo pipefail
git fetch -q origin main
base=$(git merge-base origin/main HEAD)
changed=$(git diff --name-only "$base" HEAD)
if grep -qE '^(src|apps|packages)/' <<<"$changed" && ! grep -q 'AGENTS\.md$' <<<"$changed"; then
  echo "Code changed but no AGENTS.md was touched. Run a DOX pass, or say why not."
  exit 1
fi

Điều chỉnh các path cho phù hợp với repository của bạn. Lợi ích là check sẽ fail ngay trên branch, khi việc sửa còn rẻ, và fail vì một lý do mà reviewer có thể xử lý.

Schedule chỉ là phương án dự phòng, không phải cơ chế chính. Job chạy hàng tuần sẽ bắt được những vấn đề không ai nhận ra trên branch: file bị di chuyển do rebase, package bị xóa trong lúc merge, hoặc tài liệu nhắc đến một directory không còn tồn tại. Chạy job này trên một máy nhỏ, có thể là chính máy bạn dùng để chạy coding agent trên VPS, và yêu cầu nó mở pull request thay vì push vào main.

#!/usr/bin/env bash
set -euo pipefail
cd /srv/src/myapp
git fetch -q origin
git switch -c "dox/refresh-$(date +%Y%m%d)" origin/main
# Your agent CLI goes on the next line, in whatever non-interactive mode it offers.
# Prompt: "Run a DOX pass over this repository. Change AGENTS.md files only."
git add '*AGENTS.md'
git commit -m "dox: refresh AGENTS.md tree" || { echo "nothing to refresh"; exit 0; }
git push -q -u origin HEAD
gh pr create --fill

Comment đó được để làm placeholder có chủ ý. Mỗi agent có CLI (command line interface) và flag non-interactive riêng. Một command chép từ web nhưng không khớp với version bạn đang dùng sẽ fail bên trong cron, nơi không ai thấy lỗi. Điền command đó rồi chạy script thủ công một lần trước khi tạo schedule. || exit 0 cũng quan trọng: git commit thoát với mã khác 0 cùng nothing to commit, working tree clean khi tree đã được cập nhật đầy đủ, và dưới set -e, điều đó sẽ báo một lần chạy thành công là failure.

Mỗi lần chạy đều tốn token vì quy tắc "Read Before Editing" khiến agent đọc toàn bộ chuỗi ở mỗi task. Đây là một đánh đổi cần chấp nhận, nhưng vẫn đáng theo dõi nếu bạn đã tính chi phí các lần agent chạy.

Monorepo: nhiều contract, một index

Một file AGENTS.md ở root trong repository có 40 package sẽ tạo ra một diff tái tạo mà không ai đọc, cùng một tài liệu phần lớn không liên quan đến tác vụ agent đang thực hiện. dox giải quyết việc này bằng Child DOX Index: root chứa các quy tắc áp dụng toàn repository và trỏ đến các file con, còn mỗi ranh giới ổn định tự quản lý file riêng. Cách bố trí cây này và những tool nào đọc được file lồng nhau được trình bày trong các file AGENTS.md lồng nhau cho monorepo.

Điểm dox thay đổi là phạm vi review. Một pull request chỉ chạm vào packages/api phải tạo diff tài liệu bên trong packages/api và không ở nơi nào khác:

git diff --stat -- '*AGENTS.md'

Nếu command đó liệt kê 6 file cho một thay đổi trong một package, cây đang được bố trí sai. Hoặc các ranh giới quá rộng, hoặc một quy tắc thuộc root đã bị sao chép vào mọi file con. dox nêu rõ cách sửa: quy tắc tổng quát đặt trong tài liệu của parent, chi tiết cụ thể đặt trong tài liệu của child. Các quy tắc trùng lặp là nguyên nhân khiến một lần chạy thông thường phải ghi lại mọi thứ. Nếu cùng một bộ quy tắc thực sự áp dụng cho nhiều repository riêng biệt, đó là một vấn đề khác; chia sẻ agent skill giữa các repository sẽ phù hợp hơn.

Đọc diff như đọc code

Diff của tài liệu được tạo tự động rất dễ được phê duyệt mà không cần đọc. Đây là cách các file sai được release. Hãy đọc diff với mức độ cảnh giác như khi đọc code được tạo tự động, và kiểm tra bốn điểm sau.

  • Một command mà file hiện đã ghi rõ và bạn nên tự chạy trước khi merge. Hướng dẫn build bị bịa là lỗi phổ biến nhất.
  • Một dòng bị xóa nhưng chứa ý định ban đầu. Thêm nội dung thường không gây mất mát. Mất mát thường xảy ra ở phần bị xóa.
  • Một absolute path, hostname, internal URL hoặc bất kỳ chuỗi nào có dạng credential
  • Một mục inventory cho thứ không còn tồn tại; ls sẽ xác nhận việc này trong một giây

Sau đó kiểm tra kích thước bằng wc -l AGENTS.md. Một file root dài quá two hundred lines là dấu hiệu cần tách file, vì toàn bộ giá trị của chain nằm ở việc agent chỉ đọc phần nhỏ có liên quan thay vì đọc mọi thứ.

Khi có lỗi

Pass đã xóa khối intent của bạn. Lệnh kiểm tra diff ở trên sẽ in ra các dòng đã bị xóa. Khôi phục file từ điểm phân nhánh bằng git restore --source=origin/main AGENTS.md, rồi chạy lại pass với instruction cụ thể hơn, trong đó nêu rõ các section mà pass được phép chỉnh sửa.

Cả hai branch đều tạo lại nội dung. Bạn sẽ thấy CONFLICT (content): Merge conflict in AGENTS.md và các conflict marker <<<<<<< HEAD bên trong file. Không chỉnh sửa marker bằng tay. File này được tạo tự động, nên cách xử lý đúng là chạy lại pass trên cây đã merge.

Agent hoàn toàn bỏ qua file. Kiểm tra tên file mà tool thực sự đọc. Nếu tool đọc một file khác, hãy trỏ tool đến cùng nội dung bằng ln -s AGENTS.md CLAUDE.md rồi commit symlink. Như vậy bạn chỉ duy trì một source, thay vì hai tài liệu bị lệch nội dung theo thời gian.

Cây có thêm các node con nhưng không có mục nào lập chỉ mục chúng. So sánh output của find . -name AGENTS.md với các mục index trong những tài liệu cha. Một node con không được mục index nào nhắc đến là node mà agent có thể bỏ qua hoàn toàn.

Khi generator là quá mức cần thiết

Một package, một lệnh test, hai người đều hiểu repository: hãy viết 20 dòng đó bằng tay. Một file AGENTS.md dài 20 dòng không lỗi thời đủ nhanh để biện minh cho tree, index, kiểm tra CI và job chạy hằng tuần. Hãy đọc lại file khi bạn thay đổi quy trình build. Đó là toàn bộ chi phí bảo trì, và nó thấp hơn chi phí của cả hệ thống hỗ trợ xung quanh.

dox đáng để dùng khi repository có những ranh giới mà không một người nào có thể nhớ hết: nhiều package với các quy tắc khác nhau, hoặc những contributor tham gia mà chưa có bối cảnh cần thiết. Giá trị không nằm ở phần văn bản được tạo tự động. Giá trị nằm ở chỗ tài liệu trở thành thứ có thể khiến một pull request fail. Đây là lý do duy nhất khiến bất kỳ file nào trong repository tiếp tục được cập nhật.

FAQ

Tôi có cần cài đặt gì để dùng dox không?

Không. dox là một tệp Markdown, được cấp phép theo MIT, và tính đến ngày 11 tháng 8 năm 2026, repository này không có package hay bản release nào. Bạn sao chép nội dung của nó vào AGENTS.md của project, rồi coding agent sẽ thực thi các quy tắc từ đó. Hãy pin commit bạn đã sao chép, f34ec7ad1055d3393887e5a2670e8cb7320c9165 tại thời điểm viết tài liệu này, và ghi rõ commit đó trong commit message để sau này xác định được cây mã nguồn được xây dựng theo phiên bản quy tắc nào.

Làm cách nào để ngăn quá trình tạo lại xóa các quy tắc tôi viết thủ công?

Tách riêng mục đích và inventory. Đặt phần giải thích lâu dài trong một tài liệu riêng, còn mọi nội dung bắt buộc phải nằm trong AGENTS.md thì đặt trong một block được đánh dấu. Sau đó kiểm tra block này trong CI: trích xuất nó từ branch và từ origin/main bằng sed, so sánh hai bản bằng diff, rồi cho build fail nếu có bất kỳ khác biệt nào. Khi đó, một người sẽ phê duyệt hoặc revert thay đổi, thay vì thay đổi đó âm thầm lọt vào trong một diff lớn.

Bao lâu nên tạo lại AGENTS.md một lần?

Hãy thực hiện trong pull request làm cho nó không còn đúng. Thay đổi cấu trúc và tài liệu tương ứng nên nằm trong cùng một diff, vì đó là thời điểm duy nhất người review có đủ context để kiểm tra cả hai. Một scheduled pass hằng tuần là phương án dự phòng cho drift đã lọt qua một branch, và nó nên mở pull request thay vì commit trực tiếp vào main.

Các lệnh build nên nằm trong AGENTS.md ở root hay trong tài liệu con?

Đặt chúng trong tài liệu gần nhất sở hữu các lệnh đó. Các quy tắc áp dụng trên toàn repo và index của tài liệu con nằm ở root. Một lệnh chỉ áp dụng cho một package thì nằm trong AGENTS.md của package đó. dox giải quyết xung đột theo khoảng cách: tài liệu gần hơn sẽ kiểm soát các chi tiết cục bộ, và tài liệu con không được làm yếu quy tắc của tài liệu cha. Sao chép cùng một lệnh vào mọi tài liệu con là nguyên nhân khiến một pass thông thường phải rewrite toàn bộ cây.

dox có đáng dùng cho một repository nhỏ không?

Thường là không. Một package chỉ có một lệnh test và một AGENTS.md dài hai mươi dòng sẽ xuống cấp chậm, và bạn có thể sửa ngay trong phút đầu tiên phát hiện ra vấn đề. dox đáng với chi phí sử dụng khi repository có nhiều ranh giới với các quy tắc khác nhau, hoặc có những contributor thiếu background cần thiết, vì khi đó chuỗi tài liệu đang đảm nhiệm phần việc mà không một người nào có thể tự mình đảm nhiệm.