- Published on
代码已经删了,旧文档为什么还在指挥 Agent?
- Authors

- Name
- hpoenixf
代码已经删了,旧文档为什么还在指挥 Agent?
一次 AI Coding 项目的知识维护复盘:让旧机制真正退出,让新知识按需进入。
一、我们删掉了一个功能,却还在告诉 Agent 使用它
2026 年 10 月,我们清理了一套已经不再使用的模型评测机制。
新的测试方式早已取代它,但检查仓库时,我们发现了一个奇怪的问题:
旧的评测命令还在,执行后只会提示功能已经退役;更麻烦的是,当前开发文档仍然告诉工程师应该运行这个命令。
也就是说:
代码知道这个功能已经不存在,文档却认为它还活着。
对于人类开发者,这可能只是一个过期说明。
但对于 Coding Agent,它有着不同的意义。
我们平时会让 Agent 读取项目说明、开发规范和任务计划,然后自主决定应该修改哪些文件、执行哪些命令、如何验证结果。
如果文档明确要求使用某个旧机制,即使源码已经不再支持它,Agent 仍可能认真地尝试执行,甚至认为应该先把这个机制修好。
这让我意识到:
在 AI Coding 项目里,文档不只是给人看的说明,它也是下一位 Agent 的行动依据。
删除一个功能时,如果它的旧说明还在影响后续开发,我们其实还没有彻底完成删除。
二、更危险的是:旧设计可能被重新实现出来
后来我们还遇到过另一个问题。
项目中的一条市场数据处理路线,曾经因为数据不完整而需要改进。我们设计过修复方案,也留下了部分测试和开发记录。
但随着架构升级,项目改用了一套更简单的数据接入方式。原来的处理路线已经不再需要。
这时就出现了一个容易忽视的风险。
旧设计中仍然写着:“系统应该新增这样的处理能力。”
这句话在当时没有错。
可放到今天,它要求实现的功能已经被新架构取代。
假如我们不区分历史设计和当前规范,直接把旧要求重新纳入正式规则,那么下一位 Coding Agent 就可能按照它,把刚刚淘汰的结构重新写回来。
过去正确的设计,不代表今天仍然应该执行。
我们最后没有删除当时的开发记录,也没有假装那项旧工作全部完成。
我们保留了它为什么被提出、当时验证过什么、哪些事情没有完成,同时明确让旧设计退出当前实施要求。
这样既能解释历史,也不让历史重新指挥今天。
这件事改变了我对工程文档的理解:
项目需要记住过去做过什么,但不应该永远服从过去的方案。
三、测试也可能成为旧机制的保护伞
另一次经历发生在测试代码里。
我们曾经升级过 Agent 的工具调用方式,让模型的调用请求、系统授权、实际执行和结果回传更加明确。
但部分测试仍然使用旧方式。
为了兼容,新旧方式之间存在一层自动转换代码。
这层代码相当“贴心”:测试没有明确写出的某些授权请求、来源信息和完成信号,它会按照旧约定自动补齐。
结果就是,测试看起来可以正常通过,但我们很难确认:
到底是现在的 Agent 正确完成了这些步骤,还是旧的测试辅助代码帮它补好了?
这很像升级一套考试系统,却还保留着会自动帮考生补答案的旧工具。
测试通过,不再足以说明被测试的行为真实成立。
后来我们把隐式转换改成更直接的测试方式,让每一次模型动作都尽可能清楚地写出来,再通过真正的执行边界验证。
原来有价值的授权、来源和恢复测试继续保留;只是旧的转换机制不再替系统制造隐含行为。
这给了我们一个很重要的提醒:
测试不只是在检查系统,也在定义我们相信系统应该怎样工作。
如果测试始终围绕旧结构编写,未来的 Coding Agent 就可能为了让测试继续通过,保留本来应该删除的代码。
所以删除旧机制时,不能简单地看到“很多测试还依赖它”,就断定它必须继续存在。
应该先问:这些测试是在保护真正必要的行为,还是只是在保护过去的实现方式?
四、我们甚至被自己的历史检查误导过
为了更好地维护项目,我们还建立过自动检查,希望发现规范遗漏、历史记录不一致和没有完成的开发工作。
但一次检查结果让我们发现:系统把某些已经正确删除的旧要求,误认为当前文档缺少内容。
也就是说,一个功能已经按规定退出,检查器却要求我们把它补回来。
问题不在于检查不够严格,而在于它没有正确理解“新增规则”和“删除规则”的区别,也没有处理好不同时间的历史记录。
后来我们修正了这类判断,只处理能够确认的错误,其他历史问题继续如实保留。
我们没有为了让检查结果全部变绿,就改写过去的失败记录。
这件事让我开始警惕:
知识维护工具本身,也可能成为制造新维护负担的来源。
如果它不知道一份文档是在描述过去还是约束现在,就可能把正常的架构演进误判为需要修复的问题。
五、于是,我们重新划分了知识的职责
经过这些经历,我们逐渐不再把“文档越完整越好”作为唯一目标。
不同资料应该回答不同的问题。
| 资料 | 它主要告诉我们什么 |
|---|---|
| 当前代码 | 系统今天实际上是怎样实现的 |
| 当前规范 | 系统现在应该遵守什么行为约定 |
| 开发计划 | 我们接下来希望改变什么 |
| 测试证据 | 某个版本、某个环境实际证明了什么 |
| 历史记录 | 当时为什么这样选择,遇到过什么问题 |
| 可复用方法 | 下次遇到类似情况,可以怎样分析和处理 |
它们都有价值,却不应该相互代替。
例如,三个月前的一份设计文档可以帮助我们理解为什么当时选择了固定模板,但不能据此认定今天仍然必须使用固定模板。
一次过去的测试成功,可以证明那个版本在对应范围内通过,却不能证明今天的新代码已经通过。
一份历史故障记录可以帮助我们排查相似问题,却不应该自动要求新系统继续采用当初的修复方式。
保存历史,不等于让历史拥有永久决定权。
六、让旧知识真正退出,让新知识按需进入
我们后来把这两件事一起纳入研发习惯。
删除一个机制,不只检查代码
我们会同时核对:当前开发说明是否还要求它存在,测试是否仍然依赖旧实现,工具说明是否继续教 Agent 使用旧接口。
如果没有真实使用者,就尽可能删除旧入口和不必要的兼容层。
但保留仍然有效的行为检查、必要的历史读取能力和原始证据。
这里要删除的是过时的规则和依赖,而不是已经发生的事实。
新知识也不应该无条件进入全局规则
另一个方向同样重要。
项目每修复一个问题,都可以产生新的经验。但如果我们把每条经验都加入 Agent 默认读取的全局说明,文档很快又会变成巨大的规则集合。
结果是,一个只负责改页面的 Agent,也要读完过去几个月的数据库、评测和研究故障记录。
内容越来越多,相关性反而越来越低。
所以我们开始采用一种更克制的方式:
日常开发首先读取少量必要规则和当前任务对应的文档;遇到具体的历史问题,再去查相应的设计和故障记录。
真正能够跨项目复用的方法,才考虑整理成通用指导。
而一次普通修复,只需要把实际结果记录在它所属的任务中,不必自动晋升成新的架构原则。
这也让我们重新理解长期工程记忆的目的。
它不是让 Coding Agent 永远携带全部历史,而是让它在需要的时候,能够找到可信且仍然适用的知识。
七、维护知识,实际上也是维护系统的演化能力
AI Coding 正在让新增代码变得越来越便宜。
但代码写入仓库之后,周围的文档、测试、约定和习惯也会逐渐围绕它建立起来。
于是,未来真正阻碍架构升级的,可能已经不只是代码依赖。
还可能是一份旧规范、一段过时的测试、一条早已不适用的开发指令。
我们原来以为,维护工程知识就是尽可能让 Agent 记住更多东西。
现在我反而认为,需要同时具备两种能力:
让真正有价值的经验容易被找到,也让已经过时的知识不再干扰当前开发。
当前规则负责指导今天,历史记录负责解释过去。
旧设计可以被理解,但不应被无条件复活。
新经验可以被保存,但不应自动进入每个任务的上下文。
最终,我觉得一个长期发展的 AI Coding 项目,不只是需要更会写代码的 Agent,还需要能够不断更新自己的工程知识体系。
知识维护的目标,不是让系统永远记住所有过去,而是让过去真正帮助今天,同时不再束缚明天。
取材边界:本文复盘了旧评测入口退役、市场数据旧设计退出、测试兼容机制清理及历史检查误判等真实工程记录。相关结果只证明各自范围内的修复,不代表整个项目的历史知识已经完成清理。
延伸阅读与交流
如果想继续了解工程知识怎样被选择性保存,可阅读文档按需加载与长期 History;如果更关注删除旧机制的长期成本,可读代码越来越便宜,为什么系统却越来越难升级?。另一篇周报大 Spec 怎样拆成可交付的三期?讨论复杂研发如何避免被外围需求拖住。
更多工程文章见 ETF Agent 工程文集。如果这些复盘对你有所帮助,欢迎在 GitHub 点个 Star。