SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-30

用 dox 自動維護 AGENTS.md

AGENTS.md 三週後就可能失效,讓代理程式相信錯誤指引。用 dox 從 repository 重新產生檔案,再像檢視程式碼一樣審查 diff。

3 週後,為什麼你的 AGENTS.md 內容會失效

AGENTS.md 會逐漸過時,因為沒有任何機制將它與程式碼連結。你在儲存庫呈現特定狀態的那天,手動寫下這份檔案。接著測試執行器變更、套件重新命名、服務遭到刪除,但檔案仍描述著 6 月的狀態。沒有任何步驟會失敗,因為沒有建置步驟會讀取它。

代理程式會讀取它,並相信其中的內容。這才是問題所在。沒有 AGENTS.md 的儲存庫會讓程式碼代理程式在執行操作前先查看環境。有錯誤 AGENTS.md 的儲存庫則會讓它停止查看,因為它已經有答案。它執行檔案中指定的命令,shell 回應 Missing script: "test",接著代理程式便開始猜測。它通常會修改 package.json,加入文件所承諾的指令碼。過時的檔案並非悄悄失效,而是導致你不希望發生的修改。

dox 是其中一種解決方式。它是一組為代理程式撰寫的規則,會將更新文件納入完成工作的必要步驟。因此,檔案會與導致其內容失效的程式碼,在同一個 commit 中一併變更。

dox 是什麼,以及它不是什麼

dox 是單一 Markdown 檔案。此儲存庫位於 agent0ai/dox,採用 MIT 授權;截至 11 August 2026,整個專案只有一個 3906-byte 的 AGENTS.md、一個 README、一個 LICENSE 和兩張圖片。無須安裝套件,也沒有執行階段。

這一點很重要,因為「產生器」這個詞會讓人以為它會剖析程式碼。實際上,沒有任何元件會剖析你的程式碼。dox 是編碼代理程式讀取的契約:代理程式是產生器,而 dox 是指令集,告訴它何時讀取文件、何時重寫文件,以及每份文件應採用什麼結構。

該檔案共有 10 個區段,其中 2 個負責實際工作。「編輯前閱讀」要求代理程式從儲存庫根目錄開始,逐一檢查所有計畫修改的路徑,並在目前工作階段沿著每條路徑讀取所有 AGENTS.md,不得依賴記憶。「編輯後更新」要求每次有意義的變更都執行一次 DOX,亦即在任務視為完成前先執行文件更新步驟。當用途、結構、工作流程、權限或使用者偏好發生變更時,此步驟會更新最近的擁有文件。

其餘內容定義結構。子目錄中的 AGENTS.md 預設區段順序為:用途、擁有權、區域契約、工作指引、驗證,以及子 DOX 索引。根目錄檔案包含全專案規則和最上層的子 DOX 索引;代理程式透過此索引尋找子文件。「結案」是代理程式在任務結束時執行的檢查清單:根據文件鏈重新檢查變更的路徑、更新最近的擁有文件、重新整理所有受影響的索引、刪除矛盾內容、執行現有驗證,並回報哪些文件是刻意未修改的。

將 dox 固定至單一 commit,而不是 main

此 repository 沒有 tags 或 releases,因此沒有可固定的版本號。請改為固定 commit。目前的 AGENTS.md 位於 commit f34ec7ad1055d3393887e5a2670e8cb7320c9165,日期為 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 應輸出 3906。如果輸出不同的數字,表示你沒有取得本指南所說明的檔案,因此請先讀取檔案,再決定是否信任其內容。如果誤植 commit hash,-f 會讓 curl 以 curl: (22) The requested URL returned error: 404 停止,且不寫入任何內容;接著 wc -c 會輸出 0。檔案遭截斷比沒有檔案更糟,因為 agent 會在不知情的情況下,只依循半份契約。

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 適用於尚未有 AGENTS.md 的 repository。如果已經有檔案,請勿覆寫。將 dox 區段放在現有內容上方,保留你自己的規則在下方,然後從頭到尾讀過一次。兩份互相矛盾的文件會使 agent 依循它最後讀到的內容。

接著在 repository 內要求你的 agent 進行第一輪處理。README 提供了確切文字:

Initialize DOX tree for this project now.

它會建立子目錄中的 AGENTS.md 檔案,以及指向這些檔案的索引。請先檢查處理結果,再決定是否信任:

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

find 輸出中的每個檔案,都應該在上方某處的 Child DOX Index 中出現。索引未提及的子文件,agent 可能會漏讀,因為它是 agent 找到不在目前行走路徑上的文件所依據的方式。

dox 能看見的內容,以及它無法得知的內容

建立樹狀結構的代理程式會讀取 repository,因此 repository 中的任何內容都可以納入 inventory:目錄結構、套件 manifest 與 lockfile、package.json、Makefile 或 pyproject.toml 中的 script、CI workflow 檔案、Dockerfile、entry point,以及 CODEOWNERS(如果有)。根據這些內容建立的 inventory 確實能自行維護。套件移動時,下一次掃描會一併移動描述該套件的項目。

