最近一段时间,我越来越少担心 AI 会不会写代码。

真正让我不太放心的,是它写完代码之后那段过于熟练的总结:

已完成重构
已运行测试,全部通过
修改范围符合要求
没有影响其他功能

01-假完成章

如果只是让 AI 写一个一次性脚本,我可能看一眼运行结果,也就过去了。但当我开始用 Codex、Claude Code 这类 Coding Agent 长期维护项目以后,这几句话就没有那么容易让人安心了。

它读取的项目说明是不是最新版本?
它有没有修改我没让它动的目录?
它说测试通过,测试到底在哪个代码状态下运行的?
测试结束后,它是不是又继续改了文件?
这次交付经过了哪些环节,现在还能不能算有效?
换一个 Agent 接手时,它知不知道项目过去为什么作出某项决定?

这些问题听上去很工程化,实际上很好理解。

假设你请人装修房子,对方告诉你水电已经验收通过。这个结论当然有价值,但你还需要知道:验收的是不是现在这套水电?验收结束后墙里有没有继续改线?验收记录对应的是哪个施工方案?

AI 编程也逐渐出现了类似的问题。

代码写得越来越快,但“完成”这个结论究竟对应哪份代码、哪些规则和哪次验证,反而越来越难说清楚。

这也是我开发 Agent Engineering Toolkit,简称 AET 的原因。

它不是另一个替你写代码的 AI,也不负责告诉 Agent 应该怎么思考。它更像是放在 Coding Agent 旁边的一套工程记录和验证工具:检查 AI 读取的规则、约束它的改动边界、记录真实执行过的命令、判断证据有没有过期,并把项目中的关键决定与原始资料联系起来。

项目目前已经发布到 v1.3.0。相比最初的 v1.0,它已经不再只是给一次 AI 任务生成“验收收据”,而是在逐渐形成一套轻量的 Agent 工程档案。

AI 编程真正缺少的,可能不是更聪明的模型

很多 AI 编程产品都在解决同一个方向的问题:让模型写得更准、改得更多、执行得更自动。

这些能力当然重要。

但当 Coding Agent 真正进入日常开发之后,我逐渐发现,很多风险并不是模型不会写代码,而是整个过程缺少清晰的边界。

例如,我让 AI 给一个股票分析项目增加基金分析能力。我的真实要求可能是:

基金模块只改变分析对象,模型配置、专家视角、报告结构和风险控制逻辑,应该尽量继承股票模块的现有设计。

AI 可能很好地理解了需求,只增加少量代码;也可能为了快速实现功能,复制出另一套相似逻辑;还可能顺手重构十几个文件,把一个局部需求变成全局改造。

最后,它们都可能交付一段相似的总结:

基金分析功能已经完成,并复用了现有架构

这时,光看自然语言结论是不够的。

真正需要核对的是:它到底改了哪些文件,改动是否落在批准范围内,是否突破了预先约定的变更规模,需要提供的验证有没有真正完成。

AET 的 review 就是在做这件事。

在 Agent 开始修改代码前,可以先用一份简单的意图文件说明本次任务允许修改哪些路径、变更规模大致是多少,以及交付前需要提供哪些证明。任务结束后,AET 会把真实的 Git 变更与这份约定进行对照。

它不会评价代码写得优不优雅,也不会凭空理解复杂业务。它只先回答一个更基础的问题:

这次 AI 的实际行动,有没有超出人类批准的范围?

这种机制在 AET 中叫作 Intent Gate,可以理解为“意图门禁”。

02-意图门禁

我认为它的重要性在于,它把“我大概让 AI 改这些东西”,变成了一份可以复查的合同。尤其是经过多轮对话后,人的要求和 Agent 的理解都可能逐渐漂移,有一份明确边界,比依赖聊天记录靠谱得多。

“测试通过”不代表现在这份代码通过了测试

AET v1.0 已经可以使用 trace 记录一条命令是否真实运行,并把审计、改动审查和执行记录组合成 Evidence Pack。

但项目继续迭代后,我发现这里还存在一个很容易被忽略的问题:

测试确实运行过,不代表眼前这份代码就是当时接受测试的代码。

例如,Agent 先运行测试,得到全部通过的结果,随后又顺手修改了两个配置文件。此时“测试通过”这件事仍然是真的,但它证明的是修改配置之前的代码,而不是当前准备交付的版本。

