Skill 机制:两阶段加载、生命周期与边界
一句话定位:Skill 机制是 Harness 部件 ③状态 的「流程知识」装载机制——记忆存的是事实,Skill 存的是流程(怎么一步步做成一类事)。前置:什么是 Harness、Skill 的产品行为(生命周期四步、触发调试树,产品篇已讲,本篇讲机制)、工具执行(懒加载在工具侧的孪生设计)。
先从一堆「每次都要贴的说明」说起
你们团队有一套发布流程:跑全量测试、更新版本号、写变更日志、打标签、推包。你教过 Agent 怎么做——把五六个步骤连同注意事项贴进对话,它执行得很好。
问题是这段说明从此常驻在上下文里:接下来聊别的它也带着,聊三天它还带着。流程知识「每次都要用、却只在特定时刻用」,全量常驻就是把上下文当仓库用。写成文档放在仓库里?Agent 忙起来根本不会想起去读。
流程知识能不能像工具定义一样「平时只报个名字、用时才展开」?
答案是能,而且这正是 Skill 的设计核心——两阶段加载:名字与描述组成的清单常驻上下文(轻),正文与支撑文件按需载入(重)。围绕这个核心再配上触发、生命周期与边界划分,就构成了整套 Skill 机制。
图:Skill 生命周期四阶段——「阶段 1」到「阶段 4」是本篇编号,产品篇的四步与它一一对应
渐进拆解
两阶段加载(机制核心)
类比:把 Skill 机制想象成新员工工位旁的手册架。架上贴着一页目录:「入职手册(周一用)、报销手册(月底用)、发布手册(发版日用)」——这页目录就是常驻清单,只有名字和一句话说明;遇到对应任务,把那本手册抽下来翻开,而且翻开后就一直摊在桌上(驻留),随时可查;手册末尾写着「表格模板见附件 C」,附件不复印就一直躺在架子上。目录很薄、手册厚、附件更厚——摊开在桌面的,只有被触发过的那几本。
本篇按四个阶段编号展开,两阶段即「清单常驻(阶段 1、2)+ 按需载入(阶段 3、4)」两大类。阶段 1 的清单由每个 Skill 的名字与描述组成,常驻在上下文里;阶段 3 的正文载入后驻留,后续轮次不用重新载(官方文档明文:载入后不重读文件,重复调用只加标注)。这与工具执行的懒加载是同一个思想用在两种资产上:工具定义不进上下文、搜索靠关键词检索器;Skill 正文不进上下文、匹配靠模型读描述自己判断——一个是检索问题,一个是理解问题。
清单放在哪有个标准与实现的分野:开放标准与官方博客描述的形态是「启动时把所有 Skill 的名字与描述预载进系统提示词」;Claude Code 的实际实现则把清单放进消息流(社区逆向口径)——与记忆的注入同一通道,因为清单同样是「会话中会变的数据」。无论哪种,清单都是轻的,正文都不在场。
此外还有两条兜底的机械规则:清单预算按上下文窗口约 1% 缩放,超预算时调用最少的描述先被丢出清单——官方口径按调用频次,不是按时间新旧;会话发生压缩时,官方会按预算把已载入的 Skill 回挂——每条保留开头约 5K token、合计 25K 以内。
大白话:一个 Skill 就是三样东西的组合——「什么情况下想起它」(描述,常驻)、「想起来之后怎么做」(正文,触发才载)、「细节要用再拿」(支撑文件,引用才读)。设计 Skill 的全部手艺,就是把这三种内容放到正确的层。
看一次触发的完整时序——从「用户说了一句话」到「流程知识进场」:
图:触发时序——清单常驻、描述匹配、正文驻留、附件按需;注意「载入」与「知道」发生在不同主体身上
技术定义(其余要点):
- 渐进披露架构(业界叫法):Anthropic 官方工程博客把渐进披露称为 Skill 的核心设计原则——像一本「组织良好的手册」,按需展开。清单本身有预算:官方文档明文,单条 Skill 的描述与触发说明合计截断到 1536 字符,清单总预算随窗口缩放(约 1%)——每个 Skill 的常驻成本就是这笔账。
- 触发机制:自动触发是模型读完清单后自主判断「当前任务与哪条描述匹配」;手动触发是斜杠命令直接点名(任务型 Skill 的形态,见动手段的样例),跳过匹配环节。两者覆盖不同场景:高频标准流程靠自动触发省心,低频或必须明确的操作用斜杠命令兜底。
- 为什么用专用工具载入而不用普通读文件(Claude Code 的实现选择,社区逆向口径):读文件工具只能「把内容拿进来」,专用 Skill 工具额外承载载入即驻留的语义、清单状态联动与权限生命周期的统一管理——把「读个文件」升级成「激活一项能力」。注意这是实现层的选择:开放标准的载入形态就是用普通命令读 SKILL.md。
- 生命周期六环与本篇四阶段:一种常见的拆法把生命周期分成六环(各环名称见动手段的对照表);对应到本篇编号——注册与检索在阶段 1(清单进出场)、匹配在阶段 2、编排在阶段 3、复用与下线是管理面(哪些该合并、哪些该退役)。产品篇的触发调试树管「阶段 2 出问题怎么排查」,本篇不重复。
- Skill / Memory / Tool 的边界:一句话判据——Tool 是能力(能做什么动作)、Memory 是事实(记住了什么)、Skill 是流程(怎么一步步做)。发版脚本的执行权限是 Tool,上次发版日期是 Memory,「发版要按这五步走」是 Skill;混放的症状见「边界与取舍」一节。
- 封装技能(进阶用法):把「人肉指挥的循环」装进 SKILL.md——原本你盯着屏幕喊「跑测试、看报错、改、再跑」,Skill 把这个循环写成明确的流程指令,Agent 照着自转。一个可自转的循环至少要三样:进入条件(什么情况启动)、循环体(每轮做什么、拿什么当反馈)、退出判据(什么情况算完成、什么情况必须停手求人)。这是 Skill 与普通文档的分水岭:文档描述状态,Skill 编排动作。
业界现状(2025-10 起):Skill 已从产品功能升级为开放标准(2025-12-18 发布于 agentskills.io)——SKILL.md 格式公开后,同一份 Skill 文件可跨多个编码 Agent 工具使用:跨工具目录 skills.sh(Vercel 运营)列出 20 种支持该格式的编码 Agent,含 Claude Code、Cursor、Codex CLI、OpenCode;官方工程博客把渐进披露定位为「让 Agent 适应真实世界」的核心设计。
社区同时出现一个值得注意的讨论:对「大量领域流程知识」的场景,渐进披露的 Skill 可能比预载全部工具定义的工具协议(如 MCP 的典型用法)更省上下文——两者不是替代关系,而是「流程知识」与「工具能力」的分层(与本篇的边界判据一致)。
动手:SKILL.md 的结构与触发匹配
一个最小可用的 SKILL.md 长这样(任务型 Skill——斜杠点名直通阶段 2,自动匹配同样能命中它):
---
name: release-patch
description: 发布补丁版本:跑测试、更新版本号、写变更日志、打标签、推包。当用户要求发版或发布补丁时使用。
---
# 发版流程
1. 跑全量测试,失败则停下报告,不带病发版
2. 按 semver 更新版本号(补丁位 +1)
3. 依据本次提交写变更日志(格式见 refs/changelog-style.md)
4. 打标签并推送,标签名与版本号一致
> 前置检查脚本:scripts/precheck.sh,发版前必跑
它的目录结构与载入逻辑(伪代码,阶段号呼应上图;示意用普通读写表达,实际载入经专用 Skill 工具):
release-patch/ # 一个 Skill 一个目录
├── SKILL.md # 正文:frontmatter(名字/描述)+ 流程指令
├── scripts/precheck.sh # 支撑:发版前检查脚本
└── refs/changelog-style.md # 支撑:变更日志的格式约定
def load_skill(name, skills, ctx):
meta = skills.registry[name] # 阶段 1:清单里的元数据
body = read(f"skills/{name}/SKILL.md") # 阶段 3:正文载入(专用工具)
ctx.append(body, persist=True) # 驻留:后续轮次不用再载
ctx.reminder_mark(f"skill:{name}", loaded=True) # 清单状态联动
return ctx
def maybe_trigger(task, skills, ctx):
if task.explicit_slash: # 阶段 2:手动斜杠直通
return load_skill(task.skill_name, skills, ctx)
for s in skills.manifest: # 阶段 2:自动,模型读描述自判
if model_judge_matches(task, s.description):
return load_skill(s.name, skills, ctx)
return ctx # 谁都不匹配:不触发也是结果
同一概念的叫法对照:
| 本篇用词 | 文献中的其他叫法 | 深挖去处 |
|---|---|---|
| 两阶段加载 | 两阶段披露 · 清单常驻 + 正文按需 | Skill 产品篇 |
| 渐进披露 | Progressive Disclosure · 按需展开 | 工具执行 |
| 触发匹配 | 自动触发 · 描述匹配(理解非检索) | 本篇 |
| 生命周期六环 | 注册 / 检索 / 匹配 / 编排 / 复用 / 下线 | 本篇 |
| 三者边界 | Skill=流程 / Memory=事实 / Tool=能力 | 记忆机制 |
两阶段加载省下的上下文账,画出来更直观:
图:上下文账——省的是「未触发的那些流程」的常驻占用;已触发的正文持续在场
边界与取舍:触发是卖点也是软肋
描述决定触发,这是设计也是失败模式的源头(本篇第一问)。 两条失效路径:
- 不触发:描述写得抽象(「辅助代码工作」),模型读不出它与当前任务的关联——手册在架上,你却想不起它的名字。
- 误触发:描述写得宽泛(「处理各种文件操作」),沾点边就载入——正文白占上下文还算轻,按错误流程办事算重。
写描述的正确心态:它不是广告词,是搜索引擎的查询词——要含着用户任务里会出现的词,精确多于华丽。产品篇的触发调试树(不触发查描述、误触发反向收敛)是排查手册。
跨项目复用,别让 Skill 库变成一次性脚本堆场(本篇第二问)。 判断标准一句话:换个项目还成立吗? 成立的(发版流程、代码评审清单、调试方法论)写成通用 Skill、放全局级作用域,项目差异用参数与支撑文件隔离——正文写流程骨架,项目特有的细节进引用文件;只对一个项目成立的步骤,老实写进项目记忆或项目文档,别包装成 Skill。编排上,Skill 引用 Skill 不超过两层——流程套流程太深,触发与驻留的上下文账就难算了。
与记忆、工具的边界要常清理。 三者混放是长得很慢的病:流程知识沉淀进记忆,模型「记得有这事」但做不齐步骤;事实写成 Skill,触发一次载入一大段。季度性的整理值得做:翻一遍 Skill 清单,把「其实是一条事实」的降级进记忆、把「其实是一个动作」的升级成工具——清单短一分,触发的准确度就高一分。
坏味道预警
如果你的 Agent 「该触发的没触发、不该触发的天天触发」,先别改机制——九成是描述层的问题;如果 Skill 越攒越多而触发越来越不准,这是清单过载,该合并的合并、该下线的下线(生命周期管理面的活)。
自测
合上文章先自己答,再展开对照:
Skill 的描述(description)决定触发——这个设计的失败模式是什么(不触发/误触发)?
匹配靠模型读描述自判(理解而非检索),所以描述质量直接决定两个方向的失败。不触发:描述写得抽象、不含用户任务会出现的词,模型扫清单时对不上号——手册在架上,想不起名字;排查靠产品篇的触发调试树(查描述是否覆盖任务词汇、是否被同名 Skill 覆盖、是否被截断——描述与触发说明合计上限 1536 字符,超出被剪,关键信息可能恰好被剪掉,清单超预算时调用最少的描述还会先被丢出)。误触发:描述写得宽泛,沾边就载入——轻则白占上下文,重则按错误流程办事。收敛方法是描述精确多于华丽、含具体任务词;低频关键操作改用手动斜杠调用兜底,跳过自动匹配。
Skill 编排与跨项目复用怎么做,才不会变成一次性脚本堆场?
复用的判断标准一句话:换个项目还成立吗。成立的流程(发版、评审、调试方法论)写成通用 Skill 放全局级作用域,项目差异用参数与支撑文件隔离——正文只写流程骨架,项目特有细节进引用文件,同一个骨架配不同项目的附件。只对一个项目成立的步骤,写进项目记忆或项目文档,不包装成 Skill。编排上 Skill 引用 Skill 不超过两层,触发与驻留的上下文账才好算,调试也容易。加上季度清理(事实降级进记忆、动作升级成工具、过时的下线),堆场病就不会得——堆场的病根从来不是「脚本太多」,而是「项目特有的东西被当成了通用能力」。
参考与延伸
- Anthropic 工程博客《Equipping agents for the real world with Agent Skills》(2025-10-16):渐进披露作为核心设计原则的官方阐述 — anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills
- Anthropic 官方文档:Agent Skills 总览与 SKILL.md 格式(1536 字符上限与清单预算的出处) — code.claude.com/docs/en/skills
- skills.sh(Vercel 运营的跨工具目录):列出 20 种支持 SKILL.md 格式的编码 Agent — skills.sh
- 社区综述:Agent Skills 作为跨工具开放标准的现状 — unite.ai/anthropic-opens-agent-skills-standard
本系列的后续学习路线(推荐顺序):状态机与 Checkpoint → 多 Agent 编排。