news 2026/10/30 17:51:33

Agent Skills 技能包实战:SKILL.md 编写与智能体集成指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Skills 技能包实战:SKILL.md 编写与智能体集成指南

Agent Skills 最近在智能体开发圈子里讨论度非常高。你要是做过一段时间的 Agent 应用,应该已经察觉到:单纯靠一堆工具函数去扩展模型能力,越来越不够用了。函数定义写得再细,模型也未必会在正确的时机调用正确的函数;功能逻辑散落在各处,换个项目就要重写一遍。技能(Skills)这套方案就是奔着这些问题去的,核心思路是把“完成某类任务的完整能力”打包成一个标准目录,让模型在需要时自己发现、自己读取、自己执行。

这篇文章不聊空泛的概念,直接拆到底:技能包的标准结构是什么,SKILL.md 该怎么写,模型是靠什么机制发现技能的,以及我从零做一个可用技能包的完整过程和踩坑记录。无论你是刚接触智能体开发,还是已经在用工具调用做应用,这篇文章都能给你一套可以直接上手的技能封装方法论。

1. 技能体系解决的核心问题:从零散工具到“完整手艺包”

1.1 传统工具调用的三个痛点

先说清楚我们原本是怎么做的。早期给大模型扩展能力,最通用的方案是函数调用(function calling):把外部操作封装成一个个带参数定义的函数,模型根据用户请求决定要不要调用、传什么参数。这套机制本身没问题,但用久了会撞上三堵墙。

第一堵墙是“定义越写越长,模型越看越懵”。一个真实业务系统里,工具函数动辄几十上百个。每个函数都要写清楚名称、参数、类型、含义,模型每次都要在巨大的函数列表里做匹配,不仅消耗上下文,还经常选错。尤其当两个工具的功能边界模糊时,模型一走神就调用了驴唇不对马嘴的那个。

第二堵墙是“函数只解决单点,不解决流程”。工具的本质是一个动作,但真实任务往往是多步骤的。比如“整理一份会议纪要”,这个任务包含提取议题、归纳观点、拆分行动项、确定负责人、套用输出模板好几个环节。你用函数调用去做,需要把每一步都拆成独立的函数,再指望模型自己按正确的顺序串起来。模型一旦漏一步,整个输出质量就塌了。

第三堵墙是“复用成本太高”。一个业务场景里调通的函数组合,搬到另一个项目基本要重写。因为函数与具体系统的数据结构、调用上下文耦合得很深,很难做到任务级复用。

1.2 技能包的运作模式:一个目录就是一套能力

技能(Skill)换了一条思路:不跟模型强调“你会哪些原子操作”,而是直接告诉模型“你具备哪些完整手艺”。每个技能是一整个目录,里面装着说明书(SKILL.md)、可选的辅助脚本和参考资源。目录放在技能仓库中,模型在使用时按需发现并读取其中的内容。

举个例子。传统做法里,“生成周报”可能需要五个函数:读 Git 日志、统计变更文件、汇总 PR、读取待办、拼报告。技能方案里,你只需要一个 weekly-report 目录,里面放一个 collect_commits.py 脚本,会在本地帮你拉取一周的提交记录,再放一份 SKILL.md,告诉模型这些数据怎么整理、周报按什么结构输出。模型看到用户说“把本周的周报发我”,就会去找到这个技能包,读取说明,按里面写的步骤执行。

这个模式的关键在于,模型读取的是一份有结构、有示例、有步骤的“操作手册”,而不是一串干巴巴的函数签名。任务上下文被完整地写在了技能文件里,模型不需要凭空猜测流程。

1.3 技能与工具、工作流怎么分工

很多朋友会问,技能和工作流(Workflow)又有什么区别?我个人的理解是:工作流是“预先编排好的固定流程”,每个节点做什么都是设定好的,适合重复性极高、容不得模型自由发挥的场景;技能则是“能力单元”,它把专业方法和约束条件交给模型,让模型结合当前上下文灵活执行。技能之间可以互相组合,输出可以彼此接力,扩展上更开放。

技能和函数调用也不是替代关系,而是互补。函数调用适合作为技能内部的执行手段,技能则负责更上层的任务组织。你可以在一份 SKILL.md 里写“调用 xxx 函数获取数据,再调用 yyy 函数执行写入”,这个技能就成了业务能力的封装边界。

2. 技能包的核心文件:SKILL.md 到底怎么写

2.1 基本信息段:让模型认得并记住这个技能

