别让 Skill 自己管理自己:Agent Harness 真正解决了什么
Skill 可以提供判断,却无法可靠地调度、约束、验证和改进自己。这是外部 Harness 应该承担的工作。
Agent 系统的第一个版本,往往简单得令人兴奋。
出现一个新场景,我们就写一个 Skill。Skill 会解释要检查什么、使用哪些工具、好结果长什么样,以及 Agent 绝对不能做什么。
然后又出现一个场景,我们再加一个 Skill。
一开始,Skill 库在增长,Agent 看起来也在变强。但到了某个阶段,一件怪事发生了:Skill 越写越好,系统却依然不可靠。
问题不是 Skill 太多,而是我们一直在要求 Skill 管理自己。
Skill 本身没问题,直到系统开始变大
想象一个代码审查 Skill。它对权限控制、租户隔离、数据迁移和证据要求都有周到的说明,并且强调审查期间绝对不能 push、merge 或修改文件。
这个 Skill 可能写得很好,系统却仍然可能在它开始工作之前就失败。
模型可能没有意识到该调用它,也可能加载了错误的 Skill。它可能审查了过期的 commit,又或者拿到太多无关信息、太少关键信息。
更严重的是,Agent 可能仍然拥有那些 Skill 要求它不要使用的工具。
此时,继续修改 Skill 里的文字已经不够了。失败发生在路由、上下文、权限或验证环节。这些是系统问题,而不是判断问题。
Skill 是判断方法,不是运行环境
我觉得有一个区分很有用:
Skill 是在某一类场景中反复使用的判断程序。
它可以告诉 Agent 哪些信号重要、如何考虑取舍、需要寻找什么证据,以及如何表达不确定性。
这已经是一项很大也很有价值的工作。Skill 不必再决定自己何时加载、授予自己权限、证明自己没有做错,并从自己的失败中学习。
这些责任应该属于 Skill 外部的运行系统:Agent Harness。
Harness 决定使用哪种能力、为它提供什么上下文、允许它采取哪些行动、要求什么证据,以及什么时候必须升级给人。
Skill 提供判断,Harness 让这种判断真正可用。
我们一直强塞给 Skill 的四项工作
当 Skill 库很小时,把系统责任藏在自然语言指令里似乎没有问题。但随着系统变大,四类问题会越来越明显。
Discovery:发现
没有被加载的 Skill,在运行时就等于不存在。
描述和触发词能帮助模型发现正确能力,但它们仍然是概率性路由机制。Skill 越多,可能匹配的项就越多,错过的方式也越多。
Context:上下文
每个 Skill 都想携带自己的小世界:架构说明、政策、工具指令、示例、例外和安全要求。
其中大量信息与当前任务无关。更好的系统会先判断自己正在处理什么场景,再按需加载事实和领域指导。
Authority:权限
自然语言可以要求克制,却无法强制克制。
“代码审查期间不要 push”是一句指令。审查期间彻底移除 push 能力,才是一种控制。前者依赖模型的行为,后者直接改变了哪些行为可能发生。
Learning:学习
当 Agent 犯错时,最常见的反应是往 Skill 里再加一句话。
但失败可能与 Skill 无关。Router 可能选错了领域,Script 可能收集了过期证据,缺失的 Gate 也可能放行了危险操作。
如果没有可重放的测试,我们甚至无法证明新增的那句话真的修复了旧问题。

让每一类问题回到正确的载体
最实用的改进并不是设计一种更复杂的 Skill 格式,而是根据所需的保证类型分离关注点。
Gate:绝对不能发生什么
如果一个行为必须不可能发生,就应该用代码或权限强制执行边界。
不应该只是提醒审查 Agent 不要 push、merge、安装依赖或编辑文件。在审查模式中,这些行为应该根本不可用。
Script:什么必须每次完全一致
确定性的机械步骤,就应该交给确定性程序。
固定 commit SHA、按路径分类、验证 schema、遍历 API 分页和收集测试输出,都不会因为创意性解读而变得更好。Script 让它们可重复、可观察。
Skill:什么真正需要判断
Skill 应该负责那些真正需要领域推理的窄而深的决策。
这次权限变更是否削弱了租户隔离?迁移是否可逆?证据是否真的支持结论?这些问题都包含上下文、取舍和不确定性。
Reference:什么只是这里的事实
架构、政策、数据来源和系统拓扑都是事实,而不是判断程序。
把它们保存为参考资料,再按需加载。Skill 可以指向所需的知识,却没必要随身携带整个组织的副本。
分类原则很简单:
Gate 处理禁止事项,Script 处理机械步骤,Skill 处理判断,Reference 保存事实。

Agent Harness 究竟做了什么
回到代码审查的例子。Harness 可以把一句模糊的“审查这个 pull request”变成五个可观察的阶段。
1. Freeze:冻结状态
把每一条观察绑定到同一个仓库状态和 commit SHA。如果 pull request 发生改变,之前的证据就会被明确标记为过期,而不是悄悄漂移。
2. Classify:分类变更
根据变更路径和仓库规则识别受影响的领域。支付变更不应该与文案修改或基础设施变更走完全相同的路由。
3. Load:加载能力
只加载与这些领域相关的 Skill 和参考资料。模型拿到的上下文更小,意图也更明确。
4. Verify:验证证据
要求每个结论指向证据,并要求审查者说明局限、未解问题和无法执行的检查。
5. Verdict:形成结论
把过期、无法分类、存在歧义或不可逆的情况升级给人。“我不知道”变成一种被设计过的系统结果,而不是模型需要隐藏的失败。
这套流程无法保证每次审查都正确。它先做了一件更基础的事:让整个工作过程可检查。
我们可以看到审查了哪个 commit、变更如何被分类、加载了哪些 Skill、什么证据支持结论,以及系统在哪里放弃了。
失败应该变成 Eval,而不是更多指令
只有当失败改变了正确的系统层,Agent 系统才真正在改进。
如果相关 Skill 从未加载,就修复路由。如果证据已经过期,就修复 Freeze 步骤。如果 Agent 尝试执行被禁止的操作,就增加或修复 Gate。
如果领域判断本身很差,那才是需要改进 Skill 的时候。
这次失败还应该变成 fixture 或评估用例。修改之后重放它,将它保存在 holdout 集中,再检查修复是否适用于启发它的单一案例之外。
否则,系统并没有学习。它只是在积累指令。
别让 Skill 自己管理自己
更深的转变,是不再把 Skill 目录当作操作系统,而是把它当作操作系统中的一层。
Skill 依然必不可少。领域专业知识在这里变成可重用的判断。但可靠性必须存在于判断、路由、上下文、权限、证据和反馈之间的关系里。
这才是 Agent Harness 真正解决的问题。
它不会让模型永远正确。它让能力可以分配、约束可以执行、工作可以观察、失败可以重放。
Skills 负责判断,Harnesses 负责控制,Loops 负责学习。
继续写 Skill。只是别再要求它们管理自己。