最近在做一个自动化报表项目,折腾来折腾去,最后发现真正让我省力的不是某条提示词写得多精妙,而是我给自己智能体配了一套“技能包”——就是现在大家常说的 Agent Skills。这东西说白了,就是给智能体写一份带目录的操作手册,让它遇到某类任务时知道“该按什么套路办事”,而不是每次都临时发挥、每次结果都飘忽不定。
这篇文章我打算把实际用下来最顺手的五个 Agent Skills 逐个拆开讲清楚,包括它们解决什么问题、技能文件里到底写了什么、哪些坑一定要避开。后面还会附一份完整的自定义教程,从目录结构到调试方法都过一遍。看完之后你完全可以照着做一个自己的技能包,不用再反复跟智能体强调那些基础规则了。
1. Agent Skills 到底是什么,一次说透
1.1 从“会聊天”到“会干活”,差的就是这一步
先打个比方。你招了个实习生,脑子灵光、学习能力强,但你发现他每次做报表前都要问你“这列数据怎么处理”“这个格式用什么标准”“上次不是说过吗”。后来你实在受不了,给他整理了一本《岗位操作手册》,里面写着:遇到日报,先检查哪些字段、缺失值怎么补、最终输出什么格式。从此他上手快多了,也不用来回问了。
Agent Skills 就是这个操作手册。它不是一段通用的系统提示词,而是一个结构化的、按需加载的技能说明,通常是一个带有元信息的小文件。智能体在运行时会根据任务描述判断“这件事适合用哪个技能”,然后才去读取对应的技能文件。正因为是“按需加载”,它不长期占用上下文窗口,用的时候才翻手册,不用就放着。
我在项目里感受最明显的一点是:没有 Skills 的时候,同一类任务你做三次,三次都可能出现不同风格的输出,每次都得微调提示词。但配上技能包之后,智能体的行为就稳定了,因为它有一套明确的“办事流程”可以照做,少了很多临场发挥的随机性。
1.2 Skills、工具与提示词,三者的边界别搞混
很多刚接触的人会习惯把 Skills 等同于 Tools,或者等同于提示词,这俩理解都不太对。Tools 是可调用的外部能力,比如执行某段代码、请求某个接口,它们像是“能做事的手”。而 Skills 更像是“指导手怎么做事的大脑层面的约定”,它负责定义步骤、约束行为、说明注意事项,当然在步骤里也可以明确写“这里应该调用哪个工具”。
提示词是即时的、一次性的指令,它跟对话内容混在一起,大多数情况下没有独立的管理结构。Skills 则是独立的文件、独立的生命周期,可以版本管理、可以复用、可以在不同项目之间迁移。你可以这样理解:提示词是“口头的嘱咐”,Skills 是“白纸黑字的规范文档”,Tools 是“工具箱里的家伙什儿”。
把这三者的边界搞清楚之后,你才会明白为什么有些问题不该靠加提示词来解决,而应该沉淀成一个 Skill。比如“输出格式太随意”——加多少句“请规范输出”都未必有用,但你在 Skill 里写清楚字段要求、给一个标准示例,再配上强制校验的约束,问题自然就解决了。
2. 五个真正好用的 Agent Skills 逐个拆解
2.1 代码沙箱执行类:让结论从“猜”变成“跑过”
这个技能目前是我使用频率最高的一类,没有之一。智能体现在很擅长写代码,但光“写”出来不算本事,能“跑”起来才算。代码沙箱执行类 Skill 的核心作用,是强制智能体在给出任何结论之前,先进入执行环境把代码跑一遍,拿到真实输出之后再来回答。
我写过的最简版本大致长这样:
--- name: code_sandbox description: 当需要执行Python代码、验证算法逻辑、计算结果或调试脚本时使用。 --- 1. 需要执行代码时,先确定当前工作目录,确认脚本文件路径。 2. 优先将代码写入临时文件后运行,而不是直接在生产环境执行。 3. 运行结束后,必须查看标准输出和错误信息。 4. 如果运行失败,先根据错误信息猜测原因,修改代码后重试,最多尝试三次。 5. 最终回答中附上关键输出片段,而不是只给结论。为什么这个技能好用?因为它治的是智能体“凭空编结果”的老毛病。以前让它算个数据,它经常直接给你一串看着合理的数字,你拿去用才发现对不上。配上这个技能后,它知道自己必须先跑一遍代码,把 stdout 里的真实结果抄过来。对做数据分析或者处理脚本的人来说,这直接决定了一个 Agent 可不可信。
要注意的一个细节是脚本执行环境。有些 Skill 里默认用虚拟环境,有些则在容器里执行。不同环境依赖版本不一样,容易造成“在我机器上能跑”的问题。我的做法是在技能里加一句“执行前先检查依赖是否安装,缺失则安装”,并在代码沙箱里固定好 Python 版本和常用库。
2.2 多格式文档解析:别再手动搬表格了
第二个特别常用的技能是文档解析类。日常工作中,PDF 里的表格、Word 里的正文、Excel 里的多 sheet 数据,如果每次都靠人手动转换,不仅枯燥而且容易出错。Agent Skills 可以把这套流程固定下来,让智能体拿到文件后按照既定方式处理。
这里面最值得写清楚的是“不同格式怎么拆解”的处理路径。比如我实际用的一份技能文件核心步骤是这样的:
- 先识别文件类型,扩展名不能完全代表实际格式,得检查文件头。
- PDF 文件:优先尝试提取文本层;如果文本层为空,再走 OCR 流程。
- Word 文件:区分 doc 和 docx,docx 走结构化解包,doc 需要先转换再解析。
- Excel 文件:列出所有 sheet 名称,逐个确认数据范围,不要只读第一个 sheet。
- 统一输出为 Markdown 表格或 CSV,保留原始数据的层级结构。
这个技能的妙处在于它把“解析经验”固化下来了。比如很多人不知道 PDF 有两种——有文本层的和纯扫描件,处理方式完全不同。我在技能里明确了先试文本层、再走 OCR 的次序,光这一条就帮智能体少踩很多坑。
实际使用中,最头疼的是 Excel 多 sheet 的数据错位,有些 sheet 前面几行是标题说明,直接读会把表头带歪。我在技能里专门加了一条“定位真实表头行”的规则,让智能体先扫描前五行,确认哪一行是真正的列名,再开始提取数据。这个细节非常值得你在自己项目里参考。
2.3 表格数据清洗与分析:把脏数据治得服服帖帖
做数据分析的人都知道,数据清洗占据整个工作流大半的时间。Agent Skills 在这一步帮了我大忙,因为清洗规则是高度可复用的。拿到一份 CSV,缺失值怎么处理、重复行怎么去、类型怎么统一,每家公司甚至每个项目都有自己的标准。与其每次都让智能体猜你的“潜规则”,不如写成技能,让它直接按流程走。
我写的清洗与分析技能包含的要点有这些:
- 先做一次“数据体检”:查看行数、列数、每列的非空计数、数据类型、唯一值数量。
- 缺失值分情况处理:数值型列用中位数填充还是删除,取决于缺失比例;字符型列一般统一标记。
- 重复值处理:基于全行判断还是基于关键列判断,要在技能里讲清楚。
- 统一列名规范:去掉首尾空格、统一大小写、处理中英文混用。
- 分析结果输出:描述性统计、分组汇总、趋势判断,都以 Markdown 表格形式给出。
经验之谈有一条:清洗规则千万不要写得太“死”。比如写“缺失值一律删除”,这会害死很多场景。更好的写法是给出一套决策逻辑:“缺失比例低于 5% 时直接删除;介于 5%~20% 时用中位数或众数填充;高于 20% 时先判断该列是否有保留价值,再决定是否丢弃。”这种决策树式的写法,让智能体在不同数据面前有判断余地,而不是死板执行。
另外,分组统计的口径也很重要。早先我遇到过智能体在同一份数据上两次跑出不同统计结果的情况,后来发现是分组键没写清楚。现在我的技能文件里会写明:“所有分组统计必须先指定分组列,并在输出中标注分组依据,禁止含糊地输出整体均值。”
2.4 网页抓取与内容提取:拿到干净的正文
网页抓取这个技能的适用场景很明确:需要从某个页面提取正文、标题、发布时间、作者等信息,而不想被导航栏、广告、推荐列表干扰。很多智能体在处理网页时其实没有章法,抓到什么就是什么,最终提取结果里塞满了无关内容。
我在技能文件里定义的流程大致如下:
- 抓取前先确认目标 URL,并模拟常规浏览器请求头。
- 获取 HTML 后,先分析页面结构,定位正文所在的容器。
- 剔除 footer 导航、广告位、推荐列表等非正文区域。
- 提取关键字段:标题、发布时间、作者、正文内容。
- 正文内容保留段落结构,清除多余的空行和内联样式。
- 如果是列表页,提取所有条目链接后再逐条进入详情页抓取。
这个技能有一个很关键的设计:它要求智能体“先思考再动手”。具体来说,在写入代码抓取之前,先根据页面结构猜测正文可能在哪个标签容器里,而不是盲目地把整个页面文本全部扒下来。这么做的好处是提取结果干净得多,后处理成本大幅降低。
踩过的坑也比较典型:有些网站用的是动态渲染,直接抓 HTML 拿不到正文。我在技能里特意加了一句“发现正文为空时,考虑页面是否存在 JavaScript 渲染,改用无头浏览器渲染后再解析”。这句话在很多场景下都是救命的。
2.5 结构化数据输出:让智能体学会“按规矩办事”
最后一个要重点推荐的技能,是结构化数据输出。它是所有跟外部系统对接场景的刚需。比如你要让智能体从一段对话中提取订单信息、从合同中抽取关键条款、从一堆文本里整理出联系人列表——这些任务如果没有结构化的输出约束,结果根本没法直接用。
这个技能的原理其实很简单,就是给智能体定义一个输出模板,要求它严格按模板产生结果。但很多人的技能定义写得太粗,光说“请输出 JSON”是不够的。一份合格的结构化输出技能至少包含这些内容:
- 输出的顶层类型:是对象还是数组。
- 每个字段的名称、类型、是否必填。
- 字段取值的说明,什么情况下填什么值。
- 一个完整示例,标出每个字段如何映射到源文本。
- 对非法输入的兜底策略:抽取不到返回什么值。
我实际使用的示例片段:
--- name: structured_extractor description: 当需要从非结构化文本中抽取实体、关系或构造JSON对象时使用。 --- 输出必须为合法JSON,不得包含其他解释文字。 字段定义: - name: 文本中出现的人名或机构名,字符串,必填。 - role: 该实体在文本中的角色,字符串,可填“unknown”。 - summary: 不超过50字的摘要,字符串,必填。 示例输入:张三在3月15日提交了项目结项报告。 示例输出:{"name": "张三", "role": "项目负责人", "summary": "提交项目结项报告"}这个技能为什么有效?因为它把“抽象的规范描述”变成了“具体的正反例约束”。智能体看到明确字段定义加示例后,输出格式的稳定性会显著提升。如果再配合一段校验逻辑,要求生成结果必须通过 JSON 解析,效果更加稳妥。
我在实际项目里吃过一次亏:之前没配这个技能时,智能体偶尔会在 JSON 前后多加一句“这是提取结果:”,直接导致下游程序解析失败。配了结构化输出技能之后,这类问题几乎没有再出现过。对任何一个想把 Agent 输出接入自动化流程的人来说,这个技能都值得第一时间安排上。
3. 自定义 Agent Skills 保姆级教程
3.1 目录结构:一个 Skill 就是一个文件夹
在动手写第一个技能之前,先要知道 Agent Skills 的组织方式。通常一个技能就是一个独立的文件夹,里面至少包含一份 SKILL.md 主文件,还可以根据需要携带辅助脚本、模板、参考数据等资源。
我推荐的标准目录结构是:
project_root/ └── .agent/ └── skills/ ├── code_sandbox/ │ ├── SKILL.md │ └── run_code.sh ├── csv_analyzer/ │ ├── SKILL.md │ ├── template_report.md │ └── scripts/ │ └── check_data.py └── structured_extractor/ └── SKILL.md这里面有几个关键点。首先是.agent/skills这个根目录的命名,一般主流平台都约定从项目根目录下查找技能文件夹。其次是每个技能一个子目录,目录名用短横线或下划线风格,不要带空格和中文。最后是 SKILL.md 作为主入口,命名必须严格一致,平台靠它来识别技能的元信息。
辅助文件怎么放也值得讲究。比如代码沙箱技能的 run_code.sh 脚本,或者数据分析技能的检查脚本,都可以放在技能目录的 scripts 子文件夹下。这么做的好处是“技能自包含”——换一台机器、换一个项目,整个文件夹拷过去就能用,不用再到处找依赖。
3.2 SKILL.md 的写法:元信息与正文缺一不可
SKILL.md 的格式本身不复杂,核心是两部分:顶部的 YAML 元信息区,以及下方的 Markdown 正文区。元信息区至少要有 name 和 description 两个字段,这是智能体做技能匹配的依据,花再多功夫都值得。
一份典型的 SKILL.md 长这样:
--- name: report_formatter description: 当需要生成周报、日报或项目总结报告时使用。适用于从零散信息整理成结构清晰、面向管理层的汇报文档。 --- # 工作报告生成规范 ## 目标 将零散的工作记录整理为结构清晰的报告。 ## 执行步骤 1. 收集所有原始信息,按时间线排序。 2. 识别每条记录对应的项目模块。 3. 按“进展、问题、下一步”三段式组织内容。 4. 进展描述用动宾结构,问题描述需附带影响范围。 5. 突出问题要有建议解决方案,不能只列问题。 ## 输出格式 - 标题层级不超三级。 - 每个模块内容不超过200字。 - 结尾附数据对比表,有数据的部分不能只用文字叙述。这里有一个非常容易被忽略的细节:description 字段的写法,直接决定了技能会不会被触发。写得太宽泛,比如“生成报告时使用”,会导致智能体在很多不该用它的地方调用;写得太窄,比如“仅当输入包含‘周报’二字时使用”,又会漏掉很多实际场景。
我的建议是采用“场景触发式”写法,也就是在描述里明确列出“当......时使用”,把典型场景和排除场景都写出来。一段我自己觉得好用的描述会是这样:
“当需要将零散的工作日志或进展记录整理为周报、月报、项目汇报时使用。不适用于写技术方案或代码评审意见,那些场景请参考其他技能。”
这么写的好处是,智能体在做技能匹配时有一个清晰的范围边界,减少了误调用和该调不调的情况。
3.3 编写指令的核心原则:少讲道理,多给示例
正文部分的编写原则,可以说是一门“写给机器看的管理艺术”。很多人会把技能文件写成一篇散文,讲了一堆背景和目标,但智能体读完仍然不知道具体该怎么操作。我写了多次技能之后,总结出三条最核心的原则。
第一条原则是“结构化步骤优先”。指令要拆成明确的步骤序列,每一条都是可执行的动作,而不是状态描述。比如“仔细审查数据质量”就不是一条可执行动作,而“检查每列缺失值比例并输出统计表”才是。把模糊要求变成动作清单,智能体的执行质量会明显上一个台阶。
第二条原则是“正反示例都要给”。光说“输出要规范”,不如直接给它看一个规范输出的样子。如果你再补充一个不能这么写的反面例子,效果会更好。比如在结构化输出技能里写“不要输出 ```json 代码块标记,直接输出 JSON 内容”,这句话排查掉的隐患比十句正面要求都多。
第三条原则是“善用退出条件”。技能文件里要写清楚“什么时候这个技能应该停手”。比如数据分析技能里写“若数据量超过 10 万行,先抽样 1 万行进行分析,并报告抽样比例”,这就给了智能体一个在合理边界内工作的依据。如果没有这种边界条件,它很容易在超大数据集上陷入长时间的处理。
我个人的经验是:一份好的 SKILL.md 不用写很长,重点是密度要高、动作要清晰、边界要明确。写完之后自己先“扮演一下智能体”,照着文件走一遍流程,就能发现哪些地方会卡壳。
3.4 调试三步走:触发测试、行为测试、回归测试
自定义技能写完之后,直接投入正式任务是不推荐的。我自己现在固定会做三轮测试,这让我后续少改无数次版本。
第一轮是触发测试。构造一个典型任务描述,比如“帮我把这周的工作记录整理成周报”,然后观察智能体是否正确地加载了报告生成技能。这轮核心是验证 description 写得准不准。如果没触发,问题大概率出在描述语境的匹配度上;如果触发了,再试一个排除场景,比如“帮我把这份代码改成异步版本”,看它会不会误用技能。
第二轮是行为测试。触发成功之后,观察智能体是否按照技能正文里的步骤执行。比如代码沙箱技能,看它有没有先写文件再运行;数据分析技能,看它有没有先做数据体检再做处理。这一轮最容易发现正文指令里的歧义和疏漏。
第三轮是回归测试。因为在同一个项目里可能有五个甚至更多技能,新技能可能会干扰旧技能的选择。我会把之前跑过的任务再重新跑一遍,确认那些本来稳定触发的技能没有被新技能抢走。这轮测试在技能数量变多之后尤其重要,别等接入了十几个技能才发现彼此之间的描述重叠。
调试的时候还有个实用技巧:准备一组“最小测试集”,每个技能配两三个典型输入和两三个排除输入,放在项目里固定使用。每次改了技能文件,就跑一遍测试集,比临时想测试用例高效得多。
4. 常见问题与排查技巧实录
4.1 明明写了 Skill,智能体就是不调用
这个问题我在早期几乎每写一个技能都会遇到。最普遍的原因是 description 写得跟实际任务描述不匹配。例如你写“处理表格”,但用户习惯说“帮我看看这个 CSV 文件”,技能可能就不会被触发。解决办法是打开触发记录,看看用户任务的实际用词,然后把这些常用词融进 description。
还有一个原因是技能文件位置放错了。有些项目支持多个技能目录,比如全局目录和项目目录;如果你的技能放在了全局目录,但当前项目的配置里只启用了项目目录,那自然不会被发现。检查一下技能目录是否在智能体的“可见范围”内。
如果一个技能已经正确触发但执行效果不像预期,也要注意是不是技能文件里写太多“解释性内容”,导致智能体“读了半天不知道要干嘛”。把解释性段落砍掉,直接上步骤,触发之后的行为会更干净。
4.2 工具调用失败或报错的环境差异问题
技能文件里经常写“使用脚本处理数据”,但智能体执行环境可能跟你的本地环境不一样。最常见的报错是路径不存在、Python 包未安装、编译环境缺失。这种问题最好的解决方式不是每次报错后临时找人处理,而是在技能正文里直接增加环境自检步骤。
我在技能文件里固定加了一段话:“执行前检查依赖包是否导入成功。若出现 ModuleNotFoundError,先安装缺失依赖再继续。若脚本路径不存在,检查当前工作目录并重新定位文件。”加了这段话之后,智能体会在报错时自行尝试修复,而不会直接把错误抛给你。
涉及外部服务时,比如抓取网页或调用接口,还要考虑网络策略和请求频率。一个合理的技能会包含“设置并随机延迟请求间隔”这种约束,不然稍大规模的抓取很容易触发目标站点的反制机制。
4.3 输出格式不稳定,有时对有时错
如果你发现技能配好后输出格式还是飘,那基本可以断定是“规范写得足够全、示例给得不够”。智能体对抽象描述的注意力没有你想象中那么强,但你对一份示例输出的模仿能力会准确得多。
我的做法是,每个技能至少提供一组完整的“输入-输出对”,最好能覆盖边界情况。以结构化抽因为技能为例,我会给一个正常抽取示例,再给一个“文本中字段缺失”的示例,说明这会产出什么默认值。双重示例会显著提升输出稳定性。
有时候问题也出在技能文件引导的“出口处”。比如你要求输出 JSON,但正文里本身嵌了 JSON 代码展示,智能体可能误解为“要输出这些代码块”。我的经验是,如果有标准示例,单独用代码块包裹,并在文字中明确写“上述示例展示的是逻辑结构,实际输出不得包含代码标记”。
4.4 多个 Skill 之间的优先级与冲突处理
当技能数量超过三五个,你会发现它们之间会出现“抢活”的情况。比如既有一个“数据分析技能”,又有一个“图表生成技能”,智能体在处理“分析这组数据并画个折线图”时,可能不知道哪个主刀。
这类冲突的根源是描述上的重叠。解决办法是在每个技能的 description 里明确写“不适用”的场景,让智能体能够做排除。另外也可以在技能文件的正文开头写一行“本技能不负责X,X场景请参考技能Y”,相当于给了一个显式的路由规则。
如果两个技能确实经常需要协作,比如先分析后出图,我建议不要把它们拆成两个独立技能,要么合并成一个带完整流程的技能,要么在两个技能的描述里明确写出“如果需要后续处理,请先调用技能A,再调用技能B”。智能体在步骤编排时看到这样的指引,通常能做出正确的调度。
5. 一点实操体会,给想入坑的朋友
如果让我说这段时间使用 Agent Skills 最大的变化,那就是我逐渐建立起了“沉淀意识”。以前遇到反复折腾的重复任务,我第一反应是“再优化一下提示词”,现在我会想“这段经验能不能固化成技能文件”。前者是每次对话重新谈判一次,后者是一劳永逸地降低后续协作成本。
实操建议上,我的习惯是从“最小的残留问题”开始做。你不用一上来就设计一套完备的技能体系,先选一个你的智能体最常出问题的任务,比如“总是输出不规范的 JSON”,然后针对这个写一个只包含三五个步骤的小技能。跑通之后,再慢慢迭代第二版、第三版。技能是活的,它跟着你的实际使用场景一起成长。
版本管理这块也提醒一句,技能文件本质上是代码,是配置,是协作文档,所以放进 Git 管理是必要的。我见过同事手改技能文件没留备份,后来想回退到上一个稳定版都做不到。把技能目录纳入版本控制,每次改动都留下 diff 记录,这样即使改坏了也随时能回到可用状态。
最后再分享一个小技巧:在一个技能文件里,开头最好写一行“如果你正在阅读本文件,说明你即将处理某类任务,且必须按以下步骤执行”。这一行看似废话,实则是一个强激活信号,能让智能体从“可选参考”进入“必须执行”的状态。我试过有这行和没这行的区别,输出稳定性差距肉眼可见。