ARTICLE · 1100555
AI Coding 的关键不是循环,而是可验证性
这两年,AI Coding 的形态变化很快。
最早是补全一行代码,后来是根据对话修改一个文件,再后来是 Agent 自己读仓库、改代码、跑命令、看报错,然后继续下一轮。这个过程通常被叫作 LOOP,也有人从更长远的视角,把它放进 RSI(Recursive Self-Improvement,递归式自我改进)的讨论里。
严格来说,RSI 指向的是系统改进自身能力,普通的 Coding LOOP 更多是在当前任务里迭代,两者不是同一个概念。本文不打算展开术语之争,只关注它们在工程上共有的那个动作:模型不再只给出一次答案,而是根据结果不断修正自己的产出。
直觉上看,只要模型愿意一直改,结果似乎总会越来越好。但在真正的工程环境里,我们很快会碰到一个问题:循环本身并不保证进步。
一个会反复修改代码的 AI,不一定比一次性生成代码的 AI 更可靠。它也可能在几个错误方案之间来回摆动,可能修好一个用例又破坏另一个用例,也可能误读日志之后,非常有信心地向错误方向继续前进。
所以我越来越倾向于一个判断:
RSI 或者 LOOP 在工程中真正的关键,不是能循环多少轮,而是每一轮的结果是否可验证。
AI 为什么尤其需要“准出”
人写代码也会出错,但 AI 的问题不只是“偶尔写错”。大模型的基本工作方式,是根据上下文生成一个高概率成立的后续。它擅长给出合理、连贯、看起来完整的答案,却不天然对答案在真实环境中是否成立负责。
换句话说,幻觉不是一个以后升级模型就能彻底消失的边缘问题,而是生成式模型始终存在的结构性风险。模型能力越强,它给出的错误答案有时反而越完整、越像真的。
这也是为什么,单纯把上下文窗口做大、把提示词写长,或者让模型多反思几轮,都不能直接等价为工程可靠性。模型可以检查自己的推理,但“自己认为自己对了”仍然不是证据。
工程系统需要的是另一个东西:一个独立于模型表达能力之外的准出条件。它不关心模型的解释有多流畅,只判断预先约定的目标有没有达成。
这其实并不是 AI 时代才出现的思想。编译器检查、静态扫描、单元测试、集成测试、代码评审、CI/CD 流水线,本质上都在做同一件事:把“我觉得改好了”,转换成一组可以重复执行、可以明确判定的证据。
AI Coding 只是让这件事变得更重要了。
行业里的 Agent,已经在向这个方向收敛
如果把近两年的 Agent 实践放在一起看,会发现行业并没有把重点只放在“让模型多做几步”上,而是不断给循环补充外部反馈。
Anthropic 在《Building effective agents》中把 Agent 概括为:模型根据环境反馈,在工具调用中持续循环。文中强调,Agent 每一步都需要从环境中获得 ground truth,例如工具执行结果或代码运行结果;任务还需要明确的停止条件,比如最大迭代次数。谈到 Coding Agent 时,他们列出的优势也非常直接:代码可以通过自动化测试验证,Agent 可以把测试结果作为反馈继续迭代,产出质量能够被相对客观地衡量。
SWE-agent 的研究则把注意力放在 Agent 与计算机之间的接口上。它并没有只追求更复杂的推理,而是强调:反馈应该具体、简洁,并准确反映上一步操作对环境造成了什么影响。SWE-agent 在 SWE-bench 上使用的核心指标也很朴素:补丁应用之后,是否所有相关测试都通过。
商业产品的设计同样在体现这个思路。GitHub Copilot coding agent 会在独立的开发环境中修改代码、执行自动化测试和 lint,并把最终改动放进 Pull Request,交给开发者审查。这里其实有三层约束:环境隔离、自动检查、人工审核。Agent 可以获得较高的执行自主性,但它没有绕过软件工程原有的质量边界。
这些实践背后有一条共同逻辑:
目标 -> 修改 -> 执行 -> 获得真实反馈 -> 判断差距 -> 再修改
LOOP 的价值不在箭头转了一圈,而在“真实反馈”能够改变下一轮行为。没有这个反馈,所谓自我改进很容易退化成自我说服。
可验证,也要先回答“验证什么”
说到这里,一个很自然的答案是:那就让 AI 跑测试。
但只说“跑测试”还不够。测试只能证明被测试描述出来的行为。如果需求本身含糊、系统分析漏掉了边界、测试用例只覆盖了顺利路径,那么全部通过也可能只是精确地完成了一个错误目标。
因此,可验证性的第一步不是执行,而是把需求变成可以验证的验收契约。
这里至少要完成三次转换:
从业务需求转换为系统行为,明确输入、输出、状态变化和异常分支。 从系统行为转换为测试场景,覆盖主流程、边界条件、失败路径和关键回归点。 从测试场景转换为可自动执行的用例,包括单元测试,以及必要的集成测试。
AI 很适合辅助完成这些转换。它能快速梳理影响范围,补充容易遗漏的边界,并生成大部分测试骨架。但这部分不能完全交给 AI 自己确认,因为“出题的人”和“答题的人”如果是同一个模型,它很容易在两边共享同一种误解。
我们的做法是,让 AI 先根据原始需求产出系统分析(后文简称“系分”)和测试用例,再由人对系分和用例进行 Review。人审的重点不是代码风格,而是需求有没有被正确翻译:业务语义是否准确,关键场景是否完整,边界和异常是否合理,测试断言是否真的对应验收目标。
Review 通过之后,这组系分和用例就不再只是参考材料,而是本次 AI Coding 的准出条件。
我们落地的一套闭环
整个过程可以概括成下面几步。
1. 输入需求,先产出系分和用例
AI 接收原始需求和必要的仓库上下文,生成:
需求理解与范围说明; 受影响的模块、接口和数据; 关键流程、异常分支和兼容性分析; 单元测试用例; 有跨模块行为时,补充必要的集成测试。
这一步的目标不是立刻写代码,而是先把“完成”定义清楚。
2. 人工 Review,冻结验收契约
开发者或领域人员审核系分和测试用例,修正 AI 对需求的误解,补充遗漏场景。审核完成后,测试集合成为当前迭代的基线。
这里有一个很重要的约束:进入编码循环后,AI 不能为了让测试通过而自行降低断言、删除用例或改变验收口径。如果确实发现测试本身有问题,需要退出循环,重新由人确认。
否则,指标一旦变成目标,最容易发生的事情不是代码被修好,而是标准被改松。
3. AI 修改代码并执行验证
AI 根据系分实现代码,然后运行约定的测试、静态检查和构建任务。系统把结果以结构化方式返回给 AI,包括:
失败用例及断言差异; 异常堆栈和关键日志; 编译或静态检查错误; 本轮通过率及相对上一轮的变化; 本轮代码变更摘要。
比起把几万行原始日志全部塞回上下文,这些信息更适合作为下一轮的反馈。反馈要完整到足以定位问题,也要克制到不会淹没真正的失败原因。
4. 根据失败结果进入下一轮
AI 结合本轮修改和失败日志,判断问题属于实现错误、影响范围遗漏、环境问题,还是测试与需求存在冲突,然后决定下一步修改。
之后重新执行同一组验证。如此循环,直到满足其中一个退出条件。
5. 明确成功与停止条件
我们把退出分成两类。
第一类是成功退出:约定的单元测试、集成测试、静态检查和构建全部通过,且测试集合没有被未授权修改。
第二类是停止迭代:达到最大循环次数,或者连续若干轮的用例通过率不再提高。实践中还可以增加两个信号:同一种错误重复出现,或者代码在相同位置反复修改。它们通常意味着 Agent 已经进入局部循环,继续消耗 token 和时间不会自然产生新信息。
通过率也不能单独使用。假设上一轮 A 通过、B 失败,下一轮变成 A 失败、B 通过,数字没有变化,系统状态却发生了变化;更糟的是,Agent 可能一直在两个用例之间来回修补。除了通过率,最好同时记录失败用例集合、错误指纹和修改位置,区分“暂时没有提升”和“已经开始原地打转”。
这里我们关注的不只是“跑了多少轮”,而是进展是否仍然可测量。比如可以维护一个简单的状态:
本轮状态 = 必须用例通过数 / 必须用例总数成功:状态 = 100%,且其他质量门禁全部通过停滞:连续 K 轮状态没有提升,且失败集合或错误指纹没有实质变化超限:总轮数达到 N
K 和 N 不应该拍脑袋统一设置。小型需求可能 3 到 5 轮已经足够;涉及遗留系统、环境依赖或较慢集成测试的任务,需要结合平均修复成本单独设定。关键是提前约定,而不是等 Agent 跑不动了再决定什么叫结束。
6. 人工最终审核并发布
自动化用例全部通过,不代表代码可以无人值守地进入生产。
测试擅长回答“我们写下来的这些条件是否成立”,但不擅长发现所有没被写下来的条件。架构合理性、可维护性、安全风险、观测能力、灰度和回滚方案,以及需求背后的业务判断,仍然需要人负责。
因此,闭环的最后一步是人工审核。对于成功退出的任务,人检查实现质量和未被测试覆盖的风险;对于停滞退出的任务,人根据 Agent 保留下来的修改记录、失败日志和进展轨迹继续修复,或者调整系分和测试后重新发起一轮。
人不是被排除在 LOOP 之外,而是从每一行代码的操作者,变成验收契约的制定者和最终责任人。
真正值得建设的,不只是更强的模型
在 AI Coding 的实践中,我们很容易把效果不好归因于模型不够强,然后等待下一个版本。但模型升级当然重要,工程系统本身也决定了能力上限。
一个模型如果拿不到真实的运行结果,不知道哪些检查是必须通过的,也不知道什么时候应该停止,那么再长的循环也只是概率生成的重复。反过来,即使模型并非最强,只要需求被转换成可靠的验证条件,反馈足够清晰,失败能够被下一轮使用,很多任务也能稳定完成。
所以,对 RSI 或 LOOP 来说,我认为更准确的工程表达不是“让 AI 自己不断变好”,而是:
让 AI 在一个目标明确、反馈真实、结果可判定、失败可退出的系统里持续修正。
循环提供了改进的机会,可验证性才决定这种改进是不是真的发生了。
当我们能清楚回答“什么算完成”“由谁确认”“失败后反馈什么”“什么时候停止”时,AI Coding 才从一次聪明的演示,变成一套可以交付的软件工程流程。
参考资料
Anthropic, Building effective agents Yang et al., SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering Princeton NLP, SWE-bench GitHub Docs, About GitHub Copilot coding agent