如果只看测试日志,很难发现这个差别。

因此,AET v1.1 增加了 workspace_snapshot,也就是工作区快照。

从这一版开始,审计、改动审查和命令执行记录,都会保存当时的 Git 提交位置,以及已跟踪和未跟踪文件状态的确定性摘要。生成证据包时,AET 会对比这些快照,判断审查、测试和最终打包对应的是不是同一个工作区。

用不太技术化的话解释,就是每完成一个关键步骤,AET 都给当时的项目状态拍一张“指纹照片”。

如果测试之后代码没有变化,结果可以显示为精确匹配。

如果 Git 提交没有变,但工作目录里的文件又被修改过,它会明确告诉你工作区已经不同。

如果连 Git 提交都变了,它也不会再把之前的测试结果悄悄挂到新的代码上。

这里有一个我很在意的设计:代码后来改变,不会让过去真实运行过的测试突然变成失败。

测试当时通过,仍然是 PASS;但这份证据对当前交付已经过期,交付状态会被标记为 STALE

这比简单地把所有事情压成“通过”或“不通过”更符合现实。

一张昨天的体检报告没有造假,但它不能自动证明你今天的身体状态。证据是真的,与证据现在是否仍然适用,是两个不同的问题。

03-证据过期

AET v1.2 又进一步细化了这种失效原因。它可以区分是任务意图发生了变化、配置发生了变化、未跟踪文件集合改变了,还是整个工作区或 Git 提交已经不同。

对于普通用户来说,不必记住这些状态名。只需要理解一件事:

AI 不能再拿旧状态下的测试结果,为后来修改过的代码背书。

一次 AI 交付,不能只留下几份互不相关的报告

随着审计、范围检查、执行记录和证据包逐渐增加,又会出现下一个问题。

这些产物都存在,但它们之间是什么关系?

某份审计报告属于哪一次任务?
当前任务已经完成范围审查了吗?
测试已经执行,但证据包是否生成?
证据包生成后,项目有没有再次变化?
这次交付究竟是正在处理中,还是已经正式关闭?

在 v1.0 中,这些文件更像几张独立的检查单。它们各自有用,却缺少一条完整的交付时间线。

AET v1.2 因此增加了可选的 Run Manifest

它可以理解成一次任务的本地交付账本。

一项任务从绑定意图开始,随后可以经历审计、改动审查、执行证明、证据打包,最终关闭。如果中途工作区发生变化,它会进入过期状态,而不是继续沿用原来的完成结论。

它大致记录这样一条过程:

已绑定任务意图 → 已完成规则审计 → 已完成改动审查 → 已执行验证 → 已生成证据包 → 已关闭

任何关键文件在中途发生变化,都可能让这条证据链变成 STALE

Run Manifest 采用追加记录的方式保存状态变化,不会静默改写过去发生过的事情。它也不会接管 Agent,不会主动选择命令、调用模型、失败后自动重试,更不是一个复杂工作流平台。它只是忠实记录:一次交付走到了哪里,为什么从一个状态进入了另一个状态。

这项能力看起来是为团队交付准备的,但我认为它对个人开发者同样有价值。

个人使用 AI 编程时,经常会在多个任务之间来回切换。今天改一半,明天继续;中间临时修了另一个问题,顺便更新了配置。等准备发布时,很容易记不清哪些测试是在什么时候运行的,哪些报告还对应当前版本。

Run Manifest 不会替你管理项目,但它至少能避免把不同阶段的证据混成一个模糊的“应该没问题”。

AI 说它读过项目说明,我们究竟能证明什么?

AET v1.3 增加的第一项能力叫 Context Manifest,也就是上下文清单。

这是一个我认为很符合真实 Agent 使用场景的功能。

现在维护稍微复杂一点的项目,往往会给 AI 准备很多说明材料:

AGENTS.md 里写全局规则,某个目录里还有局部说明;Skill 文件告诉 Agent 如何完成特定任务;架构文档解释模块关系;项目记忆记录过去的设计选择。

理论上,Agent 应该先阅读这些内容再开始工作。

问题是,当 Agent 说“我已经阅读了相关说明”时,我们到底能证明到哪一步?

它可能真的读取了文件,也可能只是扫描到了文件名;可能文件在任务开始后被修改;也可能它读过,但并没有正确理解。

