你有没有过这种体验:同一个任务,第一次让智能体去做,结果勉强能用;第二次换了个说法,输出完全跑偏;第三次追加了几句要求,它倒好,把前面做对的部分也改坏了。我以前总把原因归结为“模型不稳定”,后来才意识到,问题出在别处——那类任务的执行方法,从来没有被真正固化下来。我指的是现在越来越受关注的 Skills,也就是把一套可复用的任务处理流程编写成技能文件,让智能体在遇到同类任务时,按分工、按步骤、按格式去完成。这篇文章就完整记录我学习编写 Skills 的过程,包括它到底解决什么问题、一个技能文件内部如何组织、从零手写一个技能包需要经过哪些步骤,以及那些常规文档里不会写、只有踩过坑才知道的细节。无论你是每天用智能处理文字工作的运营,还是想把手头重复劳动做成标准化的开发,这篇内容都能给你一套可以直接照做的思路。
1. 先搞明白 Skills 到底是什么,为什么值得单独学
1.1 从“临时对话”到“固化技能”:Skills 解决的问题
在没有 Skills 这类机制之前,用智能体干活就像每次去一家新餐厅都要重新向厨师解释一遍口味偏好:要多辣、不要香菜、少油、米饭要软一点。第一次说得清楚,第二次可能还记得,第三次换了值班厨师,一切归零。普通对话是没有状态的,你每次给的指令,模型都当作一条全新的请求处理,它不会自动记住“我上次已经叮嘱过你需要什么格式”“这个项目里我们一贯用哪种命名规范”。
Skills 解决的正是这个问题。它的思路很朴素:把一套“碰到什么任务、按什么步骤、输出成什么样子”的操作方法,写进一个独立的技能文件。模型在对话时先通过技能的名称和描述判断“这个任务是不是该调用它”,一旦命中,就把文件里的执行步骤和格式要求注入到当前上下文中,按部就班地完成任务。
你可以把它理解成一本菜谱。一个经验丰富的师傅可以凭感觉炒菜,但味道全看当天心情;而 Skills 是把配比、火候、装盘方式都写清楚,照着菜谱做,至少能保证一道菜稳定在七八十分以上。对重复性工作来说,稳定比惊艳更重要。所以 Skills 真正擅长解决的,是那些“你明明已经做过很多次,但每次都要重新折腾一遍”的任务。
1.2 什么样的任务适合写成 Skills,什么样的不适合
我在学了几个技能、又写了几个废技能之后,总结出一条判断标准:一个任务适不适合做成 Skills,看四个特征——是否高频出现、执行路径是否相对固定、输出格式是否可预期、判断对错的标准是否明确。如果四个问题答案都是“是”,那非常适合;如果只是偶尔做一次,或者每次做法完全不同,那写成技能反而会增加管理负担。
举几个典型的“适合”例子:周报月报生成、会议纪要整理、代码审查、长文本翻译润色、数据清洗与格式统一、需求文档拆分、固定模板的文案产出。这些任务虽然内容不同,但处理框架高度一致,非常适合固化成技能。
不适合的例子同样明显:无主题的头脑风暴、探索性研究、高度依赖个人灵感且需要频繁调整口味的创作任务。这类任务的“正确做法”本身不固定,写成技能只会限制模型发挥。还有一类任务不适合,就是需要实时读取大量私有数据但当前机制又接不到外部数据源的,技能里只写了流程却没有数据支撑,最后只能产出华而不实的结果。
1.3 学编写 Skills 前需要建立的基础概念
新手看到“写技能”第一反应可能是:这是不是要会编程?实际上,核心技能包的文件主体就是一份 Markdown 文档,真正把技能做“活”的反而是文字表达能力。
但有三个基础概念必须先建立起来。
第一个是技能包的概念。一个技能不是单个文件,而是放在一个独立目录下的一组文件,目录里通常包含主文件、资源文件、示例文件和可能的脚本文件。主文件负责“告诉模型怎么做”,资源文件负责“提供模板和数据”,示例文件负责“让模型看见标准答案长什么样”。
第二个是触发机制。模型不会把所有技能内容一次性全部加载进脑子——上下文窗口有限,也没有哪次对话需要用到全部知识。它采用的做法是:先读取每个技能的“名称+描述”作为索引,当当前任务和某个技能的描述匹配时,才把技能正文真正读进来。这意味着“描述”是整个技能的命门,描述写得不好,后面内容写得再细致也没人调用。
第三个是 Skills 与普通 Prompt 的区别。Skill 是独立于对话之外的资产,可以放进版本管理、可以被多个对话复用、可以被团队成员共享;而 Prompt 只是当下的临时输入。我习惯把 Skills 看作“标准作业程序”,把 Prompt 看作“口头交代”。前者值得反复打磨、持续迭代,后者用完即走,不需要花太多心思维护。
2. 拆开一个标准技能包:从目录到每一行指令
2.1 技能包的整体目录结构与文件分工
第一次打开别人写的技能包时,我一度被目录里一堆文件搞懵。后来自己动手组织过几个,才明白这种结构不是为了复杂,而是为了各司其职、按需加载。
一个典型的技能包长这样:
skills/ meeting-minutes/ SKILL.md resources/ output-template.md examples/ demo-input.md demo-output.md scripts/ format-members.py主文件SKILL.md是绝对的核心,所有技能都有它。resources目录放的是输出模板、参考样例、背景知识,主体是在需要时按主文件指示读取。examples目录放输入输出对,给模型做少样本示范。scripts目录放可执行的脚本,用来做确定性的格式转换、文件操作或数据计算——也就是模型不擅长的、需要精确执行的事情。
这个目录设计给我最大的启发是:SKILL.md的正文应该尽量精简,只放“判断逻辑和操作指令”,把大段模板、长示例、脚本逻辑都挪到外部文件。因为每次触发技能,只有SKILL.md的正文会被完整加载进上下文,而外部资源文件按需读取。这样一来,既能保证核心指令清晰,又不会把上下文撑爆。
2.2 SKILL.md 的元数据区:名称、描述与触发判断
SKILL.md的开头是一段 YAML 格式的元数据,通常包含name和description两个关键字段。name用于标识技能,尽量简短,用英文和中划线,避免空格;description用于向模型介绍“这个技能在什么情况下使用”,它决定了技能是否会被调用。
先看一个错误示范:
--- name: 文本处理 description: 用于处理各种文本任务,可以整理、总结、提取信息,提升工作效率。 ---这个描述的问题是“太泛”。模型凭这段描述判断时,几乎任何和文本沾边的任务都会匹配进来,技能就失去了定位。更好的写法是这样:
--- name: meeting-minutes description: 用于将会议录音转文字稿或会议笔记,整理成结构化会议纪要,包含会议目标、讨论要点、结论和行动项。当用户提供会议转录文本并要求输出纪要时使用。用户只是闲聊、与会议无关时不要使用。 ---这段描述给了三样东西:触发条件是“会议转录文本+要求出纪要”;任务内容是明确的输出结构;不使用时也写清楚了“与会议无关时不要使用”。模型对这类描述的理解准确度会高很多。我后来养成了一个习惯:写完 description 之后,自己先读三遍,问一句“如果我是模型,看到一个用户的请求,我能准确判断该不该调用它吗?”
2.3 指令区域:告诉模型“怎么做”,而不是“做什么”
SKILL.md的正文是技能的神经中枢。很多人的误区在于,把正文写成了任务清单式的口号,比如“请认真整理会议纪要”“注意关键信息不要遗漏”。问题是,模型不知道什么叫“认真”,什么叫“关键”。
正文应该回答的问题是“怎么做”。我给指令区域定了一个固定结构,写起来省力,模型执行效果也稳定:
- 角色与目标:用一两句话说明模型在这个技能中扮演的角色。
- 输入说明:说明会收到什么格式的输入,以及缺失字段怎么处理。
- 执行步骤:用编号列出具体操作顺序,每步尽量可执行、能验证。
- 输出格式:直接引用模板文件,或给出明确的格式描述。
- 边界与兜底:说明什么情况不要处理,什么情况该输出占位符而不是瞎编。
用“如果……则……”这种句式至关重要。比如“如果没有提供会议日期,则输出‘未知日期’”“如果行动项没有负责人,则标记为‘待认领’”。模型对条件分支的遵循度,远高于对一句模糊要求的理解度。指令写得越接近“可以照着执行的流程图”,模型输出就越稳定。
2.4 配套资源文件与示例:少而精的示范才能拉高下限
正文指令负责搭框架,资源和示例负责兜底。我第一次写技能时,往SKILL.md里塞了六个示例,结果每次触发都消耗大量上下文,反而让正常对话变卡。后来我把示例移出主文件,只保留两三个高质量的,放在examples目录里,由正文在合适时机引用。
示例的价值在于“少样本示范”。大模型非常擅长模仿格式——前提是你给它看一个清晰的输入输出对。比如会议纪要技能,给一个转录文本和对应的成品纪要,模型就很容易理解:“原来输出要这样的,要点要落在表格里,行动项要有负责人和截止日期。”两三个覆盖不同情况的示例,效果远好于一段冗长的格式说明。
资源文件则用于存放“不参与逻辑判断,但输出时需要引用”的内容,比如标准模板、参考规范、数据字典。至于脚本,只有在需要确定性操作时才推荐使用,比如把输出强制转成 CSV、批量重命名文件、从一段文本里精确提取邮箱等。脚本是锦上添花,不是必选项。
3. 实操全过程:从零手写一个“会议纪要整理”技能包
3.1 第一步:先写触达场景说明,再动笔写内容
前面说过,描述是命门。我建议第一节就写 description,而且反复打磨它。以“会议纪要整理”这个技能为例,我在落笔之前,会先问自己三个问题:用户什么时候会用到它?用户提供什么材料?用户想要什么结果?
答案分别是:用户拿到会议录音转文字稿、会议笔记、或者是零散的聊天记录时;材料形式可能是纯文本段落,也可能是 Markdown 笔记;用户想要一份结构清晰的会议纪要,包括会议基本信息、讨论过程、结论、行动项。
于是我把 description 写成了这样:
用于把会议录音转写文本、会议笔记或零散讨论记录整理成结构化会议纪要。输入通常是原始转录稿或若干条记录;输出包括会议主题、参会人、讨论要点、结论和行动项。仅在用户明确提出整理会议内容、且提供足够素材时使用;如果只是日常聊天或询问会议相关的问题,不要使用。
这段描述里,“输入通常是什么”“输出包括什么”“仅在……时使用”都写清楚了。我后来测试过,把描述里的“参会人”去掉,模型就会漏掉这个字段;把“不要使用”的条件去掉,闲聊时它也会强行套模板。每个词都有代价。
3.2 第二步:把执行步骤拆到“可以照着做”的程度
描述定稿后,开始写SKILL.md正文。我不会直接写一堆要求,而是先把执行流程过一遍:拿到原始材料后,第一步做什么,第二步做什么,最后怎么拼装成输出。这相当于写菜谱时先把工序理清,再写调味品清单。
会议纪要技能的执行步骤可以拆成五步:
- 阅读全部输入,区分“有效会议内容”与“无关口语内容”,比如寒暄、设备调试、重复语气词。
- 提取会议基本信息:主题、时间、参会人、记录人;缺失的字段写“未知”,不要猜测。
- 将讨论内容归纳为主干要点,按议题分组,每组突出结论而非过程。
- 提取行动项,逐条列出负责人、动作、截止时间;没有负责人的写“待认领”,没有时间的写“待确认”。
- 按模板输出最终纪要,语言改为书面表达,口语词、冗余内容全部清理。
这段指令的特点是:每一步都在处理“输入”并产生“中间结果”,最后汇总成输出。模型跟着跑一遍,不太会跑偏。相反,如果只写“请生成一份会议纪要”,它大概率给你一篇看起来不错、但格式随机的文字。
3.3 第三步:定义输入输出边界,防止模型“自由发挥”
很多人忽略边界定义,导致技能在正常输入下表现不错,一碰到残缺输入就翻车。所以我在正文中专门写了边界说明:
- 输入形式:接受纯文本、Markdown、转录稿附件内容;不支持音频文件本身,如用户直接丢音频,提示其先转成文字。
- 输出格式:固定按照
resources/output-template.md渲染,不得自创字段。 - 状态字段:行动项状态限制为“未开始 / 进行中 / 已完成 / 已阻塞”,不要追加其他词汇。
- 事实边界:不以猜测补充参与者名单、日期和数字;转录稿中听不清的部分,保留原意并标注“此处转录不清”。
- 闲聊边界:如果输入不构成会议素材,直接输出“未检测到可整理的会议信息”,不要硬编。
这几条写下来,等于给模型划了一个圈。它不需要在圈外发挥创意,只需要在圈内把活干漂亮。对重复性任务来说,这正是我们想要的。
3.4 第四步:配置模板与少样本示例
我建立resources/output-template.md,内容大致如下:
## 会议主题 (主题名称,取自输入,如未知则写“未命名会议”) ## 会议信息 - 时间: - 参会人: - 记录人: ## 讨论要点 (按议题分组,每个议题下写结论或关键分歧) ## 行动项 | 事项 | 负责人 | 截止时间 | 状态 | | --- | --- | --- | --- | | 准备上线方案 | 小王 | 3月20日 | 未开始 |然后准备了两个示例放进examples。第一个是理想的转录输入与输出对,让孩子模型知道“标准答案长什么样”;第二个是信息残缺的输入,比如只有三行零散记录,输出里大量出现“未知”“待确认”,让模型学会在信息不足时克制编造。
这里踩过的一个坑是:示例太少,模型学不会格式;示例太多,上下文扛不住。我的经验是两个足够、三个封顶,且一定要覆盖“缺字段”的情况,不能全放完美样本。
3.5 第五步:测试与迭代,一次一次打补丁
写技能不能写完就宣告完工。我的习惯是准备五类测试输入,一轮轮跑:
- 一段逻辑完整、篇幅正常的会议转录稿;
- 一段语音转文字产物,满是口语和“嗯”“啊”;
- 一段信息严重残缺的记录,只有几个关键词;
- 一段与会议无关的用户请求,比如“今天天气怎么样”;
- 一段混合内容,前面是闲聊,后面突然进入会议主题。
第一轮跑完,常见结果是:无关请求也会被触发——那是因为 description 里没写“不要使用”的边界;残缺输入输出里出现了“参会人:未知”,但模板渲染不一致。每发现一个问题,就回头改 description 或正文,而不是修改示例来迁就错误。把测试记录写在技能目录的CHANGELOG.md里,虽然看起来繁琐,但等技能迭代到第三版时,你会庆幸有个记录能告诉你“这个问题之前是怎么解决的”。
4. 编写过程中常见的坑,以及排查技巧实录
4.1 描述写得太宽泛:技能变成了“万能工具”
第一个高频坑就是 description 过宽。比如写“处理文本数据”,那几乎每个任务都匹配;写“提供企业运营支持”,范围大到等于没说。结果就是模型频繁加载技能,输出却总是不搭,极大的浪费。
我的修复方法是强制在描述里写满三个部分:触发条件、任务内容、不使用场景。触发条件要具体到“输入是什么、用户想要什么”;不使用场景一定要写,哪怕只有一句“与会议无关时不要使用”。我见过不少效果很好但总被“误触发”的技能,加一句负面排除后,准确率立刻提升一个台阶。
4.2 指令太抽象:模型“听了”但“没做”
第二个坑是正文写成了口号。“请仔细总结”“请重点关注”“请合理呈现”——这些词在自然语言对话中没问题,但作为技能指令,它们无法被验证。模型只能猜“仔细”是什么意思,猜对了还好,猜错了你毫无办法。
指令必须写成可以执行的步骤,最好带上量化约束。比如“每个要点不超过30字”“用表格列出前三条建议”“不要输出背景信息,直接给出结论”。把抽象形容词换成数字和结构,执行偏差会大幅缩小。我甚至会把“语气专业”这种要求,换成“不使用第一人称,不使用感叹号,不使用口语化缩略词”,这样模型就有了明确的检查维度。
4.3 上下文被撑爆:技能反而拖累对话质量
技能文件本身写得越大,触发时加载进上下文的 token 就越多。如果正文加示例加模板达到上万字,每次技能被调用,正常对话的上下文空间就被分走一大块,结果模型在后续对话里“记忆力”变差,回答质量下降。这是我自己吃过亏的地方——曾把一个技能写得像小百科,最终效果反而不如精简版。
控制篇幅的方法有三个:一是正文保持精简,只保留判断逻辑和流程;二是长模板和示例移入resources和examples,按需读取;三是一个技能只负责一类任务,别把所有相关功能合并成一个巨无霸。把技能“做小、做专”,比“做大、做全”在成本上划算得多。
4.4 技能与技能互相打架:描述重叠就会随机触发
当技能库里的技能越来越多,彼此之间就会出现描述重叠。比如一个技能叫“文本总结”,另一个叫“会议纪要”,用户说“把会议内容总结一下”,两个技能都可能触发,到底加载哪个就变得不确定。这种随机性会极大影响复现率。
我的排查流程是:每次测试时先只启用当前技能,确认单技能表现;再与其他技能一起启用,观察触发是否变化。如果出现冲突,就在各自的 description 里加上互斥条件,比如“本技能仅在用户明确要求整理会议纪要时使用,普通的文本总结请走总结技能”。给每个技能划定清晰领地,比试图让所有技能具备模糊的“通用能力”更重要。
4.5 排查问题速查表
| 症状 | 可能原因 | 排查方法 | 建议修法 |
|---|---|---|---|
| 任务无关也会触发技能 | description 过宽 | 查看触发时用户原话 | 增加“仅在……时使用”和“不要使用”条件 |
| 技能触发了但格式不对 | 指令缺少格式约束 | 检查输出与模板差异 | 在正文指定输出模板,并增加实例 |
| 字段经常缺失 | 指令未列出所有字段 | 观察缺失字段是否固定 | 在正文补充“必须包含字段清单” |
| 输入信息不足时瞎编 | 缺少边界定义 | 检查残缺输入下的输出 | 增加“缺失字段写未知”的兜底规则 |
| 之后的对话质量下降 | 技能内容过大 | 估算技能加载的 token | 精简正文,资源文件按需读取 |
| 多个技能随机触发 | description 重叠 | 单独启用各技能对比 | 给每个描述加互斥条件 |
5. 把 Skills 编写能力沉淀成自己的方法体系
5.1 用“技能库思维”规划,而不是临时拼凑
学到后半段,我最大的变化是不再一个个零散地写技能,而是先规划技能库。按工作类别划分,每一类下面再落具体技能,避免技能之间边界模糊。比如我给自己定的四层结构:
- 内容生产:写作、翻译、润色、摘要、格式转换。
- 数据分析:CSV 清洗、指标口径统一、可视化描述。
- 代码开发:代码审查、接口文档生成、Bug 复现步骤整理。
- 日常事务:会议纪要、周报月报、邮件回复、日程整理。
每新增一个技能之前,先问一句:这个功能是不是已经被现有技能覆盖了?如果覆盖了,优先优化现有的;如果确实没有覆盖,再考虑新增。这套保守策略能让技能库保持精简,避免“技能之间互相打架”的维护噩梦。
5.2 发布前检查清单:我用十问来把关
技能写到差不多要发布时,我会逐项过一遍检查清单。这份清单是我踩了不少坑后提炼出来的,基本可以保证一个技能具备可用性:
- description 是否包含触发条件、输出说明、不使用场景?
- name 是否简短、无空格、便于识别?
- 正文是否用步骤化指令替代模糊要求?
- 每一类输入是否都有明确的处理分支?
- 输出格式是否有模板或字段清单?
- 是否定义了缺失信息时的兜底行为?
- 是否提供了两个左右的输入输出示例?
- 长模板和示例是否放在主文件之外?
- 是否已进行多轮测试,覆盖正常、残缺、无关输入?
- 是否与已有技能检查过描述重叠?
这十问其实也是学习 Skills 编写最核心的思考框架。我把它存在笔记里,每次新建技能照着一项项回答,效率明显比想到什么写什么高得多。
5.3 从单个技能到技能协作:下一步还能往哪里走
当单个技能已经稳定,就可以考虑让技能之间协同工作。最简单的做法是“主技能调用子技能”:在正文中设定一个步骤,指示模型先调用某技能完成中间处理,再调用另一个技能完成最终输出。比如“活动策划”技能,可以内部调用“市场分析”技能来生成背景部分,再调用“文案润色”技能来包装输出。
另一个方向是团队共享。把技能包放到团队的公共仓库,大家共同维护 description 和示例,让团队在处理相同类型任务时保持统一口径。我实际体验下来,技能共享的最大收益不是“别人帮你写”,而是倒逼你把流程讲清楚,让隐性经验显性化,这本身就是职场里很值钱的能力。
我在长期维护技能库后,最明显的感受是:写 Skills 表面是在教模型做事,本质是在逼自己把“我大概会做”变成“我知道怎么做”。每一次把口头经验落成指令,都是对工作方法的一次复盘。这种复盘带来的能力沉淀,可能比模型输出本身更有价值。如果你也想从零开始学写 Skills,我的建议很简单:挑一个你每周都要做、但每次都折腾的任务,先按上面的步骤写一个技能包,跑通、测试、迭代,再慢慢扩展。一个就够了,剩下的,会在你反复修改 description 的过程中自然展开。