☰
Agent Skills实践指南:告别提示词堆砌,让AI掌握可复用技能包
2026/10/7 11:46:30 网站建设 项目流程

去年年底我一口气把手里七八个项目都接进了 Agent 工作流,最开始非常爽,什么活儿都丢给模型干。但大概两周之后,我发现自己陷入了一个很蠢的循环:每次让模型处理 PDF 提取、整理会议纪要、批量改文件格式,都得把同样一大段 instruction 粘进对话里,粘到系统提示词快比业务代码还长。而且换个项目、换个环境,这套"咒语"又得重新调一遍。

后来我接触到 agent-skills 这套做法,才意识到问题不在于模型不够聪明,而在于我一直把"技能"和"提示词"混为一谈。Skills 的核心思路其实特别朴素:把某个场景下可复用的能力,打包成一个结构化的技能目录,让 Agent 在需要的时候自己去加载调用,而不是每次由人在外部拼凑指令。这篇博文就来聊聊我这一路实践下来的理解,包括 skills 的目录结构、SKILL.md 怎么写、和 MCP 和子代理怎么分工,以及实测里真正容易翻车的地方。

1. agent-skills 到底是什么:先看清它和工具、子代理的边界

1.1 从一次真实的重复劳动说起

我先讲一个具体场景。我手上有个内部知识库的项目,经常要处理几十份 PDF 格式的行业报告,把它们转成结构化 Markdown,提取摘要、关键结论、数据表格,然后归档。这个流程看起来简单,但细节特别碎:排版要统一、表格要转成管道符格式、引用要保留原文页码、图表要单独截图出来。

之前我的做法是,每来一批新报告,就把这些要求重新敲一遍给模型。后来我试着把要求写进 system prompt,但 system prompt 越来越长,长到模型有时候会忽略中间的某几条规则,输出就开始飘。直到我把这套流程封装成一个 skill,问题才真正解决——模型只要识别到"任务里有 PDF 报告需要整理",就会自动定位到我写好的 skill 目录,按里面的标准流程执行,不再依赖我把规则重复贴一次。

1.2 skill 的本质:目录即技能包

那 skill 到底是个什么东西?用大白话说,它就是一个包含说明文件和可选辅助资源的目录。目录里最关键的是一个SKILL.md文件,里面通过 YAML 格式的 frontmatter 声明技能的元信息(名字、描述、触发场景),正文部分写具体的执行步骤、规范、注意事项。

目录里通常还会放一些模型执行时可能用到的辅助资源,比如:

  • 转换脚本(例如把.docx转成 Markdown 的 Python 脚本)
  • 模板文件(例如报告输出格式模板)
  • 参考文档(例如企业内部的写作规范、代码风格指南)

Agent 在运行时会去扫描可用的 skills 目录,通过description字段判断当前任务是否命中某个 skill。一旦命中,它会进入该目录读取SKILL.md,相当于按图索骥地调用这套"操作手册"。

这套设计最巧妙的地方在于,skills 是延迟加载的。模型不会一开始就把所有技能内容塞进上下文,只有在任务匹配到相应技能时才会去读取,这能显著减少 token 消耗,也避免大而全的提示词稀释模型的注意力。

1.3 一条清晰的分工线:function / MCP / skill / subagent

我刚开始搞这套的时候最大的困惑是:skills 和 function calling、MCP、subagent 这些概念到底什么关系?我踩了不少坑之后才总结出它们其实是四个维度的东西,各管一摊:

机制本质适合解决什么问题一个形象的比喻
Function calling把外部函数暴露给模型,让模型决定何时调用实时的数据读写、API 交互、精确的计算给模型配了一套工具,模型知道什么时候用什么工具
MCP统一的外部工具接入协议,把工具服务化打通外部数据源和工具生态,多个 Agent 复用同套工具给模型提供了一套"即插即用"的标准外部设备接口
Agent Skills把"经验+流程+规则"编码成可复用的技能包沉淀领域知识、标准操作流程、模型行为规范给模型一整本"岗位手册",干这类活就翻这一本
Subagent独立运行的小型代理,负责一个完整子任务需要多步骤、独立上下文、并行处理的复杂任务把活分包给专门的人,各干各的再汇总

