导学阶段-Skills 按需加载的领域知识
本文整理自 CNB 上的开源课程 《Vibe Agent:从零搭建 Coding Agent》。课程讲义、示例代码与练习仓库均在 CNB 上公开,文中示例出自该仓库对应章节。
给 Agent 增加能力,最初只有一条路:写工具。想让它查天气就写一个查询函数,想让它发邮件就写一个发送函数,然后注册、打包、重新部署。这条路能走通,但成本结构不合理。能力越多,发版越频繁,而且规范类的东西,比如”团队统一的 docstring 一律用 Google 风格”,根本不适合写成一个函数。
Skill 要解决的就是这类问题。
一条更轻的扩展路径
工具扩展的流程是写代码、注册、重新打包、上线。Skill 扩展的流程是把一个 Markdown 文件放进指定目录,重启后生效,多数实现甚至不用重启。
差别不只是工作量。工具与代码库强绑定,换一个项目就要重新适配;而一份 Markdown 文件是纯文本,复制即用,可以随仓库分发,也可以放进中心仓库供人检索下载。后一种形态常被称为 Skill Hub,类比 npm 或 PyPI。
把能力定义从代码下沉到文本,带来的直接后果是写的人变了。会写 Markdown 的产品经理、文档工程师、业务同事,都能直接贡献一份规范,不需要提交代码。
手与规矩的分工
Skill 和 Tool 经常被放在一起比较,但两者不是替代关系。
工具是手,负责执行动作;Skill 是规矩,规定事情该按什么标准做。写一篇周报、补一段 docstring、按团队的 commit 规范提交,这些都属于规矩。规矩不需要被执行,它只需要被读到。
这引出一个容易误解的点:Skill 自己什么都不执行。有的 Skill 目录里会附带脚本,但真正运行脚本的仍然是 bash 这个工具。Skill 只是在正文里写清楚”用 bash 跑 scripts/fill.py,参数按下面格式传”,模型读到之后自己发起工具调用。
有意思的是,Skills 机制本身也是用工具实现的:一个是 list_skills,列出所有可用能力;一个是 load_skill,按名字加载完整规范。用工具去加载知识,这句话本身就把两者的定位说清了。
SKILL.md 的结构
每个 Skill 是一个目录,目录里放一份 SKILL.md,由 YAML frontmatter 和 Markdown 正文组成。
1 | --- |
name 是唯一标识,通常与目录名一致;description 是一句话摘要,会被注入到 system prompt 里,供模型判断何时加载。正文则是完整规范。如果文件没有 frontmatter,宽松的实现会退化成取正文第一个非标题非空行当摘要。
两级加载
如果每次对话都把全部 Skill 的全文塞进上下文,问题只是从”工具太多”换成了”提示词太长”。真正的解法是分级。
第一级在启动时完成:扫描 skills 目录,只读每个文件的元数据,取出 name 与 description,拼成一份索引注入 system prompt。每个 Skill 只占一行,几十个 token。模型开局就知道有哪些能力可用,但不知道每份规范的具体内容。
第二级在运行时发生:只有当某份规范真的被用到,才读取全文并注入上下文。
1 | class SkillLoader: |
索引惰性构建,第一次访问才扫盘,之后走缓存。加载前要校验名字,并且确认最终路径仍在根目录之内,否则一个写成 ../../etc 的名字就能读到任意文件。
这段成本模型的准确说法是每个 Skill 常驻一行索引,总量随数量线性增长。它不是零成本,只是从”全文常驻”降到了”一行常驻”。
两种触发方式
规范加载进来有两条路径。
第一条是模型自主判断。system prompt 里已经有索引,用户说”帮这个函数补一下 docstring”,模型识别出命中 add-docstring,主动调用 load_skill 取全文。这条路径不需要用户知道 Skill 的存在,代价是多一次工具往返。
第二条是用户点名。输入以 @ 开头,程序在调用模型之前就把规范全文拼到任务前面,再整体交给 Agent。这条路径少一次往返,但用户必须记得 Skill 的名字。
两条路径可以同时保留,实现上只在入口处加一个预处理分支:
1 | def preprocess(user_input, loader): |
分发的代价
Skill 把规范变成了可复制的文件,也把攻击面变成了可复制的文件。
SKILL.md 是原样注入上下文的指令文本,一份恶意 Skill 相当于一次可安装的提示词注入。加载器目前只做了名字白名单和路径校验,这两项防的是越权读取,防不住正文里的指令。一旦 Skills 可以在社区自由下载,来源校验、内容审查、权限声明就成为必须补上的环节。
同样的问题也出现在可靠性上。索引是线性增长的,能力很多时需要分组或按项目裁剪;规范之间的矛盾没有自动检测,两份 Skill 对同一件事给出不同要求时,模型只能自己挑一个。
这类问题没有技术上的银弹,只能靠工程约束:谁能发布、发布前审什么、冲突时以哪份为准。
规范的载体变了
Skill 的意义不止于省了几次部署。它把团队规范从散落在文档站、聊天记录、口头约定里的东西,收拢成一种可版本管理、可分发的文件。
Agent 的行为边界,很大程度上由它读到的规范决定。规范能像依赖一样被安装和升级,团队才有可能把 Agent 调教成符合自己习惯的样子。
下一节换一个角度:Agent 打包成镜像之后,怎么让它进入日常工作流,在有人提 issue 的时候自动接手。


