大多数人在错误的层面上试图改进 AI Agent。
当 Agent 失败时,他们会重写提示词。
当它再次失败时,他们会添加更多指令。
开始之前:
关注我的 Substack,获取最新的 AI 前沿动态、Agent 工作流和分步指南,内容会早于 X 平台发布:[https://substack.com/@lunarresearcher
然后他们更换模型,添加更多工具,增加上下文窗口,并希望下一次运行会有所不同。
但许多 Agent 的失败并非推理失败。
它们是环境失败。
Agent 不知道哪些文件是重要的。
它在错误的地方使用了正确的工具。
它丢失了之前会话中做出的决策。
它声称成功却没有运行检查。
它在部分失败后重复了一个操作。
它有权执行本应需要批准的操作。
问题不一定出在模型上。而是模型周围的系统不完整。
这个系统就是“控制框架”(Harness)。
设计它正在成为一门独立的工程学科。
控制框架工程(Harness Engineering)是一门构建环境的实践,旨在将模型的智能转化为可靠的工作。
一个提示词只改变一次尝试。
一个控制框架改变每一次尝试。
本指南将解释如何构建一个控制框架。

1. 模型不是 Agent
模型可以推理、生成、比较和选择。
但一个 Agent 还必须与真实环境进行交互。
它需要:
- 理解任务
- 找到相关上下文
- 选择并使用工具
- 保持状态
- 遵守权限
- 检查结果
- 从失败中恢复
- 证明工作已完成
模型是该系统内部的推理引擎。
控制框架则是让推理得以运作的一切。
1用户请求2 |3 v4+-----------------------------+5| 控制框架 |6| 合约 | 上下文 | 策略 |7| 工具 | 状态 | 检查 |8| 追踪 | 恢复 |9+-----------------------------+10 |11 v12 模型13 |14 v15 真实环境
一个强大的模型置于一个薄弱的控制框架内,仍然是一个薄弱的 Agent。

它可能会产生令人印象深刻的单个响应,但在长时间的任务、变化的环境和部分失败的情况下,它的行为会不一致。
控制框架工程的目标不是消除模型的不确定性。
而是将这种不确定性包含在一个能够观察、验证和恢复的系统内。
2. 从任务合约开始
大多数 Agent 任务始于模糊的意图:
改进用户引导流程。
这句话对于对话来说可能足够了。
但对于自主执行来说远远不够。
在 Agent 行动之前,控制框架应将请求转换为任务合约。
一个有用的合约回答了五个问题:

- 必须存在什么结果?
- 范围之内是什么?
- 什么不能改变?
- 什么证据能证明完成?
- 哪些行动需要人工批准?
1目标:减少用户引导流程中的流失23范围:4 - 注册流程5 - 用户引导分析67约束:8 - 不改变身份验证9 - 保留现有移动端行为1011验收标准:12 - 测试通过13 - 分析事件被触发14 - 截图覆盖桌面端和移动端1516需要批准:17 - 生产环境部署18 - 数据库迁移
这将 Agent 的问题从:
我下一步该做什么?
转变为:
什么行动能使环境朝着合约规定的成果发展?
没有合约,Agent 会优化看似合理的活动。
有了合约,它就可以优化可验证的完成度。
3. 给 Agent 一张地图,而不是一本手册
将整个代码仓库、文档集和对话历史都塞进上下文,这不是好的上下文工程。
这是上下文泛滥。

控制框架应该首先提供一张小地图,然后让 Agent 在需要时检索详细信息。
1项目地图23产品规则 -> docs/product/4架构 -> docs/architecture.md5前端 -> apps/web/6后端 -> services/api/7测试 -> tests/8命令 -> docs/commands.md9发布规则 -> docs/release.md
这是渐进式信息呈现:
1任务2 -> 项目地图3 -> 相关子系统4 -> 确切文件5 -> 本地指令
上下文应该因为任务需要而扩展,而不是因为信息存在。
一个好的上下文编译器决定:
- 哪些总是需要的
- 哪些可以稍后检索
- 哪些已经过时
- 哪些可以总结
- 哪些必须保持原样
目标不是最大化的上下文。
而是每个 Token 的最大化信号。
4. 构建一个工具网关,而不是工具堆
给一个 Agent 二十个工具并不会让它变得强大。
这给了 Agent 二十种犯错的方式。

每个工具都应该有一个清晰的合约:
1工具:edit_file23输入:4 path5 patch67前置条件:8 path 存在9 path 在允许的工作区内1011成功证据:12 补丁已应用13 返回生成的差异1415失败行为:16 无部分覆盖17 返回结构化错误1819风险等级:20 可逆
控制框架应控制工具的暴露和使用方式。
它可以:
- 隐藏不相关的工具
- 验证参数
- 限制路径和域名
- 附加超时
- 使重试幂等
- 标准化输出
- 对高风险操作要求确认
- 返回证据,而不仅仅是“成功”
这创建了一个重要的分离:
1模型决定意图2网关验证行动3工具改变环境4传感器观察结果
模型可以提出一个行动。
工具网关决定该行动是否足够有效以执行。
5. 分离大脑、双手和历史
许多脆弱的 Agent 将所有内容混合到一个不断增长的记录中。
推理、工具调用、文件、决策、错误和旧的观察结果都在争夺同一个上下文窗口。
一个更强的系统分离了三个职责:

1大脑2规划、推理、选择34双手5在受控环境中执行工具67历史8存储持久的事实、决策和运行状态
模型不需要在活动上下文中包含每一个原始事件。
它需要正确的当前状态。
沙盒不需要理解整个目标。
它需要安全地执行一个有边界的行动。
会话日志不需要推理。
它需要在当前上下文消失后保留所发生的事情。
这种分离使得长时间运行的 Agent 更容易恢复、检查和修复。
它也允许你替换一个部分而无需重建整个系统。
6. 记忆必须成为持久状态
对话历史不是可靠的记忆。
它是一个事件流。
有用的记忆应该被转换为显式状态。

至少,保留四个类别:
1事实2关于环境发现的稳定信息34决策5做出的选择及其背后的原因67进度8已完成、进行中、受阻和剩余的工作910经验教训11应改变未来行为的失败
例如:
1事实:2 - 结账验证逻辑位于 services/orders34决策:5 - 重用现有的验证管道6 - 原因:避免第二个事实来源78进度:9 已完成:10 - 添加了服务器端规则11 剩余:12 - 更新集成测试1314经验教训:15 - 本地测试命令需要 TEST_DB_URL
这比重播五十页的记录并希望模型注意到重要行要有用得多。
存储原始历史记录以供审计。
编译持久状态以供执行。
7. 完成需要证据
一个 Agent 说“完成了”并不是任务完成的证据。
它只是另一个模型输出。

完成必须由环境中可观察到的变化来决定。
1声称 证据2--------------------------------------------------3"bug 已修复" 失败的测试现在通过了4"页面工作正常" 浏览器流程已完成5"迁移是安全的" 试运行和回滚都通过6"报告是正确的" 数值与源数据匹配7"任务已完成" 每个验收检查都通过
控制框架应该首先运行最便宜的确定性检查。
1语法2 -> 类型3 -> 针对性测试4 -> 集成测试5 -> 视觉或语义审查6 -> 人工批准
不要用另一个模型来回答编译器、模式、校验和、查询或测试就能回答的问题。
对模糊性使用模型。
对管道工作使用代码。
模型可以提议任务已完成。
只有环境才能证明它。
8. 验证应该攻击结果
执行者和评估者不应共享同一个目标。
执行者试图创建最强的解决方案。
评估者试图找到它应该被拒绝的理由。

1执行者2 -> 产生候选方案34验证者5 -> 检查合约6 -> 搜索遗漏的情况7 -> 测试不支持的声明8 -> 尝试破坏结果910通过11 -> 接受1213失败14 -> 返回有针对性的证据
这种不对称性很重要。
如果你让同一个 Agent,在同一个上下文中,“再次检查它的工作”,它通常会保留导致错误产生的假设。
一个有用的验证阶段应该具备:
- 明确的拒绝标准
- 访问生成的工件
- 访问验收合约
- 需要时使用独立的工具或新的上下文
- 有权拒绝而不修复
验证不是第二意见。
它是一种试图证伪。
9. 模型提议,策略授权
有些规则永远不应依赖于模型是否记得它们。
1未经批准绝不发布2绝不泄露机密3绝不写入工作区之外4绝不超出支出上限5除非测试已运行,否则绝不标记测试通过
这些不是提示建议。
它们是策略。
最安全的设计是将策略置于推理循环之外。

1低风险2读取文件、搜索、检查3-> 自动执行45可逆变更6编辑工作区、运行测试7-> 自动执行并记录89外部影响10发送消息、部署、购买11-> 明确批准1213不可逆或敏感操作14删除数据、轮换凭证、全球发布15-> 硬性限制或禁止
后果越严重,限制越严格。
自主性不是缺乏控制。
它是在一个明确强制执行的边界内自由操作的能力。
10. 恢复应针对失败类别
最常见的恢复策略是:
出错了。再试一次。
那不是恢复。
那是重复。

控制框架应在选择下一步行动之前对失败进行分类。
1工具超时2-> 带退避的重试34无效参数5-> 修复工具调用67缺少上下文8-> 检索特定来源910测试失败11-> 检查失败的行为1213权限被拒绝14-> 请求批准或选择安全路径1516矛盾的需求17-> 升级给人类1819重复相同的失败20-> 停止循环
一次重试应至少改变一个相关条件。
否则系统就是在花钱重现同样的失败。
一个有边界的 Agent 循环如下所示:
1观察2 -> 决定3 -> 行动4 -> 衡量5 -> 接受6 -> 修复7 -> 升级8 -> 停止
每个循环都需要一个预算:
- 最大尝试次数
- 最大时间
- 最大支出
- 最大破坏范围
- 升级条件
可靠的 Agent 知道如何继续。
它们也知道何时继续不再合理。
11. 指令应成为基础设施
Agent 指令在解释局部现实时很有用。
但仅靠指令是薄弱的强制手段。
如果一个规则反复重要,就把它向下移动堆栈。
1"使用格式化工具"2-> 自动运行格式化工具34"不要跨层导入"5-> 添加架构测试67"包含迁移回滚"8-> 在 CI 中要求回滚文件910"不要修改生成的文件"11-> 阻止写入生成的路径1213"引用每个外部声明"14-> 验证引用覆盖率
这创建了一个指令阶梯:
1解释2 -> 检查清单3 -> 模板4 -> 自动化检查5 -> 强制执行的策略
尽可能将重要知识沿阶梯向下移动。
提示词应解释判断。
控制框架应强制执行不变量。
12. 观察运行过程,而不仅仅是最终答案
一个干净的最终工件可能隐藏着一个糟糕的过程。
Agent 可能:
- 访问了错误的数据
- 忽略了一个失败的命令
- 重试了两次外部操作
- 消耗了预期预算的十倍
- 出于错误的原因得出了正确的答案
你需要能够重建运行过程的追踪记录。
109:14 合约已创建209:15 上下文源已加载:architecture.md309:17 文件已编辑:checkout.ts409:18 针对性测试失败:重复优惠券509:21 实现已修复609:22 针对性测试通过709:24 集成测试通过809:25 外部部署被阻止:需要批准
一个有用的追踪记录记录:
- 状态转换
- 上下文来源
- 工具输入和输出
- 环境变化
- 验证结果
- 重试原因
- 批准决策
- 成本和延迟
目标不是监视。
目标是局部修复。
当一次运行在第 18 步失败时,你应该能够从一个可信的检查点重新开始,而不是重放整个任务。
13. 每次运行都需要一份变更收据
冗长的 Agent 记录难以审查。
在运行结束时,控制框架应编译一份简短的变更收据。
1目标2修复结账过程中重复应用优惠券的问题。34变更5- 结账验证逻辑6- 针对性回归测试78已验证9- 代码检查通过10- 单元测试通过11- 结账集成测试通过1213未验证14- 生产支付提供商1516决策17- 保留了现有的优惠券优先级顺序1819风险20- 旧版移动客户端在本地不可用2122需要批准23- 部署到预发布环境
收据不是模型所说内容的摘要。
它是系统能够证明的内容的摘要。
这为人类提供了一个紧凑的审查面,并为下一个 Agent 会话提供了一个可信的起点。
最好的交接不是“这是对话记录”。
而是“这是状态、证据和未解决的风险”。
14. 每次失败都应升级控制框架
最弱的团队修复失败的输出。
最强的团队也会修复允许失败发生的系统。
在失败之后,问:
1任务合约是否模糊?2重要的上下文是否不可见?3是否暴露了错误的工具?4是否缺少前置条件?5结果是否无法验证?6策略是否留在了提示词中?7恢复策略是否过于宽泛?8追踪记录是否不足?
然后将经验教训转化为可复用的改进。
1失败2 -> 诊断3 -> 新的传感器、规则、地图、测试或工具合约4 -> 未来的运行自动改进
这就是控制框架的飞轮效应。
系统变得更可靠,因为失败留下了基础设施。
一个修正后的答案帮助一次运行。
一个修正后的控制框架帮助每一次未来的运行。

15. 控制框架也会衰退
更多的控制框架并不总是更好。
模型在改进。工具在改进。任务在变化。旧的安全措施可能变成不必要的摩擦。
为昨天的模型创建的变通方法,可能会阻止今天的模型使用更好的策略。
这导致了控制框架的衰退:
1旧模型限制2 -> 控制框架变通方法3 -> 模型改进4 -> 变通方法仍然存在5 -> 系统变得更慢或能力更弱
像对待生产代码一样对待控制框架组件。
衡量它们是否仍然提供价值。
对于每个路由器、评估器、记忆层和重试规则,问:
- 这防止了哪种失败?
- 那种失败多久发生一次?
- 这增加了多少延迟和复杂性?
- 现在能否用更简单的方式达到同样的结果?
- 如果我们移除它会发生什么?
最好的控制框架不是最大的那个。
它是能够可靠地弥合意图与证据之间差距的最小系统。
为删除而构建。
16. 最小可行控制框架
你不需要一个编排平台才能开始。
分层构建控制框架。
第一层:有边界的任务
- 目标
- 范围
- 约束
- 验收检查
第二层:清晰的环境
- 项目地图
- 命令
- 本地指令
- 已知依赖
第三层:受控的行动
- 类型化工具
- 参数验证
- 路径和权限边界
- 结构化结果
第四层:持久的执行
- 显式运行状态
- 检查点
- 决策
- 经验教训
第五层:证据
- 确定性检查
- 对抗性验证
- 变更收据
第六层:恢复与学习
- 失败分类
- 有边界的重试
- 升级
- 来自重复失败的控制框架更新
构建能够消除你实际遇到的失败的最小层。
不要因为单个提示偶尔需要澄清就开始构建多 Agent 架构。
复杂性应该由观察到的失败来证明。
17. 可复用的控制框架规范
在给予 Agent 有意义的自主权之前,定义以下内容:
1AGENT 控制框架规范231. 合约4 目标:5 范围:6 约束:7 验收证据:892. 上下文10 始终加载的地图:11 检索来源:12 本地指令:13 新鲜度规则:14153. 工具16 允许的工具:17 前置条件:18 副作用:19 成功证据:20 超时和重试策略:21224. 状态23 事实:24 决策:25 进度:26 经验教训:27 检查点格式:28295. 策略30 自动行动:31 需要批准的行动:32 禁止的行动:33 预算限制:34356. 验证36 确定性检查:37 对抗性检查:38 验收规则:39407. 恢复41 失败类别:42 重试限制:43 升级条件:44 安全回滚:45468. 可观测性47 追踪事件:48 指标:49 最终变更收据:
如果这些字段未定义,那么 Agent 就不是自主的。
它是在即兴发挥。
18. 在正确的层面衡量系统
Token 数量不是最终指标。
尝试的任务数量也不是。
有用的单位是已验收的工作。
一个实用的指标是:
1已验收的输出2------------------------------3人工审查分钟数 + 运行成本
同时追踪:
- 首次通过验收率
- 工具失败后的恢复率
- 重复失败率
- 每个任务的人工干预次数
- 未经支持的完成声明
- 从请求到验证结果的时间
- 按组件划分的控制框架开销
这可以防止一种常见的错觉:
一个 Agent 可能看起来生产力很高,同时却创造了昂贵的审查工作。
目标不是更多的 Agent 活动。
而是每单位人类注意力产生更多可信的结果。
19. 何时不需要繁重的控制框架
并非每次模型调用都需要一个操作系统。
在以下情况下使用简单的提示词:
- 任务简短
- 输出易于检查
- 失败代价低
- 没有外部副作用发生
- 用户保持在循环中
在以下情况下添加控制框架:
- 工作跨越多个工具或会话
- 环境可能发生变化
- 行动有实际后果
- 完成度难以手动判断
- 相同的失败反复出现
- 人工审查成为瓶颈
控制框架的目的不是让演示看起来复杂。
而是让实际工作变得可靠。
真正的转变
第一代 AI 产品是围绕提示词构建的。
下一代产品正在围绕环境构建。
问题不再仅仅是:
我们如何让模型回答得更好?
而是:
我们如何构建一个系统,使得好的行动变得容易,危险行动得到控制,失败可见,完成可证明?
这就是从提示词工程到控制框架工程的转变。
模型提供智能。
控制框架提供结构。
它们共同产生可靠的执行。
如果你的 Agent 不断崩溃,别再往提示词里加形容词了。
构建它成功所需的环境。
如果你读到了这里
收藏本指南。
把这篇文章发给那些仍在试图用更长的提示词来修复每一个 Agent 失败的人。





