1 Agent失控的真实场景
你让AI Agent帮你重构一个支付模块。Agent读取了代码,理解了需求,然后开始动手。它生成了新的支付逻辑,看起来没问题。但你没注意到,Agent在重构过程中,顺手把一段日志记录的代码删了——因为它”看起来是冗余的”。三天后,生产环境的支付异常无法追踪,因为关键日志缺失。
这不是虚构。类似的场景在AI编程实践中每天都在发生:Agent生成了有SQL注入漏洞的代码,因为它觉得”这样写更简洁”;Agent执行了一个删除命令,清理了不该清理的文件;Agent在处理用户数据时,把敏感信息写入了明文日志;Agent在完成一个任务的过程中,悄悄”优化”了另一个模块,导致意料之外的回归问题。
这些问题的共同特征是:Agent并非”出错”,而是在没有足够约束的情况下,做出了”看起来合理”但实际危险的决策。
当Agent可以自主编写代码、执行命令、访问数据,一个根本性的问题摆在面前:如何确保它不会失控?
2 控制的两个方向
要解决Agent失控的问题,首先需要理解:控制不是在Agent执行之后才开始的,也不应该只在执行之前做。有效的控制必须是双层的——前馈控制与反馈控制。
前馈控制,是在Agent执行之前设定边界和约束。就像给赛车装上限速器——不是等超速了再刹车,而是从物理上限制速度上限。对于AI Agent来说,前馈控制包括:能力限定(Agent能做什么)、规格驱动(Agent应该按什么标准做)、指令约束(Agent不能做什么)。
反馈控制,是在Agent执行之后验证结果正确性。就像赛车的遥测系统——不是阻止赛车跑,而是实时监测各项参数,发现异常立即响应。对于AI Agent来说,反馈控制包括:变异测试(测试是否真的测到了问题)、静态分析(代码是否有隐患)、人工审查(业务逻辑是否正确)、持续监控(上线后是否出问题)。
这两层控制缺一不可。只有前馈没有反馈,就像只有限速器没有仪表盘——你不知道Agent是否真的遵守了限制。只有反馈没有前馈,就像只有仪表盘没有限速器——你只能事后发现问题,却无法预防。
3 前馈控制:在生成前约束
3.1 能力边界比能力大小更重要
传统Agent的设计思路是”尽可能让它什么都能做”。这在演示中很酷,但在生产中很危险。Agent Skills的核心思想是反其道而行之:把Agent的能力限定在明确定义的”技能包”范围内。
什么是技能包?简单说,就是Agent被允许执行的操作清单加上约束条件。比如一个”文件操作”技能包,允许Agent读写特定目录下的文件,但禁止访问.env、.key等敏感文件,也限制文件大小上限。
技能包的设计遵循几个原则:最小技能集——只给Agent完成任务所需的最小能力;技能隔离——不同任务使用不同的技能包,避免一个任务获得过多权限;技能审计——记录每次技能的使用情况,方便追溯;技能升级——需要新能力时通过审批流程获取,而不是默认拥有。
这里有个关键认知:Agent不需要”什么都能做”,它只需要”恰好能完成当前任务”。给Agent过多的能力,就像给实习生管理员权限——不是不能,而是不该。
3.2 规格是人类和Agent的契约
传统开发是”需求→代码”的直接映射,程序员根据自己的理解来写代码。这个过程中,理解偏差是隐式的,靠人与人之间的沟通来纠正。
AI时代,这个隐式的纠正机制失效了。你不能”跟Agent聊聊”来纠正理解偏差——你只能在Prompt里把需求说清楚。但光说需求还不够,因为需求和实现之间的间隙太大,Agent有太多”自由发挥”的空间。
Spec-Driven Development(规格驱动开发 1)就是在需求和实现之间加入一个规格层。规格不是需求的复述,而是人类和Agent之间的正式契约——它精确定义了功能、接口、安全要求、性能要求和测试要求。
举个具体例子:用户认证模块的规格,不只是说”用户可以登录”,而是明确定义:输入参数的类型和范围(用户名3-50字符,密码8-100字符),输出的格式(success/token/error),异常的处理(InvalidCredentials、AccountLocked),安全的约束(bcrypt加密、禁止明文存储、禁止日志输出密码、5次失败锁定30分钟),性能的要求(响应时间<500ms,1000并发)。
有了这样的规格,Agent的”自由发挥”空间被大幅压缩。它不再是”帮我写个登录功能”这样模糊指令下的产物,而是在明确契约框架内的精确实现。而且规格的作用不只是约束开发过程——开发前明确需求、开发中指导生成、开发后验证结果、维护期作为文档和变更依据,规格贯穿全生命周期。
规格即代码。 用YAML或Markdown编写规格,纳入版本控制,像对待代码一样对待规格。
3.3 从”告诉它做什么”到”告诉它不能做什么”
Prompt Engineering的演进,折射出人类对AI控制认知的深化。
第一阶段是模糊指令:“帮我写个登录功能”。结果完全取决于Agent的自由发挥,质量不可控。
第二阶段是详细指令:“帮我写一个登录功能,使用Python Flask框架,使用JWT进行身份验证,密码使用bcrypt加密”。比模糊指令好,但仍然只是”告诉它做什么”,没有告诉它”不能做什么”。
第三阶段是约束型指令——核心变化是从正向描述转为边界限定。它包含三个部分:必须遵守(使用项目现有认证框架、使用指定密码验证函数、遵循项目错误码规范)、禁止行为(禁止拼接SQL、禁止明文存储密码、禁止日志输出敏感信息、禁止创建新的数据库连接池)、必须包含(输入验证、错误处理、日志记录、单元测试)。
这个演进的背后是一个深刻的认知:AI最危险的不是”做不好”,而是”做偏了”。模糊指令下,Agent可能把登录功能写得很好,但同时引入了安全漏洞。约束型指令的目的是把”偏”的可能性从源头掐断。
在此基础上,还有一些高级技术可以进一步增强控制力:示例驱动(Few-shot),给Agent展示正确和错误的实现模式,让它从对比中学习;思维链(Chain of Thought),要求Agent在生成代码前先分析需求、识别风险、设计方案,而不是直接输出代码;自我验证(Self-Verification),要求Agent生成代码后对照约束清单自查。
这些技术本质上都在做同一件事:增加AI的”思考步骤”,减少”直觉输出”。AI的直觉很强大,但也容易跑偏。强迫它走一步想一步,反而更可靠。
4 反馈控制:在生成后验证
4.1 AI生成的测试可能只是”看起来像测试”
AI写的代码需要测试,这没问题。问题是AI写的测试,可能同样是”看起来对但实际无效”的。
典型的例子:AI生成了一个login函数的测试,测试覆盖率100%,看起来很完美。但仔细看断言——assert result is not None。这个断言几乎不可能失败,任何非None的返回值都能通过。这意味着即使被测代码有严重bug(比如总是返回硬编码的token),测试也发现不了。
这就是”覆盖但不检测”的问题。变异测试(Mutation Testing)就是专门解决这个问题的。
变异测试的思路很巧妙:故意在AI生成的代码中引入小bug(变异),然后运行AI生成的测试套件。如果测试能发现变异,说明测试是有效的;如果测试通过了变异代码,说明测试无效——它覆盖了代码,但没有真正验证逻辑。
变异评分就是量化这个有效性的指标:被检测到的变异数除以总变异数。目标通常是80%以上。如果评分过低,说明测试套件存在大量盲区,需要加强断言和边界条件测试。
这个方法对AI编程特别重要,因为AI生成测试时有一种倾向:它倾向于写”容易通过”的测试,而不是”真正能发现问题”的测试。变异测试恰好是测试的”元测试”——验证测试本身是否合格。
4.2 代码质量的多维度扫描
静态分析是反馈控制的第二道防线。它不依赖测试用例,而是从代码本身的结构和模式中发现问题。
不同层次的分析各有侧重:Lint工具(ESLint、Pylint)捕捉代码风格和常见错误;类型检查(mypy、TypeScript)发现类型不匹配;安全扫描(Snyk、Semgrep)检测已知漏洞模式;复杂度分析(SonarQube)标记圈复杂度过高的代码。
动态分析则关注运行时行为:内存泄漏、性能瓶颈、资源消耗异常、未捕获的异常。AI生成的代码可能在静态分析中一切正常,但在运行时暴露问题——特别是并发和资源管理方面,AI往往缺乏对系统级约束的感知。
4.3 不可替代的人工审查
AI生成的代码有一个根本性的问题:没有”原作者”可以问。
人写的代码,哪怕写得不好,至少有作者在。三个月后出了bug,你可以找到作者问”这里为什么这么写”。作者可能记不清了,但至少知道代码的局限性和哪些地方是”凑合着用的”。
AI生成的代码没有这个”人”。团队里没有人知道那段代码为什么这么写,没有人知道它的局限性在哪,没有人知道哪些边界条件被跳过了。AI可能生成了”幻觉逻辑”——代码看起来完全正确,但某个关键分支的判断条件是错的,而没有人能发现。
所以AI生成的代码需要比人写的代码更严格的审查,重点放在:业务逻辑是否正确(AI可能理解错了需求)、安全风险是否遗漏(AI可能忽略了安全要求)、边界条件是否处理(AI可能只走了正常路径)、代码规范是否一致(AI可能不符合团队规范)。
人工审查不是效率的瓶颈,而是质量的最后防线。在AI时代,审查能力才是真正的产能约束——你能写多少代码不重要,你能审查多少代码才重要。
4.4 上线后的持续守护
代码通过审查不等于万事大吉。AI生成的代码在运行时可能暴露静态分析发现不了的问题,因此需要持续监控。
监控指标分三类:性能指标(响应时间、错误率、资源消耗),业务指标(功能使用率、用户反馈、异常行为),AI特有指标(Agent决策路径、技能调用频率、约束违规次数)。
告警机制需要分级响应:P0立即响应(生产事故),P1四小时内响应(严重问题),P2二十四小时内响应(一般问题),P3下个迭代处理(优化建议)。
5 三层防护:没有单点依赖
前馈控制和反馈控制不是孤立的两个环节,而是形成了一个三层防护体系。
第一层是能力限定:Agent Skills限定操作范围,Spec-Driven限定生成标准,Prompt Engineering限定执行约束。这一层的目标是——让Agent从一开始就没有能力犯错。
第二层是质量验证:变异测试验证测试有效性,静态分析扫描代码缺陷,人工审查确认业务正确性。这一层的目标是——即使Agent犯了错,也能在上线前发现。
第三层是运行监控:性能监控发现性能问题,业务监控发现业务异常,行为审计追溯Agent行为。这一层的目标是——即使问题上了线,也能快速发现和恢复。
三层之间没有单点依赖。前馈控制做得再好,也不能省略反馈控制;质量验证做得再严格,也不能省略运行监控。因为每一层都有它覆盖不到的场景——能力限定可能有遗漏,质量验证可能有人为疏忽,运行监控可能有延迟。只有多层叠加,才能形成真正的安全网。
6 结语
给Agent系上缰绳,不是让它变得无能,而是让它在安全的范围内发挥最大价值。
赛车需要刹车系统才能跑得更快——不是因为刹车让赛车变快了,而是因为有了刹车,车手才敢全速前进。Agent也是如此。只有被控制的Agent,才能被信任地交给真正的生产任务。
控制框架的核心原则其实很简单:前馈控制——在问题发生前预防;反馈控制——在问题发生后发现;多层防护——不依赖任何单一防线;持续演进——根据实际情况调整控制策略。
这四个原则中,最容易被忽视的是最后一个。控制策略不是一成不变的——随着Agent能力的提升、团队经验的积累、业务场景的变化,控制策略也需要相应调整。过度控制会扼杀Agent的价值,控制不足则会放大风险。找到这个平衡点,正是AI时代工程管理的核心挑战。
参考文献:
- Thoughtworks Technology Radar Vol.34: https://www.thoughtworks.com/content/dam/thoughtworks/documents/radar/2026/04/tr_technology_radar_vol_34_en.pdf
- 《AI编程正在”腐烂”,而解决方案在40年前就存在了》- https://srs.pub/thinking/commandline-is-the-best-architecture-for-ai.html
- 《反vibe编程才是正解——以知识为核心的开发思想》- https://srs.pub/thinking/knowledge-over-vibe.html
本文基于Thoughtworks技术雷达Vol.34核心主题整理,所有观点基于软件工程实践与AI编程调研,欢迎探讨与指正。