SKILL.md 是每个技能包里真正起决定性作用的文件。它的编写质量,直接决定了模型能不能在正确时机发现技能、能不能准确执行技能。这个文件通常以一段 YAML frontmatter 开头,里面至少包含 name 和 description 两个字段。

name 是这个技能的唯一标识,相当于人的姓名。它需要短、准确、可记忆。比如 meeting-minutes、weekly-report、code-review,这类命名比“文档处理助手”要好得多,因为模型在做概念匹配时会更自然地命中。

description 是整个技能包的“广告牌”。模型决定是否调用技能,主要就是看这段描述与当前用户请求的语义匹配程度。很多人在这里犯的最大错误是“宽泛无边界”,比如写成“用于处理文档”,结果用户每次提到“文档”它都想往上凑,频繁误调用。

我建议 description 里至少说清楚四件事:技能完成什么任务、适用于什么输入、输出什么产物、不适用于什么情况。这就像给技能划了一块清晰的责任田,模型只有在用户需求落在责任田内时才会接管。

2.2 正文说明书:步骤、模板与边界条件

frontmatter 之下就是正文。正文是写给模型看的操作手册,目标是从自然语言层面描述具体怎么做。结构上建议分成几个固定段落:目标、适用场景、操作步骤、输出模板、注意事项。

目标段用一两句话说明这个技能要达成的最终产物。适用场景段列举哪些输入适合使用这个技能,哪些情况应该明确拒绝。操作步骤段是整个文档的灵魂,要按顺序列出所有执行环节,同时把“如何判断”“遇到异常怎么办”这类决策规则写进去。输出模板段给模型一个明确的最终格式样本,让模型知道产出的样子。注意事项段用来写负面清单和边界条件,比如“不要编造信息”“不要修改原始文件”“材料缺失时标注待确认”。

还记得前面提到的会议纪要例子吗?实际操作步骤可以这样组织:先通读用户提供的会议材料,识别会议主题、时间、参会人和缺席人;然后提取核心议题,按主题分组归纳主要观点;接着区分“已决定事项”和“待讨论事项”;最后从待办描述中提取行动项,明确负责人与截止时间,材料里没写明的标注“待确认”。每一步都指向明确的产出,模型执行起来不会迷路。

在正文末尾,强烈建议加一段“输入示例”。给1到2个真实触发样例,比如“帮我整理今天的会议纪要”“把这段聊天记录转成行动项”,这样模型会更清楚什么场景下该把这段说明书翻出来。实测下来,带样例的技能比不带样例的技能触发准确率高不少。

2.3 技能粒度:多大才算“一个技能”

技能粒度是新手最容易失控的地方。技能切太粗,比如搞一个巨大的“全能办公助手”,模型读取时会花费大量上下文,而且内部步骤互相纠缠,执行质量很不稳定;技能切太细,比如“提取标题”“提取正文”“格式化输出”各做一个技能,模型要来回切换好几个包才能完成一个任务,效率和准确率反而更低。

我的经验是,一个技能应该对应“一个完整、可独立交付的任务”,任务内部可以有步骤,但步骤不应该散到外部。比如“整理会议纪要并产出行动项”是一个技能,而“从文字里提取时间”就不值得做成一个技能。粒度判断还有一个简单标准:如果这个能力你换了项目还要反复用到,且每次执行方式基本一致,就值得封装成技能;如果只是某个业务流程里的一次性小动作,留在提示词里就行。

2.4 给技能加工具:辅助脚本与资源文件

SKILL.md 负责“讲方法”,但有些任务光靠讲方法不够,还需要真实的外部数据。比如统计 Git 提交、抓取网页、读取本地文件,这些操作是模型本身做不了或做不好的,这时候就要在技能目录里附上辅助脚本。

辅助脚本的使用约定要写得非常明确。我习惯在 SKILL.md 的步骤里写明“先运行目录下的 collect_commits.py,把运行结果作为输入数据,再进行整理”,同时注明脚本的运行方式:“python collect_commits.py /path/to/repo”。这样模型就知道什么时候该调脚本、脚本该怎么跑。

技能目录里还可以放模板文件、参考文档、示例输出这些静态资源。它们的作用是给模型提供稳定的输出参照。脚本生成的数据、模板定义的格式、模型负责的归纳整理,三者各司其职,一个技能包就成了一个微型自动化流水线。

3. 从零做一个会议纪要技能:完整实操记录

3.1 先想清楚技能的输入输出边界

