本文由 莫潇羽@无忆研习社(www.wuyi.wiki)撰写,转载请注明出处。
快速摘要
Agent Skills 是 Anthropic 在 2025 年底推向主流视野的智能体能力扩展机制。一句话说清楚:它把一个领域的标准作业流程(SOP)、参考资料、可执行脚本打包成一个"技能文件夹",智能体在真正用得到的时候才会逐层加载。 它解决的是过去我们写超长提示词带来的三个老毛病——上下文窗口被撑爆、注意力涣散、工具调用混乱。本文按"原理拆解—结构剖析—编写规范—六条铁律—端到端实战—多平台适配—踩坑提示"的顺序一次说透,核心实战部分会落到一个真实可跑的"会议总结助手"案例:用户丢进去一段开会的对话记录,Skill 自动产出标准化纪要、按需引用公司财务手册做合规提醒,再调用脚本把纪要同步到云端。同一份 Skill 不改一行代码,在 Claude Code、Trae、CodeBuddy、Codex、OpenCode 上都能跑起来,这也是 Skills 比 MCP、比 Function Calling 更值得投入时间的根本原因。如果你最近在折腾智能体却始终卡在"能跑但不稳"那一步,这篇就是为你写的。想看完整拆解,往下翻。
一、提示词工程到了天花板,Skills 才是下一站
我最初做智能体的时候踩过一个特别经典的坑。给一个对话助手写系统提示词,洋洋洒洒堆了快两千字,角色、口吻、知识范围、不允许做什么、要遵循的格式、调用工具的判断条件,通通塞进去。本地跑几个简单测试,效果看着不错。真把它放到一个稍微复杂点的业务流里——客户问了一个跨场景的问题,要先查订单,再判断状态,再决定推什么话术——它当场就懵了,要么忽略掉某个关键判断,要么把不该调的工具叫了一遍,要么输出格式跑偏。
折腾几轮我才意识到一个事:这不是提示词写得不够好,而是单靠一段长文本去控制多维度、非线性的复杂工程逻辑,本身就是个错配。
1.1 长提示词的三个固有缺陷
把这个错配拆开看,有三个非常具体的问题。
第一个是注意力稀释。 大模型底层是 Transformer 的注意力机制,这一点接触过原理的朋友都熟悉。注意力是一种有限资源,上下文越长,模型对每一段信息分配到的"心思"就越少。你可能感觉它读完了你那两千字的提示词,但真到推理的时候,中间那部分的细节经常被吃掉。这就是大家在长对话里偶尔看到模型突然"忘了之前的设定"的根因。
第二个是步骤失控。 你试图用一段线性的文字去描述一套有分支、有循环、有条件判断的流程,结果就是模型把它当成"参考建议"而不是"严格步骤"。它会自作主张地跳过某一步,或者把第三步先做了再回头补第一步。任务越复杂,这种失控就越明显。
第三个是工具调用混乱。 Function Calling 这个机制本身没问题,但是当你的智能体可以调用的工具达到十几二十个,每个工具的命名又占用大量 token,模型很容易选错工具,或者把同一个工具反复叫好几次。这里头还有个更隐蔽的成本问题——就算有些工具这次根本用不到,只要它们的定义被注入到上下文里,就要持续消耗 token。 这一笔账很多人没算过。
1.2 Skills 是怎么对症下药的
Anthropic 在 2025 年 10 月那篇 Equipping Agents for the Real World with Agent Skills 工程博客里提出的解法,本质就是把"线性的、笼统的提示词"拆成"结构化的、可按需加载的能力包"。
具体的对症点有这么几条。把 SOP 单独写成一份 Markdown 说明书,流程要素清清楚楚,而不是混在闲聊的提示词里。把外部知识下沉到 reference 目录,只有任务真正用到的时候才读进上下文,这样既保留专业深度,又不浪费 token。把确定性的逻辑写成可执行脚本(Python、Bash 等),让脚本去跑那些"每次都要重复做、必须可靠"的活,而不是每次都让大模型重新生成代码。
这三件事合起来,就是 Skills 这个机制的核心价值——它让智能体既能像专家一样"懂规矩",又能像工程师一样"能复用",还能在不污染上下文的前提下"按需扩展"。 把这套机制理解透了,你后面写出来的智能体应用,稳定性和成本都会比纯提示词方案上一个台阶,这点我自己在无忆研习社做几个内部项目时反复验证过。
再多说一句,提示词工程并没有过时,它只是有了边界。面对简短的、单轮的、灵活的任务,一段写得好的提示词依然是最优解;但面对那些需要稳定输出、需要复用、需要团队多人共维的智能体应用,Skills 把"工程化"这件事真正落了地。理解这层差异,才能避免一个常见误区:看到新工具就想着替代老工具。在莫潇羽的实践里,提示词、Function Calling、MCP、Skills 经常在同一个智能体里同时存在,各自负责最适合自己的那一部分工作。
二、Agent Skills 究竟是什么:一份给智能体看的"专业说明书"
理论铺垫到这,该把 Skills 的定义讲清楚了。我尽量不用官方那种学术化的说法,换成接地气的解释。
2.1 一句话定义
一个 Skill 就是一个文件夹,文件夹里放着一份给智能体看的说明书(SKILL.md)、一些可执行的脚本(scripts/),以及一些供它查阅的参考资料(reference/)。 智能体启动时只会扫到文件夹的"门牌号",真要干活的时候才会推门进来翻具体内容。
打个生活化的比方。想象你家厨房里有一台微波炉,微波炉面板上有"一键解冻"这种快捷指令——这就像传统的 Function Calling,功能单一、按一下就响应。厨房里还放着各种刀具——这是 MCP,通用性强,但你得自己拿、自己用、自己指挥它怎么切。Skills 则像贴在冰箱上的菜谱:它把一道菜从备料、火候、刀工到摆盘的每一步都写清楚,你只要按谱子走,新手也能做出大致不离谱的成品。
这个类比里有几个关键点要再强调一下。Function Calling 是"按钮",MCP 是"工具",Skills 是"流程"。三者不是替代关系,而是配合关系。 一个成熟的智能体应用里,菜谱(Skill)告诉智能体先干什么后干什么,菜谱里某一步说"切丝"的时候,智能体会去拿厨房的刀(MCP)。这个组合拳才是工业级智能体的常态。
2.2 Skills 与 MCP 的边界划分
这是个高频问题,我专门拆开讲。
|
维度 |
MCP |
Agent Skills |
|
核心目标 |
让模型能调用外部工具、访问外部数据 |
让模型按标准流程做事 |
|
配置形式 |
基于 JSON 协议,需要部署服务器 |
基于文件夹,纯文本就能写 |
|
共享方式 |
复制 JSON 配置、修改连接信息 |
打包文件夹、丢给别人用 |
|
上下文占用 |
工具定义常驻在系统提示中 |
渐进式加载,默认只占元数据 |
|
是否需要外网 |
通常需要,因为要连服务 |
不必,Skill 内容全部本地化 |
|
跨平台移植 |
受协议实现影响 |
同一份 Skill 跨多个平台运行 |
理解了这张表,你就明白为什么 Skills 推出后社区里有"Skills 比 MCP 更值得投入"的声音了。不是 MCP 不好,而是 Skills 解决了一个 MCP 没解决好的问题——专业流程的封装与复用。莫潇羽@无忆研习社这边的实践经验是:有内部数据要访问就上 MCP,有标准流程要复用就上 Skills,二者经常同时存在于一个智能体里。
举一个 Skills 和 MCP 联手干活的真实例子。我们做过一个"销售订单异常处理助手",流程是这样的:Skill 里写明 SOP——先核对订单状态、再检查物流信息、最后判断要不要触发售后流程。但订单数据、物流接口、售后系统都在公司内网,智能体没法直接访问。这时候 MCP 就上场了:订单数据库通过 MCP 暴露查询接口,物流系统通过 MCP 提供查询能力,售后工单系统通过 MCP 接受创建请求。智能体执行 SOP 的每一步时,通过 MCP 拿到所需的数据,再按 Skill 的规则做判断。这种 Skills + MCP 的组合形态,在企业级智能体里非常常见,也是莫潇羽强烈推荐的工程范式。两套机制各司其职,谁也不抢谁的活。
2.3 Skills 的三大组成
每一个 Skill 在物理结构上是这样的:
my-skill/
├── SKILL.md ← 必需,说明书 + YAML 元数据
├── scripts/ ← 可选,可执行的脚本
│ └── upload.py
├── reference/ ← 可选,知识库 / 参考资料
│ └── company-finance-manual.md
├── templates/ ← 可选,模板文件
│ └── report-template.md
└── examples/ ← 可选,示例输入输出
└── sample.md
SKILL.md 是唯一必须存在的文件,其余目录都按需选用。这里面有几个细节要注意。
文件夹的名字会成为 Skill 的命名标识,智能体在加载列表里看到的就是这个名字。scripts/ 里的文件优先放可执行代码,这部分内容默认不会进上下文,只有智能体决定要跑它的时候才会执行,这一点跟把代码塞进 SKILL.md 是本质区别。reference/ 里放的是"模型需要查阅的资料",注意,不是塞给用户看的,是塞给模型在干活时查阅的,所以语气和组织方式要往"工具书"的方向写。
graph TD
A[智能体收到任务] --> B{扫描可用 Skills}
B -->|读取 YAML 元数据| C[L1 元数据层]
C --> D{当前任务匹配吗?}
D -->|不匹配| E[跳过该 Skill]
D -->|匹配| F[L2 主体说明加载]
F --> G{需要参考资料吗?}
G -->|不需要| H[直接执行]
G -->|需要| I[L3 资源按需加载]
I --> J{需要跑脚本吗?}
J -->|否| K[输出结果]
J -->|是| L[沙箱执行脚本]
L --> K
H --> K
这张流程图就是 Skills 工作机制的全貌,后面几章我们会把每一层都拆开来讲。
三、拆解一个标准 Skill 的内部结构
光看目录树不够直观,我们直接看 SKILL.md 的真实模样,然后逐字段说清楚每一处的写法。
3.1 YAML Frontmatter 的写法规范
每一个 SKILL.md 的开头都有一段 YAML 元数据,被两组三个减号包起来,这段就是 L1 加载层的全部内容。
---
name: meeting-summarizer
description: >-
This skill should be used when the user provides raw meeting
transcripts and asks for structured meeting minutes, action
items, or wants to sync the summary to a server. Also triggers
on words like "总结会议"、"会议纪要"、"同步到云端".
---
# 会议总结助手
## 总结规则
...
这里有几条规范是经过踩坑得到的硬经验,莫潇羽建议你照抄。
name 字段只能用小写字母、数字和短横线,不能有空格,长度不超过 64 个字符。命名要有动名词感,比如 meeting-summarizer、pdf-extractor,直接告诉智能体这个技能"是做什么的"。
description 字段是整个 Skill 里最重要的一行字,这话不夸张。因为智能体决定"要不要加载这个 Skill"完全是基于这个字段的描述。 Anthropic 给出的字符上限是 200 个字符以内,但写得越精准越好。三个原则:用第三人称(写"This skill should be used when..."而不是"Use this skill when...")、写清楚"做什么"和"什么时候用"、包含关键的触发词。
举几个反面例子让你对照感受一下。
# 反面案例 1:太笼统
description: Helps with code
# 反面案例 2:太技术化,只描述实现不描述用途
description: Queries /api/v2/sprint endpoint with OAuth2 bearer token
# 反面案例 3:范围太宽,会过度触发
description: Assists with any development task
# 正面写法
description: >-
Generates weekly sprint reports by pulling data from Jira and
GitHub. Use when the user asks for sprint summary, velocity
metrics, or wants to share weekly status with the team.
3.2 SKILL.md 正文的组织方式
YAML 之后就是正文,这部分是 L2 加载层的内容。智能体一旦决定使用这个 Skill,正文就会被完整注入到上下文里。注意,这意味着正文里每一行字都是反复消耗的 token,所以一定要精炼。
我把会议总结助手的 SKILL.md 正文骨架贴出来,你看一下结构:
# 会议总结助手
## 角色定位
你是一位资深的会议记录专员,擅长把零散的会议对话整理成
结构化的会议纪要。
## 总结规则
对输入的会议对话,按以下维度做提炼:
1. 参会人员:列出所有出现过的发言人
2. 核心议题:不超过三句话,概括讨论焦点
3. 关键决定:明确写出会议达成的共识
4. 后续行动:每条行动要包含「谁、做什么、何时完成」
## 财务合规检查
当对话内容包含「预算、采购、签约、报销、付款」等关键词时,
必须读取 reference/company-finance-manual.md,并在输出末尾
加上「财务提醒」段落。
## 上传规则
当用户在提示中包含「上传」「同步」「推送到云端」等词汇,
按照如下流程执行:
1. 先完成会议纪要生成
2. 调用 scripts/upload.py 把纪要传给云端
3. 在最终输出中附上返回的文档 ID 和访问链接
## 输出格式
统一使用 Markdown 格式,标题层级从 # 开始,代码块带语言标识。
## 示例输入
[一段五人会议的口语化对话片段]
## 示例输出
[对应的标准纪要 Markdown]
骨架要写到这种颗粒度,智能体才不会自由发挥。有一个细节很关键:正文里不要再重复 YAML frontmatter 里已经写过的信息。 比如 description 已经说了这个 Skill 是用来做会议纪要的,正文里就不用再开一段"本技能用于会议纪要生成"。重复的内容只会让 token 多花一遍。
3.3 scripts 目录:写一个真正能跑的脚本
scripts/ 里放的是可执行代码,适合那些"每次都要做、必须可靠、不依赖大模型创造性"的工作。最典型的例子就是文件上传、调用第三方 API、数据格式转换、批量处理等。
会议总结助手的 scripts/upload.py 长这样(完整可跑版本):
"""
会议纪要上传脚本
作者: 莫潇羽 @ 无忆研习社
说明: 演示用,实际生产请替换为真实的云端接口
"""
import sys
import json
import time
import hashlib
import argparse
def validate(content: str) -> bool:
"""基础校验,确保内容非空且长度合理"""
if not content or len(content.strip()) < 10:
print("[ERROR] 纪要内容为空或过短,放弃上传")
return False
return True
def compress(content: str) -> str:
"""模拟压缩步骤,实际可换成 gzip"""
return content.strip()
def upload(content: str) -> dict:
"""模拟上传过程,真实环境替换为 requests.post 调用"""
if not validate(content):
return {"status": "failed"}
payload = compress(content)
doc_id = hashlib.md5(payload.encode("utf-8")).hexdigest()[:12]
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
print(f"[INFO] 正在连接云端服务器...")
time.sleep(0.3)
print(f"[INFO] 上传中...")
time.sleep(0.5)
print(f"[INFO] 上传成功")
result = {
"status": "success",
"document_id": doc_id,
"uploaded_at": timestamp,
"access_url": f"https://docs.example.com/d/{doc_id}",
}
return result
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--content", required=True, help="会议纪要 Markdown")
args = parser.parse_args()
result = upload(args.content)
print(json.dumps(result, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()
这个脚本有几个细节要在自己工程里复用。命令行参数化:智能体调用脚本时是通过 shell 命令传参的,不要写成需要交互式输入的脚本。输出 JSON:让智能体能稳定解析返回值。日志和结果分离:print 的人类可读日志走标准输出,结构化数据用 JSON 序列化,这样智能体能精确捕捉到。幂等性考量:如果脚本可能被反复调用,记得加上去重或者版本号机制。
3.4 reference 目录:智能体的"专业工具书"
reference/ 是 L3 资源层的核心。这里放的内容只有在 SKILL.md 主体里被显式引用或者匹配到特定关键词时才会读进上下文,所以你可以放心地把比较厚的领域知识塞进去,不用担心常驻成本。
会议总结助手里我放了一份精简版的公司财务手册,看一下大致结构:
# 公司财务管理手册(精简版)
## 第一章 报销规范
...
## 第二章 预算审批
单笔金额低于 1 万元,部门负责人审批后即可执行。
单笔金额 1 万至 5 万元,需提交财务主管复核。
单笔金额超过 5 万元,需走 OA 审批流程,且至少提前 7 个工作日提交。
## 第五章 营销活动与对外公关
单事项履行需提前 14 个工作日走 OA 审批,
营销物料采购需附带三家以上比价报告...
智能体在处理"预算八万元"这种关键词时,会按 SKILL.md 里的约定读取这份手册,把第五章的 14 个工作日规则带进最终输出。这就是渐进式加载机制最直观的好处——领域知识可以无限扩展,但你不必为没用到的部分付费。
3.5 templates 与 examples:常被忽略的两个目录
除了 scripts 和 reference,Skills 还约定了两个补充目录:templates/ 放可填充的模板文件,examples/ 放示例输入输出。这两个目录都是 L3 资源层的延伸,被使用得不多,但用对了能让 Skill 的稳定性上一个台阶。
templates/ 适合放那些"骨架固定、需要填空"的产出物。我自己写过的几个典型例子:周报模板、技术方案模板、客户回复模板、PR 描述模板。这些文档的章节结构是固定的,变化的只是每一节的具体内容。SKILL.md 主体里写一句"基于 templates/weekly-report.md 的结构生成本周周报",智能体就会去把模板读进来,逐节填充。
examples/ 的作用前面提过,这里再细说一下。每个 Skill 都建议在 examples 目录里放至少一组完整的"输入—输出"对照,智能体在不确定输出格式的时候会主动来翻这里的样本。重要的是,examples 里的样本要真实、要细致,而不是凑个意思糊弄事。我之前贪图省事,examples 里只写了三行简化版,结果智能体输出的纪要总是缺少"后续行动"这一段,因为示例里没体现完整结构。后来把示例补全到完整版,问题立刻消失了。
四、渐进式加载机制深度剖析
这一章是整篇文章最关键的一章,Skills 跟普通提示词工程的本质差异就在这里。把这套机制想明白了,后面所有的工程实践都会顺。
4.1 三层加载的物理含义
按照 Anthropic 官方工程博客 Equipping Agents for the Real World with Agent Skills 的描述,Skills 采用的是三层渐进式披露(Progressive Disclosure)架构。每一层加载的内容、加载的时机、token 的占用都不一样。
graph LR
A[L1<br/>元数据层<br/>~100 tokens] -->|匹配后展开| B[L2<br/>主体说明<br/>~500-3000 tokens]
B -->|按需读取| C[L3<br/>资源 + 脚本<br/>~0 到上万 tokens]
style A fill:#e8f5e9
style B fill:#fff9c4
style C fill:#ffebee
L1 元数据层:这一层始终常驻在系统提示中。它只包含每个 Skill 的 name 和 description 两个字段。假设你的环境里装了 50 个 Skill,L1 加起来通常也就两三千个 token,负担不重。
L2 主体说明层:这一层只在智能体判断"当前任务跟某个 Skill 相关"时才会展开。L2 的内容是 SKILL.md 除 YAML 之外的全部正文。一个写得克制的 SKILL.md 控制在 500 到 1500 个 token 之间。
L3 资源层:这一层是 reference 目录、scripts 目录、templates 目录里的所有文件。L3 的特点是完全按需加载:智能体在执行过程中如果判断要查某份资料,就把那份资料的内容读进来;如果要跑某个脚本,脚本本身不进上下文,只把执行结果带回来。
4.2 实测一下 token 节省效果
我做过一组对比实验,场景是处理 5 轮对话的会议总结请求,环境里挂载了 10 个 Skill。
|
方案 |
系统提示 token |
单轮平均 token |
5 轮总 token |
|
把所有 Skill 完整内容塞进系统提示 |
~28,000 |
~30,500 |
~152,500 |
|
把 Skill 拆成 SKILL.md + reference,但全部预加载 |
~18,000 |
~20,500 |
~102,500 |
|
标准 Skills 渐进式加载 |
~2,400 |
~6,800 |
~34,000 |
数据非常直观。渐进式加载的方案,只用了第一种方案约 22% 的 token 量,就完成了同样的任务。 而且这还不是 token 上限被压缩到极致的场景,如果你的领域知识库再大一点,差距会拉得更夸张。莫潇羽@无忆研习社早期一个内部知识助手项目,从普通提示词方案改造成 Skills 之后,单月推理成本直接降到了原来的三分之一。
4.3 智能体怎么决定"现在该用哪个 Skill"
这里有一个很多人会误解的细节。Skill 的选择机制不是关键词匹配,也不是某种算法路由,完全是纯 LLM 推理。 大模型读到 L1 层的所有元数据后,基于用户的当前请求,做一次"这个任务最匹配哪个 Skill"的判断。
理解这一点后,你就会明白为什么 description 的写法是 Skill 工程里最值钱的一项技能。description 写得模糊,智能体会"看走眼";description 写得太宽,智能体会"过度触发"。一个写得好的 description 应该包含三块信息:这个 Skill 做什么、什么时候应该使用、关键能力。这种写法跟金字塔原理是一脉相承的。
flowchart TD
A[用户输入请求] --> B[模型读取所有 Skill 的 L1 元数据]
B --> C{是否有匹配的 Skill?}
C -->|无| D[使用基础能力回答]
C -->|有| E[加载 L2 主体说明到上下文]
E --> F[模型按 SKILL.md 指引执行]
F --> G{需要参考资料?}
G -->|是| H[读取 L3 reference 文件]
G -->|否| I{需要执行脚本?}
H --> I
I -->|是| J[沙箱中运行 scripts/]
I -->|否| K[直接生成输出]
J --> K
4.4 Token 经济学:一笔账让你彻底想明白
我把这个话题专门拎出来讲,因为团队里很多技术同学一开始没把这笔账算清楚。
假设你在做一个面向公司全员的智能助手,挂载了 30 个 Skill,平均每个 Skill 完整内容(SKILL.md + reference + scripts)大约 3000 个 token。你的助手每天处理 5000 次对话,每次对话平均 4 轮交互。
全量加载方案:每一轮交互都把 30 个 Skill 的完整内容塞进上下文。单次对话上下文携带量 = 3000 × 30 = 90,000 tokens。一天的 token 量 = 90,000 × 4 × 5000 = 18 亿 tokens。按目前主流商用模型的定价折算成本,每天数千到上万元只是入门级。
Skills 渐进式加载方案:L1 元数据常驻,每个 Skill 大约 100 tokens,30 个加起来 3000 tokens。L2 主体平均加载 1 个 Skill,大约 1500 tokens。L3 资源大约 50% 的对话会触发,平均加载 500 tokens。单次对话上下文携带量 ≈ 3000 + 1500 + 250 = 4750 tokens。一天的 token 量 = 4750 × 4 × 5000 ≈ 9500 万 tokens。
两个方案之间的差距是 19 倍。这还不算多轮对话累积后的差异——长对话场景下,渐进式加载的优势会被进一步放大。
理解了这笔账,你就明白为什么 Anthropic 把 Skills 称作"工业级智能体的核心标配"。它不是一个增量功能,它直接改变了智能体的成本结构,让那些原本因为 token 成本算不过来而做不出来的应用,现在可以做出来。莫潇羽@无忆研习社做过一组测算,一个智能客服系统全量提示词的方案每月推理预算 12 万元,改造成 Skills 之后压到 3 万元出头,功能不打折扣。
五、写好一个 Skill 的六条铁律
这一章是我自己踩了不少坑之后总结的方法论,你可以当成检查清单用。每写完一个 Skill,对照过一遍再发布。
5.1 铁律一:严守单一职责
一个 Skill 只做一件事。 这是最重要也是最容易被违反的一条。
新手最常见的错误是"贪心":想做一个"通用助手"Skill,集合写邮件、整理日程、做会议纪要、回复客户。结果就是 description 写得很笼统,智能体永远不知道该不该选它;SKILL.md 主体被写得很长,每一次加载都吞掉巨量 token;真出问题了,你也定位不出来到底是哪一段逻辑错了。
正确做法是把它拆成五六个独立的 Skill:email-drafter、schedule-organizer、meeting-summarizer、customer-reply-helper,各管各的。智能体加载时只取需要的那一个。
5.2 铁律二:description 写得越具体越好
这条前面讲过,这里再加一个判断方法。写完 description 之后,自己读一遍,问自己一个问题:"如果有 100 个 Skill 并排放着,智能体看到我这条描述,能精准选中吗?" 如果你自己都觉得模棱两可,智能体一定选不准。
5.3 铁律三:始终用第三人称写描述
description 字段是注入到系统提示里的,所以视角必须一致。
# 错误写法
description: 我帮你处理 Excel 文件,生成报告
# 正确写法
description: This skill processes Excel files and generates summary reports
中文场景下也是同样原则,用"该技能用于..."而不是"我能帮你..."。
5.4 铁律四:控制 SKILL.md 体积
Anthropic 官方建议 SKILL.md 主体不超过 500 行。我自己的实践经验更严格:能控制在 300 行以内就别写到 500 行。详细的领域知识、长篇规范、API 文档全部下沉到 reference/ 目录,通过"当涉及到 X 时,参考 reference/Y.md"这种语句桥接。
主体里写的应该是"动作指令",而不是"知识叙述"。
5.5 铁律五:把确定性逻辑下沉到脚本
这条容易被忽略,但效果非常显著。
凡是"每次都需要一模一样地做"的事情,都不要让大模型去生成,而是写成脚本。比如:文件格式转换、API 调用、数据校验、加解密。这些活让大模型干有三个坏处:每次重新生成代码消耗 token、可能写错、行为不可预测。
把它们做成脚本之后:代码只占磁盘空间不占上下文,行为完全确定,可以版本化管理,出问题能精准追溯。
5.6 铁律六:提供示例,圈定边界
人类写指令会下意识省略示例,觉得"对方应该懂"。大模型不懂。永远在 SKILL.md 里附上一组"输入是什么、输出应该是什么"的示例,效果立竿见影。
举个对照例子。我之前写过一个 Skill,要让智能体把会议纪要按特定 JSON 结构输出,只写了字段说明,没给示例,结果生成的 JSON 字段名经常对不上、有时还会漏字段。加了一个完整示例之后,准确率直接从 60% 提到 95% 以上。
5.7 调试 Skills 的几个实用技巧
六条铁律之外,再补充几条调试经验,都是从踩坑里学到的。
第一,先用对话日志反推问题在哪一层。Skill 跑出问题的时候,先看智能体的思考链:如果它压根没提到这个 Skill,是 L1 元数据层的 description 出了问题;如果它加载了 Skill 但跳过了某些步骤,是 L2 主体说明写得不够刚性;如果它读取了 reference 但用错了内容,是 L3 资源层的资料组织有问题。三层定位法,排查效率会高很多。
第二,给 Skill 准备一组测试用例,每次改动都回归。我自己的做法是在 examples/ 目录下放一个 test-cases.md,里面列 5 到 10 个典型场景的输入和期望输出。每次改完 SKILL.md 之后,逐个跑一遍,看输出是否还符合预期。这种做法跟单元测试是一个思路,只是测试对象换成了智能体行为。
第三,description 难写的时候,反过来想"什么场景下不要用"。很多人卡在 description 写不出来,是因为陷入了"我能做什么"的思维。换个角度,先写"这个 Skill 在什么场景下绝对不应该被触发",反向圈出边界后,正向描述就清晰了。
第四,合理拆分 SKILL.md 主体。如果你的 SKILL.md 主体超过 300 行,先停下来,看哪些段落是"具体怎么做",哪些是"背景资料"。背景资料一律下沉到 reference/,主体只保留指令。
第五,定期清理无效 Skill。装得多不如装得精。我每隔一段时间会把当前环境里的 Skill 全列出来,逐个问自己"过去一周里我用过这个 Skill 吗",没用过的就删掉。Skill 装得越多,智能体在 L1 元数据层做选择的难度就越大,误触发的概率也越高。莫潇羽自己电脑上长期保留的 Skill 维持在 8 到 12 个之间,效果反而最好。
第六,把 SKILL.md 当代码 review。SKILL.md 不是个人笔记,是给智能体看的指令文档。提交到团队仓库之前,找一个同事帮你 review 一遍——看 description 是否精准、看主体是否啰嗦、看示例是否覆盖了边界场景。一次 review 能挑出来的问题,比自己反复调试半天还多。
六、实战:从零搭建一个能跑通的"会议总结助手"
理论看完了,该上代码了。这一章我们把前面所有概念落地成一个真实可用的 Skill,你可以照着把项目跑起来。所有路径和代码都给到完整版本,不缺东西。
6.1 需求拆解
业务场景非常具体:产品经理把团队会议的录音转文字结果丢给智能体,智能体要做三件事——把零散对话整理成结构化纪要;如果对话里涉及预算、采购等财务话题,需要参考公司财务手册给出合规提醒;如果用户明确说"上传"或"同步",就把生成的纪要推送到云端文档系统。
输入示例(精简版):
张磊:这次活动总预算控制在八万以内。
李雯:我建议三万投放在公众号广告。
王峰:剩下五万做线下物料采购。
期望输出:
## 会议纪要
参会人员:张磊、李雯、王峰
核心议题:营销活动预算分配方案
关键决定:
- 总预算上限 8 万元
- 公众号广告投放预算 3 万元
- 线下物料采购预算 5 万元
后续行动:
- 李雯:5 个工作日内提交公众号广告投放方案
- 王峰:5 个工作日内确认物料采购清单
财务提醒:
本次活动涉及营销预算 8 万元、物料采购 5 万元,
根据公司财务手册第五章:营销活动需提前 14 个工作日
走 OA 审批,物料采购需附带至少三家比价报告。
6.2 目录结构创建
打开终端,在你的项目目录下执行:
mkdir -p .claude/skills/meeting-summarizer/{scripts,reference,examples}
cd .claude/skills/meeting-summarizer
touch SKILL.md
最终结构应该是这样:
your-project/
└── .claude/
└── skills/
└── meeting-summarizer/
├── SKILL.md
├── scripts/
│ └── upload.py
├── reference/
│ └── company-finance-manual.md
└── examples/
└── sample.md
不同 IDE 对目录名的要求略有差异:Claude Code 用 .claude/skills/,Trae 用 .trae/skills/,CodeBuddy 用 .codebuddy/skills/,Codex 用 .codex/skills/。OpenCode 则用 ~/.config/opencode/skills/ 作为全局目录。我们在第七章会一一对照,本节先以 Claude Code 的规范为基础。
6.3 SKILL.md 完整内容
---
name: meeting-summarizer
description: >-
This skill should be used when the user provides raw meeting
conversations and asks to generate structured meeting minutes.
Triggers on phrases like "总结会议"、"会议纪要"、"整理一下这段对话".
Also h