Agent Skills技能化实战:从Prompt困境到可复用技能库搭建
最近在给团队搭内部Agent平台有个词被反复提起agent-skills。你要是关注AI Agent方向最近几个月应该没少见这个词——它的大意是把某个具体任务的操作知识写成一个标准化技能说明让Agent在遇到对应场景时能主动加载并照着执行。最早我是从项目群里的工程师安利知道的当时团队最痛苦的一件事是Agent能聊、能写、能查资料但一让它干点“具体的活儿”就拉胯每次都得靠人在Prompt里临时补全操作步骤。后来我把这套思路落地到自己项目里效果比预想的好很多。这不只是一份“给Agent看的说明书”它其实改变了我组织Agent能力的整套方式。这篇就把我的理解、踩过的坑和一套可以直接抄的搭建流程完整写出来。适合谁看正在做Agent应用、被“Prompt越来越长但能力越来越不确定”折磨的人以及想给团队搭统一Agent技能体系的工程和产品同学。不一定需要多深的算法背景只要你动手写过几个Agent脚本就能跟上。1. Agent Skills到底是什么为什么要做技能化改造1.1 从一个让人崩溃的Agent说起先讲个真实场景。之前我在做一个内部客服Agent功能是按用户问题检索知识库并生成回答。上线第一周效果不错准确率能看。但第二周运营提了个需求让Agent每天自动把前一天的工单导出成Excel报表按类型统计、标出超时项。我当时第一反应是——加个Tool不就行了于是我给Agent加了一个“导出工单报表”的函数接入工单API。结果呢它确实能调用但每次调用前我都要在系统Prompt里写一大段“报表生成规则”哪些字段要保留、超时怎么算、文件名怎么命名、输出路径在哪。改一次规则Prompt就得跟着改一次。更要命的是这个过程完全依赖写Prompt的人去“替Agent记住”所有步骤一旦换人维护这段Prompt基本没人敢动。类似的场景你应该也遇到过Agent能写代码但不会按你们项目的代码规范走Agent会调API但不知道要带哪个鉴权头Agent能操作文件但不知道临时文件该放哪。这些都不是模型能力的问题而是“操作知识”没有沉淀下来。Skills解决的正是这个问题把这类“如何做一件具体事情”的知识从Prompt里、从人的脑子里、从零散代码中抽出来变成一个独立、可复用、可维护的单元。1.2 Skills带来的三个关键转变从这个案例里我体会最深的是三个转变。第一从“每次现写”到“即插即用”。以前每次给Agent加一个新能力要么在Prompt里写一大段说明要么写死在代码里。技能化之后一份技能说明写好任何Agent在任何场景下都能调用——只要它会加载Markdown或YAML格式的说明文件。Agent理解的是“技能说明”我们维护的也是“技能说明”两边对齐了改动再也不需要翻山越岭找代码。第二从“藏在代码里”到“放在明面上”。传统做法里业务规则往往藏在函数注释里、写在Prompt深处。技能化以后规则变成一个可阅读的文档业务专家也能看懂、能提修改意见、甚至能自己改描述。这个价值在做企业级落地时特别明显——技术团队终于不用再当“翻译官”了。第三从“模型死记硬背”到“按需加载”。在长Prompt时代我们倾向于把所有规则一股脑塞进上下文结果模型越到后面越“失焦”。Skill的做法是默认不加载等Agent判断“当前任务需要XX技能”时再读取对应文件。这样上下文更干净模型的注意力也能集中在当前任务上。实测下来遇到技能边界清晰的场景输出稳定性的提升是非常可感知的。1.3 Skills与Tools、Workflow、Plugins的区别很多人刚接触时都会把Skills和这几个概念搞混我一开始也晕。这里用一张表说清楚概念粒度核心作用典型例子和Skills的区别Prompt无固定粒度约束模型行为角色设定、语气要求全局生效无法按任务动态选择Tool / Function函数级把模型和外部系统连接查天气、发邮件只解决“能调什么”不解释“怎么用”Skill任务级把“完成某类任务的方法”整体打包周报整理、代码审查、表格清洗包含工具调用说明也包含操作步骤和质量要求Workflow / Plugin流程级编排多步骤的固定流程自动发版、客服机器人更重、更强调流程编排Skill更轻量、更偏知识表达我个人的判断是Tool解决的是“模型能碰到什么”Skill解决的是“模型知道该怎么干”。Workflow解决的是“多个步骤怎么串”而Skill可以被Workflow复用也可以被Agent在单轮任务里独立使用。四者不是替代关系而是不同层级的表达方式。实际项目里通常是Tool作为底座、Skill作为方法、Workflow作为编排三层叠加用。2. 技能库的设计思路与格式拆解搞清楚了Skills是什么接下来就是最核心的一个技能文件到底应该长什么样我最终用的是类Anthropic Agent Skills的规范但实际上这套格式思想是可以平移到任何Agent SDK上的——核心就两点一份给模型看的说明书SKILL.md外加一批给说明书配套的资源文件脚本、模板、参考数据。2.1 目录结构与最小可用格式一个最小的技能包只需要一个目录加一个SKILL.md文件skills/ └── weekly-report/ ├── SKILL.md └── reference/ └── template.xlsxSKILL.md本身就是Markdown格式用自然语言描述“这个技能是干什么的、什么情况下用、怎么一步步做”。模型读到这份文件后会把里面的步骤当成执行指南。这一点是Skills和传统Prompt模板最大的差异它不是一段“底线要求”而是一份“操作手册”。就我的经验SKILL.md里应该包含这几块内容技能名称与简述适用场景什么时候该用输入要求需要哪些信息和材料执行步骤核心要具体到操作输出规范交付物的格式和质量要求注意事项与边界哪些不能做、哪些情况要停下来问人依赖和引用文件脚本、模板、参考文档的路径。下面我拆开讲每一块的写法以及我踩过的一些坑。2.2 元信息区name、description、dependencies怎么写很多教程会推荐在SKILL.md开头放一个YAML frontmatter类似这样--- name: weekly_report description: 将零散的周报材料整理成结构化周报适用于周报汇总、进度同步等场景。当用户需要从即时通讯、邮件、文档中汇总团队成员的工作内容时使用。 dependencies: - python3 - openpyxl ---这里有一个非常容易犯的错description写得太泛。比如写“帮助用户整理周报”模型没法判断“什么时候该用这个技能”结果就是频繁误调用。我后来养成的习惯是description里必须写清三件事一是这个技能完成什么任务二是适合什么输入材料三是“当用户……时使用”这种触发条件句式。实测下来触发条件写得越明确Agent选择的准确率越高。dependencies也是一样别只写个“python3”。要具体到版本和库最好是能直接拿去建虚拟环境的那种。否则换个环境跑Agent按技能说明执行到一半发现openpyxl没装就会卡在那里瞎猜。我一般会在SKILL.md里把依赖拆成两部分硬依赖没有就跑不了和软依赖缺少时可以用替代方案分别写清楚。2.3 技能正文把“隐性的操作知识”变成“显性的步骤”技能正文是整个文件的心脏。很多教程给出的示例都太简单比如“1. 读取文件 2. 整理数据 3. 输出报告”这种写法模型看了等于没看——它不知道读哪个文件、怎么整理、输出成什么样。真正有用的写法是要把操作细节展开到“换一个工程师也能照着执行”的程度。拿周报整理来举例我早期的写法是读取本周工作记录文件。按成员、按项目归类工作内容。生成周报Markdown。后来改成读取输入目录下所有 Markdown 或 Excel 格式的工作记录。按文件名前缀识别成员按“项目标签”字段归类任务。对每条任务保留完成状态进行中/已完成/阻塞完成度低于80%的在周报中标注为风险项。输出统一格式的周报 Markdown标题为“第X周工作周报”结构为本周完成、下周计划、风险与阻塞。如果输入中存在无法归类的条目在周报末尾单独列出不要自动丢弃。差别在哪第一版只有“做什么”第二版写清楚了“怎么判断”“什么情况下怎么办”“边界在哪”。模型是概率生成它不会自动脑补你们团队的命名规则和状态口径。你给的颗粒度越细它的执行就越稳定。这是一个我在项目里反复验证过的结论技能文件的详细程度直接决定Agent执行质量的稳定性。3. 从0到1搭建一个实用技能“批量整理周报”完整过程概念讲完我用一个完整案例带你把流程走一遍。这个案例我实际在团队里跑过背景是每周五运营要手动把几十个团队成员的周报汇总、归类、标风险、出周报耗时一小时以上。我们想把这个活交给Agent但Agent一开始根本不会干。3.1 先想清楚边界什么该做成技能什么不该很多人一上来就动手写技能文件写完发现没用。问题往往出在需求边界没想清楚。我在做周报技能前先列了一个判断清单这个任务是高频的吗——每周一次是。流程是稳定可描述的吗——汇总步骤固定归类规则固定是。输入输出是明确的吗——输入是各位成员的周报文本输出是统一格式的汇总周报是。允许的容错空间大吗——允许少量整理遗漏但不能乱编进度需要边界。四条都满足才值得做成Skill。反过来如果任务是临时性的、流程每天都在变、输出没有统一标准那就不适合做技能硬做只会维护成本爆炸。我见过有人把“回复客户投诉”这种高度依赖临场判断的任务硬做成Skill结果每次都需要人工重写步骤最后反而比不用Skill还累。3.2 编写SKILL.md一个能跑的完整示例确定要做之后我写的第一版SKILL.md长这样完整结构可以直接参考--- name: weekly_report_aggregator description: 将多个团队成员的工作记录汇总为一份结构化周报。当用户上传周报材料、要求汇总周报、或要求生成本周进度报告时使用。 dependencies: - python3 3.10 - pandas 2.0 --- # Weekly Report Aggregator ## 适用场景 - 输入包含多位成员的周报材料Markdown或CSV或一个包含多个材料的目录。 - 输出一份按成员和项目维度整理的周报 Markdown 文件。 ## 输入要求 1. 每个成员材料需包含成员姓名、日期、任务描述、任务状态进行中/已完成/阻塞。 2. 材料格式Markdown 表格或 CSV 表头 name,date,task,status,project。 ## 执行步骤 1. 读取输入目录下所有 .md 和 .csv 文件识别成员姓名从文件尾注的“成员XXX”或 CSV 的 name 字段读取。 2. 对所有任务按项目字段分桶没有项目字段的归入“未归类”。 3. 统计每个项目下的任务数量、已完成数量阻塞项单独标记。 4. 生成周报格式要求 - 标题第X周工作周报 - 章节本周完成 / 本周进行中 / 风险与阻塞 / 下周计划如材料中有 5. 生成周报后用 scripts/render.py 渲染为最终 markdown输出到当前目录 weekly_report_YYYY-MM-DD.md。 ## 输出规范 - 不允许编造材料中不存在的任务状态。 - 对于缺失成员姓名的条目保留原始文本并在周报末尾标注“来源不明”。 - 材料中有明确冲突时如同一任务状态在不同材料中不一致在该条目标注“状态冲突”不要自动取其一。 ## 注意事项 - 本技能只做汇总和格式整理不做任务优先级判断。 - 输入材料超过20个文件时先询问用户是否需要分批处理。这份文件的每个字段都是我在实际试探后打磨过的。比如“阻塞项单独标记”第一期没有这句Agent就会把阻塞项混在“本周完成”里那周的风险提示基本等于没有用。加一句明确规范之后输出立刻变了。3.3 配套脚本与资源文件怎么组织SKILL.md是给模型看的但执行时往往还是需要真实代码来兜底。比如上面提到的render.py就是个十几行的小脚本负责把中间数据转成格式统一的Markdown。这样设计的目的很清楚把通用格式的活交给脚本把需要判断的活留给Agent。两者各有分工脚本保证格式稳定Agent负责识别和判断这样可以降低对模型的过度依赖执行结果也更可控。技能包里的文件组织我一般是按作用分目录weekly-report/ ├── SKILL.md ├── scripts/ │ └── render.py ├── reference/ │ ├── 项目清单.csv │ └── 周报模板.md └── assets/ └── example_output.mdscripts放可执行代码reference放执行时要用到的参考数据assets放给Agent“学习”的示例输出。示例输出非常重要它相当于给模型一个“标准答案”的锚点。Agent在不确定的时候会先模仿示例的结构再发挥输出质量会明显更稳定。这也是我强烈建议每个技能包里都放一个example_output.md的原因。4. 实操中的Schema选择与加载机制技能文件的格式和内容定了接下来要考虑的是另一个层面的问题整个技能库怎么被Agent发现和使用。这块搞不清楚再好的技能文件也只是躺在仓库里落灰。4.1 技能表达格式Markdown、YAML、JSON怎么选先说最基础的选择用Markdown、YAML还是JSON来表达技能。我的结论是表示元信息用YAML步骤正文用Markdown结构化数据用JSON。理由很简单Markdown最适合让LLM读懂——它本来就是模型训练数据里高频出现的格式YAML适合解析元信息JSON适合给程序消费。这三者的分工可以列一张表格式适合内容优点缺点我的用法Markdown步骤、说明、注意事项模型易读可读性好程序解析困难SKILL.md主体YAML元信息、参数声明解析方便可生成schema大段步骤写成YAML非常难受frontmatterJSON结构化配置、工具声明程序处理最可靠人读体验差不适合写长文内部配置和工具描述一个常见的反面教材是把整个SKILL.md写成一份超大的YAML每步步骤都塞进YAML的list里。结果模型读起来费劲不说人维护也痛苦。YAML的缩进地狱会成为日常灾难。别贪图“全能格式”Markdown就是技能正文最好的载体。4.2 后端加载从目录扫描到语义检索技能文件写好了Agent怎么找到它最简单的实现是从固定目录扫描把当前目录下的所有技能名和description拿去做关键词匹配。这种方法在技能库小于10个时完全够用。但技能库一旦超过20个关键词匹配就开始失灵用户说“帮我汇总下这周大家干了啥”不一定会触发“weekly_report”这个英文技能名。更稳的方案是给技能描述加一个向量化检索层。把每个技能的description预编码成向量Agent输入先做语义向量再用余弦相似度选出top-k个候选技能加载。这一步我用过本地Embedding模型也用过在线API效果差异不大关键是description写得够清晰。另外不管用什么检索方式我都建议在技能的description里埋一些关键词的等价说法比如“周报”“汇总”“进度报告”这样关键词和语义两条路都能命中。4.3 上下文管理不要把整个技能库塞进Prompt这是新手最容易犯的错把技能库里的所有SKILL.md拼在一起一次性塞进系统Prompt。刚开始技能少还不觉得技能加到二三十个以后系统Prompt会膨胀到几万字Agent注意力崩得一塌糊涂——每个技能都“好像相关”结果它一个都没用好。我的做法是分两层第一层只把技能的“技能目录”name description 触发条件作为候选清单总量控制在几千token内第二层Agent判断任务后只加载匹配到的单个技能的完整SKILL.md以及它依赖的reference数据。这样上下文占用小而且“当前任务该看哪份说明书”这个判断本身也是很轻量的。实测在20技能规模下这种两层结构的加载正确率能稳定在九成以上上下文消耗却只有全量方案的三分之一左右。5. 常见问题与避坑实录最后把我踩过的坑、以及在社区交流里看到的高频问题集中写一下很多问题看起来小但影响很大。5.1 技能描述写得太泛Agent乱调用这是排第一的高频问题。描述里只写“整理周报”四个字Agent在用户说“帮我写一下本周工作总结”的时候也会加载它然后套周报模板输出一份完全不是用户要的东西。解决方法很简单描述里必须写清触发条件和排除条件。例如“适用于多个成员的周报合并不适用于单个成员的简要总结”。在description里增加“不适用于”这一句实测能把误调用率降一半以上。把这段加到我的所有技能里之后效果立竿见影。5.2 技能之间互相冲突加载了A却该用B技能多了以后会出现两个技能都声称“处理CSV”或者“整理表格”。如果不做约束加载哪个全看检索排名结果经常加载错。我后来给技能定义加了一个优先级字段同时限定同一个任务最多激活两个技能当两个技能都匹配时Agent必须输出一个选择理由再由中间层规则裁决。这个方法虽然粗暴但在工程上很有效。另外公共能力尽量沉淀到reference或脚本里不要重复写进多个技能技能之间通过引用而不是复制来共享逻辑也能避免大量冲突。5.3 缺乏评估技能改坏了都不知道给Agent加技能和给传统系统加功能不一样它没有单元测试可以一步到位验证“功能正常”。一开始我改完技能文件只靠几个手工示例试一下就觉得可以了结果在真实场景里翻车。后来我给自己定了一套最低限度的评估流程为每个技能准备一个测试集包含至少5个正例应该触发并执行成功的输入和3个负例不应该触发的输入。每次改动技能文件后跑一遍测试集统计触发率、执行完成率、输出格式合规率。这套流程很轻量但能防止大部分“改坏没发现”的情况。测试集本身就是宝贵资产后续新增技能时还能顺带拿来验收新旧技能之间是否有冲突。5.4 依赖环境不一致同样的技能换个机器就“失灵”技能文件里写“需要pandas”但没写版本脚本用了一个新接口在本地跑没问题扔到服务器上就报错。这类问题在技能化场景里特别普遍因为技能要被不同的Agent在不同环境里加载。建议在技能包里带一个requirements.txt能锁版本就锁版本。同时SKILL.md里的依赖声明要和requirements.txt对应最好在加载流程里加一步自动检查缺依赖时先提示安装而不是直接开跑。这个自动检查脚本我写了不到50行但省下来的排查时间非常多。到这里关于agent-skills怎么设计、怎么写、怎么落地我把我能想到的细节都讲透了。最后再分享一个我个人的小体会技能化改造这件事看起来是在改Agent的能力实际上是在改团队的协作方式。一份Skill写得好不好不只看它执行多稳还看它好不好养——业务能看懂工程能维护Agent能照做这三者同时满足才算一份合格的技能。我在实际项目里最深的感受是别一上来就追求技能数量先把一两个核心场景打磨透让团队看到效果再逐步铺开。技能库不是越大越好而是越“有边界”越好。你现在从手头最痛的那个高频任务开始做第一个技能比研究一百份最佳实践都管用。