做技能的第一步不是写文件,而是先想清楚输入和输出的边界。我以“会议纪要整理”为例,把这个思考过程完整过一遍。

输入侧,这个技能要能处理三类材料:会议录音的转录稿、线上聊天中的会议讨论记录、用户手写的碎片笔记。输出侧,它要产出一份结构化的会议纪要,包含会议信息、会议目标、讨论要点、决定事项、行动项五个部分。同时,行动项必须明确负责人和截止时间,没有负责人信息的,宁可标“待确认”也不能编造。

想清楚边界之后,还要确定“什么情况不归它管”。我的做法是,在 description 里明确写上“本技能仅用于会议相关材料的整理,不适用于日常任务记录、个人备忘录或项目管理排期”。这个负向约束非常有用,能挡掉大量误触发。

3.2 搭建目录与编写 SKILL.md

接下来是搭目录。我的技能仓库路径很简单,每个子目录一个技能包,目录名就是技能名。会议纪要技能的目录结构长这样:

skills/ ├─ meeting-minutes/ └─ SKILL.md

这个技能不需要外部脚本,因为核心工作是信息提取和结构化整理,直接用 SKILL.md 把方法论写清楚就够了。下面是完整的 SKILL.md 内容,你可以直接照抄改成自己的版本:

--- name: meeting-minutes description: 将会议材料整理成结构化纪要与行动项。适用于会议录音转录稿、聊天讨论记录、手写会议笔记等输入。当用户要求生成会议纪要、总结会议内容或提取会议行动项时使用。不适用于日常任务清单整理、个人备忘录或项目管理排期。 ---
# 会议纪要整理 ## 目标 从原始会议材料中提取关键信息,输出一份干净、结构化、可直接分发的会议纪要。 ## 适用场景 - 会议录音转录稿的整理 - 群聊中会议讨论记录的归档 - 用户零散笔记补充成正式纪要 ## 操作步骤 1. 通读用户提供的材料,识别会议主题、会议时间、参会人与缺席人。 2. 提取讨论过的核心议题,按主题分组归纳主要观点。 3. 区分“已决定事项”和“待讨论事项”。 4. 从“待办”描述中提取行动项,明确负责人与截止时间;材料中未提及的,统一标注“待确认”。 5. 按下方模板输出最终纪要。 ## 输出模板 ### 会议信息 ### 会议目标 ### 讨论要点 ### 决定事项 ### 行动项(负责人 / 截止时间 / 状态) ## 注意事项 - 不编造参会人、时间或结论;材料缺失时明确标注“待确认”。 - 保持原始表述中性,不添加主观评价。 - 行动项必须包含负责人;没有负责人的行动项一律列为“待确认”。

这里面有几个细节值得说一下。操作步骤里的第4步专门强调“负责人缺失时标注待确认”,是为了防止模型强行编造人名;输出模板固定了五个区块,是为了让模型每次产出的结构都一致;注意事项里的负面清单,是为了压制模型“自由发挥”的冲动。这些细节决定了技能的实际可用度,而不是停留在“看起来不错”的层面。

3.3 挂载到客户端并验证触发效果

写好 SKILL.md 之后,需要把它挂载到智能体客户端里做验证。目前主流的智能体客户端基本都支持自定义技能目录,把 skills 目录路径加入配置,客户端启动时会自动扫描每个技能子目录,并建立技能索引。

我建议用一个对照实验来验证技能是否生效。准备一段模拟的会议讨论记录,分别用两种方式向客户端提问。方式A不包含“会议纪要”四个字,只说“这段内容帮我理一下,看看有哪些事要做”;方式B明确指出“帮我生成一份会议纪要并列出行动项”。对比两种情况下的响应,重点观察模型是否主动读取了技能。

如果模型在方式B下正确调用了技能,说明 description 的触发匹配是有效的;如果方式A也能触发,反而说明描述写得过于宽泛,会带来误触发风险,需要收紧边界。我第一次测试时,方式A频繁触发,后来我把 description 里加上了“仅限会议记录场景”的限定词,误触发率立刻降了下来。

3.4 用脚本技能做进阶:自动汇总周报

纯文本指令型技能只能做到“整理”,还做不到“获取”。如果想做一个能自动汇总项目进展的周报技能,就需要在技能目录里加入辅助脚本,让技能同时具备“读取数据”和“组织内容”两段能力。

目录结构可以这样设计:

skills/ ├─ weekly-report/ ├─ SKILL.md ├─ collect_commits.py └─ weekly_report_template.md

