2026年4月17日·2 分钟阅读

Skill:Agent行动手册

梳理 Skills 的定位、边界和落地方式。

AgentSkillsEngineering

在谈到Skills之前,我想先提到 Harness,之前一直很火的一个概念,名为驭术。

关于Harness更具体的可以看这篇文章:Codex中的工程技术

它们之间的关系是

Harness = 任务运行/验证外壳
Skill = Agent 执行任务时使用的能力提示包

更直白点说,Harness 在组织一次任务运行/测试/评测时,可以把某些 Skill 作为运行条件的一部分加载进去。

Skill存在于Agent之中,在需要时被调用/启用。

在做 NeoCode 的过程中,我一开始以为 Code Agent 最重要的是“工具能力”:能读文件、能搜索代码、能执行命令、能修改文件。

但后来我发现,模型“会调用工具”和“会稳定完成某类任务”之间,还有一段很长的距离。

比如同样是代码 Review,Agent 可能会读文件、会 grep、会跑测试,但它不一定知道 Review 的重点是什么:是架构边界?错误处理?并发风险?安全问题?还是 API 兼容性?

如果每次都让用户在 prompt 里重新解释一遍流程,这件事既重复,也不稳定。

所以我后来对 Skill 的理解变成一句话:

Tool 是手,Skill 是手册。

Tool 解决“Agent 能做什么动作”,Skill 解决“Agent 做某类任务时应该怎么做”。

技能系统

Claude Code的技能系统是一个多层次的扩展机制。它允许用户通过 Markdown 文件定义可复用的 prompt 模板,也允许开发者通过 TypeScript 代码注册编译时内置的技能。整个系统的设计目标是:零配置可用,自定义配置强大

为什么Agent需要 Skill

最开始的原因很简单:我发现模型“会用工具”和“会稳定完成某类任务”之间还有很大距离。

比如同样是代码 Review,模型可能会读文件、会 grep、会跑测试,但它不一定知道 Review 的重点是什么:是看架构边界?安全问题?错误处理?并发风险?还是 API 兼容性?

如果每次都靠用户在 prompt 里重新解释:

你要先看模块边界,再看错误处理,再看安全风险,最后按 P0/P1/P2 输出。

这会很重复,也不稳定。

所以我觉得 code agent 需要 Skill,本质上是为了把某类任务的经验沉淀下来。它不是给模型新增工具,而是告诉模型:当你做这类任务时,应该按什么方法、什么约束、什么输出格式来做。


Agent “会调用工具”和“会完成任务”之间差了什么?

差的是任务策略。

会调用工具只是底层能力,比如:

read_file
grep
bash
edit_file
webfetch

但会完成任务,需要模型知道:

什么时候该读文件?
先读哪个文件?
读完如何判断问题?
什么时候应该停止?
结果应该怎么组织?
哪些动作不能做?

所以 Skill 想补的不是单纯知识,也不只是 prompt,而是:

知识 + 流程 + 约束 + 经验 + 输出规范

比如 Go Review Skill 不只是告诉模型“你是 Go 专家”,而是告诉它:

先看包边界
再看错误处理
再看并发和资源释放
再看测试覆盖
最后按 severity 输出 findings

这才是 Skill 的价值。


Skill 解决的核心问题

第一,减少重复提示词。 很多任务的要求是固定的,不应该每次都让用户重新写一遍。

第二,复用任务经验。 比如 Review、Debug、Issue 写作、RFC 写作、竞赛方案、政审表填写,这些任务都有可复用方法。

第三,提高工具使用质量。 Skill 可以告诉模型某类任务应该优先用哪些工具、少用哪些工具、什么情况下不要贸然执行。

第四,规范输出。 尤其是工程协作场景,输出格式比“灵感”更重要。比如 issue 要有背景、问题、目标、非目标、验收标准;review 要有 severity、证据、建议。


Skill 和普通 prompt

普通 prompt 是一次性的,Skill 是可管理的。

区别主要有几个:

1. Skill 有 metadata,可以被发现、索引、启用、禁用;
2. Skill 是可复用的,不是一次性输入;
3. Skill 是结构化的,可以包含 instruction、references、examples、tool_hints;
4. Skill 可以会话级激活,而不是每轮手动复制;
5. Skill 可以被 runtime 注入,而不是靠用户记得粘贴。

普通 prompt 更像临时口头要求;Skill 更像团队沉淀下来的任务手册。


Skill 和 Tool / Harness / Hook

Skill 和 Tool

Tool 是动作能力,Skill 是使用能力的方法。

比如:

Tool:read_file,可以读文件
Skill:做 Go Review 时,应该先读 go.mod,再读核心 package,再看错误处理

Tool 负责“能做什么”,Skill 负责“怎么做得更好”。

Skill 不应该直接执行动作。 它可以建议模型优先使用某些工具,但不能自己绕过 runtime 去执行,也不能改变权限。

一句话:

Tool 是手,Skill 是手册。

Skill 和 Harness

Harness 是任务运行和验证外壳,Skill 是 Harness 或 Agent 在执行任务时可以加载的能力提示包。

Harness 更偏外部组织:

准备任务
设置运行环境
注入测试
验证结果
评测 agent

Skill 更偏 agent 内部能力:

任务策略
操作流程
输出规范
工具使用建议

所以关系可以是:

Harness 组织一次任务运行;
Skill 作为运行条件之一被加载;
Agent 在该 Skill 指导下执行任务。

比如做一个 Go 项目修复 Harness,它可以要求加载:

go-debugging skill
go-test skill
issue-writing skill

Skill 和 Hook

Hook 是生命周期扩展点,Skill 是模型上下文策略。

Hook 运行在 runtime 生命周期里,比如:

before_tool_call
after_tool_result
before_completion_decision

它可以观察、阻断、补充事件、生成通知。

Skill 不在生命周期里执行,它只是被注入到模型上下文,影响模型行为。

二者可以配合:

Skill 告诉模型:做安全 review 时要关注敏感文件;
Hook 在 before_tool_call 阶段阻止模型访问超出范围的文件。

也就是说:

Skill 是软约束;
Hook 是运行时硬边界或扩展点。

能力 解决的问题 在 Agent中的位置 不应该做什么
Tool Agent 能执行什么动作 动作执行层 不负责决定任务策略
Skill 某类任务应该怎么做 任务 SOP / 上下文策略层 不新增工具,不绕过权限
Hook 生命周期节点上如何观察、拦截、增强 Runtime 扩展点层 不替代主循环和权限系统
Permission 某个动作能不能执行 安全授权层 不负责生成任务流程
MCP 接入外部工具和服务 外部能力接入层 不负责沉淀任务经验
Harness 如何组织任务运行和验证 任务运行 / 评测外壳 不直接替代 Agent 内部策略

Skill 不应该做这些事:

1. 不应该绕过权限;
2. 不应该注册真实工具;
3. 不应该替代 verifier;
4. 不应该改变 runtime 终态;
5. 不应该隐藏执行逻辑;
6. 不应该成为“提示词里的后门”;
7. 不应该让模型以为自己拥有未暴露的能力。

尤其要注意:Skill 不能说“你可以直接修改任意文件”这种话。真正能不能修改文件,要由工具暴露和 permission 决定。

Skill 只能影响模型选择,不应该改变系统权限。


Skill 文件应该怎么设计

我觉得 metadata 里至少要有:

id: go-review
name: Go Review
description: Review Go code for correctness, safety and maintainability.
version: 1.0.0
scope: user
source: ~/.neocode/skills/go-review/SKILL.md
tool_hints:
  prefer:
    - filesystem_read_file
    - grep
    - bash
  avoid:
    - filesystem_write_file

核心字段是:

id:唯一标识
name:人类可读名称
description:什么时候该用
version:版本
scope:user / project / builtin
source:来源
tool_hints:工具使用建议

后续还可以有:

tags
activation_keywords
risk_level
compatible_modes

但我们目前做的没有太复杂。

# Instruction
这个 skill 的核心行为要求。

# Workflow
推荐步骤。

# Constraints
不能做什么。

# Tool Hints
建议优先使用哪些工具,避免哪些工具。

# Output Format
最终输出格式。

# Examples
好例子和坏例子。

# References
可选参考资料。

其中最重要的是:

Instruction
Workflow
Constraints
Output Format

因为 Skill 不是知识库文章,而是要指导模型执行任务。


Skill 应该是任务 SOP

差的写法是:

你是资深 Go Reviewer,请认真审查代码。

好的写法是:

一个 NeoCode 里的 Skill 示例:Issue 写作 Skill

在 NeoCode 项目里,我最早明显感受到 Skill 价值的场景,是写 GitHub Issue。

一个好的工程 Issue 不只是标题和一句需求,它应该包含:

  • Background
  • Problem
  • Goal
  • Non-goal
  • Proposed Design
  • Acceptance Criteria
  • Test Plan
  • Risks

如果每次都让用户手写这些结构,成本很高;如果只靠模型自由发挥,输出又很不稳定。

所以 Issue Writing Skill 的价值,就是把“如何写一个工程化 Issue”的经验沉淀下来。它不需要新增任何工具,只需要告诉 Agent:

  1. 先明确用户目标;
  2. 区分当前问题和预期行为;
  3. 写清楚验收标准;
  4. 对未完成能力保持边界;
  5. 最后输出可直接复制到 GitHub 的 Markdown。

这就是 Skill 的典型价值:它不是增加 Agent 的手,而是让 Agent 更会用已有的手。

所以 Skill 应该是:

少一点“你是谁”
多一点“你怎么做”

Skill 加载引擎

flowchart LR
    FS[Skill Files<br/>~/.neocode/skills / project skills] --> L[Loader<br/>扫描与解析]
    L --> R[Registry<br/>索引与查询]
    R --> F[Filter<br/>按 session / workspace / scope 过滤]
    F --> C[Context Builder<br/>注入当前会话上下文]
    C --> A[Agent Runtime]

Loader / Registry / Filter

这三层边界是清楚的。

Loader:负责从文件系统扫描、读取、解析 SKILL.md
Registry:负责把解析后的 skill 放进内存索引
Filter:负责按当前 session/workspace/source/scope 决定可见哪些 skill

换句话说:

Loader 关心“有什么”
Registry 关心“怎么查”
Filter 关心“当前能不能用”

这样以后加项目级、远程 skill、builtin skill 都比较自然。

但项目级 Skill 要谨慎,因为它可能来自仓库,存在 prompt injection 风险。 所以项目级 Skill 必须配合 trust workspace:

未信任 workspace:不自动加载项目 skill
已信任 workspace:允许加载

加载顺序可以是:

builtin
user
project trusted

但优先级要定义清楚。


加载失败怎么处理

单个 Skill 失败不影响整体加载

比如:

metadata 无效
内容为空
文件过大
id 冲突

这些都应该记录成 LoadIssue,然后继续加载其他 Skill。

但是 id 冲突要 fail-closed。 因为如果两个 Skill 都叫 go-review,系统无法确定用户到底启用了哪个,继续加载会有安全和可预测性问题。

所以规则是:

普通解析失败:跳过该 skill,记录 LoadIssue;
id 冲突:冲突项全部不可用;
整体 registry 不因为单个 skill 崩溃。

Skill 怎么被使用

我更支持手动启用:

/skill use <id>
/skill off <id>
/skill active

好处是可控。

Skill 会影响模型上下文,如果自动启用太激进,用户可能不知道为什么模型突然按某个 SOP 做事。

手动启用的优点:

1. 用户明确知道当前激活了什么;
2. 避免错误匹配;
3. 便于 debug;
4. 便于复现;
5. 不会让项目级 skill 悄悄影响模型。

Skill 如何影响LLM

当前设计是 Runtime 在每轮 context 构建时注入一个 Skills section,包括:

instruction
tool_hints
references
examples

这个方式优点是简单、可解释、provider 无关。

缺点是:

1. 会占用上下文;
2. 多个 Skill 同时启用可能冲突;
3. Skill 太长会污染 prompt;
4. 模型可能过度服从 Skill,而忽略当前用户请求。

所以需要限制:

最大注入长度
Skill 数量上限
冲突检测
优先级
摘要注入

其实好的方案是:Skill 激活后只注入必要部分,不要把整个 SKILL.md 原文全塞进去。


tool_hints

tool_hints 只能是提示,不能改变权限。它可以做:

优先展示 read_file
提醒模型少用 bash
建议先 grep 再读文件

但不能做:

新增工具
绕过 permission
暴露隐藏工具
自动授权高危工具

当前文档里写“只调整已暴露工具排序,不新增工具、不改变权限决策”,这个边界我认同。

一句话:

tool_hints 影响模型选择,不影响 runtime 权限。

Skill 拓展

第一阶段:本地用户 Skill。(已实现)

~/.neocode/skills/
手动启用
注入上下文
支持 tool_hints

第二阶段:项目级 Skill。(已实现)

.neocode/skills/
需要 workspace trust
适合团队共享 SOP

比如一个项目可以自带:

project-architecture-review
project-test-guideline
project-release-process

第三阶段:Skill 与 Harness 联动。(未开发)

Harness 可以声明:

本任务需要 go-test skill
本评测需要 issue-writing skill
本修复任务需要 debugging skill

这样任务运行和能力注入就能组合起来。

第四阶段:Skill 质量评测

Skill 不能只是写出来,还要知道有没有用。可以统计:

启用次数
任务成功率
用户关闭率
是否导致工具误用
是否导致输出变差

第五阶段:Marketplace / 版本管理

远程 Skill marketplace 有价值,但要很晚做。因为它引入安全问题:

远程 Skill 是否可信?
是否有 prompt injection?
是否诱导模型泄露信息?
版本升级是否破坏行为?

所以 marketplace 必须建立在签名、版本、权限、trust 之上。


总结

Tool 让 Agent 能做事,Hook 让 Runtime 能被扩展,Harness 让任务能被运行和验证,而 Skill 让 Agent 在某类任务上“知道该怎么做”。它不是执行层,不是权限层,也不是评测层,而是把可复用的任务经验、流程约束和输出规范沉淀成可激活的上下文能力。

(完)

返回文章列表

评论

评论组件加载中…