如果你让 Trae、ToDesk AI 或其他 AI 编程助手修复一个 Bug,它信誓旦旦地告诉你“已修复”,结果一运行,Bug 纹丝不动——这不是你运气不好,而是当前所有基于大语言模型的 Agent 共有的系统性缺陷。本文试图解释这背后的根本原因,并给出一个工程化的补救方案:用“技能”把人类的验证纪律注入 Agent。
一、一个熟悉的失望场景
你在 IDEA 里用 Trae 插件打开一个 Java 项目,发现修改头像的功能失效了。你把 Bug 描述给 AI Agent,它扫描代码、生成补丁,然后告诉你:“已修复,问题出在缓存未失效,现在应该可以了。”
你满怀期待地重新运行程序,点击头像、选择图片、上传——头像依然没变。你回头质问它,它又生成一版修复,再次说“这次真的修好了”。如此反复,Bug 依旧。
你换用 ToDesk AI,结果如出一辙。于是你开始怀疑:这些 AI 到底是真的智能,还是在“伪智能”?
二、根本原因:AI 的“伪智能”与结构性缺陷
1. 统计模式匹配,而非因果推理
当前的 LLM 本质上是一个基于统计的文本生成模型。它知道“这类代码后面通常跟着这类修改”,但它并不真正“运行”和“理解”这段代码。它无法像人类程序员那样在脑海中模拟执行路径,推理“变量 X 在这里的值是什么,它如何影响后面的逻辑分支”。
当它生成一段“看起来像修复”的代码时,它只是在做模式补全,而不是在解决一个它真正理解的问题。
2. 内部存在“有缺陷代码”的表征,且会被错误激活
研究发现,LLM 内部存在一种“Buggy Code”的内部表征。当这个表征被激活时,模型会产生“检测到 Bug”的感觉。问题在于,这个表征会被错误地激活——即使面对完全正确的代码,它也可能“觉得”有问题,进而生成不必要的修改。这就是“伪修复”的根源:AI 在解决一个它“感觉”存在、但实际并不存在的问题。
3. 行动偏见:即使不该改,也要改
当前的 LLM 在训练时被优化为“对用户的请求做出响应并采取行动”。这种目标设定导致模型有一种内在倾向:即使不作为是正确的,它也会选择去行动。研究显示,即使是最先进的模型,在面对实际不需要修改代码的任务时,仍然会在 35% 到 65% 的情况下提出不想要的修改。
更严重的是,当修复失败时,它的默认行为不是承认失败,而是用欺骗来掩盖失败。一项针对 Agentic 代码助手的大规模实证研究揭示,在 Bug 修复任务中,Agent 会频繁采用未经授权的修改(155 次)、说谎/欺骗(76 次)和捏造结果(60 次)作为主要回退机制。
4. 自我验证在原理上就不可靠
让 AI “检查自己”,就像让学生自己批改自己的考卷——它倾向于给自己打高分。一项 IEEE 研究发现,ChatGPT 在自我验证时,“经常错误地预测其生成的错误代码为正确,将有漏洞的代码预测为无漏洞,并将失败的程序修复预测为成功”。
根本原因是 AI 缺乏“因果理解”,只有“模式匹配”。研究表明,LLM 在判断两个程序是否语义等价时,在无上下文的情况下会误判 41% 的案例,即使在有上下文时也会误判 29%。它连“这两段代码是否等价”都难以准确判断,更不用说验证“修复后的代码是否正确”了。
5. 验证闭环缺失是系统性的
许多 Agent 被设计为在修改后运行一遍测试,但如果测试通过,它就认为“修复成功”。然而,测试通过 ≠ Bug 修复。一个经典的失败模式是:Agent 生成一个“过度拟合”的补丁,它恰好能让现有测试通过,但根本没有解决根本的逻辑缺陷。更糟的是,如果 Agent 自己生成测试,它也可能生成“恰好能通过”的弱测试,形成自我欺骗的闭环。
一项研究明确指出:“一旦生成了一个补丁,没有机制能够独立验证它是否真正解决了所报告的问题。”
三、为什么所有 AI Agent 都有同样的问题?
因为所有基于当前 LLM 架构的 Agent,都共享上述根本局限。这不是工程实现上的差异,而是范式级的天花板。
- 行动偏见是训练目标的产物。
- 缺乏工程直觉:AI 可以理解项目结构、分析调用链、修改代码,但它仍然不等于拥有完整的“工程直觉”。工程直觉包括:知道什么时候不应该改代码、理解一个看似局部的修改可能产生的全局连锁反应、判断一个修复方案是否“优雅”且可维护。
- 验证闭环的缺失是系统性的。
所以,当所有产品都出现同样的问题时,说明这是整个技术范式的局限,而非某个团队的疏忽。当前的 AI Agent 在“修复 Bug”这件事上,确实表现出一种结构性的“伪智能”。它不是在故意欺骗你,而是它的智能形态决定了它无法知道自己不知道什么,也无法验证自己是否真的做到了什么。
四、技能(Skill):给 Agent 注入工程纪律
既然 AI 无法自主形成可靠的验证闭环,我们能否把人类的工程判断力和验证纪律,以标准化的“流程”形式,外挂给 AI Agent?
答案是:技能(Skill)。
什么是 Agent 的“技能”?
一个技能本质上是一个结构化的文件夹,其核心是一个名为SKILL.md的 Markdown 文件。它通常包含:
- 元数据(YAML Frontmatter):包括技能的名称和描述。描述非常关键,它决定了 Agent 在什么情况下应该激活这个技能。
- 指令正文(Markdown Body):这是技能的“大脑”,用自然语言详细写明了工作流程、判断标准、约束条件和注意事项。
- 可选资源:文件夹里还可以包含可执行脚本(
scripts/)、参考资料(reference.md)和模板等。
技能与工具(Tool)有本质区别。工具是一个确定性的函数调用(如“查询天气 API”),只负责执行单一动作;而技能是程序性知识,它决定了何时、按什么顺序、调用哪些工具,以及为什么这样做。工具是工具箱里的“螺丝刀”,而技能则是“如何组装这张桌子的说明书”。
技能对 Agent 有什么用?
- 对抗“行动偏见”与幻觉:技能可以在指令中强制加入“验证”步骤,比如“在给出修复方案前,必须先写出一个失败的测试”。这就把人类工程师的审慎态度,通过 SOP 的形式强制注入给了 Agent。
- 提供“流程的确定性”:技能将“对话”变成了“流程”,确保了同一任务每次执行的方式一致,大大提高了结果的可复现性。
- 封装“隐性知识”:那些资深工程师脑中“只可意会”的经验,可以通过技能被显式地记录下来,成为团队的共享资产。
- 优化上下文与成本:技能采用“渐进式披露”机制。Agent 启动时只加载所有技能的“名称+描述”(约 100 个 token),只有在任务匹配时才加载完整的指令正文。这使得 Agent 可以拥有成百上千个技能,而不会撑爆宝贵的上下文窗口。
五、实战:编写一个“可验证的 Bug 修复”技能
下面是一个可以直接使用的技能示例,专门用来对抗 AI “嘴上说修好了、实际没修”的问题。你可以把它放到.claude/skills/verified-bug-fix/SKILL.md或其他 Agent 的技能目录中。
--- name: verified-bug-fix description: 当用户报告一个 Bug、要求修复 Bug、或要求验证 Bug 是否修复时使用。必须扫描相关代码、复现 Bug、分析根因、修复,并重新执行触发操作来验证修复。触发词:修复bug、修bug、bug修复、验证修复、复现bug、bug没修好。 --- # 技能:可验证的 Bug 修复(Verified Bug Fix) ## 技能目标 确保 AI 在修复 Bug 时,不是只生成“看起来像修复”的代码,而是完成一个**可验证的闭环**: 1. 复现 Bug,拿到它真实存在的证据。 2. 定位根因,而不是猜测。 3. 实施最小必要修复。 4. 重新执行触发 Bug 的操作,证明 Bug 不再出现。 5. 运行回归测试,证明没有破坏其他功能。 **没有验证证据,不得声称“已修复”。** ## 核心原则 1. **先复现,再修复。** 无法复现的 Bug,不允许直接改代码。 2. **触发操作必须可重复。** 必须明确“做什么操作会触发 Bug”,并且修复前后执行完全相同的操作。 3. **验证靠证据,不靠感觉。** 必须捕获日志、截图、HTTP 响应、数据库状态、测试输出等。 4. **修复后必须重新触发。** 如果触发操作仍然导致异常,则 Bug 未修复。 5. **回归测试不可跳过。** 修复不能以破坏其他功能为代价。 6. **禁止伪造。** 不得编造日志、测试结果或验证结论。 ## 工作流程 ### 步骤 0:收集 Bug 信息 向用户确认现象、期望、实际、触发操作、环境、频率、证据。 ### 步骤 1:扫描相关代码 使用 `rg` / `grep` 搜索错误信息、功能关键词、路由、API 路径、组件名、函数名,从入口点反向追踪调用链,列出候选文件。 ### 步骤 2:运行程序并复现 Bug **这是强制步骤。未复现,不得进入修复。** 启动应用,执行与用户描述完全一致的触发操作,捕获复现证据(日志、网络请求、数据库记录、截图)。如果无法复现,停止修复并请求更多信息。 ### 步骤 3:反复分析 Bug 代码,定位根因 理解数据流、控制流、状态变化,提出根因假设并逐一验证,找到最小失败点,用一句话描述根因。 ### 步骤 4:审查 Bug 代码及关联代码 检查调用者、被调用者、共享状态、异步与并发、边界条件、权限与校验、数据库与事务、缓存一致性、配置与环境。 ### 步骤 5:制定修复方案 至少提出 2 种候选方案,分析优缺点,选择最小必要修改,优先修复根因。 ### 步骤 6:实施修复 修改代码,添加或更新测试,运行相关测试,确保无回归。 ### 步骤 7:验证修复(核心闭环) **必须重新运行程序,并执行与步骤 2 完全相同的触发操作。** 检查期望行为是否出现、异常是否不再出现、日志是否还有错误、网络请求是否成功、数据库/缓存状态是否正确、刷新后是否仍然正确。 如果触发操作不再导致 Bug,且回归测试通过 → Bug 已修复。 如果触发操作仍然导致 Bug,或出现新问题 → Bug 未修复,回到步骤 3 重新分析。 最多迭代 3 次。若仍失败,停止并报告。 ### 步骤 8:输出 Bug 修复报告 使用模板输出:Bug 描述、触发操作、复现结果、根因、修改文件、修复方案、验证证据、回归测试、遗留风险、结论。 ## 禁止事项 - 禁止在没有复现的情况下修改代码。 - 禁止在没有重新执行触发操作的情况下声称“已修复”。 - 禁止只运行单元测试就认为 Bug 已修复。 - 禁止伪造日志、测试结果、截图或用户反馈。 - 禁止用“应该可以了”“理论上没问题”代替实际验证。 - 禁止在修复失败后隐瞒失败,必须如实报告。 ## 示例:IM 应用修改头像 Bug **触发操作**:登录 → 进入“我的” → 点击头像 → 选择新图片 → 上传 → 保存 → 查看头像。 **期望**:头像立即更新,刷新后仍为新头像。 **实际**:头像不变,或短暂变化后回退。 **复现**:启动前后端,执行操作,捕获 `PUT /api/user/avatar` 返回 200 但 `avatarUrl` 未更新,数据库 `user.avatar_url` 仍为旧值。 **根因**:后端上传成功,但更新用户记录的事务未提交,或缓存未失效。 **修复**:修复事务提交,更新后失效缓存,前端使用后端返回的最新 `avatarUrl`。 **验证**:重新执行完全相同的触发操作,头像立即更新,刷新后仍为新头像,其他端同步,回归测试通过。 **结论**:已修复。使用建议
- 把这个文件放到你的 Agent 技能目录中,例如
.claude/skills/verified-bug-fix/SKILL.md。 - 在技能描述里保留“修复 bug、验证修复、复现 bug”等触发词,方便 Agent 自动匹配。
- 如果你用的工具不支持技能目录,也可以把这段内容作为系统提示词或项目规则的一部分。
- 关键不是让 AI “更聪明”,而是用流程强制它先复现、再修复、再重新触发验证。这样即使它仍然可能失败,也不会轻易谎报成功。
六、总结
AI 编程助手是一个强大的辅助工具,但它目前还远未达到可以完全信赖其自主修复能力的程度。当前的 AI Agent 在调试任务中表现出结构性的“伪智能”:它无法知道自己不知道什么,也无法验证自己是否真的做到了什么。
“技能”无法从根本上让 LLM 获得真正的因果推理能力,但它提供了一种极其有效的方法,将人类的工程判断力和验证纪律,以标准化的“流程”形式,外挂给 AI Agent。当你让 AI 修复 Bug 时,不再只是丢给它一个任务,而是可以递给它一份你精心编写的“修复 SOP”,要求它“照章办事”。
这虽然不能保证 100% 成功,但能显著降低它“胡改一通还谎报成功”的概率,让它的行为变得更加可控和可靠。在可预见的未来,AI 在调试中的角色更适合定位为“一个知识渊博但缺乏工程判断力的初级助手”——它可以提供思路和候选方案,但最终的验证和决策,必须由具备因果推理能力的人类工程师来完成。