这里的核心区别在于:function 和 MCP 解决的是"模型能调用什么外部能力",skills 解决的是"模型应该知道怎么做这一类事的完整套路"。skill 不是工具,它更像是一份给模型看的"工作手册",但这份手册里可以引用工具、可以触发脚本、可以约定必须调用 MCP 里的某几个服务。一个复杂任务的落地,往往是这四者协作的结果。

2. 第一个 skill 的完整解剖:从目录结构到 SKILL.md 写作

2.1 标准目录骨架

先给一个最标准的 skill 目录骨架,这是我目前项目里一直在用的:

my-skill/ ├── SKILL.md # 技能说明:frontmatter + 执行指令 ├── scripts/ # 存放辅助脚本 │ ├── convert.py │ └── extract_tables.py ├── templates/ # 存放模板文件 │ └── report_template.md └── references/ # 存放参考资料 └── formatting_guide.md

SKILL.md放在根目录,名字必须叫这个,Agent 在扫描时就是按这个既定名称来找的。scripts、templates、references这几个目录不是强制的,但强烈建议按这个习惯组织,因为当你的 skills 越来越多,统一的目录约定能让维护成本大幅下降。

这个骨架我调整过好几次,最初我把辅助脚本直接平铺在 skill 根目录,后来发现一个 skill 里的脚本多了之后又乱又容易命名冲突,还是分目录管理最省心。

2.2 frontmatter 的 name 与 description:触发命中的关键

SKILL.md的开头是一段 YAML frontmatter,这是整个 skill 里最不能马虎的部分。我用一个实际案例来说明:

--- name: pdf_report_converter description: 将 PDF 格式的行业研究报告转换为结构化 Markdown。当用户提供 PDF 文件或要求“整理报告”“提取摘要”“转换格式”“归档行业报告”时使用。需要结合 report_format_v2 模板。 ---

这里有两个关键设计点。

第一,name要尽量代表一个"能力",而不是一个"任务实例"。"将 PDF 转换为 Markdown" 是能力,而"转换上个月的电力行业报告"是具体任务。前者适合做 skill,后者只是调用 skill 时传入的参数。我一开始犯的错误是给每个具体任务起一个名字,最后维护了几十个几乎一样的 skill,后来才合并成一个参数化的技能包。

第二,description的核心任务是让 Agent 准确判定"什么时候该用、什么时候不该用"。这里的文本尽量包含三个信息:做什么、在什么场景触发、有什么关键约束。特别是触发场景,要写用户可能的原始说法,因为 Agent 判断技能匹配靠的就是这份描述的内容,写得太抽象会导致该触发时不触发,写得太宽泛会导致不该触发时乱触发。

2.3 正文怎么写才不会被模型跳过:动作式指令 + 边界说明

frontmatter 之下是正文部分,这才是 skill 真正的灵魂。我写过十几个 skill 之后得出的体感是:正文不需要写得多华丽,但必须让模型清楚"第一步做什么、第二步做什么、每一步做到什么标准、遇到边界情况怎么办"。

还是拿我那个 PDF 转换 skill 来说,正文核心大概是下面这样:

# PDF 报告转换流程 ## 执行目标 将用户提供的 PDF 文件转换为结构化 Markdown,生成摘要、关键数据表和归档目录。 ## 执行步骤 1. 定位文件:确认 PDF 文件路径存在,若用户未提供路径,先询问获取。 2. 提取文本:调用 scripts/extract_text.py 提取全文,保留原始段落结构。 3. 转换表格:调用 scripts/extract_tables.py,将 PDF 中的表格转换为 Markdown 管道符格式,必须保留原始表头。 4. 生成摘要:根据提取内容,提炼 3-5 个要点,含关键数据与结论。 5. 添加元信息:在文档头部追加 source、date、page_count 字段。 6. 输出与归档:按 templates/report_template.md 输出,并在 archive/ 目录建立索引。 ## 明确边界 - 如果 PDF 是扫描件,必须先调用 OCR 脚本,不得直接跳过。 - 如果 PDF 超过 100 页,先输出内容大纲,再由用户确认后分章节处理。 - 遇到公式图片,保存为独立图片文件并在 Markdown 中引用。 - 表格数据缺失超过 30%,在文档中标注“unverified”,不得无中生有补全数据。

我故意把"明确边界"单独拎出来写,这一点非常关键。模型在开放式任务里最喜欢自由发挥,而边界恰恰是保证输出质量控制风险的地方。像"不得无中生有补全数据""必须保留原始表头"这类硬规则,写进边界里比写在步骤里更不容易被忽略。我测试过很多次,把约束写在步骤里模型经常当背景信息略过,单独成段作为"硬性规定"时执行效果明显更好。

另外正文不要太长,我给自己定的红线是普通技能正文不超过 150 行。如果一个 skill 的正文要写 300 行,那说明这个技能太庞杂了,应该拆成多个子技能或者配合 subagent 使用,而不是把所有情况都堆进一个文档里。

3. 从零构建一个能落地的 skill:以"批量整理 PDF 重点"为例

3.1 先想清楚这个 skill 的"输入产出"

动手之前最重要的一件事,是把这个 skill 的输入和产出定义清楚。很多人上来就写指令文件,写着写着就跑偏,根本原因是没想清楚边界。

我每次都会先画一张最简单的逻辑表:

项目内容
输入一个 PDF 文件路径,或一个包含多个 PDF 的目录路径
产出每个 PDF 对应的结构化 Markdown 文件 + 一个汇总索引文件
触发信号用户提到"整理 PDF""提取重点""转成 Markdown""归档报告""摘要"
关键约束表格转换格式、摘要长度、页码保留、扫描件走 OCR
辅助依赖extract_text.py、extract_tables.py、report_template.md

如果你发现一个 skill 有多个明显不同的产出物或者依赖完全不同的工具,那这个"技能"很可能应该拆成两个。我的原则是:一个 skill 最好只解决一类问题,内聚性越高,模型调用的稳定性就越高。

3.2 完整步骤:目录、描述、指令、脚本、验证

下面按我实际执行的顺序,把从零搭建一个 skill 的完整过程走一遍。

第一步,创建目录骨架。我在项目根目录下建了skills/pdf_report_converter/,并在里面建好scripts、templates、references三个子目录。

第二步,写SKILL.md的 frontmatter。这里提醒一个细节:description 里一定要包含"用户可能用的口语化说法"。我最初写的描述是"将 PDF 转换为 Markdown",结果用户说"帮我看看这份报告里讲了啥,整理成文档"时模型识别不到这个技能。后来我把描述改成包含"整理报告""提取重点""转成文档""归档"等常见表达,命中率一下就上来了。因为模型做技能匹配本质上是在做语义匹配,词汇覆盖越贴近真实用户表达,匹配越准。

第三步,写正文执行流程。这个前面已经展示过了,需要强调的是每一步都要有"可验证的输出标准",比如"生成 3-5 个摘要要点""表格转换为管道符格式"。不要让模型自己去揣摩"什么叫整理好",标准写得越具体,输出一致性越高。

第四步,编写辅助脚本。这一步很多人会忽略,我一开始也以为 SKILL.md 写好就够了,后来发现模型在执行中需要把 PDF 表格精确转出来,靠纯手工格式化几乎必出错,必须有脚本兜底。我写脚本时的核心考虑是:脚本要能在当前工作目录下独立运行,最好不依赖特定环境变量,接收明确的参数(例如输入文件路径),输出固定到指定位置。一个典型的调用接口大概长这样:

