AI Agent、架构决策记录与工程上下文治理:团队如何把隐性约束留在仓库里。

0 阅读9分钟

ADR 不是新概念。AI Agent 进入代码库后,它的价值被重新放大:代码库必须留下当初为什么这样做。

导语

很多团队都遇到过同一种维护现场。

接手一段老代码,看到一个明显不够优雅的实现:多绕了一层判断,缓存策略看起来保守,接口字段命名也不像今天的风格。第一反应通常是重构掉它。

但问题在于,这段代码也许不是随手写坏的。它可能绕过了某个线上兼容问题,也可能牺牲了一点性能去换稳定性,还可能是为了适配一个已经没人记得的外部约束。

如果作者还在,问一句就能知道答案。作者离职、聊天记录散落、评审文档过期时,剩下的就只有猜,Agent 凭感觉直接“优化”,然后把当年的坑重新踩一遍。

这背后的根因很简单:代码记录了​怎么做​,却没有记录​为什么这么做​。而在维护、重构、协作和 AI 介入开发时,“为什么”往往才是最贵的上下文。
inline-01-agent-reading-adr.jpg

图:代码告诉 Agent 系统怎么运行,ADR 告诉它当初为什么这样设计。

ADR 记录的是技术决策,不是流水账

ADR,全称 Architecture Decision Record,通常翻译为​架构决策记录​。它是一种轻量文档,用来记录重要技术决策、决策背景、被放弃的备选方案,以及这些选择会带来的后果。

它最早由 Michael Nygard 在 2011 年提出。核心思想并不复杂:把架构决策当成代码资产的一部分,放进仓库,纳入版本控制,随着 PR 一起 review。

一份足够可用的 ADR 不需要复杂模板。一个典型结构可以很短:

# ADR-007: 用带 TTL 的 LRU 缓存替代 sync.Map

Status: Accepted
Date: 2026-07-14

Context:
chatModelCache 当前使用 sync.Map,没有淘汰策略。压测中内存随请求量持续增长,存在 OOM 风险。

Decision:
改用带 TTL  LRU 缓存,容量上限 10000,过期时间 30 分钟。

Consequences:
- 内存上限可控,降低 OOM 风险
- 缓存命中率会略有下降
- 引入新的缓存依赖,需要纳入升级维护

Supersedes:
ADR-003

真正重要的不是字段数量,而是几个约束:

约束含义工程价值
一决策一文件每个重要决策单独成篇,编号递增可引用、可检索、粒度清晰
和代码同仓放进 git,跟随 PR 一起演进决策与实现拥有同一条生命周期
状态明确Proposed、Accepted、Deprecated、Superseded一眼判断当前决策是否仍然有效
可推翻但不抹除新 ADR 推翻旧 ADR,旧记录保留保留系统演进轨迹,避免重复争论

这套机制真正保存的不是结论,而是​当时为什么只能这么选​。三个月后有人质疑这个设计,仓库里能给出答案;三年后系统已经改过很多轮,团队仍然能看见决策是怎么一步步走到今天的。

讨论可以在协作工具里,结论必须跟代码走

很多团队会把技术评审放在飞书、Confluence、Notion 这类在线协作工具里。这当然合理。讨论过程需要评论、@、多方协同、富文本和临时草稿,不一定适合全部塞进代码仓。

但问题出在另一处:讨论结束后的结论,如果只留在线文档里,就会和代码分家。

代码改了三版,评审文档还停在初稿。git blame 能查到谁改了这一行,却查不到当初为什么这么改。新人接手时找不到上下文,AI Agent 接手时更找不到。

更稳妥的分工是:

内容适合位置原因
讨论过程在线协作工具适合多人评论、临时方案、争论和非工程角色参与
决策结论代码仓 ADR适合版本控制、diff、review、检索和长期维护

也就是说,讨论可以留在协作场,但​结论必须跟着代码走​。

甚至从长期看,讨论本身也有进入仓库的价值。只是当下最该先做的是把结论收进来,因为它成本低、收益直接,也最容易被 Agent 消费。
mermaid-01.png

图:讨论可以发生在协作工具里,但被接受的技术决策应进入仓库并随代码演进。

ADR 过去难坚持,是因为收益太晚

ADR 不是新东西。它提出很多年了,很多团队也试过,但常见结局是开头认真写几篇,后面慢慢停掉。

原因不复杂:写 ADR 的成本发生在现在,收益却押注在未来。