一个容易制造虚假安全感的工具,会直接告诉用户:

Agent 已理解全部项目上下文。

AET 刻意不这样说。

aet context discover 可以发现当前工作区内可用的项目指令和 Skill,并记录它们的 SHA-256 哈希。这能够证明某个文件在当时确实存在,内容是什么。

aet context record --read 则可以记录 Agent 或宿主声明自己读取过某份材料。

但在证据等级上,这仍然只是一条 attestation,也就是声明或背书。它不能证明模型真的看见了全部内容,更不能证明它理解并正确使用了这些内容。AET v1.3 明确将文件发现与哈希视为本地证据,而把“已读”单独保存为 Agent 声明。

这听起来似乎有点较真,但我觉得恰恰是 Agent 工程里最需要的边界。

我们经常把“文件已经提供给模型”“模型说自己读过”和“模型正确理解了文件”当成同一件事。实际上,这是三个不同层次。

Context Manifest 不会试图证明最后一层。它只把目前真正能验证的事情记录下来:

哪些上下文文件在任务发生时可以被发现
它们当时的内容哈希是什么
Agent 声称读取了哪些文件
这些文件后来有没有改变

几天后再次运行 verify,如果某份项目说明已经被修改,之前的读取声明不会继续被默认为有效。系统会明确告诉你,当前上下文与当时记录的上下文已经不同。

这对长期运行的 Coding Agent 特别重要。

因为很多 Agent 出错,并不是代码能力不足,而是使用了已经过期的项目说明,或者沿用了上一次任务留下的上下文。

项目为什么这样设计,不能永远只存在于某次聊天里

v1.3 增加的第二项核心能力,是 Decision Ledger,决策账本

做项目时间长了以后,最难保存的通常不是代码,而是代码背后的决定。

为什么这个功能没有采用最简单的实现?
为什么没有引入某个依赖?
为什么基金模块必须继承股票模块,而不是复制一份?
为什么评分机制被放弃,只保留态度和证据?
为什么某个数据源后来被替换?

这些决定刚做出时,往往非常清楚。它们可能来自一次 Issue 讨论、一份设计文档、一段实验结果,或者一次对现有架构的复盘。

但几个月后,代码还在,理由却已经散落了。

尤其是使用 AI 开发时,很多设计讨论发生在临时对话中。对话结束以后,新 Agent 只能看到最终代码,不知道哪些方案曾经被认真考虑过、哪些路线已经被否定。

结果就是,同一个问题可能被反复讨论,甚至重新走回过去已经证明不合适的方案。

Decision Ledger 的作用,是把关键项目决定保存成带来源的本地记录。

一条决策不只是写一句“我们决定这样做”,还可以记录它的证据状态、来源文件的哈希,以及后来是否被另一项决策替代。

例如,可以记录:

DEC-0001:所有测试执行必须保持显式,不允许 Agent 自动把未运行命令声明为验证完成。

这条决定可以引用项目设计文档作为来源。以后运行验证时,如果来源文件发生变化,AET 会提示原来记录的内容哈希已经不一致。

如果未来项目改变了方向,也不需要删除旧决定。可以新增一条决策,并明确说明新记录替代了旧记录。

这样得到的不是一份永远正确的“项目真理”,而是一条可追溯的决定演化链。

AET 也刻意强调,Decision Ledger 不是一个通用的 Agent Memory,更不是 RAG 知识库。它不会自动吸收所有聊天,也不会让模型把一切内容都存进向量数据库。它只保存维护者选择记录、并且能够追到来源的关键决定。

这个边界很重要。

项目记忆不是越多越好。把所有对话永久保存,往往只会得到越来越混乱的上下文。真正有价值的是:哪些决定仍然有效,它们基于什么来源,后来是否已经被替代。

即使不会编程,也能理解 AET 在做什么

看到命令行、Git 和哈希这些词,没有编程基础的人可能会觉得,AET 显然还是程序员工具。

从安装方式来说,目前确实如此。它还不是一个打开网页、点击几个按钮就能完成检查的消费级应用。

但它解决的问题,并不要求用户先懂代码才能理解。

假设你完全不会编程,只是让 AI 帮你做了一个个人记账网站。

第一次,你让它增加登录功能。

第二次,你让它增加 Excel 导出。