以下內容都需要由你自行說明,因為 repository 中沒有這些資訊可供讀取:

  • 規則存在的原因。這能避免代理程式將其視為不必要的複雜度而移除
  • 兩條可運作路徑中哪一條受支援,以及哪一條正等待刪除
  • repository 以外的任何內容,例如 staging environment,或某個 dependency 為何固定在落後兩個版本
  • 你預計下週要做的事。這正是檔案目前有效與檔案實際有用之間的差異

dox 了解自身的限制。它自己的規則指出,Work Guidance 必須反映專案目前的標準或使用者的指示;如果目前尚未有任何標準或指示,就將該區段留白。Verification 必須反映既有的檢查,因此如果 repository 中沒有 test framework,該區段就應保持空白,直到 repository 中建立 test framework 為止。會自行捏造標準的 generated file 比空白區段更糟,因為代理程式之後會強制執行這個捏造的標準。

讓手寫意圖不被產生的清單覆寫

這是最容易讓人放棄產生式文件的問題。你撰寫一段文字,說明工作佇列必須維持單一取用者。3 週後,某次執行程序重新產生檔案,這段文字就消失了。它被埋在 40 行差異中,而其中大多數只是重新排列檔名,因此沒有人發現。

這裡需要兩種機制,而且兩者都要使用。

首先,將持久性的意圖移到其他檔案。設計決策及其理由應放在 為 agent 撰寫的 DESIGN.md,供人員閱讀的備註則應放在你 從 AGENTS.md 拆出的 HUMAN.md 中。AGENTS.md 接著只保留清單與本機契約;程式碼變更時,這正是應該同步變動的部分。

其次,將必須留在 AGENTS.md 中的意圖加上保護。用標記包住它,並將該區塊視為由人員維護:

## 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 -->

Markdown 註解不會顯示在頁面上,但 agent 仍會讀取。接著讓這個區塊的保留狀態可供檢查,這樣執行程序若刪除它,就會明確失敗。在每個 pull request 的 CI(continuous integration)中執行:

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 在區塊未變更時不會輸出任何內容,並以 0 結束。任何輸出都表示執行程序改寫了由人員維護的文字;此時應由人員核准變更,或將其還原。這項檢查不需要任何人記得執行,也能持續生效。

在 pull request 上重新產生,不要依計時器執行

重新整理文件的最佳時機,就是讓文件失效的那個 commit。將 DOX pass 放在同一個 pull request 中,與結構變更一起提交,diff 才會小到足以實際閱讀。

以下是強制執行的阻擋檢查:

#!/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

請依照儲存庫調整路徑。這種做法的價值在於,問題會在分支上立即失敗,修正成本較低,而且失敗原因能讓 reviewer 採取行動。

排程是備援,不是主要機制。每週執行的工作可以捕捉分支上沒有人注意到的問題,例如檔案因 rebase 而移動、套件在 merge 中遭到刪除,或文件仍指向已不存在的目錄。請在小型主機上執行,例如可用來在 VPS 上執行 coding agent的同一台主機,並讓它開啟 pull request,而不是直接推送到 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

這則註解是刻意保留的 placeholder。每個 agent 都有自己的 CLI(command line interface)與 non-interactive flag;從網頁複製、但與目前版本不相容的命令,在 cron 中執行時會失敗,而且沒有人會看到錯誤。請填入正確內容,並在排程前先手動執行一次腳本。|| exit 0 也很重要:當 tree 已經是最新狀態時,git commit 會搭配 nothing to commit, working tree clean 以非零狀態結束;在 set -e 下,這會把正常完成的執行回報為失敗。

每次 pass 都會消耗 tokens,因為「Read Before Editing」要求 agent 在每項工作中讀取完整流程。這就是取捨;如果你已經在計算 agent 執行的成本,就值得持續監控。

Monorepo:多個合約,單一索引

在包含 40 個套件的 repository 中,若只放置一份根目錄 AGENTS.md,重新產生內容時會出現沒有人閱讀的差異,而且文件大多與 agent 目前處理的工作無關。dox 的解法是 Child DOX Index:根目錄保存整個 repository 適用的規則,並指向子目錄;每個持久邊界則擁有自己的文件。如何配置這棵目錄樹,以及哪些工具會讀取巢狀文件,請參閱 適用於 monorepo 的巢狀 AGENTS.md 文件。

dox 改變的是審查範圍。修改 packages/api 的 pull request 應只在 packages/api 內產生文件差異,不應出現在其他位置:

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

如果該命令為只涉及一個套件的變更列出 6 個文件,表示目錄樹配置錯誤。可能是邊界劃分過於粗略,也可能是應放在根目錄的規則被複製到每個子目錄。dox 直接說明修正方式:廣泛適用的規則放在父層文件,具體細節放在子層文件。重複的規則會讓例行執行一次就改寫所有內容。如果相同規則確實適用於不同 repository,那是另一個問題;此時使用 在不同 repository 之間共用 agent skills 會更合適。

