如果你最近在折腾 AI Agent、写自动化脚本或者研究让模型更听话地执行复杂任务,那“skills”这个词你一定绕不开。我身边好几个做智能体应用的朋友,这两个月都在聊它。有人把 skill 比作“给 AI 配的一本说明书”,有人叫它“外挂能力包”,说得天花乱坠。其实没那么玄乎,它就是一套让模型更稳定地完成特定任务的结构化方案。这篇文章我想把我自己从零开始折腾 skills 的经验完整拆给你看,包括它解决什么问题、目录怎么设计、里面每一段内容该怎么写、实际能跑通的小例子,还有我踩过的坑。无论你是刚接触 Agent 开发的新手,还是已经在写复杂工作流的进阶玩家,这篇应该都能给你一些可复用的参考。
1. 重新理解 skills:它不是插件,而是“给模型的一份操作手册”
1.1 为什么 Agent 会突然“失灵”,问题到底出在哪
先说个我自己的真实经历。之前我写过一个做竞品分析的 Agent,让它在网上抓资料、读文档、最后生成报告。流程看着很顺,结果一到真跑就翻车。模型不是不会用工具,而是不知道“什么时候用”“用完怎么接”。它会抓取一堆无关紧要的页面,也会在生成报告时把一个很基础的数据格式搞错。后来我把指令反复调整了很多次,效果还是不稳定。
问题其实不在模型本身,而在“任务知识”没有和模型的工作机制对齐。模型本身有很强大的泛化能力,但它不知道你的项目里那些具体的、约定俗成的操作细节。比如“什么是我们内部定义的有效线索”“报告里标题级别怎么定”“请求 API 时哪个字段该动态生成”。这些内容塞在系统提示词里会太长,塞在代码里又写死,最终你得到的就是一个“能力很强但老办错事”的 Agent。
Skills 的出现就是来补这个洞的。它的核心思路,是把某一项技能所需要的全部上下文单独拆出来,放进一个目录,让模型在需要的时候按需加载。这个加载不是像传统编程那样导入一个库,而是把一份写好的“操作说明”注入到模型的上下文里。效果相当于你招了一个新员工,不指望他什么都会,但只要他遇到对应的工作,就有一份 SOP 可以照着做。
1.2 和插件、函数调用、提示词到底有什么区别
很多教程喜欢把 skills 和插件(plugins)、函数调用(function calling)混着提,但如果你真要开始落地一个项目,这几个概念的差别得先弄清楚。我自己更愿意把它们放在一条链路里看待:提示词是“告诉模型怎么做”,函数调用是“给模型一个能执行的动作”,而 skill 是“把怎么想、怎么做、用什么工具、按什么顺序、什么算对,打包成一套完整流程”。
打个比方,函数调用相当于给模型提供了一把螺丝刀,模型知道要旋螺丝的时候用它;插件是给模型一套带把手的工具箱;而 skills 则是“螺丝刀使用手册”,它甚至能告诉模型“什么情况下选梅花头而不是一字头”“拧到什么力度算到位”“拧完要做什么检查”。这种差别很细微,但实际用起来差距极大。
我在实际项目里观察到一个很明显的现象:如果只靠函数调用,模型能正确调用工具,但经常忽略调用后的校验逻辑;如果只靠提示词,指令一长模型就“注意力稀释”;而配置了 skill 之后,模型会在合适的时间点主动把 skill 内容读进上下文,按里面的步骤执行。这背后其实是利用了 agentic 工作流里的一个特性——模型不是一次性看完所有内容,而是分阶段决策,需要时就“翻手册”。
2. 动手前的关键设计:一个 skill 的核心结构应该怎么定
2.1 先想清楚你真正要封装的是“知识”还是“流程”
我自己第一次封装 skill 时犯过一个错误:把实现细节塞得太多,以为越详细越好。结果模型每次执行都变得非常僵硬,换个输入条件它就不知道怎么处理。后来我慢慢明白,skill 封装的不是死流程,而是“完成该任务所需的决策边界”。
比如说,我封装过一个写周报的 skill。如果我只写“把工作内容填进模板”,这就是死流程。但如果我写清楚“周报的第一段必须写业务结论、第二段写关键数据、第三段写问题与计划,数据口径与上周报表保持一致”,那模型就知道在不同输入下该往哪个方向调整。知识和流程都要有,但知识——也就是判断依据——才是灵魂。
所以你在设计 skill 目录之前,先问自己一句:这个任务里,模型最容易在哪个环节犯错?把这个环节的决策依据写清楚,比罗列一万个步骤更有用。
2.2 目录结构与命名规范,决定了 Agent 的加载效率
一个 skill 在代码层面其实就是一个文件夹,里面放一个说明文档,外加若干参考资源。Anthropic 在 Agent Skills 里推荐的目录结构大概是这样的,我也沿用了这套来做:
skills/ └── competitor-analysis/ ├── SKILL.md ├── reference/ │ ├── report-template.md │ └──>--- name: competitor-analysis description: 用于系统性地分析竞争对手的公开产品信息、定价策略与用户口碑。仅当用户要求了解某公司或产品的竞争格局时使用;不用于泛泛的行业研究报告。 ---这段描述里我把“什么该用”写清楚了,也把“什么不该用”点出来了。别小看后面这一句,边界约束越清晰,模型误调用的概率越低。我自己就遇到过写了个“资料收集”类 skill,因为描述没写边界,模型在用户聊家常时都试图加载它,正确率反而下降了。
3. 核心实操:从零到一写一个真正能跑的 skill
3.1 先用一个最简单的“报告优化器”练手
我第一次完整跑通一个 skill,项目目标是“帮助非专业用户优化周报的表达”。这个需求足够简单,但又有明确的决策点,非常适合拿来做实验。整个 skill 的 SKILL.md 核心内容我写得很克制,没有一上来就铺满模板。下面这个是简化后的实际结构:
--- name: report-polisher description: 将用户输入的周报草稿改写成结构清晰、表达专业的版本。保留原有事实与数据,只优化逻辑、句式与用词。当用户给出周报、月报类文字草稿时使用。 --- # Report Polisher ## 你的任务 将用户输入的工作周报草稿改写为高完成度版本。你只做表达优化,不做事实补充。 ## 关键处理原则 - 保留原文中的所有业务事实、时间节点、数据指标,禁止自行“脑补”。 - 每个工作块建议按“背景-动作-结果”三层组织。 - 第一句话必须是该工作块的核心结论,避免“本周我继续跟进”这类无效开头。 - 数据相关句子前置,说明性句子后置。 ## 处理步骤 1. 提取原文中的事实要点与各项数据。 2. 将内容按优先级排序,业务结果靠前,过程细节靠后。 3. 重写每个工作块的描述,确保结论先行的表达方式。 4. 通读一遍,保证没有遗漏重要信息,没有改变原始含义。 ## 输出格式 以 Markdown 输出,使用二级标题分隔不同工作块。这个 skill 里没有写死任何模板,没有指定固定的语气词,但它把最关键的决策依据写清楚了:保留事实、结论先行、数据前置。就凭这几条,模型输出质量已经比直接丢给模型“帮我润色一下”稳定很多。
很多人会把这种任务直接写进系统提示词,我当时也这么想过。但你会发现一个问题:系统提示词里如果同时有任务 A、B、C 的完整 SOP,模型在处理任务 A 时依然会受到 B 和 C 内容的影响。而用 skill 的方式,模型只在需要时读取对应说明,上下文更干净,执行准确性更高。
3.2 加一点“负面约束”,输出效果立刻质变
我第一次写的 report-polisher 版本其实效果一般,问题出在模型输出的风格“太 AI”了,一看就是机器改写。后来我在 skill 里加了一段负面约束,效果一下子就不一样了。
## 禁止事项 - 禁止使用“成功完成”“圆满达成”“进一步推进”之类空洞表述。 - 禁止在改写后添加任何原文没有的结论性修饰语。 - 禁止将原文里的口语化表达全部替换为正式表达,保留适度个人语气。 - 如果原文本身足够清晰,仅做小幅调整,不要为改而改。就这一段,输出的自然度立刻上来了。我发现很多 skill 在写规则时只写“要做什么”,很少写“不能做什么”。但模型恰恰需要明确的行为禁区来抑制默认倾向。这个经验几乎可以套到任何类型的 skill 里。
3.3 引入脚本和参考资源,让 skill 能做更多事
光有 SKILL.md,很多任务其实做不完整。比如我有一次要做竞品价格监测,光靠模型去推理价格变化是不够的,得让它自己去请求 API 拿实时数据。这时候 skill 目录里的 scripts 就派上用场了。
我在 scripts 里放了一个简单的 Python 脚本 fetch_competitor.py,作用是根据给定竞品名称,返回产品名称、价格区间和最近动态。SKILL.md 里会有这样一段:
## 使用脚本 1. 当用户提供竞品名称时,运行 `python3 scripts/fetch_competitor.py --name "<竞品名称>"`。 2. 将脚本输出的 JSON 数据作为后续分析的基础,不要擅自改动其中的字段值。 3. 如果脚本执行失败,根据错误信息判断是网络问题还是参数问题,并向用户说明。这里有个容易踩的坑:模型不一定能在对话环境里直接执行 Python 脚本,你需要通过 framework 或自己的 executor 把“运行脚本”的能力暴露给模型。换句话说,skill 本身只是定义了“可以运行这个脚本”,但如果 Agent 没有连接一个能执行代码的工具,模型还是会卡住。所以设计 skill 时,要先确认自己项目里有没有对应的工具底座。
参考资源(reference)的使用思路类似。不要把大段模板直接写进 SKILL.md,测试下来模型在前置信息过多时,反而忽略真正要用的细节。正确做法是把完整模板放进 reference 目录,在 SKILL.md 里指向它,并告诉模型“输出格式参照 reference/report-template.md”。这样模型在需要时主动打开阅读,平时不影响主流程。
4. 编排多个 skill:真正的 Agent 工作流是“多本手册”协同
4.1 让不同 skill 各管一段,Agent 工作流就活了
单个 skill 再强,也只是单个任务环节。实际做 Agent 项目时,最有趣的是把多个 skill 编排在一起,让模型像员工一样在不同阶段调用不同的“工作手册”。我自己搭过一个内容生产 Agent,里面就同时挂了三个 skill:资讯收集、行业分析、写作出稿。每个阶段模型会自动选择对应 skill 去加载。
这个编排过程不需要多复杂的调度框架,关键靠两个东西:一是每个 skill 的 description 写得足够精准,让模型能区分“现在该用哪个”;二是在更高层的系统提示词里定义工作流的主逻辑。比如我写系统提示词时会说:“先使用资讯收集 skill 获取素材,再用行业分析 skill 归纳要点,最后用写作出稿 skill 生成文章。”模型会照着这个主逻辑走,然后在对应节点加载具体 skill。
有一次我测试,故意删掉了资讯收集 skill 的 description 里的边界描述,结果模型在行业分析阶段也尝试加载它,输出质量明显变差。后来我把 description 改了,明确声明“本 skill 仅用于素材阶段的原始信息获取,不要用于归纳分析”,报错率立刻降下来了。
4.2 权限与灵活性的平衡,是编排时最容易翻车的地方
很多人在编排时喜欢把步骤写得非常死,要求模型必须按顺序执行。但实际跑几轮你就会发现,用户的输入是充满不确定性的,模型需要一定的灵活性才能处理好边界情况。
我自己取舍下来的做法是:在 SKILL.md 里把“标准流程”和“分支情况”分开写。比如资讯收集 skill 里,如果用户没有明确指定来源,模型可以从推荐清单里选;如果用户给了特定来源,就按用户要求来。这种“默认路径 + 弹性分支”的结构,让 skill 在真实场景下不至于僵化。
同时在编排时注意控制每个 skill 的作用范围,不要试图让一个 skill 把所有事都做完。Agent 工作的单位是“决策”,每个决策点的上下文越清爽,模型判断越准。宁可多配置几个 skill,也别把一个大 skill 写成巨型文档。
5. 避坑实录:我在 skills 落地中踩过的 5 个典型问题
5.1 skill 描述太宽泛,模型频繁误加载
这是我遇到的第一个问题。我给“通用资料收集”这个 skill 写描述时只写了“收集用户需要的信息”,结果模型在所有需要一点背景知识的地方都调用它。上下文被塞进很多无关内容,执行质量直线下降。
解决方法很简单,把 description 写“窄”一点。明确说出“仅在用户要求收集外部资料时使用,不用于基于已有知识作答”。边界清晰之后,误调用的情况基本消失。
5.2 SKILL.md 写得像论文,模型反而不看了
另一个常见问题是内容过多。很多教程会让你尽量写详细,但实际操作下来,SKILL.md 超过 150 行之后,模型对里面指令的执行一致性反而下降。核心规则要在前面突出,细节性内容放进 reference 或者用“如果遇到 X 情况,参考 reference/Y”这样的指引。
我自己习惯把每个核心原则控制在 5 行以内,步骤控制在 8 步以内,超过的部分全部挪进参考文档。这样模型读起来负担小,执行聚焦度明显更高。
5.3 忽略了与底层工具的连接,skill 成了空壳
skill 不是高配版提示词,它最后的落地依赖于底层工具能力。比如你要让模型读数据库里的表,skill 里写“读取数据表”没有用,你必须给模型暴露一个 read_database 这样的函数调用能力。skill 只是告诉模型“什么时候该用到这个能力、用的时候注意什么”,真正干活的还是那套底座。
我刚开始做的时候就把注意力全放在 skill 的文本上,结果模型总在正确的时间点提出“我需要读取数据”,但根本没有对应的工具可以执行。后来我先梳理项目里已有的工具集,再去设计 skill 的操作流程,顺畅多了。
5.4 没有做版本管理,改一次就“翻车”
skills 本质上是代码目录,但它又不像代码那样有直觉上的“报错”机制。改一个描述,可能模型行为就完全变了。我早期经常“盲改”,改完没有对比测试,上线后才发现行为异常。
现在我的习惯是:每个 skill 建立独立版本标签,修改后先在小范围测试集跑一遍,确认输出质量符合预期,再放进主流程。这里分享一个很笨但有效的方法:准备 5 条代表性的测试输入,每次改动之后先跑这 5 条,看结果差异再决定是否合并。这个方法帮我拦下了至少三次回归事故。
5.5 容易忽略多模型兼容性
最后一条经验,如果你的 Agent 后期可能切换底层模型,skill 的表现可能完全不同。同一个 SKILL.md,在顶级模型上执行得很顺,换个小参数模型可能就“理解不了”。后来我会在 skill 里把关键决策点写得更加直白,减少需要“领悟”的内容。这样做的附加效果是,即使在大模型上执行,输出稳定性也更高。
6. skill 还能怎么扩展:从单点功能到系统性工作流
6.1 多 skill 之间的信息交接,值得在一开始想清楚
我的经验是,如果只是为了一个简单任务,大可不必上 skills。但一旦你的 Agent 需要完成一个多步骤的复杂工作,skill 的模块化价值立马体现出来。
比如说我做的“竞品研究 Agent”,主流程是:用户给出一个竞品名字,Agent 先调用 fetcher 脚本拿原始数据,再基于数据做结构化分析,最后生成一份包含价格对比、功能差异、优劣势判断的报告。这三个步骤对应三个 skill:数据获取、分析框架、报告输出。
其中最有意思的,不是单个 skill 怎么写,而是三个 skill 之间如何“交接”。我的做法是:数据获取 skill 的输出统一 JSON 结构;分析 skill 依赖这个 JSON;报告 skill 只接收分析结论。这种接口式的设计让每个 skill 可以独立迭代,不会牵一发动全身。做 Agent 项目时先把 skill 之间的输入输出协议定好,比写任何具体逻辑都重要。
6.2 写 SKILL.md 的经验已经可以反哺团队规范
到了后期,我发现自己写 skill 的收益不只在具体执行效果上,更重要的是它倒逼我梳理了团队的“隐性知识”。以前很多操作经验只存在老员工脑袋里,现在可以沉淀成“模型也能读懂”的文档。这对个人的项目复盘、对团队的知识管理都有很直接的价值。
所以我现在的建议是:哪怕你只是做个人项目,也值得从一个小 skill 开始练手。挑一个你重复做过多次、有明显固定套路、但又有不少隐性判断的任务,把它封装成 skill。你会在封装过程中更加理解 Agent 的决策逻辑,也会更明白模型在复杂任务中的优势与局限。
一个小技巧是,当你觉得某个任务自己已经“闭着眼睛都能做”的时候,就是封装成 skill 的最好时机。这份熟练本身就是最好的知识素材来源。