这种经历大家都有过。
你加入一个新团队,打开代码仓库,看到一份写得漂亮的 README.md、一份架构文档,还有一堆 Markdown 文件,讲解系统怎么运作。
你开始读。
几分钟后你发现,架构图和实际实现对不上。文档里提到的工具早就不存在了。有些配置项已经变了,还有几个重要组件压根没写进去。
文档是在那儿,可你能信它吗?
这是软件工程里最常见的问题之一:文档慢慢和源代码脱节了。
原因不是开发者不懂文档的重要性,而是维护文档是件持续的事,太容易忘。
但要是能把这份责任交给 AI Agent 呢?
源代码才是唯一的事实来源
先从一个简单的原则说起:
源代码永远是唯一的事实来源。
文档是系统运作方式的一种人类友好呈现,帮开发者理解架构、发现可用工具、了解约定、带新成员上手。
但文档绝不该凌驾于实现之上。
实现一变,相关文档就该检查,必要时更新。
难的是判断文档什么时候需要关注。
有个简单的小技巧。
在 Markdown 文件里加上 Git commit 引用
如果每份技术 Markdown 文档都带上元数据,说明它最后一次是基于哪个 commit 审阅的,会怎样?
比如:
---
commit: '9b6f166af5227ff4093af7347084d8f7d2a81e4f'
updated: '2026-11-04'
---
就这么简单。
两条简单的信息:
-
commit:文档最后一次审阅并同步时所对应的 Git 提交。 -
updated:文档最后一次审阅的日期。
这个小小的补充带来了一个非常有用的东西:一个参照点。
打开一份 Markdown 文档,就能立刻看到它上次审阅的时间,以及那次审阅落后代码库多远。
更重要的是,AI Agent 可以把那个提交作为审阅文档的起点。
比如,文档引用的提交是 9b6f166,Agent 就可以检查该提交之后发生的所有变更,判断其中是否有变更影响到了文档。
这样一来,文档和源代码之间就有了一条简单而明确的关系。
认识 sync-docs 技能
设想有一个名为 sync-docs 的 Agent 技能。
它的职责很明确:
确保技术文档准确反映代码库的当前状态。
工作流大致如下:
- 找出带有同步元数据的 Markdown 文档。
- 读取每份文档 frontmatter 中记录的提交。
- 将该提交与当前 HEAD 进行比较。
- 审阅该提交之后引入的变更。
- 找出哪些变更影响了文档。
- 检查当前实现,核实文档是否准确。
- 更新文档,使其反映当前实现。
- 更新
commit和updated元数据。 - 提交一个包含文档变更的 pull request。
例如,Agent 可能会发现,自上次文档审阅以来:
- 引入了一个新服务。
- 某个现有 API 发生了变化。
- 某个配置选项被移除。
- 新增了一个开发工具。
- 架构经过了重构。
- 某个依赖被替换。
然后它可以检查相关源文件,并据此更新文档。
请注意一个关键点:Agent 并不是简单地把最新的 Git 变更总结一下、追加到文档里。
它需要理解现有文档,检查当前实现,判断文档是否仍然准确描述了系统。
目标是准确,而不只是有动作。
实现会是什么样?
我们来具体看看。
需要两样东西:
- 一个知道如何同步文档的 Agent 技能。
- 一个 GitHub Agentic Workflow,定期调用该技能并发起 pull request。
关键区别在于:逻辑由技能负责,工作流只负责编排。
1. 实现 sync-docs 技能
我们来创建以下结构:
.agents/
skills/
sync-docs/
SKILL.md
SKILL.md 文件包含 Agent 必须遵循的实际指令。
下面是一个示例实现:
.agents/skills/sync-docs/SKILL.md
---
name: sync-docs
description: Review and synchronize Markdown
documentation against the current source code.
---
# Sync Documentation
Your responsibility is to ensure that technical
documentation accurately reflects the current
implementation in the repository.
The source code is always the source of truth.
## 1. Discover documentation
Find all Markdown files containing the following
frontmatter fields:
- commit
- updated
These fields identify the last source-code commit
against which the document was reviewed.
Ignore files without this metadata.
## 2. Review each document
For every document:
1. Read its recorded commit.
2. Verify that the commit exists in the repository.
3. Identify the source files relevant to the
document.
4. Inspect changes introduced since the recorded
commit:
git diff <recorded-commit>..HEAD
5. Inspect the current implementation of the
affected components.
6. Determine whether the documentation still
accurately describes the implementation.
Do not assume that every code change requires
a documentation change.
## 3. Update documentation
When documentation is outdated:
- Update incorrect descriptions.
- Add missing architectural information.
- Remove references to obsolete tools,
components or configuration.
- Update examples that no longer match
the implementation.
- Preserve useful explanations and the
existing writing style.
Never invent implementation details.
Never modify application source code.
## 4. Update synchronization metadata
After successfully reviewing a document,
update its frontmatter:
commit: <current HEAD commit>
updated: <current date>
The commit must represent the exact source-code
revision that was reviewed.
If the review cannot be completed confidently,
do not advance the metadata.
If the document is already accurate, its content
does not need to change, but its review metadata
should still be updated.
## 5. Report findings
At the end, provide a summary containing:
- Documents reviewed.
- Documents updated.
- Documents already accurate.
- Documents that could not be reviewed.
- Architectural inconsistencies discovered.
- Potential bugs or unexpected implementation
changes worth investigating.
Do not fix application code or architectural
issues as part of this task.
Leave those findings for human review.
整个技能就这些。
有意思的是,它对 GitHub、拉取请求和定时调度一无所知,只专注一件事:让文档与源代码保持同步。
正因如此,它才能被反复使用。你随时可以在编码 Agent 中手动调用:
使用 sync-docs 技能,检查并同步本仓库的技术文档。
也可以把它作为更大 Agent 工作流的一环。
2. 用 GitHub Agentic Workflows 实现自动化
接下来把它自动化。
创建以下文件:
.github/
workflows/
sync-docs.md
这个工作流刻意保持简单,不包含任何文档同步指令,因为这些指令已经放在我们的 skill 里了。
它唯一的职责就是调用 skill,并根据结果创建一个 PR。
.github/workflows/sync-docs.md
---
name: Sync Documentation
on: weekly on monday
permissions:
contents: read
pull-requests: read
safe-outputs:
create-pull-request:
title-prefix: "[docs-sync] "
labels:
- documentation
allowed-files:
- docs/**
- README.md
---
# Synchronize Technical Documentation
Your task is to maintain the technical
documentation in this repository.
## Instructions
1. Read and follow the skill located at:
`.agents/skills/sync-docs/SKILL.md`
2. Invoke the `sync-docs` skill and let it
perform the complete documentation review.
3. Inspect the resulting changes and findings.
4. If documentation or synchronization
metadata has changed, create a pull
request containing:
- The updated Markdown documents.
- A summary of documents reviewed.
- A summary of documentation changes.
- Any architectural inconsistencies or
potential issues discovered.
5. If there are no changes to propose,
do not create an empty pull request.
## Important
Never merge pull requests automatically.
All documentation changes must be reviewed
and approved by a human.
Do not modify application source code.
这个工作流使用定时触发器,调用我们可复用的技能,并在有变更需要提交时创建 PR。
可以看到,工作流本身的逻辑非常少。这是有意为之。
我们不希望同一套流程维护两份实现。
技能定义文档如何同步,工作流则定义何时执行,以及如何处理结果。
GitHub Agentic Workflows 可以通过 gh aw CLI 把这些 Markdown 工作流定义编译成标准的 GitHub Actions 工作流文件:
gh extension install github/gh-aw
gh aw compile
编译过程会在 Markdown 源文件旁生成一个 .lock.yml 工作流。你需要把这两个文件都提交到仓库。
你可以选择不同的执行频率,比如每两周一次或每月一次,具体取决于代码库的演进速度。
更多信息请参阅 GitHub Agentic Workflows 文档。
注意:本示例假设所选 Agent 运行时支持该 skill 格式,且该 skill 在其执行环境中可用。工作流必须配置为加载并调用它;仅引用文件路径并不会自动执行 skill。
3. 同步 PR 能带来什么?
设想工作流创建了这样一个 PR:
标题:[docs-sync] Synchronize architecture and tooling documentation
它可能包含:
| 文档 | 结果 |
|---|---|
docs/architecture.md |
更新了服务依赖关系 |
docs/development-tools.md |
删除了过时的 CLI 参考 |
docs/deployment.md |
已审阅,无需修改内容 |
docs/api.md |
更新了端点描述 |
PR 描述中还可以列出值得关注的发现:
- 架构文档描述的是同步交互,但实现现在已改用异步消息传递。
- 代码中存在某个配置选项,但文档里没有。
- 某个内部工具仍出现在文档中,但似乎已被移除。
这正是有意思的地方。
这个 PR 不再只是一次文档更新,它还为工程团队提供了又一次审视系统的机会,去发现那些平时容易被忽略的问题。
我们用 AI 维护文档,同时也在借助文档评审来提升软件本身的质量。
为什么用 commit 而不是时间戳?
时间戳只能告诉我们某件事发生的时间。
Git commit 则能精确告诉我们审阅的是哪个版本的源代码。
这个区别很重要。
假设某份文档上次审阅是在两周前。这两周里,代码库可能发生了很大变化,也可能完全没有与该文档相关的改动。
有了 commit 引用,Agent 就能查看实际改动,而不是根据文档的更新时间去猜测。
这也让整个过程变成增量的。
Agent 不必每次运行都重新梳理项目的完整历史,可以从上次审查过的 commit 出发,只调查那之后发生了什么。
当然,commit 引用并不保证文档一定准确,它只是上一次成功审查的记录。那次审查的质量依然重要。
为什么不自动合并 PR?
这里有个重要细节:工作流应当创建 pull request,绝不自动合并文档更新。
为什么?
因为审查这些 PR 本身就很有价值。
设想 Agent 更新了一份架构文档,因为它发现某个服务的行为与文档描述不符。
审查过程中,开发者可能会意识到实现已经偏离了原本的架构设计。
又或者,Agent 发现了一处未记录的配置变更、一个意料之外的依赖,或一个已不再使用的工具。
这些都是有用的信号。
一次文档同步 PR,可以成为发现架构不一致、意外复杂度、文档缺失乃至潜在 bug 的机会。
Agent 负责调查并提出更新,开发者审查改动、质疑结论,再决定是否合并。
这样既让人始终参与其中,又大大减轻了维护工作的负担。
几点值得注意的事项
实施时有几个关键细节需要处理好。
1. 只在审查成功后才更新 commit
frontmatter 中的 commit 应当代表实际审查过的最新代码版本,而不是简单的最新 HEAD。
如果 Agent 没能检查某份文档,或无法确信它是否准确,就不应悄悄推进 commit 引用。
2. 不要为了改而改
如果源代码变了,但文档依然准确,就没有理由修改文档内容。
Agent 仍可更新审查元数据,记录该文档已对照更新的 commit 检查过。
3. 绝不自动合并
始终创建 pull request,交由开发者审查。
除了防止错误的文档更新进入主分支,这些审查还能暴露原本可能被忽视的问题。
4. 明确审查范围
并非每个 Markdown 文件都需要描述整个代码库。
架构文档可能依赖多个服务的变更,而工具参考文档可能只依赖某个特定目录。
该技能应利用文档内容来判断仓库中哪些部分与之相关。
5. 妥善处理无效或不可用的提交
文档引用的提交可能在本地已不存在,或者根本不在当前仓库历史中。
Agent 不应猜测从哪里开始。它应将该文档标记出来交由人工排查,而不是悄悄替换掉引用。
更大的图景
我尤其喜欢这个思路,因为它改变了我们对文档的认知。
如今,文档往往被视为开发功能、启动项目或新人入职时才写的东西。
然后慢慢就被遗忘了。
但文档应该更像代码:需要持续维护。
我们的仓库里早已有自动化测试、linter、格式化工具、依赖更新和安全扫描在运行。
文档为什么不能有自己的维护工作流?
只需一小段元数据、一个可复用的 AI 技能,再加上一个定时 GitHub 工作流,就能让文档维护变成持续过程,而非偶尔的清理工作。
还有一个额外好处:每次同步 PR 都给团队一次机会去审视系统、质疑架构决策、发现不一致之处。
源代码在演进,文档也应随之演进。
或许最棒的一点是,下一位加入团队的开发者不必再怀疑:自己读的架构文档描述的到底是不是今天的系统。
他们能看到文档上次审查的时间、对照的是哪个代码版本,并相信团队有一套流程让它保持最新。