像檢視程式碼一樣檢視差異

產生的文件差異很容易在未閱讀的情況下核准,錯誤檔案就是因此發布的。請以檢視產生程式碼時的懷疑態度閱讀,並尋找以下四項內容。

  • 檔案現在列出的指令。合併前應自行執行該指令。虛構的建置指示是最常見的錯誤。
  • 刪除的說明性行。新增內容容易補回,真正的遺失通常發生在刪除內容。
  • 絕對路徑、主機名稱、內部 URL,或任何看起來像認證資訊的內容
  • 已不存在項目的清單項目。使用 ls 可在幾秒內確認

接著使用 wc -l AGENTS.md 檢查大小。root 檔案超過 200 行時,表示應將其拆分。這套流程的價值在於讓 agent 讀取少量且相關的內容,而不是讀取全部內容。

問題發生時

這次執行刪除了你的意圖區塊。 上方的 diff 檢查會列出遭移除的行。使用 git restore --source=origin/main AGENTS.md 從分支點還原檔案,然後以更狹窄的指示重新執行,明確指定允許修改的區段。

兩個分支都重新產生了檔案。 你會看到 CONFLICT (content): Merge conflict in AGENTS.md,且檔案內有衝突標記 <<<<<<< HEAD。不要手動編輯這些標記。此檔案是產生的,因此正確的處理方式是在合併後的樹狀目錄上重新執行一次。

代理程式完全忽略了檔案。 確認工具實際讀取的檔名。如果讀取的是其他檔案,使用 ln -s AGENTS.md CLAUDE.md 將它指向相同內容,並提交符號連結,這樣只需維護一份來源,不會讓兩份文件逐漸分歧。如果檔名已正確,但規則仍被略過,請先執行 為何 coding agents 忽略你的指示中的診斷,再次改寫文件。

樹狀目錄新增了無人建立索引的子項目。 將 find . -name AGENTS.md 的輸出與父文件中的索引項目進行比對。索引中沒有提及的子項目,代理程式就可能直接略過。

產生器不值得使用的情況

只有一個套件、一個測試命令,而且兩位開發者都熟悉儲存庫時,直接手寫這 20 行即可。20 行的 AGENTS.md 不會快速過時,不值得為此建立樹狀結構、索引、CI 檢查和每週工作。修改建置流程時重新閱讀即可。這就是全部的維護成本,而且低於周邊機制的成本。

當儲存庫具有沒有任何單一人員能完整掌握的界線時,才值得投入成本使用 dox:例如多個規則不同的套件,或不了解背景的新貢獻者。價值不在於產生的文字,而在於文件能成為 pull request 可能檢查失敗的項目。這是儲存庫中的檔案能持續更新的唯一原因。

FAQ

使用 dox 需要安裝任何項目嗎?

不需要。dox 是單一 Markdown 檔案,採用 MIT 授權;截至 11 August 2026,該 repository 沒有套件,也沒有 releases。將其內容複製到專案的 AGENTS.md,coding agent 就會依據其中的規則執行。固定複製版本的 commit,本文撰寫時為 f34ec7ad1055d3393887e5a2670e8cb7320c9165,並在 commit message 中標明該版本,日後才能確認此 tree 是依據哪個規則版本建立。

如何避免重新產生內容時刪除我手寫的規則?

將意圖與清單分開。持久性的理由放在獨立文件中,任何必須保留在 AGENTS.md 內的內容則放在標記區塊中。接著在 CI 中檢查該區塊:從分支與 origin/main 擷取內容,使用 sed 比較兩者,並使用 diff 在有任何差異時使 build 失敗。之後由人員核准或還原變更,而不是讓變更藏在大型 diff 中而未被注意。

應多久重新產生一次 AGENTS.md?

在使其內容不正確的 pull request 中重新產生。結構變更與其文件應放在同一個 diff 中,因為這是有人能同時檢閱兩者的唯一時機。每週排程執行是補救分支中遺漏之 drift 的備援方式,而且應開啟 pull request,而不是直接 commit 至 main。

Build command 應放在根目錄的 AGENTS.md,還是子目錄中?

放在擁有該命令的最近文件中。全 repository 規則與子目錄索引放在根目錄。只適用於單一 package 的命令,放在該 package 的 AGENTS.md 中。dox 會依距離解決衝突:較近的文件控制本地細節,子文件不得放寬父文件規則。將相同命令複製到每個子目錄,才會導致例行執行時重寫整個 tree。

小型 repository 使用 dox 值得嗎?

通常不值得。單一 package、單一 test command,以及 20 行的 AGENTS.md 退化得很慢,發現問題後可在 1 分鐘內修正。當 repository 具有多個適用不同規則的邊界,或有缺乏背景知識的貢獻者時,dox 才能發揮價值,因為此時文件鏈正在處理沒有任何單一人員能獨自處理的工作。