☰
大模型Skills开发实战:标准目录结构与完整开发步骤拆解
2026/10/22 7:15:17 网站建设 项目流程

直接上干货。这些年我调试过的Agent应用少说也有几十个,从最初靠Prompt硬怼,到后来用Function Calling,再到现在的Skills机制,最大的感受是:模型本身的智商在涨,但真正拉开体验差距的,是你能不能把“能力”组织得足够规范。Skills这套东西,说白了一点不玄乎,它就是给大模型准备的一套“可复用、可插拔、可被自动识别”的外挂能力包。这篇继续深入大模型系列第13篇,就来把Skills的标准目录结构和完整开发步骤掰开揉碎讲清楚。

这篇文章的受众,是已经玩过Prompt、知道Agent大概是怎么一回事,但还没系统搞过Skills,或者被社区里各种“Skill模板”绕晕的开发者。看完你至少能自己从零搭一个干净的Skill,并且知道每一步为什么要这么做。

1. 大模型Skills到底是什么,为什么需要一个“标准目录结构”

先把概念对齐一下。大模型Skills,你可以理解成一套“说明书 + 工具箱”的组合包。也就是说,它不只是几段Prompt文字,而是把“告诉模型怎么做事”的指令,和“做事要用的脚本、参考数据、依赖文件”放在一起,形成一个结构化的目录。模型在处理任务时,会根据你写的描述自动判断“这一步该不该调用这个技能”,一旦调用,它就按照技能包里的说明去执行,必要时调起脚本,拿到结果再继续推理。

这个思路其实是从早期的Agent框架里慢慢长出来的。最早我们做Agent,能力边界全靠System Prompt堆字,函数的调用靠Function Calling约定JSON Schema,逻辑一多,提示词就变成一团乱麻。后来社区开始尝试“一个技能一个文件夹”的玩法,把指令和资源打包,模型通过检索决定用哪个包。这个“文件夹”就是Skills的雏形。

1.1 Skills与普通Prompt、Function Calling的根本区别

要搞清楚Skills的定位,最好的办法是做个对比。传统Prompt是“一次性沟通”,你给模型说清楚这次任务怎么做,它就做这一次,下次任务换个场景,还得重新写。Function Calling是“点菜式调用”,模型按你给的Schema去调一个写好的函数,擅长处理结构化、单一目标的任务,但函数的逻辑是定死的,模型自己不能调整执行过程。

Skills恰好站在中间:它比Function Calling灵活,因为技能包可以包含多步骤的操作说明和多份资源文件,模型在调用时有一定的自主决策空间;它又比纯Prompt可靠,因为技能的核心逻辑被结构化了,不会因为模型的自由发挥而跑偏。

这里的核心逻辑是:Skills不是替代上述两者,而是在更高层面重组了它们。一个Skill内部,你可以嵌入Prompt来引导模型行为,也可以用脚本承担计算任务。真正关键的是,Skill让“模型判断何时调用外部能力”这件事从硬编码变成了一种可检索、可命名的标准行为。

1.2 标准化目录结构的三个直接价值

有的朋友可能觉得,我搞个文件夹放个README不就完了吗,干嘛还要弄一套标准?实际跑一跑你就知道区别了。标准化目录结构解决的是三个非常现实的问题:

  • 被自动化工具识别:不管你是自己写调度器,还是准备接入现成框架,有一套约定的目录规范,才能让工具在扫描Skills目录时批量加载、校验元信息、生成索引。没有标准,每次接入一个平台都要手工处理,维护成本直接失控。
  • 技能包的自包含与可迁移:一个技能依赖哪些脚本、哪些参考文档、哪些配置文件,全部锁在同一个根目录里。换环境部署时整个目录拷走就行,不需要再翻聊天记录或者邮件找附件。
  • 模型对技能的理解效率:模型不会像人一样点开每个文件仔细读一遍,它通常先根据SKILL.md的元信息判断“这个技能是干嘛的、适不适合当前任务”,命中后再读取正文。目录结构清晰,模型的判断准确率就会明显更高。

我自己实测过,一个结构混乱的Skill,模型有时候能瞎猜到你的意图,但更多时候是调用之前犹豫半天、或者调用了但执行步骤连不上。把目录理顺之后,这类问题发生率下降非常明显。

