
最近大半年我一直在折腾企业内部的一个智能体项目最开始用的时候觉得“能调模型、能跑通流程”就完事了但等到真要把十几个任务都交给 Agent 去处理时问题一个接一个冒出来同一个任务昨天回答一个风格今天回答另一个风格同一个工具换个场景就忘了该怎么用想让模型按公司规范输出只能把大段大段的指令塞进 System Prompt塞到最后上下文都快装不下了。后来接触到 agent-skills 这个概念才意识到我之前缺的不是“更强的模型”而是一套把能力外置、按需加载的技能体系。这篇文章就把我这段时间从理解到实战的完整过程整理出来包括技能文件的内部机制、我踩过的坑、一个完整技能的构建过程以及什么情况下该用技能、什么情况下不该用。如果你也在搞 Agent 应用或者准备把 Agent 从“能跑 demo”推向“能扛业务”这篇内容应该能帮你少走不少弯路。1. 为什么需要 agent-skills从一次失控的项目里学到的教训先说一个我真实经历的场景。当时我在做一个内部知识问答 Agent功能很简单根据公司文档回答员工问题。一开始 Prompt 只有几行字模型回答得还挺像回事。但业务方很快提了新需求回答要附带文档来源、要区分“政策类问题”和“操作类问题”、要按不同格式输出、要识别敏感信息并拒绝回答……于是 System Prompt 一路从 300 字涨到 3000 字再涨到 6000 字。结果就是模型在长上下文中越来越“偏科”——有时过度关注后面的指令而忽略前面的要求有时为了满足格式反而答非所问。最离谱的一次它把一个月前在示例里出现过的错误答案原封不动地输出了出来。这个经历让我意识到一个关键问题大模型本身不擅长“一心多用”你塞给它的规则越多它在具体任务上的表现就越不稳定。而 agent-skills 的思路正好反着来——把每一个任务对应的知识、流程、工具说明拆成独立的“技能文件”Agent 在运行时先判断当前任务需要哪项技能再把对应技能加载进上下文。这样一来模型每次面对的都是精确匹配的指令集而不是一锅乱炖。1.1 没有技能体系时的“需求膨胀”陷阱我见过不少团队在做 Agent 时都陷入同一个循环第一阶段Prompt 只有几行效果惊艳。第二阶段加需求 Prompt 翻倍效果开始不稳定。第三阶段继续加需求模型开始“顾此失彼”于是再调 Prompt、再加示例陷入死循环。这背后的本质是上下文窗口是有限的但业务需求是无限的。你不可能靠“把所有规则都写进 Prompt”来应对所有场景。哪怕上下文窗口扩到 20 万 token模型的注意力也是有限的指令越长关键指令的权重反而被稀释。我后来做过一个对比实验同样一个格式化输出任务单独下发指令时的准确率是 94%混在 5000 字长 Prompt 里时只剩 71%。这个差距不是模型变笨了而是注意力被分散了。1.2 agent-skills 的本质把“能力”从“指令”中解耦先给一个最小定义agent-skills 是一组结构化的指令和资源文件它们描述了“如何完成某一类任务”。每个技能通常包含一个主文件定义触发条件和执行步骤 若干辅助资源示例、模板、子流程、参考数据。Agent 在收到用户请求后会通过一套匹配机制判断当前任务需要哪个技能然后只把那个技能的上下文注入到模型中。打个比方没有 skills 的 Agent 像一个应聘者简历上写着“我会做 100 件事”但面试官问细节时只能泛泛而谈有 skills 的 Agent 像一个带着工具箱的工程师你告诉他“拧这个螺丝”他不会先背一遍《机械工程手册》而是直接抽出对应的螺丝刀开始干活。这个“按需取用”的设计才是 agent-skills 的精髓所在。1.3 它和 plugins、tools、memory 的边界在接触 agent-skills 之前我先把周边概念理了一遍避免混淆概念核心作用与 agent-skills 的关系Tools / Function Calling让模型调用外部函数获取数据或执行操作技能里通常包含如何调用工具的描述甚至技能本身就是工具的“使用说明书”Plugins可插拔的功能模块插件偏“软件架构”技能偏“模型指令”但实践中两者经常结合Few-shot Examples提供输入输出示例指导模型技能内部可以包含少量示例但示例是技能的一部分不是散落在 Prompt 里Memory保存跨会话的用户偏好和历史信息技能解决“怎么做”记忆解决“记住什么”两者互补说白了tools 是“手”skills 是“操作手册”。你的 Agent 可以有一百只手工具但如果不知道什么时候用哪只手、用的时候该按什么步骤来手再多也是摆设。技能体系解决的正是这个“调度和运用”的问题。2. 技能文件的内部结构SKILL.md 到底怎么写才有效在动手设计第一个技能之前我先拆解了技能文件的工作方式。当时我研究的是 Claude 的 Agent Skills 设计规范里提到的一种做法——用 Markdown 文件描述技能辅助参考文档铺开细节。可能看到这里有的人会说“这不就是个文档吗”——对形式上是文档但它的“工作方式”决定了它和普通文档完全是两回事。一个技能文件不是给人看的而是给模型“照着执行”的所以它的结构、措辞、颗粒度都要围绕“模型如何解析和执行”来设计。2.1 技能文件的最小骨架一个标准的技能文件通常包含以下部分技能名称和一句话简介这部分用于让 Agent 快速判断“这个技能是否匹配当前任务”。触发条件什么场景下使用该技能什么场景下绝不能使用。核心执行步骤用编号列表给出主流程前后顺序明确。关键规则与边界必须遵守的约束比如“不要编造数据”“必须引用来源”等。参考文件索引指向辅助文件例如模板、示例、数据集。用通俗的话讲一个技能文件就是一份“给模型看的 Standard Operating Procedure标准作业程序”。它不要求文采只要求语义精确、无歧义、可执行。2.2 技能描述是“触发开关”不是“任务简介”我最初犯的一个错误是把技能描述写成了“这个技能用于完成文本分类任务”。这种描述太模糊了Agent 根本不知道什么时候该触发它。后来我把描述改成了## 技能描述 上传 CSV 文件后需要按内部规则对每一行内容做安全分类。 当用户上传包含批量内容的 CSV 文件并要求“检查”“分类”“过滤”时使用。 不适合单个文本的实时分类、非 CSV 格式的批量处理。这里的关键变动是把“功能描述”改成了“条件描述”——明确什么时候触发、什么时候不触发。模型在判断是否启用技能时本质在做一次意图匹配。你的描述越接近用户可能的表达方式比如“检查一下这份 CSV”匹配的准确率就越高。2.3 技能描述与辅助文件的“分工”主技能文件的篇幅是有限的。如果所有细节都堆在主文件里上下文压力又回来了。正确做法是主文件只放“决策和流程”辅助文件放“细节和参考”。比如我做一个“数据分析报告”技能时主文件SKILL.md里只写识别输入数据、做描述性统计、选图表类型、生成报告结构。辅助文件report_template.md里放报告的具体结构和示例段落。辅助文件chart_guidelines.md里放什么时候用折线图、什么时候用柱状图的选择逻辑。这样主文件保持精简Agent 按需读取辅助文件即可。实测下来这种分层的设计比“长文档一锅端”的加载效率高很多而且后续维护也轻松——改模板不用动主流程。3. 避坑实录我设计技能时反复踩过的五个真实问题技能文件看起来简单真正用起来全是细节。这一节把我踩过的一些典型坑梳理一下基本都来自实际项目不是理论推演。3.1 坑一把技能描述写成了“需求文档”我第一次设计技能时写出来的描述是这样的这个技能用于自动整理会议纪要要求包括会议主题、参会人、时间、结论、待办事项并按照公司格式输出...看起来没问题对吧问题出在“识别”上模型接到用户输入“帮我整理一下今天下午和周会的纪要”它需要自己判断要不要用这个技能。如果技能描述写得像任务说明书模型的匹配依据就只剩关键词“整理纪要”这一层很容易误触发或者漏触发。后来我改成当用户提供会议录音转写文本、会议笔记草稿并要求“整理纪要”“提取待办”“生成会议结论”时使用。 不适用用户只问“上次会议讲了什么”这类信息检索场景。改动核心是加入“触发条件”和“不适用场景”。一个技能描述里如果没有“不适用场景”模型就经常会“强行套用”。这个问题几乎每个技能设计者都会遇到值得反复测试。3.2 坑二技能内部塞入太多步骤模型执行时“迷路”技能执行步骤不是越多越细越好。我试过一个技能里写了 15 个步骤从“加载数据”到“检查字段缺失”到“处理异常值”到“生成图表”到“写结论”……模型一次推理只能处理 5-8 个核心决策点。超过这个范围它就会“顾此失彼”比如做完前两步就开始输出结论中间步骤被跳过。我的经验是主流程步骤控制在 3-5 步每步只描述一个明确动作。复杂流程拆成多个子技能或者用“读取子文件获取详细规则”的方式分层处理。举个例子如果任务是“数据清洗 分析 出报告”我不会把它放进一个技能而是拆成“数据清洗技能”和“分析报告技能”。两段式处理模型每次只聚焦一件事出错率明显下降。3.3 坑三没有写“失败条件”和“降级方案”这个坑很隐蔽。我最初设计的技能文件全都是“正向指令”做什么、怎么做。但模型在实际执行时经常遇到“条件不满足”的情况——用户给的数据格式不对、缺少必要字段、输入内容跑出了技能边界。没有失败条件时模型会硬着头皮继续执行产出很多胡说八道的结果。后来我在每个技能里都加了一节## 失败处理 - 如果输入数据缺少必需字段输出“缺少字段xxx”不进行后续分析。 - 如果用户请求超出本技能范围不调用工具直接回复“该请求需要人工处理”。 - 如果生成内容涉及未经验证的信息明确标注“该结论未经证实”。加完失败处理之后Agent 的“答非所问率”明显降低了。这个细节很多教程不会提但实际使用中特别重要。技能文件不仅要告诉模型“怎么做对”还要告诉它“怎么做错”以及“怎么做不下去时怎么办”。3.4 坑四技能之间互相“打架”当技能数量超过 10 个之后一个新的问题出现了多个技能的触发条件重叠模型经常选错。最典型的是“文本摘要技能”和“会议纪要技能”——用户说“帮我总结一下这个会议记录”两个技能都能执行但输出格式完全不一样模型随机选一个结果风格不稳定。解决办法是“触发条件互斥设计”。我给每个技能加了一节“优先关系”## 优先级说明 本技能与“文本摘要技能”的触发条件存在重叠。 当输入内容包含会议时间、参会人、待办事项等结构化信息时优先使用本技能。 纯散文类文本无会议结构请使用“文本摘要技能”。调整之后技能冲突率从 40% 降到 8% 左右。这种“技能之间的边界说明”非常重要但也是新手最容易忽略的。3.5 坑五技能迭代没有版本管理技能文件本质上是一段“活的代码”。你改了技能描述但没改技能文件名过了一周之后你可能根本记不清线上跑的是哪个版本。我第一次改技能时直接覆盖了原文件结果效果还不如旧版想回滚已经来不及了。现在我给每个技能文件都加了一个简单的版本头--- name: meeting_minutes_skill version: 2.3 last_updated: 2025-11-20 changelog: 修复触发条件模糊问题补充失败处理逻辑 ---同时在技能目录里保留历史版本只通过 symlink 或配置文件指向当前版本。这套做法借鉴了代码管理的思路简单但非常管用。4. 完整实操从零构建一个“会议纪要整理”技能理论讲再多不如完整走一遍流程。下面我以“会议纪要整理”技能为例把从设计到测试的全过程拆开来讲。这个技能本身很简单但麻雀虽小五脏俱全足以展示完整的构建思路。4.1 第一步定义场景边界设计技能之前先回答三个问题输入是什么答会议录音转写的文本可能带有多位发言人。输出是什么答结构化会议纪要主题、参会人、讨论要点、结论、待办事项。不做的事情是什么答不做实时语音转写不自动发送邮件不进行会议安排。这三个问题看着简单但回答清楚之后技能的所有细节就有了锚点。4.2 第二步编写技能主文件基于上面的边界我写了一个主文件SKILL.md结构如下--- name: meeting_minutes version: 1.0 description: 将会议录音转写文本整理为结构化会议纪要 --- ## 触发条件 - 用户提供会议录音转写文本并要求“整理纪要”“生成会议记录”“提取待办”时使用。 - 输入内容包含明显的会议对话结构多轮发言/多人对话/讨论。 ## 不适用场景 - 用户仅询问某次会议的结论不提供原始文本。 - 输入内容是单一发言人的演讲或文章非会议讨论文本。 ## 执行步骤 1. 阅读用户提供的完整转写文本提取会议主题、时间、参会人若文本中无明确信息标注“未提取到”。 2. 将讨论内容按“话题块”分组。每个话题块提炼为核心观点 结论 争议点如有。 3. 汇总所有待办事项格式为“负责人 行动项 截止时间如提及”。 4. 按模板组织输出模板见 reference/template.md。 5. 输出前检查确保所有结论均有文本依据禁止编造未出现的观点。 ## 失败处理 - 若输入文本明显是正常对话而非会议记录输出“未检测到会议讨论结构请确认输入是否正确”。 - 若无法提取任何待办事项在待办部分填“无”不强行编造。这个文件的关键设计是什么是第 5 步的“输出前检查”——让模型在生成最终答案前有一个独立的“自查动作”。“步骤 自查”这个组合在几乎所有任务型技能上都有效。但注意写入主文件的步骤数很少每个步骤背后其实可以配套子文件展开更细的规则避免主文件过长导致模型迷失。4.3 第三步写辅助模板然后我准备了一个模板文件reference/template.md规定了输出的具体格式# 会议纪要 - 会议主题xxx - 时间xxxx-xx-xx - 参会人A、B、C ## 讨论要点 1. 【话题一】 - 观点xxx - 结论xxx - 争议xxx 2. 【话题二】 ## 待办事项 | 负责人 | 行动项 | 截止时间 | | --- | --- | --- | | A | xxx | xxx |模板不要求多花哨重点是把“输出结构”固定下来避免模型自由发挥导致每次格式都不一样。这里我可以补一句经验模板文件最好也用 Markdown别用 PDF 或图片——模型读文本的能力远远强于读图片而且文本可被精确引用和局部修改。4.4 第四步构建测试集并验证技能写完之后最关键的一步是验证。我准备了三组测试数据正常会议转写文本多人讨论、有结论、有待办。边缘情况转写文本中未提及参会人只有讨论内容。反例一段文章不是会议记录看技能会不会误触发。测试方法分别用“带技能”和“不带技能”跑同一组输入对比输出质量。我记录了几个维度格式是否符合模板、内容是否缺失、有没有编造信息、触发是否正确。实测结果里有一个典型的失败案例测试第 2 组时模型在“参会人”一栏填了“参会人未提供”但随后在“待办事项”里出现了“负责人系统生成”这种编造内容。原因是模板里没有说明“负责人不明确时怎么处理”。我在失败处理里补了一条“待办事项无法对应具体负责人时写‘待确认’。”重新测试后这个问题消失了。这个环节很多人会跳过但它恰恰是整个技能设计里性价比最高的一步——你花 20 分钟做的测试能省下上线后一星期的 debug 时间。4.5 第五步技能性能评估验证不是一次性的。我把技能丢到一个简单的“技能评估集”里持续跟踪几条指标评估维度说明通过标准触发准确率该触发时触发、不该触发时不触发不低于 90%格式命中率输出结构是否符合模板100% 严格匹配信息准确率是否有编造的结论或待办不发生编造边界处理率输入不完整时是否按失败处理执行不低于 85%如果某项指标下滑我会回头查是不是技能描述被改坏了或者新技能和旧技能的边界发生了重叠。这套“持续评估”的思路把技能维护从“感觉”变成了“数据”方向一旦偏了能第一时间发现。5. 进阶用法技能的组合、动态加载与设计边界基础技能做熟之后我开始研究更复杂的用法一个任务需要多个技能协作怎么办技能之间的依赖关系怎么处理不同角色的 Agent 需要不同的技能库如何做隔离这些问题的答案直接决定了技能体系能否规模化扩张。5.1 技能列表太长时的选择器设计技能数量一旦超过二三十个让模型从全部技能里“大海捞针”地选一个准确率会明显下降而且越靠后的技能越容易被忽略。解决方案是分两层第一层粗粒度的“技能分类器”把技能分为“内容生成类”“数据分析类”“信息检索类”“流程执行类”等几个大类。第二层在选定分类内再做细粒度技能匹配。这个“先分桶、再精排”的思路和大规模的检索排序系统是一样的。我实测过直接 30 个技能里硬选准确率约 76%分两层之后准确率恢复到 92% 左右提升幅度非常可观。5.2 技能之间的依赖与编排有些复杂任务需要多个技能串行执行这时候需要在技能文件里显式声明“前置技能”和“后置技能”。例如“会议纪要技能”的输出可以作为“待办管理技能”的输入。“数据分析技能”依赖“数据清洗技能”先行处理。我见过的做法是在技能文件头部的元信息里加一个字段requires: - data_cleaning_skill provides: - cleaned_dataset然后在 Agent 的编排逻辑里做一个简单的依赖检查如果用户的任务需要“数据分析”但原始数据尚未清洗则先触发“数据清洗技能”。这种硬编码的依赖关系虽然不够“智能”但在工程上是稳定可控的比让模型自由决定顺序靠谱得多。5.3 什么时候不该用 agent-skills最后说说边界的问题。技能体系并不是万能的我总结了三种不适合硬套技能的场景一次性、高度定制化的任务如果任务没有重复性写成技能反而浪费维护成本。需要大量实时外部状态感知的任务技能本质上是“静态指令”如果任务高度依赖某个系统的最新状态技能的静态描述很难跟上变化。低延迟场景每次加载技能都意味着额外的上下文输入会增加首 token 延迟。如果是实时客服这种对延迟极其敏感的场景技能加载的成本需要认真评估。一个朴素但有用的判断标准是如果同一类任务你没有经历过至少 3 次先不要急着做技能如果已经经历过 10 次且每次处理方式都不一致那大概率值得做。技能的价值来自复用没有复用就没有收益。技能体系这东西上手容易做精很难。我在这段时间里最大的体会是设计技能最核心的能力不是“写文档”而是“拆问题”——把模糊的任务拆成清晰的边界、把复杂的流程拆成可执行的单步动作、把潜在的异常拆成可预期的失败处理分支。这套能力一旦练出来不管底层模型怎么升级你的 Agent 应用都能稳得住。如果这篇文章里的某些实践对你有点启发可以从一个最小的技能开始试试不需要很多一个就好然后把它用到一个真实的重复任务里对比一下前后的效果和稳定性。体验过那个落差之后你就知道自己该不该继续往下做了。