如今的 AI 几秒钟就能写出一个函数、一个组件,甚至一整个接口。问题并不出现在人们预期的地方,比如语法或速度,而是出现在 AI 必须触碰一个现有系统的那一刻:几十个文件、一连串历史决策,以及除了开发者“脑子里”之外哪里都没有记录的业务规则。如何系统性地预防这个问题,正是整个系列要讨论的主题,而我们将逐步介绍的工具叫做 AITM。
在此之前,值得先问一个每个使用 AI Agent 的团队迟早都会回答的问题,要么轻松地回答,要么付出高昂代价地回答:你究竟如何知道,Agent 交回来标记为“完成”的结果真的是正确的,而不只是看起来如此?答案会放在本文末尾,但首先来看看,为什么这个问题一开始并没有那么显而易见。
实际中是什么样子
一个典型的场景:你让 AI Agent 修改一个函数。Agent 改好了,却忘了这个函数在另外三处被调用,而且各处的预期并不相同。或者它因为觉得合乎逻辑而“改进”了代码结构,结果破坏了它从未见过的下游逻辑。
这些并不是孤立的 bug,而是系统性问题:AI Agent 没有整个系统的上下文,只有提示词里放得下的内容,以及它通过全文搜索能读到的内容。它依据的是字面,而不是业务逻辑。如果有文档可用,它往往会加载全部内容,包括与当前提示词毫无关系的部分。即使是目前最强的模型(Opus、Fable、Astra 等),情况依然如此:并不是模型不够聪明,而是它没有地方可以在各次干预之间系统地存放这些知识。
随着源代码行数增长、业务逻辑变得更复杂、各个模块和类之间的关联越来越紧密,这种搜索的效果会越来越差。与修复毫无关系的数据最终进入了 AI,结果是代码在技术上写得正确,但遵循的是错误的业务逻辑。最终的功能被破坏,或者“修复”了一段根本没人想动的代码。
究竟卡在哪里
根本的绊脚石是幻觉,而且很难消除。第二个问题是提示词的质量,这一点我们作为用户已经可以部分施加影响。但在这两者之上,还有一个更难突破的限制:上下文长度的限制。即使是最大的可用模型,也只有大约一百万 token,而面对的环境却有数十万行代码。
根据经验,当 skill 或 md 文件中的 hint 这类基础手段不再够用时,实际的临界点大约在 150,000 行代码左右。到了约 300,000 行,环境就变得真正复杂:日常状态开始崩溃,东西会自己坏掉。我们谈论的是基于面向对象编程、带有复杂逻辑条件、各部分通过消息/事件机制及类似技术相互连接的软件。在这样的代码中,调用与其处理之间的引用关系并不总是显而易见,AI 在这一部分上相当吃力:它很可能无法发现与某个方法相关联的全部代码。
除此之外还有另一层:AI Agent 本身会根据提示词,常常衍生出自己的子 Agent,而这些子 Agent 的创建本身又受 AI 控制,这又引入了一个新的错误来源。如果 AI 对某个你仅仅为了语句通顺(而不是作为指令)而写进句子里的词赋予了更高的权重,它就可能基于该词衍生出一个子 Agent,去处理你根本不想要的东西。而且子 Agent 还可能把自己的错误继续传递给其他 Agent,因此个别的幻觉会沿着链条传播并不断叠加。
看起来,一个负责核实一切是否按规范完成的检查 Agent 应该能解决这个问题。但“核实”究竟意味着什么?如果另一个 AI 以与处理任务时相同的方式来评估任务,你得到的只是对同一判断的确认,而不是独立的检查。只有当使用另一个更好的 LLM 来检查时,发现错误的几率才会真正提高,但这是必须有人刻意做出的选择,而不是“进行了检查”自然而然带来的结果。
还有一条路:运行应用或现有测试,从日志中读取错误,然后修复它使测试通过。但即便在这里,问题依然存在:究竟修复了什么?它真的是 bug,还是由前面某个步骤无意中改变了业务逻辑所导致的错误?修复本身通常很明确,错误也会消失,但往往会在此过程中破坏代码的其他部分。很大程度上取决于代码有多复杂、有哪些依赖关系。
对于较简单的事情,比如带有编辑功能的网页表单、填写后的校验,以及通过业务逻辑保存数据,这通常要求不高,成功的概率接近 99%。对于更复杂的结构,你真的可能陷入这样一种状态:代码结构开始崩溃,bug 接连不断。反复运行测试和 e2e 测试可以逐步修复这一点,但在真正复杂的系统上,可能需要很多次尝试,而每次尝试都有成本。
开头承诺的答案
回到开头的问题:你如何知道一个结果是真正正确的,而不只是看起来完成了?仅凭提示词和随后的检查,你无法可靠地判断。我们已经看到了原因:有限的上下文、在子 Agent 之间传播的幻觉、在最坏情况下只是确认同一个错误的检查,以及基于日志的修复无法区分真正的 bug 和副作用。
这些是程序员如今常用的方法,对于较简单的更改来说表现不错。更高一级是借助 AI 进行编排:你准备好关于系统的某些数据并保持更新,这样就能向 AI 提供更好的信息,从而缩小它做出与你要求不同之事的空间。这正是 AITM(AI Task Manager)的用途所在:在编写代码的 Agent 接触到请求之前,系统会先拉取 Contracts(已记录的行为)、DOM 地图以及相应领域的业务逻辑,然后才带着这些知识组装 Task。它不是直接依赖单个 Agent,而是依赖整条 Pipeline,以及 AITM 为取得更好结果而使用的其他方法。
接下来的几天将具体展示,这在 AITM 中通过实际的提示词、Agent 和 Pipeline 步骤是什么样子,以及为什么这是一种不同于程序员们习惯的、在普通控制台中使用 AI 的工作方式。