2. 标准目录结构逐层拆解:每个文件该放什么、不该放什么

这部分是今天最关键的内容,我会把一份基础但完整的目录结构拆开讲。先给出整体模板,再逐层说明设计意图和写法要点。这套结构不是什么官方强制标准,而是目前各大框架里最常见、兼容性也最好的约定。

2.1 基础目录模板:一个干净Skill包应有的样子

my-skill/ ├── SKILL.md ├── scripts/ │ ├── run.py │ └── config.json ├── references/ │ ├── guide.md │ └── data.csv └── assets/ └── example.pdf(可选)

粗看就四个组成部分。根目录只有一个入口文件,这是为了便于扫描工具快速定位;scripts放可执行代码,references放模型在推理过程中可能翻查的资料,assets放不常被直接读、但在特定场景下有用的二进制文件。如果你只需要写一个纯指令型技能,连scripts和references都可以不要,目录里只留一个SKILL.md就够了。

有人喜欢把所有说明都写在SKILL.md里,这没错,但前提是你的技能确实足够简单。一旦技能涉及多步骤操作或需要查表决策,把内容拆到references里会更合理,因为SKILL.md太冗长会影响模型的解析速度,它只需要知道“什么时候用”,没必要在入口文件里把每个细节都背下来。

2.2 SKILL.md:技能包的“门面”,也是调用的决策依据

SKILL.md是整个Skill里最重要的文件,它做两件事:一是给调度系统(或者你自己写的Agent框架)提供技能描述,二是给模型提供执行指引。标准写法采用YAML Frontmatter + Markdown正文:

--- name: date_calculator description: 计算两个日期之间的天数,或从指定日期推算N天后的日期。适合日程规划、项目排期等场景。 ---

这部分是给模型看的。description尤其重要,它决定模型在什么情况下会想到这个技能。写法上的核心技巧是:写清楚输入、输出、典型场景,不要写成散文。你写“这个技能可以帮助用户处理与日期相关的问题,如计算相差天数、推算日期等场景”,模型也能理解,但命中率不如“计算两个日期之间的天数,或从指定日期推算N天后的日期。适合日程规划、项目排期等场景”这种句式高。原因很简单:模型做技能匹配时本质是语义检索,关键词堆得越具体、边界越明确,召回的准确率就越高。

正文部分建议包含以下几类内容:

  • 技能目标:一句话说明这个技能解决什么问题,避免模型误解。
  • 使用条件:什么情况下用、什么情况下不要用。这项很多开发者会漏掉,实际价值很高,能避免模型在边缘场景里硬套技能。
  • 执行流程:分步骤列出操作流程,每步尽量明确输入输出。如果步骤里需要调脚本,要在这一步明确写出脚本的调用方式和参数。
  • 注意事项:容易出错的点,比如“输入日期必须是YYYY-MM-DD格式”“只支持公历”等。

2.3 scripts与references:体力活与知识点分离

scripts目录放的是技能要用的可执行脚本。判断该不该把一段逻辑写成脚本,标准很简单:如果是确定性计算、文本处理、数据读写这类不需要模型“动脑”的任务,就写进脚本;如果是开放式的解释、分析、策略判断,就留在SKILL.md里让模型直接发挥。

references目录放的是模型在推理时“临时翻阅”的参考资料,通常以文本类文件为主。这里有一个常见的误区:把动态生成的中间数据也塞进references。这是不对的,references里的内容应当是相对稳定的领域知识或规则说明,至于运行过程中需要读写的数据,应当放在脚本能访问的工作目录或数据目录里,而不是技能包内部。

3. 手把手开发一个Skill:从灵感到落地的完整实操

理论部分差不多了,下面进入实操环节。这一节我会从一个实际技能需求出发,完整走一遍“定义能力 → 写描述 → 写指令 → 补资源 → 本地验证 → 迭代优化”的流程。为了好理解,就用一个“会议纪要素材整理”的Skill作为例子。

3.1 明确技能边界:先想清楚“什么不让它做”