第三次,你让它修改数据库结构。

到了第四次,Agent 告诉你:“为了继续开发,我需要对整个项目进行重构。”

你未必能看懂它修改的每一行代码,但你完全可以提出几个合理要求:

只能修改与这次功能相关的目录
修改前先阅读项目规则
修改后必须运行指定测试
测试完成后不能继续偷偷改变代码
重要架构决定需要记录来源
没有验证过的部分必须明确说不知道

05-四次改站

这些要求,本质上并不比验收一次装修更难理解。

对于非程序员来说,更现实的使用方式也不是自己背下全部 AET 命令,而是把 AET 的 Skill 安装到 Codex、Claude Code 等 Agent 环境中,然后用自然语言提出要求:

修改代码前,先检查项目说明和 Skill 是否存在失效引用,并记录本次可用的上下文

或者:

修改完成后,检查改动是否超出我批准的目录,运行测试,并确认测试之后工作区没有发生变化

又或者:

把这次关于数据库方案的最终决定记录下来,引用对应设计文档;不要把推测写成已证实结论

AET 自带一个可移植的 Agent Skill,可以引导支持 Skill 的 Agent,在审计、范围审查、执行证据、任务生命周期、上下文记录、决策记录和仓库演进分析之间选择合适的流程。

用户与 Agent 仍然可以用自然语言交流,但最终交付不再只剩下一句“相信我,已经做好了”。

AET 和测试工具、安全扫描工具有什么区别?

AET 并不替代测试,也不替代安全扫描、代码审查或 Coding Agent 本身。

测试工具关注的是:代码在指定条件下能否产生正确结果。

安全扫描关注的是:代码中是否存在已知漏洞或危险模式。

代码审查关注的是:实现方式是否合理,是否容易维护。

AET 关注的则是它们之间经常被忽略的一层:

Agent 当时依据了哪些规则,人类批准了什么范围,真实改动是什么,验证命令是否执行,证据是否仍对应当前代码,以及关键决定能否追溯到来源。

所以它并不是一个裁判,更像是记录员和证据管理员。

它不会告诉你某个 Agent 的可信度是 92 分。

因为这样的总分虽然看起来直观,却很容易掩盖真正重要的问题:到底是哪一项通过,哪一项失败,哪一项根本没有证据。

AET 保留 PASSFAILUNKNOWNNOT_APPLICABLE 等独立状态。缺少证据就是 UNKNOWN,不会被折算成一个大体还不错的分数。

04-证据四态

它唯一使用权重的地方,是 triage 对待修问题进行排序;这个排序不会改变原始检查状态。

这也是整个项目一直坚持的原则:

证据优先,不是结论优先。

从 v1.0 到 v1.3,它真正补上的是什么?

如果只看命令列表,可以说 v1.3 比 v1.0 多了工作区快照、Run Manifest、Context Manifest 和 Decision Ledger。

但这些变化背后,其实对应了四个更具体的问题。

v1.0 回答的是:

AI 做了什么,有没有证据?

v1.1 进一步追问:

这些证据对应的是不是现在这份代码?

v1.2 开始回答:

一次交付已经走到了哪个阶段,整条证据链是否仍然有效?

v1.3 则补上:

Agent 当时可以看到哪些规则,它只是声称读过什么;项目关键决定来自哪里,后来有没有被替代?

这让 AET 的定位发生了一点变化。

最早,它更像一张 AI 编程任务的工程收据。

现在,它正在变成一份轻量、可验证、能够持续更新的项目工程档案。

06-工程收据

这份档案不会保存所有内容,不会替项目编造一个完整故事,也不会声称理解模型内部发生了什么。它只记录那些能够明确描述、验证和追溯的事实。

哪些人可能真正需要它?

第一类,是已经让 Codex、Claude Code、Cursor 或类似 Agent 修改真实项目的人。

当 AI 只补一个函数时,可能不需要额外流程。但当它一次修改几十个文件,开始接触数据库、配置、权限和发布流程,仅靠聊天窗口里的总结就不太够了。

第二类,是同时维护多个项目的独立开发者。

个人开发最大的优势是快,最大的风险也是快。没有完整团队替你做审查、测试、交接和发布管理时,许多判断都压在一个人身上。AET 不能替你建立一支工程团队,但可以让一些关键过程不再只依赖记忆。