collect_commits.py 的作用,是从指定仓库读取最近一周的提交记录并输出成 JSON 格式,方便模型后续处理。脚本核心逻辑很简单:用 Git 命令读取提交日志,解析出哈希、作者、日期和提交说明,再输出标准 JSON。

#!/usr/bin/env python3 import subprocess, json, datetime, sys def get_commits(repo_path, days=7): since = (datetime.date.today() - datetime.timedelta(days=days)).isoformat() log = subprocess.run( ["git", "-C", repo_path, "log", "--pretty=format:%h|%an|%ad|%s", "--date=short", f"--since={since}"], capture_output=True, text=True, check=True ).stdout commits = [] for line in log.strip().splitlines(): hash_id, author, date, subject = line.split("|", 3) commits.append({"hash": hash_id, "author": author, "date": date, "subject": subject}) return commits if __name__ == "__main__": repo = sys.argv[1] if len(sys.argv) > 1 else "." print(json.dumps(get_commits(repo), ensure_ascii=False, indent=2))

SKILL.md 里的步骤就要写清楚两段式执行:先运行脚本拿到一周提交记录,再结合用户口头的重点进展,组装成一份带本周概述、提交明细、风险提示三部分的周报。这里面有个容易被忽略的点,就是脚本输出的格式越规整,模型后续的整理成本越低。数据清洗的动作尽量在脚本里做完,不要指望模型替你做。

4. 实战中高频踩坑:现象、原因与排查方法

4.1 模型迟迟不调用技能,问题多半出在描述上

技能包做好了,挂上了,配置也对了,但模型就是不调用。这是所有人都会遇到的第一道坎。我排查这类问题的顺序是固定的:第一步确认技能目录有没有被客户端正确扫描到,第二步检查 name 和 description 是否与用户请求里的关键词匹配,第三步看 description 是不是写得太抽象。

最常见的坑就是用了内部术语当技能名,比如把“会议纪要”技能命名为 doc-processor。用户嘴里说的是“把会议记录理一下”,模型脑子里想的是“会议记录”,再看技能列表里只有 doc-processor,它根本对不上号。所以技能命名原则是:用目标用户最常说的自然词汇命名,而不是用内部代号。如果你的描述里连“会议纪要”“行动项”“会议记录”这类同义词都没覆盖到,模型识别不到也正常。

4.2 技能给了,但模型“读不进去”

另一个让人头疼的情况是,模型明明触发了技能,但产出结果完全没按 SKILL.md 里的要求来,好像那份说明书根本不存在。这个问题的根源通常是文档太长、结构太散。模型读取技能说明书时也有注意力瓶颈,一份几千字、把背景故事写了好几段的说明书,模型很可能看完前面忘了后面。

应对方法是改用“金字塔结构”:最重要的步骤和输出模板前置,背景和解释靠后。操作步骤控制在5步以内,每步用一个动词开头,简明扼要。输出模板必须挨着操作步骤放,让模型在决定输出结构时能直接看到。我还有一个习惯,就是在注意事项里挑一条最关键的放在最前面,比如“严禁编造缺失信息”,这比写在最后有效得多。

4.3 技能里的脚本执行失败

脚本型技能出问题的点比较集中,常见的有四类:路径写错、依赖没装、权限不够、输出格式不符合预期。

路径问题最普遍。脚本里用了相对路径,但模型执行时的工作目录未必在技能包目录下。我的做法是在 SKILL.md 里明确要求使用脚本时带上完整路径,且脚本内部统一用绝对路径拼接,不依赖当前工作目录。依赖问题更简单,凡是技能包需要的外部库,要么在 SKILL.md 里写清楚安装命令,要么就用 Python 标准库实现,避免运行时还要装包。权限问题主要体现在执行位没设置好,解决方法是建技能时就 run chmod +x 设置可执行权限,并在文档里写清楚。

如果脚本输出了空结果或者异常数据,别急着改脚本,先手动在终端跑一遍,确认脚本本身没问题,再回头看是模型调用方式的问题还是数据源本身的问题。脚本负责的边界要收敛到“稳定输出结构化数据”,其余所有判断和归纳都交给模型处理。

4.4 多个技能相互打架时怎么办

技能库一多,就会出现边界重叠。比如你同时有“会议纪要”和“每日总结”两个技能,用户发来一段会议转录稿说“帮我总结一下今天讨论了什么”,两个技能都被激活了,模型就得猜该用谁。