开发Skill的第一步不是写代码,而是划边界。我见过太多人上来就想做一个“能处理会议纪要所有环节”的Skill,结果写出来的SKILL.md又大又空,模型根本不知道重点在哪。正确做法是先拆任务,把一个完整流程拆成多个小技能,每个技能只负责一个明确子任务。

以会议纪要为例,完整流程可能是:录音转文字 → 段落清洗 → 要点提取 → 待办事项整理。你不需要一个Skill搞定全部,可以先做一个负责“从会议文字稿中提取结构化要点和待办项”的Skill。输入是一段长文本,输出是固定格式的Markdown,包含“议题、结论、待办事项、责任人”。边界越窄,描述越好写,模型执行越稳定。

这一步做完,你应该能回答三个问题:输入是什么?输出是什么?在什么场景下用户会用到它?答不上来,就先别往下走。

3.2 编写SKILL.md:让模型一眼就知道“该用我”

边界确定后,开始写SKILL.md。先写Frontmatter,再写正文。这里强调一下description的写法,同一段话换几种口气,命中效果天差地别。

我不会用那种散文式的“本技能旨在协助用户处理……”,而是用动宾结构直接描述能力:“从会议文字稿中提取议题、结论和待办事项,输出结构化Markdown。适合会议结束后整理纪要素材。”这样模型在做语义匹配时,能快速把它和“会议”“纪要”“提取待办”这些查询词关联起来。

正文的执行流程部分,我的习惯是写得像操作手册,而不是写作文:

  1. 阅读输入的会议文字稿全文,忽略寒暄和与主题无关的内容。
  2. 将内容按议题归类,每个议题列出讨论结论。
  3. 列出所有明确提出的待办事项,标明责任人和截止时间,若原稿未提及,标注“未指定”。
  4. 按“议题、结论、待办事项、责任人”四列输出Markdown表格,每个议题一个小节。

每一条都是模型可以直接照做的动作,没有冗余修饰。你可以把SKILL.md理解成一份“新员工入职手册”,新人(模型)没经验,但你写清楚步骤,它就能像模像样地干活。

3.3 补齐脚本与参考资料:只在必要时才加

此前已经决定不写脚本,那么这个Skill严格来说是个“纯指令型”技能,除了SKILL.md,不需要额外文件。我在做项目时,能不加脚本就不加脚本,因为脚本会引入执行环境依赖,增加运维负担。只有当任务涉及确定性计算或外部数据读写时才值得加。

比如同样是会议纪要场景,我另一个“会议时间协调”Skill就必须带脚本,因为它要根据与会者的日历数据计算空闲时段。这种脚本我一般用Python写,入口函数固定,输入参数通过命令行或标准输入传递,输出必须是最简结构的数据,不要带无关的日志和调试信息。模型调用脚本时,只关心标准输出里的结果,多余信息会导致解析出错。

如果确实需要参考资料,比如整理纪要时要参照公司特定的汇报模板,那就把模板放在references/template.md里,并在SKILL.md正文里写明“输出格式严格遵循references/template.md中的模板”。把模板细节放在references里,可以让SKILL.md正文保持精简。

3.4 本地实测与迭代调优:测试用例是Skill的生命线

写完SKILL.md,真正的挑战才开始。很多人有个错觉,觉得Skill写完就能直接用,其实模型在执行开放式任务时,不确定性比你想象的大得多。我的习惯是准备至少3组测试输入:一组是典型场景,一组是边界场景,一组是易混淆场景。

以会议纪要Skill为例:典型场景是“一段2人讨论的对话,包含明确结论”;边界场景是“发言内容跳跃、多次打断、结论不明确”;易混淆场景是“类似会议的对话,但实际是闲聊,不产出任何待办”。

跑一轮测试,你会发现几个共性问题:模型可能遗漏还没细分议题;可能把闲聊内容也归纳成待办事项;可能输出格式和预期不一致。这类问题都是靠调SKILL.md解决的,比如在看到“把明显无结论的讨论概括为一个待办项”后,就补一句“仅当原文中存在明确行动要求时,才将其列为待办事项”。每次测试后记下问题,改完再跑,直到稳定为止。

调优时有个原则:能通过修改描述解决的,绝不增加脚本。脚本增加了系统复杂度,引入的环境问题(路径、依赖、权限)往往比模型理解问题更麻烦。只有当你发现模型“理解到位但算不对结果”时,才应该考虑用代码兜底。