第三类,是使用 AI 做产品、但编程基础并不深的人。

这类用户可能看不懂复杂代码,却完全可以理解允许修改的范围、必须运行的验证、过期的证据和有来源的项目决定。

事实上,边界表达得越明确,Agent 越不容易在模糊要求中自由发挥。

第四类,是需要进行任务交接和版本发布的小团队。

一项工作从某个 Agent 交给人,再从人交给另一个 Agent,或者从开发进入发布阶段时,Run Manifest 和 Evidence Pack 可以提供一份轻量的交接记录。

第五类,是刚刚接手陌生仓库的人。

AET 的 evolve 可以连接 Git、文档、版本发布、Issue 和 Pull Request,生成带来源的时间线与决策索引。Decision Ledger 则可以补充维护者明确保存的关键决定。

相比让 AI 读完仓库后直接写一篇流畅的“项目历史”,这种方式可能没有那么会讲故事,但更适合支持真实判断。

它目前依然有明显门槛

我不想把 AET 包装成所有人安装后都能立刻受益的万能工具。

它当前更适合已经使用本地 Coding Agent、并且愿意维护基本工程流程的用户。

它仍然需要命令行环境;Context Manifest 只能证明文件被发现和被声明为已读,不能证明模型真正理解了它;Decision Ledger 只能验证来源内容是否改变,不能证明某项决定永远正确。

它也不会替你判断业务需求本身是否合理。

如果你让 Agent 删除用户数据,AET 可以检查它有没有超出批准范围、是否运行了指定验证、证据是否过期,却不能替你决定“删除用户数据”这个需求是不是正确。

它同样无法证明测试覆盖是否充分,也无法保证没有安全漏洞。

AET 是测试、安全扫描、代码审查和 Agent runtime 之间的一层证据基础设施,而不是这些能力的替代品。

对于一个写完就丢的一次性脚本,完整流程可能显得过重。对于长期维护、涉及真实数据、需要多次交接和发布的项目,它的价值才会逐渐显现。

所以项目没有要求每次改代码都运行全部能力。

简单任务可以只做一次审计;需要控制改动范围时增加 review;需要证明命令执行时使用 trace;正式交付时再建立 Run Manifest;只有需要长期保存的上下文和关键决定,才写入 Context Manifest 与 Decision Ledger。

不是流程越多越专业,而是在风险出现的地方留下恰当证据。

我为什么觉得这类工具会越来越重要?

AI 编程正在让“做出一个软件”变得越来越容易。

过去,一个不会写代码的人想做网站,最大的障碍是没有能力实现。现在,他可以用自然语言让 Agent 一步一步完成。

但软件开发的难点从来不只有代码生成。

当产品开始拥有真实用户、保存真实数据、持续更新以后,问题会从“能不能做出来”变成:

这次改动会不会影响旧功能?
Agent 是否遵守了原来的规则?
测试结果是否对应现在的代码?
任务交付以后,证据有没有过期?
更换 Agent 以后,新的 Agent 是否知道过去为什么这样设计?
当结果出现问题时,能不能找到当时依据了什么?

AI 降低了代码生产成本,也放大了验证、交接和项目记忆的重要性。

代码生成得越快,工程证据越不能只留在聊天窗口里。

这就是我继续迭代 Agent Engineering Toolkit 的原因。

我并不认为所有问题都应该继续交给模型解决。

有些事情,更适合让确定性的本地程序完成:

检查路径,计算变更范围,记录文件哈希,绑定工作区快照,保存命令退出状态,记录交付阶段,验证上下文是否改变,维护决策的替代关系。

Agent 负责理解和行动,AET 负责边界、证据和留痕。

一个负责把事情做快,另一个负责提醒我们:做得快,不等于已经证明做对了。

项目地址:

Agent-Engineering-Toolkit

目前 AET 已发布 v1.3.0。相比 v1.0,它新增了工作区快照与证据新鲜度检查、可追加记录的 Run Manifest、Context Manifest,以及带来源哈希和替代历史的 Decision Ledger。回归测试也从 v1.0 的 20 项增加到了 v1.3 的 27 项。

它距离真正面向普通用户的无门槛产品还有一段距离,但它至少试图认真回答一个以后可能越来越常见的问题:

当 AI 说“我已经完成了”,我们除了相信它,还能留下哪些可以复查的东西?

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