解决思路是在 description 里把“触发条件”写得再窄一点。可以用“当用户明确提到会议、纪要、行动项时使用”和“当输入是个人当天完成事项时使用”这类句式,把两个技能的适用场景彻底隔开。如果两个技能确实经常同时匹配,那就要认真考虑是不是技能划分本身有问题,把粒度重新调一下,而不是靠 description 硬撑。

4.5 技能调试速查表

我把这几个月的调试经验整理成一张表,遇到问题先对着表排查,能省不少时间。

现象可能原因快速验证方法处理建议
技能从不触发描述与用户措辞不匹配用描述中的原词改写提示词再测补充同义词与触发样例
技能频繁误触发描述过于宽泛查看所有误触发上下文限定场景边界,加排除条件
技能内容被忽略SKILL.md 过长、重点靠后让模型复述技能步骤金字塔结构,步骤前置
脚本执行失败路径或依赖问题手动运行脚本用绝对路径、预装依赖
输出结构不统一缺少模板或模板不清晰对比多次输出差异提供固定输出模板和示例
多技能混淆边界重叠查看激活日志收紧描述,调整粒度

5. 个人体会:技能不是堆出来的,是打磨出来的

动手做了一段时间技能库之后,我最大的感受是:技能数量的多少不重要,技能说明书的清晰度才决定一切。一个描述精准、步骤清晰、边界明确的技能包,能顶得上十个写得模棱两可的“全功能包”。每次遇到执行结果不稳定,我做的第一件事永远是回头修改 SKILL.md,把模糊的表述改精确,把缺失的约束补上,而不是急着增加新技能。

另一个体会是,技能体系的真正价值在于积累。你每做完一个项目,都会沉淀下来一批可复用的技能目录,下一次做类似项目时直接挂载就能用,这比每次从零开始在提示词里写方法论高效得多。我现在的新项目启动流程,就是先盘一遍技能库里有哪些能直接用,再针对增量需求新增技能包。

最后分享一个我踩过几次坑之后养成的习惯:在技能包目录里额外放一个 notes.md,记录这个技能的调整历史和调试中发现的关键信息。看起来多此一举,但技能越积越多之后,这个文件的价值会被无限放大——它能帮你回忆起当时写这个技能时到底堵了什么坑、规避了什么风险。关于 Agent Skills,我目前觉得最值得投入精力的方向,就是不断打磨每个技能说明书的质量。毕竟对模型来说,一份清晰的操作手册,比任何花哨的技术方案都更管用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 13:28:34

深入解析Java SPI机制与Spring Boot扩展实践

1. SPI机制的本质与Java原生实现在深入探讨Spring SPI之前,我们必须先理解SPI(Service Provider Interface)机制的本质。SPI是一种服务发现机制,它允许第三方为某个接口提供实现,而框架能够自动发现并加载这些实现。这…

作者头像 李华
网站建设 2026/10/23 13:24:22

Python单元测试框架unittest详解与实践指南

1. unittest框架概述unittest是Python标准库中内置的单元测试框架,它最初受JUnit启发而设计,为Python开发者提供了一套完整的测试解决方案。这个框架在2001年随Python 2.1版本首次引入,经过多年发展已成为Python生态中测试代码的基石工具。在…

作者头像 李华
网站建设 2026/10/23 8:18:54

Netty与SpringBoot整合实践:从Socket到TCP长连接的物联网设备接入全攻略

搞物联网设备接入这件事,我踩过不少坑,尤其是用Netty对接socket设备再配合SpringBoot做业务处理,中间有太多细节比官方文档里写的要曲折。最近团队刚完成一个仓储物流场景的设备接入平台,几十台扫码设备和传感器通过TCP长连接实时…

作者头像 李华
网站建设 2026/10/23 7:47:10

大模型API统一网关liteLLM:模型路由、密钥管理与成本控制实战

干这行最头疼的事,不是模型效果不好,而是“调接口调得想骂人”。手上一堆项目要接不同厂家的模型,有的用这种方式鉴权,有的要那种格式传参,A家的输出和B家的输出还不完全兼容。原本半小时能写完的功能,光对…

作者头像 李华
网站建设 2026/10/23 2:56:18

Vue3登录状态持久化实战:Pinia与localStorage实现Token管理

1. 为什么每个 Vue3 项目都得面对登录状态持久化做过前端的同学应该都有过这种体验:辛辛苦苦把登录页做完,接口也通了,跳转也正常了,结果自己按了一下 F5,心里瞬间一凉——又回到登录页了。更尴尬的是,明明…

作者头像 李华