写的人要补背景、整理取舍、描述后果。可当下代码照样能合,需求照样能上线,团队也不会因为少写一条 ADR 立刻出事故。它的读者是“未来某个可能接手的人”。这个人可能永远不会来,来了也可能直接找你问一句。

所以 ADR 过去更像一种职业自觉。自觉当然重要,但它很难对抗交付压力。

但现在 ​AI Agent 改变了这笔账​。

AI 让 ADR 的写作成本也下降了

AI 不只改变了读者,也改变了写作者的成本。

过去写 ADR 是从空白页开始。现在可以让 AI 先基于代码、PR diff、测试和变更说明、聊天记录等起草一版“现状解释”,人再补上 AI 读不出来的部分。

这个分工很清楚:

角色更擅长记录什么
AI代码当前做了什么、模块关系是什么、变更影响哪些路径
当初为什么选这个方案、否掉了什么方案、有哪些隐性约束

AI 可以把“是什么”写得很快,人只需要补少量“为什么”。这会把 ADR 从额外写作,变成一次​决策确认​。

甚至对存量代码也一样。过去给老代码补 ADR 接近考古,很少有人愿意做。现在可以让 AI 扫模块、生成现状快照,人再挑关键决策补理由。存量系统第一次有了低成本补上下文的机会。

没有 ADR,Agent 会自信地猜错

这不是文档洁癖,而是 AI 协作下的可靠性问题。

一个没有决策记录的代码库,人看不懂时还能问人、翻历史、凭经验判断。Agent 主要依赖仓库中的显式上下文。没写下来的约束,对它来说就等于不存在。

典型风险包括:

场景没有 ADR有 ADR
重构老代码Agent 把故意保守的实现当技术债优化掉Agent 读到历史约束,知道这段代码不能简单替换
方案反复换一个人或 Agent,又提出三个月前已否掉的方案Supersedes 链条记录旧方案为什么被否
架构漂移每次局部修改都按当前上下文自由发挥ADR 提供架构基线,变更要么对齐,要么显式推翻
隐性约束丢失兼容性、灰度、依赖限制只存在于人脑中约束变成 Agent 可检索的工程上下文

ADR 在这里起到的作用,是给 Agent 加一道“先别急着改”的刹车。它把人脑里的隐性知识,转成机器能读到的​显性上下文​。
inline-02-agent-refactor-risk.jpg

图:没有决策记录时,Agent 很容易把历史约束误判成可以清理的技术债。

ADR 与测试、契约、CI 不是一类护栏

在 AI 工程里,常见护栏包括测试、CI、类型检查、接口契约、lint 规则。这些工具守住的是“代码现在对不对”。

但它们回答不了另一个问题:这段代码为什么长这样?

测试能告诉 Agent 不能破坏某个行为,但不能解释这个行为当初为什么存在。接口契约能告诉它字段必须叫这个名字,但不能解释为什么选了这种边界。CI 能拦下回归,却不能拦下“看似合理、实则误解意图”的改动。

ADR 补的是​意图层​。

护栏主要回答
测试行为有没有坏
类型和契约接口边界有没有破
CI工程规则有没有过
ADR这套设计为什么成立

测试和契约让 AI 不轻易改坏,ADR 让 AI 不轻易误解。

落地时要轻,不要追求完美

ADR 最常见的失败方式,不是写得不够正式,而是写了几篇就停了。要让它持续,关键是门槛必须低。

可以从五条规则开始:

  1. 只记录重要决策。数据模型、接口契约、模块边界、关键依赖、上线和回滚策略,值得写;普通实现细节不必写。
  2. 一篇 ADR 控制在十分钟内能完成。背景、决策、后果、状态、是否推翻旧决策,足够用了。
  3. 和代码放在同一个 PR。决策和实现一起 review,一起合入。
  4. 旧 ADR 不删除。决策过期时,用新 ADR 标注 Supersedes,而不是覆盖历史。
  5. CI 做软提醒。改动 schema、IDL、核心配置时提示“是否需要 ADR”,不要一开始就硬卡。

结语

ADR 本身没有变。变的是代码库的读者。

过去,它写给某个不确定的未来同事,所以收益遥远,靠自觉维持。现在,AI Agent 成了代码库里的高频读者。它不会去工位问作者,也不会天然理解团队历史。它只能读到仓库里被写下来的东西。

所以,AI 时代的 ADR 不再只是“给后来人留个交代”的工程美德,而是让 Agent 正确协作的​上下文基础设施​。

代码需要告诉机器怎么运行,也需要告诉机器为什么这样运行。ADR 的价值,正是在这里被重新激活。