把一项能力写进 SKILL.md,再封装成 Agent 插件,并不难。真正困难的是,当它被不同用户、不同项目和不同 Agent
宿主反复调用之后,如何保证它仍能被正确触发、执行和验证,并证明一次修改带来的是改善,而不是退化。
本文结合 Better Harness 的开发实践,从规格驱动、上下文编排、确定性验证、行为评测和证据闭环五个方面,讨论如何把 Agent 插件中的能力从“写出来能用”,逐渐变成可验证、可维护、可持续演进的软件资产。
引子:从 Agent 插件说起
加入 Qoder 的这三个月里,除了设计基于 Canvas 的 Agentic UI 体系,我另外一项持续投入的工作,是构建 Agent 插件生态。从筛选社区里已有的软件工程流程插件,到创建 Architecture Visualization、Design Review 等插件,我们尝试把原本分散在不同角色、不同工具里的能力,封装成 Agent 可以发现和调用的能力。
例如在 Architecture Visualization 插件中,Agent 可以直接通过 Canvas 可视化架构模块之间的依赖关系,并分享给团队成员,帮助他们理解系统结构:
一开始,插件更像是对 Agent 能力边界的扩展:缺什么能力,就补一个 Skill、一个工具或者一段工作流。但随着插件越来越多、越来越复杂,我们开始遇到另一个问题:
这些能力应该如何被长期维护?
特别是在构建 Better Harness 的过程中,这个问题变得越来越明显。Better Harness 面向 Coding Agent 的工作流分析与持续改进,其中包含一个核心 Skill、大量 JavaScript 脚本、参考资料、评测逻辑,以及不同 Agent 宿主的适配。
当这些能力真正作为插件的一部分被长期维护之后,我们发现,问题已经不再只是“怎么写好一个 SKILL.md”。
Agent Plugin 到底是什么?
如果你已经熟悉 Agent Plugin 和 Agent Skills,可以直接跳到下一节。
简单来说,Agent Plugin 是能力的交付与分发边界,Skill 是其中可以被 Agent 独立发现和执行的能力单元。一个典型的 Plugin 可以同时包含 Skill、MCP Server、Hook,以及针对不同 Agent 宿主的扩展:
my-plugin/
├── plugin.json
├── skills/
│ └── summarize/
│ ├── SKILL.md
│ ├── scripts/
│ └── references/
├── mcp.json
└── com.example.client/
└── hooks/
其中,SKILL.md 并不是插件本身,而更像插件中的一个能力入口。它描述这个能力什么时候应该被发现、如何执行,以及需要继续读取哪些资料和工具。如果
Skill 只是自己偶尔使用的 Prompt,这种区别并不重要;但一旦它进入 Plugin,被不同用户、不同项目和不同 Agent 宿主反复调用,事情就不一样了。
为什么插件需要工程化?
在个人使用阶段,写清任务和步骤通常就够了;但当一个插件被不同用户、不同项目、不同 Agent 宿主反复调用之后,一系列更接近软件工程的问题就会自然出现:
- 行为契约:它应该怎么工作? 什么场景应该触发,什么场景不应该触发;需要哪些上下文,可以调用哪些工具,又有哪些行为必须禁止?
- 变更验证:修改之后还是对的吗? Skill、脚本或参考资料发生变化之后,如何确认原有能力没有被破坏,已经修复的问题不会再次出现?
- 环境兼容:换个环境还能工作吗? 当模型、Agent、宿主乃至运行环境发生变化时,这套能力是否仍然能够被发现、加载和正确执行?
- 效果评估:它真的让 Agent 变好了吗? 即使 Skill 被正确触发并完整执行,我们又如何证明,相比不使用 Skill,它确实改善了真实任务的结果?
这些问题已经很难通过“把 Prompt 写得更详细”来解决。它们对应的其实都是软件工程中非常熟悉的问题:定义契约、验证变更、管理兼容性,以及评估真实效果 。继续往下拆,才会进一步涉及规格、知识与依赖组织、接口和权限边界、自动化测试、回归验证,以及跨模型、跨宿主的行为评测。
也正是在 Better Harness 的开发过程中,我们逐渐开始用另一种方式理解 Skill:
Skill 一旦从个人 Prompt 进入插件生态,它面对的问题就越来越像软件,而不是提示词。
下面结合 Better Harness 的实践,依次展开这五个工程环节。
一、规格驱动:把 Agent 行为写成可验证契约
规格驱动(Spec-driven)是我们在 Better Harness 中最早开始实践的部分。它的核心思想是:在实现之前,先把“什么时候做、做什么、做到什么程度”写成可验证的契约。
我们在 AGENTS.md 中约定:
只要 Skill、脚本、模板、宿主适配或评审工作流发生会影响实际行为的变化,就要先建立规格和可追踪的验收条件。
一份规格至少要回答几个问题:什么请求应该触发,哪些相似请求不应该触发;需要读取什么信息,允许调用哪些工具;哪些行为明确禁止;证据不足时应该停止、降级,还是交回给人;最终又用什么证据证明这次实现符合预期。
每条验收条件还应该有稳定编号,例如 AC-01、AC-02
,并分别对应实现、测试和评审证据。一份边界加固规格
就把已经复现的问题拆成 AC-01 到 AC-09。
例如,Agent 扫描写入内容时不能回显密钥;分析某个 workspace 时,不能顺手把其他目录的会话也算进来;无法确认 Git
基线时,应明确停止,而不是把失败伪装成“没有变更”。最后再由 AC-09 收口到完整测试与打包验证。
规格本身也需要评审。在 Better Harness 的
triangulate-spec-review
Skill 中,我们会让至少两个、通常三个评审 Agent 在相同上下文下,分别检查实现复杂度、使用便利性和长期演进。主评审 Agent(Lead
Agent)负责合并同类问题、核对证据和修改文档,其他评审 Agent 只提供独立判断,不直接改文件。规格驱动的价值,就是先把这些模糊从运行时搬到设计时。
不过,规格驱动也有边界。验收条件写得过细时,AI 很容易把测试变成对 Skill 文本的逐字匹配,而不是验证真实行为,反而降低测试稳定性。因此,规格应该约束可观察行为,而不是锁死具体措辞。
规格定义了能力应该怎样工作,下一步则是让 Agent 在执行时准确找到支撑这些行为的知识。
二、上下文编排:让 Skill 知识在需要时准确抵达
Agent Skill 通常采用渐进式披露:知识不应该一次性全部进入上下文,而应按任务需要逐步展开。
宿主先读取
name和description完成发现,决定使用后才加载完整的SKILL.md,更细的资料则按任务需要进入上下文。它本质上是一种面向 Agent 的上下文工程:不是把所有知识一次性塞给模型,而是设计知识何时出现、从哪里进入,以及如何被继续追踪。
对应到目录结构上,入口应该保持短:
my-skill/
├── SKILL.md # 触发条件、主流程、停止条件
├── references/ # 按需读取的判断规则
├── scripts/ # 可重复执行的确定性逻辑
└── assets/ # 模板与交付骨架
SKILL.md 负责触发、路由和停止条件;详细判断放进 references/;稳定执行的逻辑放进 scripts/;模板与交付骨架放进
assets/。
但在 Better Harness 的实践中,我们发现,仅仅把知识拆开放置还不够:文件存在,不代表 Agent 找得到;入口曾经引用过,也不代表重构之后路径仍然有效。
所以,我们主要从三个方面保证知识路由:
- 可发现:通过
SKILL.md的入口和明确引用,把相关资料纳入 Agent 的知识路径,而不是依赖它临时搜索。 - 可到达:通过自动测试 检查相对链接是否有效,以及 Skill 所需资料是否真正被入口路由。
- 可追踪:通过文档图生成器从真实 Markdown 引用生成 Mermaid 图,并验证生成结果是否与当前引用关系一致。
这样,Markdown 引用本身成为事实来源,图只是知识路由的一种可验证投影。文档移动、链接断裂或路由关系发生变化时,可以由机器及时发现,而不是依赖维护者人工同步。
上下文编排的目标,不是让 Agent 读得更多,而是让正确的知识在正确的时机,通过仍然有效的路径进入上下文。知识准确抵达之后,下一个问题是:哪些边界应该交给程序直接判断,而不是继续让模型猜。
三、确定性验证:把能判断的交给程序
在 Skill 和插件里,并不是所有问题都应该交给模型判断。关键词、正则和程序检查适合处理边界明确、结果可判定的问题,例如元数据、目录结构、断链、数据格式、废弃名称和权限声明;但它们不能证明 Agent 是否理解了任务,也不能替代语义质量评审。
在 Better Harness 中,我们主要用三层确定性机制守住这些边界:
- 静态检查(Lint):检查文件头、目录结构、断链、数据格式和权限声明,尽早发现低成本、可确定的问题。
- 单元测试(Unit Test):验证脚本、解析器和模板转换等确定性逻辑,保证基础能力在修改之后仍然成立。
- 契约测试(Contract Test):验证命令和入口真正允许发生什么,包括输入输出、错误状态、产物位置,以及副作用边界。
一个比较典型的例子,是 Better Harness 对 --help 路径的测试。
better-harness-cli.test.mjs
不只是检查帮助信息是否正确,而是进一步验证:执行帮助命令时,不应该读取工作区、写入文件、等待标准输入、启动子进程或访问网络。只要其中任何一种副作用发生,测试就会失败。
这里真正被验证的,不是“帮助文案长什么样”,而是这个入口被允许做什么、不允许做什么 。这也是确定性验证的价值:把原本容易被模型行为掩盖的边界,变成可以自动检查、持续回归的工程约束。在 Agent 系统里,模型更适合理解、规划和权衡,确定性程序则更适合验证、约束和拒绝。
能被程序明确判定的,就不要交给模型猜;需要语义判断的,也不要硬塞进字符串断言。
不过,确定性验证只能守住可判定边界,无法证明 Agent 在真实任务中真的照做。这就需要进入行为评测。
四、行为评测:验证 Agent 是否真正照做
Skill 存在、被发现、被加载、被执行、最终带来改善,是几件不同的事。静态检查通过,只能说明文件和脚本没有明显问题;Agent 会不会在正确的时候选择 Skill、执行关键步骤,并在证据不足时停下来,仍然需要行为评测。
在 Better Harness 中,我们通常准备三类场景:应该触发的正例、不应该触发的负例,以及措辞相似但意图不同的边界用例 。执行过程中重点观察四件事:
- 选择:该用时有没有用,不该用时有没有误触发;
- 上下文:有没有读取真正需要的资料;
- 执行:关键步骤、工具和权限是否符合约束;
- 结果:最终产物能否通过独立验证。
同一个场景还需要重复运行,因为一次成功只能证明“这次跑通了”,不能证明行为足够稳定。
到了宿主边界,Better Harness 还会通过真实 Qoder CLI 和插件加载链路做端到端验证,并从中立目录发起测试:
python3 <skill-creator-root>/scripts/quick_validate.py <skill-dir>
qodercli --cwd <neutral-dir> --plugin-dir <plugin-root> -p "<forward-test-prompt>"
qodercli plugin validate <plugin-root>
从 neutral-dir 发起测试,是为了避免 Agent 意外借用当前仓库中的配置、上下文或未声明依赖,让“能跑通”显得比真实情况更乐观。与此同时,
qodercli 的回答只属于模型行为证据,最终是否通过,仍然由本地校验器、产物检查和 Git 状态等确定性证据决定。
模拟用例负责覆盖异常和边界场景,真实宿主测试则验证 Plugin 加载、Skill 发现、资料读取、工具调用到最终交付这条链路是否真的连通。 行为评测真正要证明的,不是 Agent “看过” Skill,而是 Skill 要求的关键行为确实发生了。
但证明 Agent 确实执行了 Skill,仍不等于证明这个 Skill 带来了更好的结果。后者需要进入证据闭环。
五、证据闭环:先证明 Skill 有效,再谈自我演进
行为评测回答的是“Agent 有没有照做”,证据闭环进一步回答:面对同样的任务,使用这个 Skill 之后,Agent 是否真的做得更好?
在 Better Harness 中,我们把它设计成一套评测执行协议 。在任务、模型、工具、权限和测试环境保持一致时,进行三组对照:无 Skill / 当前版本 Skill / 候选版本 Skill。
评测不只看最终成功率,还要观察关键步骤是否执行、验证是否完整、时间与 Token 成本,以及有没有额外副作用。否则,一个看起来“更好”的 Skill,可能只是用了更多权限或资源。
这里尤其要防止一种“假使用”:Agent 找到了 Skill,也读取了 SKILL.md,但并没有真正执行其中要求的步骤。Better Harness 将这种情况称为“
已经路由,但没有真正执行”(routed-but-not-applied)。
因此,我们会沿着一条证据链继续判断:
- 存在吗? Skill 和相关机制是否存在;
- 找得到吗? 真实任务能否发现并选择它;
- 执行了吗? 要求的关键步骤是否真正发生;
- 有效吗? 相比不使用 Skill,结果是否确实改善。
在 Agent Work Loop 中,这对应“已存在 →
已接入 → 已执行 → 有效果证据”(Present → Wired → Exercised → Outcome-supported)。核心原则只有一个:
证据走到哪一步,结论就只能说到哪一步。**
这也和近期 Skill 评测研究的方向一致:SkillsBench 关注同一任务下使用与不使用 Skill 的结果差异,Skill Coverage 则进一步检查 Skill 中要求的行为是否真的出现在执行轨迹里。前者回答“结果有没有变好”,后者回答“过程有没有真正发生”。
结果改善和过程覆盖,两种证据缺一不可。 只有这条证据链建立起来之后,自我演进才有意义。否则,Trace2Skill、EvoSkill、CoEvoSkills 或 SkillOpt,都可能只是帮助 Agent 更快地产生更多未经验证的 Skill。
Skill 的演进,不应该从“生成更多经验”开始,而应该从“证明这次修改确实让下一次做得更好”开始。
结语
Agent 插件工程的核心,不是把 Skill 写得更复杂,而是把插件中的能力当作软件资产来维护:用规格约束行为,用上下文编排知识,用确定性验证守住边界, 用行为评测确认执行,再用对照证据判断效果。
当这些机制能够共同工作时,一个插件才真正从“写出来能用”,走向“可验证、可维护、可持续演进”。
把 Agent 插件当作软件来开发,也意味着每一次修改,都应该留下足够的证据证明它变得更好了。
或许您还需要下面的文章: