Skip to content

技能系统:Agent 的训练手册

本章摘要

技能系统的核心是按需加载——上下文是稀缺资源,把所有知识塞进系统提示既浪费空间又稀释模型判断。技能用"名称+描述"先进入名单,用到时再加载完整内容。

如果说 Agent Loop 是 Agent 的心跳,工具系统是它的双手,那技能系统就是一本训练手册

有了手,Agent 能读写文件、执行命令;但"能做什么"不等于"知道怎么做"。Git 提交规范、代码审查清单、部署流程——这些领域知识不能靠模型自己猜,需要被注入。

最直接的办法是把所有知识塞进系统提示。但这样有两个问题:

  1. 浪费空间——大部分技能与当前任务无关
  2. 稀释判断——无关信息让模型难以聚焦

技能系统的解法是按需加载

  • 第一阶段(启动时):系统提示只放名称和描述,每个约一两百字
  • 第二阶段(按需时):模型判断需要某个技能时,才加载它的完整内容

这种两阶段加载的设计哲学和查字典非常类似,不需要把字典完整背下来,而只需要记住字本身的拼写即可。

技能的来源层级

技能可以来自不同位置,按作用范围划分:

  • 系统级:编译进二进制,开箱即用
  • 管理策略级:企业管理员下发
  • 用户级:跨所有项目的个人偏好
  • 项目级:仅当前项目生效
  • 远程级:通过外部协议(MCP)提供的远程技能

启动时,系统按优先级合并去重。多层之间是拼接而非覆盖——去重是基于文件路径,不是技能名称。不同来源提供的同名技能可以共存,只有同一个文件通过符号链接等方式出现在多个目录时才会去重。

技能的加载方式

skill-loader

在扫描各来源目录,合并去重后,技能按是否带触发条件分成两类:

  • 无条件技能:立即可用,注入系统提示
  • 有条件技能:带触发规则(SKILL 的配置中带 paths 字段,如 paths: ["src/**/*.ts"],只有处理符合 "src/**/*.ts" 通配符的文件时会进入技能列表),会先进入待命池,等条件满足后被激活(会被放到一个 <system-reminder> 包裹的用户提示词块中,下次一并发送给模型 API)

对于子项目的技能(比如 sub-project/.claude/skills/some-skill),也只会在操作该子项目的时候被动态加载,类似上述有条件技能

等到模型需要使用该技能时,则会经历如下步骤:

  1. 根据技能的 context 配置:判断是 inline 执行(直接加载到当前的上下文中)还是 fork 执行(复制一份当前的上下文单独执行技能,完成后返回结果,类似后续会介绍的 fork subagent 的方式,防止当前的上下文污染)

  2. 根据技能的 arguments 配置:类似于字符串模板,可以根据用户传入的参数来替换技能中的占位符。

  3. 根据技能的 allowed-tools 配置:将这些工具的权限改为直接放行。

注意allowed-tools 只是将某些工具改成直接放行,而不是说禁用其余工具

写一本自己的训练手册

技能本质上是一个目录,里面放一个 SKILL.md 文件。SKILL.md 的开头是一段 YAML 格式配置(frontmatter),后续是 Markdown 正文。

可用配置项

所有字段都非必需,但是推荐至少写 namedescription 字段。

字段描述
name/ 菜单中的显示名称。不参与命令匹配——调用时按目录名匹配,未设置 name 时回退为目录名
description功能说明和使用场景。Claude 用它决定何时调用。省略则取正文第一段
when_to_use何时调用的额外上下文(触发短语、示例请求),追加到 description 后,合并展示于技能列表中
argument-hint在输入框键入斜杠命令时,会作为浅灰色的占位符显示,用于提示该命令期望的参数内容
arguments命名位置参数,用于正文中的 $name 替换。按顺序映射到参数位置
disable-model-invocationtrue 阻止 Agent 自动加载,仅限 /name 手动触发。默认 false
user-invocablefalse/ 菜单隐藏,用于背景知识类技能。默认 true
allowed-tools技能激活时可免确认使用的工具列表
model覆盖当前轮次的模型,如 sonnethaikuinherit(保持当前)
effort思考力度:lowmediumhighxhighmax
context设为 fork 在独立子代理中运行
agentcontext: fork 时使用的子代理类型,比如 Explore、Plan
hooks可以在此处定义随技能加载的生命周期钩子
paths仅在处理与 paths 定义匹配的文件时将该技能注入上下文
shell技能中内联命令使用的 shell,bash(默认)或 powershell

示例

markdown
<!-- ~/.claude/skills/gen-api/SKILL.md -->
---
description: 生成 REST API 端点的完整代码骨架
when_to_use: 需要创建新的 API 端点时
arguments: method resource
argument-hint: "[GET|POST|PUT|DELETE] [resource-name]"
allowed-tools:
  - Read
  - Write
  - Grep
  - Glob
---

为资源 $resource 创建 $method 方法的 REST API 实现。

基于项目既有模式,生成以下文件:
1. 路由定义
2. 请求/响应类型
3. 控制器逻辑
4. 基本测试

参数按位置映射,顺序必须严格

/gen-api POST users   →  $method=POST,  $resource=users  ✓
/gen-api users POST   →  $method=users, $resource=POST   ✗(参数错位)

调用方式:

  • 手动触发:输入 /gen-api POST users
  • 自动触发:对模型说"帮我生成一个创建用户的 API",模型识别意图后自动调用该技能

参数不足 arguments 声明数量时,多余变量替换为空字符串。未使用 $name 占位符的多余参数会追加到内容末尾。

三条核心原则

一技一事。 技能粒度要细——"全栈开发"技能不如"API 生成""组件生成""测试生成"三个独立技能。

描述精确。 描述是模型选择技能的依据。模糊描述导致选错——"代码审查"比"帮助改进代码"好得多。

用条件技能减少噪音。 加触发规则,只在操作匹配文件时激活。技能多不是问题,技能同时出现在列表里才是问题。

本章要点

  • 技能系统是 Agent 的"训练手册",把领域知识按需注入
  • 按需加载有两层含义:①启动时只放名称描述 ②条件技能按触发条件激活
  • 多层技能按优先级合并,拼接而非覆盖
  • 最小权限原则体现在 allowed-tools:技能可限定允许使用的工具
  • 写技能的核心是一技一事、描述精确、触发合理