# scripts/extract_tables.py import sys import pdfplumber def main(pdf_path: str, output_path: str): with pdfplumber.open(pdf_path) as pdf: tables = [] for page in pdf.pages: page_tables = page.extract_tables() if page_tables: tables.extend(page_tables) # 输出为管道符格式 Markdown 表格 with open(output_path, "w", encoding="utf-8") as f: for table in tables: for row in table: cells = [cell.replace("\n", " ") if cell else "" for cell in row] f.write("| " + " | ".join(cells) + " |\n") f.write("\n") if __name__ == "__main__": main(sys.argv[1], sys.argv[2])

脚本不需要写得特别复杂,但接口一定要简单明了。Skill 的脚本和普通业务代码的不同之处在于,它是给 Agent 人机协作用的,Agent 会根据 SKILL.md 的指令来决定怎么调用它,所以脚本的命令行参数设计要足够"直觉化",避免那种需要读半天文档才能搞懂的调用方式。

第五步,做一次完整验证。我先扔给它一个干净的 PDF 报告,观察模型是否在对话一开始就加载了这个技能,然后逐步检查每一类输出。这个阶段我习惯开启模型的"详细思考"模式,看它内部是怎么理解步骤的,这能帮我定位到底是描述写得不够清楚,还是脚本接口有问题。

3.3 让模型"记住"要用 skill:不要光靠 Agent 自己发现

如果只是把 skill 目录放在那里,不同的 Agent 客户端对它的处理方式其实不太一样。有些 Agent 会在初始化时把所有可用 skill 的 name 和 description 扫一遍放进上下文,有些则是完全靠用户主动提及。我实测下来的经验是:不要让模型"随缘发现"技能,最好在任务描述的初始阶段就显式提示可用的技能集。

例如我会在项目级说明文档里写上:

本仓库已配置以下技能,遇到对应任务时请优先调用: - pdf_report_converter:用于 PDF 报告整理、转换、归档 - meeting_minutes_formatter:用于会议纪要结构化整理 - code_review_helper:用于代码评审辅助

这样模型在规划任务时就能主动考虑调用技能,而不是边做边发现。这个"主动把技能暴露给模型"的动作,是很多教程里没有讲清楚的地方,也是最影响实际体验的一个环节。我见过很多人搭好了 skill 目录结果发现模型根本不调用,以为机制坏了,其实只是缺少初始化阶段的提示。

4. 实测中最容易翻车的五个细节

4.1 description 措辞:太宽泛 vs 太具体

这是一个值得单独拿出来讲的坑。我最早有个 "data_analyzer" 的 skill,description 写的是:

当用户需要进行数据分析时使用。

看起来没问题,结果在另一个项目里,用户提交代码时要求"分析这段代码的复杂度",模型判断这是数据分析,就把这个技能调了出来。整个技能的内容都是关于数据处理和图表生成的,跟代码复杂度分析完全不沾边,模型为了不违背技能描述,硬着头皮套了一套完全不合适的流程,最后输出惨不忍睹。

后来我总结出一个改善措辞的方法:先写下至少 5 个用户可能的原始说法,再写至少 3 个应该排除的场景。如果描述能让模型对"何时不用"也有清晰的判断,命中质量会提高很多。我的新版描述一般长这样:

当用户提供 CSV、Excel 或数据库导出的数据文件,要求做统计描述、相关性分析、可视化图表时使用。注意:不含代码复杂度分析、文本语义分析。

4.2 指令文件膨胀:技能包变成说明书

Skill 有个很自然的膨胀路径:随着使用次数增加,看到一次失败就往 SKILL.md 里加一条规则,半年之后这个文件可能变成两千行的巨型说明书。我曾经有一个写代码规范的 skill,里面每条规范都来自某个真实线上事故的补救,满满当当写了两百多条,结果模型执行时根本读不过来,重要规则反而不突出了。