4. 常见问题与排查技巧实录

这块内容是我在实际开发中反复遇到的,也是社区里问得最多的。整理成一个速查表,方便复盘。

4.1 Skill没被调用:问题十有八九出在description

表现:任务很明确,但模型完全没提你的Skill,或者绕了一大圈用其他方式硬做。排查方法很简单,先换位思考:如果你是模型,看到一个技能描述,你会觉得它能处理“计算项目剩余天数”这个问题吗?

常见的描述通病包括:篇幅太长,核心能力被淹没在背景介绍里;场景词与用户输入不匹配;只写了“能做什么”,没写“输入输出格式是什么样的”。还有一个不成文的规律:description里包含具体名词和动作词的技能,被召回的概率远高于只写抽象能力的技能。

我自己的Debug手段是,用对话方式模拟一遍检索:“用户问了这个任务,描述里哪个句子能让我确定该调它?”找不到,就重写。

4.2 模型“看到”了Skill但执行动作混乱:指令层级出了问题

表现:Skill确实被调用了,但模型在执行时跳步骤、顺序颠倒、或者输出格式跑偏。这种情况下,先把责任归到SKILL.md正文的组织方式上。

踩过的一个坑是正文里既有步骤说明又有注意事项,两者混在一起,模型分不清优先级。解决办法是结构清晰化:步骤用有序列表,注意事项单独用一个“警告”小节,并且用加粗强调。模型在解析时,对“步骤说明”的权重判断要高于“背景介绍”,所以不要把核心操作写在背景段落里。

另外,如果技能流程较长,建议在步骤之间明确标注“上一步的输出作为下一步的输入”,让模型把执行看作流水线,而不是若干独立动作的拼凑。

4.3 多技能共存时的调用冲突与优先级管理

一个Agent装了多个Skill之后,会遇到“模型不知道选哪个”的尴尬。最典型的情况是:两个技能描述相似,一个负责生成文案,一个负责润色文案,模型可能直接选择调润色的那个来从零生成。

这种问题的根治手段不在Skill内部,而在技能命名和描述的去重。两个技能能力边界重合时,一定要在description里写明“不适用场景”,也就是给每个技能加入排他性描述。比如“本技能只接收已写好的文案,不负责从零创作”,就能帮助模型快速排除错误选项。

如果技能数量继续增加到很多个,手动去重就不太现实了。这时我会在Agent调度层加一个轻量的意图分类模型,先把用户请求粗分类到某个技能域,再让领域内模型做精确匹配。当然这是后话,多数项目几十个以内技能,靠写好description足够。

5. 实操心得与进阶建议

最后聊点经验性的内容,算是给想继续深入的朋友提供几个方向参考。

第一点,Skill的开发永远是从“窄”开始,不要一开始就想做一个全能技能。窄范围派生出的Skill往往描述精准、输出稳定,而全能型Skill在维护和调优上会消耗掉你绝大部分时间。我的经验是,一个技能如果连“输入是什么”都要解释一大段,那它八成还不够窄。

第二点,定期复盘已有Skill的实际调用记录。我每隔一段时间会拉一下日志,看看哪些Skill从不被调用、哪些Skill频繁被误调用,这些数据是优化目录结构和改写description最好的素材。你会发现,被冷落的Skill不一定没用,很可能只是描述写得不够清楚,改完描述后调用率明显上升。

第三点,拥抱社区既有的目录约定。虽然本文给了你一套完整模板,但实际使用时,多留意你所在平台或框架对Skill目录的特殊要求。有些平台会识别自定义字段来加载依赖,有些平台要求入口文件的命名完全固定。在写模板之前,先去查目标框架的文档,遵循已有约定可以省掉非常多对接成本。

开发Skill这件事,说难不难,说简单也不简单。掌握好“结构规范、描述精准、指令清晰”这三板斧,配合充分测试,你就能在自己的Agent项目里用上这套可复用能力了。接下来要做的就是多写几个不同场景的Skill练手,踩坑的滋味虽然不好受,但每踩一个,你对模型决策逻辑的理解就更深一层。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询