轻一点的 harness,强一点的 runtime:Agent 训练轨迹里的信号问题
讨论 Agent 的时候,我们很容易把注意力放在模型本身:参数更多了、上下文更长了、工具调用更稳了。但真正把一个模型变成可工作的 Agent 的,往往是模型外面那层 harness。
这里的 harness 可以理解成 Agent 的脚手架或外骨骼:Planner、状态机、工具路由、反思模块、子 Agent 调度、上下文压缩、权限规则、重试策略、执行环境、日志系统等等。它的初衷很合理:模型不够稳定时,用工程系统把它扶住,让任务能跑完。
问题在于,如果 harness 太重,它也会反过来污染训练信号。很多看起来成功的轨迹,未必说明模型真的学会了工作,也可能只是框架把模型一路扶到了终点。
重 harness 最大的问题:成功不再好解释
设想一个 coding agent 修好了一个测试。表面轨迹可能长这样:
读测试文件 -> 读源码 -> 修改代码 -> 运行测试 -> 修复失败 -> 最终通过这条轨迹看上去很漂亮。但它背后可能有两种完全不同的因果解释。
第一种是模型真的会工作:
模型判断应该先读测试;
模型选择运行最小测试;
模型根据错误日志定位原因;
模型决定做小范围修改;
模型主动验证结果。第二种是 harness 很强:
框架规定 bug fix 任务必须先读测试;
框架自动注入相关文件;
框架自动运行测试;
框架发现失败后自动重试;
框架用规则选择了修复策略。两种轨迹表面相似,训练价值却完全不同。前者能训练出更强的通用 Agent;后者更像是在训练模型适应某一套流程。也就是说,harness 越重,越难判断成功到底来自模型能力,还是来自框架托举。
模型学到的可能不是原则,而是环境习惯
重 harness 还有一个更隐蔽的问题:它会让模型学习到某个框架的局部习惯,而不是可迁移的工作原则。
比如一个框架里的工具叫:
ReadFile
SearchCode
RunShell
ApplyPatch另一个框架里工具变成:
read
grep
bash
edit如果训练轨迹强依赖前一个框架,模型可能学到的是:
看到测试失败 -> 调用 SearchCode -> 调用 ApplyPatch而不是更抽象的原则:
看到测试失败 -> 找失败证据 -> 找相关代码 -> 做最小修改 -> 运行验证后者可以迁移到任何工具环境,前者只能适配某个 harness。这就像学生不是学会了数学,而是背熟了某本练习册的答案格式。一换题型,就开始不稳。
所以,高质量 Agent 训练数据不能只保存某个框架的内部流程,而要尽量抽象出底层语义:
当前目标是什么;
可见证据是什么;
模型选择了什么动作;
动作产生了什么结果;
结果是否支持继续;
任务是否真的完成。这也是为什么轨迹数据需要标准化。不要只记录:
framework_state = RETRY_STEP_3更有价值的是转换成语义事件:
{
"event": "tool_call_failed",
"tool": "Bash",
"reason": "test_command_not_found",
"model_next_action": "inspect_package_scripts",
"outcome": "recovered"
}前者是框架状态,后者才是可以跨框架复用的经验。
重 harness 会制造虚假的 Agent 能力
更危险的是,重 harness 会让我们高估模型本体。
如果框架自动压缩上下文,模型看起来就像长程记忆很好;如果框架自动选择工具,模型看起来就像工具使用很好;如果框架自动重试失败命令,模型看起来就像错误恢复很好;如果框架自动生成计划,模型看起来就像规划能力很好。
这些都可能是真能力,也可能只是外部系统给出的错觉。
一旦换到新的执行环境,问题就会暴露:
模型不会自己找上下文;
不会判断风险;
不会决定验证方式;
不会从失败日志里恢复;
不会在工具变化时迁移策略。所以,重 harness 的最大风险不是效率低,而是掩盖了模型真实的能力边界。它让我们以为自己在训练一个更会工作的模型,实际却可能只是在训练一个更会配合某个工作台的模型。
训练时最难的是 credit assignment
Agent 训练里最难的问题之一,是功劳归因。一次任务成功,背后可能有很多参与者:
模型;
工具;
权限系统;
上下文检索器;
Planner;
Verifier;
重试器;
子 Agent;
人类用户;
测试环境。任务成功以后,到底应该奖励谁?
如果模型选择了危险命令,但 harness 拦截并改写成安全命令,最后任务成功了,那么这条轨迹能不能直接当正样本?不能。因为模型原始动作是错的。如果只看最终成功,就会错误奖励:
危险动作 -> 被框架救回来 -> 最终成功模型可能学到“危险动作也没关系”。
再比如,模型没有主动运行测试,但 harness 在最后自动跑了测试并发现通过。如果我们把这条轨迹当成“模型完成前会验证”的正样本,也是不准确的。
真正有价值的轨迹数据,必须拆开记录:
模型原始意图是什么;
harness 改写了什么;
工具真实执行了什么;
权限系统拦截了什么;
最终结果是谁导致的;
模型有没有从反馈中主动修正。否则,训练闭环会吸收很多错误信号。最终模型学到的不是“怎么把事情做好”,而是“怎么在框架保护下看起来做得不错”。
训练期的 harness 应该像观察仪器,而不是代驾司机
更适合训练的 Agent harness,应该薄而透明。它不应该过度替模型做认知决策,而应该把真实反馈暴露出来,让模型从反馈中学习。
例如,不要直接替模型决定:
这个任务应该读哪些文件。更好的方式是让模型自己选择文件,并记录:
模型读了哪些文件;
哪些文件后来证明有用;
哪些文件是无效读取;
缺少哪个文件导致失败;
成功轨迹通常先读哪些文件。这样训练出来的是上下文选择能力。
再比如,不要直接替模型决定:
测试失败后应该怎么修。而是记录:
模型看到的错误日志;
模型提出的修复假设;
模型修改的 diff;
测试是否通过;
失败后模型是否换策略。这样训练出来的是错误恢复能力。
训练期的 harness 更像一台观察仪器:它记录、约束、回放、验收,但尽量不替模型思考。模型承担认知责任,框架承担工程责任。
不是 harness 越轻越好,而是认知层要轻,执行层要强
这里很容易走到另一个极端:既然重 harness 会污染训练信号,那是不是 harness 越轻越好?
我觉得不是。更准确的说法是:
认知层要轻,执行层要强。也就是:
少替模型思考;
多约束模型行动。框架应该尽量少做这些事:
替模型规划;
替模型选工具;
替模型决定下一步;
替模型总结自己做得好不好;
替模型自动修正策略。但必须强力保留这些能力:
权限控制;
沙箱隔离;
日志记录;
超时中断;
回滚恢复;
工具参数校验;
数据脱敏;
离线回放;
结果验证;
安全边界。未来好的 Agent 框架不应该是重编排器,而应该是强 runtime。
哪些能力应该蒸馏进模型,哪些必须留在框架
可以把 harness 能力分成两类:可蒸馏能力和不可蒸馏边界。
可蒸馏能力,是那些长期应该被模型学会的工作能力:
| Harness 能力 | 未来是否应内化到模型 | 原因 |
|---|---|---|
| 任务分解 | 是 | 模型应学会自己规划 |
| 工具选择 | 是 | Agent 的核心能力 |
| 上下文选择 | 是 | 决定效率和质量 |
| 错误恢复策略 | 是 | 泛化能力关键 |
| 何时验证 | 是 | 体现真实工作流 |
| 避免重复无效动作 | 是 | 需要从失败轨迹学习 |
| 小范围修改偏好 | 是 | coding agent 的基本习惯 |
不可蒸馏边界,是不能完全交给模型自觉的系统能力:
| Harness 能力 | 是否应保留在框架 | 原因 |
|---|---|---|
| 权限执行 | 必须保留 | 模型不能自己批准自己 |
| 沙箱隔离 | 必须保留 | 防止真实副作用 |
| 审计日志 | 必须保留 | 用于追责、调试和回放 |
| 密钥保护 | 必须保留 | 安全边界不能靠模型自觉 |
| 工具参数校验 | 必须保留 | 防止非法调用 |
| 版本回滚 | 必须保留 | 真实文件修改需要恢复能力 |
| 离线评估 | 必须保留 | 新模型不能直接线上试错 |
一句话:可以让模型学会怎么工作,但不能让模型成为唯一的安全边界。
一个好的训练 harness 应该长什么样
我会把它概括成六个部分:
薄认知编排
+ 强执行护栏
+ 完整轨迹记录
+ 可插拔评估器
+ 标准化事件格式
+ 离线回放环境具体到设计原则,大概是这些:
1. 不强制固定 Planner,让模型自己决定是否规划。
2. 不硬编码工具顺序,让模型自己选择工具。
3. 不自动替模型完成验证,但可以标注“未验证”。
4. 不隐藏工具失败,要把失败原样反馈给模型。
5. 不把权限拒绝静默改写,要让模型看到拒绝原因。
6. 不只保存最终结果,要保存完整行为链。
7. 不把最终成功当作唯一奖励,要标注每一步动作质量。
8. 不让生产安全依赖模型自觉,要由框架强制执行。这套设计的核心,就是让模型承担尽可能多的认知责任,让框架承担不可替代的工程责任。
判断一个 harness 模块该不该退场
可以问三个问题:
1. 这个模块是在替模型做判断,还是在约束真实世界风险?
2. 这个模块产生的能力,能不能通过轨迹训练内化到模型?
3. 去掉它以后,只是模型表现下降,还是会造成安全、数据、资产风险?如果答案是:
替模型做判断;
可以训练内化;
去掉后主要影响效果,不直接造成不可接受风险;那它就应该逐步简化。
如果答案是:
约束真实世界风险;
不能完全依赖模型内化;
去掉后可能造成安全、隐私、资产或合规问题;那它必须保留在框架里。
最终形态:轻 harness 不是少系统,而是少认知干预
所以,我会把这件事总结成一句话:
不是 harness 越轻越好;
而是认知 harness 越轻越好,执行 harness 越强越好。未来 Agent 框架的方向应该是:
少编排,多运行时;
少流程,多约束;
少替模型想,多让模型做;
少看最终回答,多看完整轨迹;
少线上试错,多离线回放;
少自我反思,多外部验证。Agent 训练真正宝贵的不是一段看起来顺滑的完成过程,而是轨迹里可解释、可归因、可迁移的因果信号。harness 可以保护模型与真实世界之间的边界,但它最好不要把模型该学会的工作能力全都代劳掉。