我的做法是给 SKILL.md 分三个层次:最前面是"必须遵守的 5-8 条硬性规则";中间是"标准流程步骤";最后是"常见问题与兜底处理"。

模型在执行时会优先完成前面的规则,后面的内容只在遇到具体情况时才参考。这有点像给新员工写 SOP,你不能把二十个常见异常全塞到开头的"工作原则"里,要分主次,否则核心流程被淹没,反而处处出问题。

4.3 路径与工作目录:模型不认相对路径

这是我踩得最痛的一个坑,没有之一。有一天我让 Agent 调用某个技能处理一个相对路径下的文件,它一直报错找不到文件。后来我发现技能里的脚本里有这样一段逻辑:

OUTPUT_DIR = "outputs/"

如果技能被调用的工作目录和 skill 所在目录不是同一个,这个相对路径就会失效。Agent 的执行环境通常以项目根目录为基准,而你的 skill 目录在skills/xxx/下面,这就导致脚本里的路径全部错位。

现在的解决方案是:所有脚本一律接收绝对路径作为参数,或者从环境变量里读取项目根路径。SKILL.md 里明确写明"所有路径参数必须是绝对路径":

注意:调用 scripts/extract_tables.py 时,pdf_path 和 output_path 必须是绝对路径。禁止在脚本内部使用相对路径。

这个规则我确认过很多次,模型不会自动去解析路径语义,就是按纸面规则执行的。你不写清楚,它就会用相对路径,然后脚本就挂。

4.4 环境依赖:换一台机器就废了

Skill 里如果带了 Python 脚本,就避不开依赖问题。我最初的一些 skill 脚本依赖十来个第三方库,在当前环境跑得很顺。有一天我换了台机器,重新拉取项目开始跑,结果 Agent 一调用脚本就报ModuleNotFoundError,干活的心情瞬间没了。

从那次以后,我给所有带脚本的 skill 加了一个依赖声明文件:在 skill 根目录放一个requirements.txt或者在 SKILL.md 里单独写一段"环境依赖说明"。这样模型在执行时可以主动检查依赖、主动提示安装,而不是等报错了再手忙脚乱。

另外我还发现一个细节:尽量把脚本的依赖控制在标准库加少数常用库,能用pdfplumber就不用额外的 OCR 库,能自己写纯 Python 解析的就不要拉一个巨大的数据分析框架。依赖越少,skill 的漂移率越低,跨环境的稳定性越好。

4.5 更新策略:模型引用旧版本

你改完一个 skill 之后,Agent 不一定马上用上新版。这个问题在长对话场景特别明显:对话前期的上下文里可能已经缓存了旧版技能内容,后续执行会继续沿用旧规则。我最初的困惑是明明改了 SKILL.md,模型还是按老办法做。

现在我的习惯是:每次修改完 SKILL.md 之后,开启一个新的会话测试,不在原会话里做验证;如果是通过配置文件加载的技能列表,也要确认版本号被正确刷新。还有一个土办法,我习惯在 SKILL.md 的 frontmatter 里加一个 version 字段,同时在项目说明里写明当前版本号。这样只要模型输出对不上版本号,我能第一时间意识到它引用的是旧版,而不会稀里糊涂地以为改动没生效。

5. 组合决策:什么任务该上 skill,什么任务不该上

5.1 一张判断表

实践久了之后,我意识到 agent-skills 不是万能的,不是所有任务都适合打包成技能。我给自己整理了一张决策表,每次拿不准的时候就拿出来对照:

场景是否适合做 skill原因
重复出现的多步骤任务,规则相对稳定适合可以把标准流程沉淀下来,减少每次都要现场叮嘱
需要实时查询外部数据不适合,应该走 MCP/API 工具数据是动态的,skill 里的静态指令解决不了
高度依赖上下文和项目现状的决策不适合这类任务需要子代理去研究,不是一个技能能覆盖的
一次性的临时任务不适合不值得为一次性的事归档技能
团队内需要统一质量标准的任务非常适合skill 本身是共享文件,天然可以做规范下发
需要大量模型自由发挥的创意任务不适合技能约束会限制创造性

这个表的意义在于帮你省下不必要的维护成本。我见过一批人上来就什么任务都做成 skill,最后目录里几十个技能,每个技能都只有寥寥几行,完全是形式主义。真正有价值的 skill,是那些被反复调用、承载着你核心业务规则的东西。

5.2 和 MCP 配合的实战模式

在实际工作里,skill 和 MCP 不是二选一,而是配合使用。我给你讲一个我最常用的组合模式。

我的项目里用 MCP 接了一个内部知识库服务,可以检索文档、查询条目。另一个 skill 是"行业报告竞争分析",它规定了一套分析框架:竞品名单、产品对比维度、市场定位判断标准。实际执行时,模型先调用 skill 里的分析框架,然后通过 MCP 去实时检索竞品的新闻和产品文档,再把检索结果灌进框架里生成报告。

在这个模式里,skill 负责"怎么分析",MCP 负责"从哪拿数据"。前者提供的是方法论和经验规则,后者提供的是数据管道,两者互补才完整。如果你把"怎么分析"硬编码进 MCP 工具里,工具会变得非常臃肿;如果把"从哪拿数据"写死在 skill 里,数据又会过期。保持 skill 不含实时数据、MCP 不含业务规则,是我实践下来的最佳分工。

5.3 什么时候该用 subagent 而不是 skill

最后聊聊 skill 和 subagent 的边界。两个机制都能实现多步骤任务,但重点不一样。

我现在的判断标准是:如果任务流程是"线性的、单线程的、规则明确的",优先用 skill。例如 PDF 转换、数据清洗、格式规范化,这些按部就班执行就完事了,用 subagent 反而浪费资源和时间。

但如果任务是"需要多轮探索、需要自己查资料、需要根据中期结果调整策略"的,那就该上 subagent。例如"调研某个技术方向最近半年的进展并输出建议报告",这种任务你没法在 skill 里写死步骤,它需要子代理自己去检索、筛选、综合、判断,几次迭代之间还有决策反馈。skill 是"执行已知流程",subagent 是"完成未知探索",一句话总结两者的核心差异。

我踩过的混合坑是:把一个"探索型"任务硬做成 skill,写了很长的"步骤"让模型去查各种信息,但模型每走一步都需要灵活应变,结果步骤和实际行为对不上,技能名存实亡。后来我把这种任务改成 subagent 模式,只给目标、约束、输出格式,把过程交给子代理自己安排,效果反而好很多。

最后,说说我现在怎么维护这套东西

我现在项目里常驻十几个 skill,有大有小,最常用的几个已经迭代到了八九个版本。维护它们比起最初写代码并没有轻松太多,但收益是实打实的:以前每次新项目进来我都要在提示词里写一大段要求,现在直接把目录指给模型就行,大家看到的能力边界完全一致,产出的质量也稳定得多。

如果你准备开始用 agent-skills,我给一个最实际的建议:不要一上来就追求把全部工作流都技能化。挑一个你最常重复、规则最稳定、失败成本最低的任务先试水,比如日志分析、报告格式化、代码规范检查这一类。把一个 skill 从零打磨到顺手,你就理解了它的脾气,再往后扩展就是水磨工夫了。等你维护了十几个技能之后自然会形成自己的判断:哪些值得沉淀、哪些赶紧拆掉、哪些该交给 MCP、哪些该推给 subagent——这些东西只看文档是体会不到的,亲手把一个又一个"工作咒语"变成可复用的技能包,才是这套机制真正的乐趣所在。

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

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

立即咨询