ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

如何写出好用的Agent Skill:SKILL.md结构设计与触发准确率优化实战

如何写出好用的Agent Skill:SKILL.md结构设计与触发准确率优化实战 1. 从一次翻车说起为什么“能跑”的 Skill 和“好用”的 Skill 是两回事去年冬天我接手了一个内部 Agent 平台的 Skill 治理工作当时平台里已经沉淀了 200 多个 Skill覆盖代码审查、文档生成、数据清洗、会议纪要、竞品分析这些场景。按理说数量不少了但实际调用数据非常难看Top 20 的 Skill 吃掉了 85% 的调用量剩下 180 多个基本处于“写了没人用”的状态。更尴尬的是有几个 Skill 明明功能很刚需但用户试了一次就再也不碰了。我拉了十几个失败案例逐个复盘发现问题几乎都不在模型能力上而是出在 Skill 本身的写法上。有的 SKILL.md 写得像产品说明书模型读完不知道什么时候该触发有的把参数塞了十几个模型每次都要猜该填哪个还有的 Skill 描述里全是“智能”“高效”“一键”这种词模型根本抓不到可执行的语义锚点。那一刻我才真正意识到写 Skill 不是写文档是在给模型设计一套它能在正确时机、用正确方式调用的“操作契约”。这篇内容就是把这半年踩过的坑、改过的版本、跑出来的数据整理出来聊聊怎么写出一个真正好用的 Skill。不管你是刚接触 Agent 开发的新手还是已经在维护 Skill 库的老手下面这些经验应该都能直接拿去用。核心关键词就几个LLM、Agent、Skill、skill-creator、SKILL.md我会围绕它们把“好 Skill”的判定标准、结构设计、参数取舍、测试方法全部拆开讲。2. 先搞清楚 Skill 到底是什么它不是函数也不是提示词2.1 Skill 在 Agent 体系里的真实位置很多人第一次接触 Skill 会把它理解成“一个函数”或者“一段提示词模板”这两种理解都不太对。函数是确定性输入输出提示词是纯文本引导而 Skill 是介于两者之间的东西它是一份带有元信息、触发条件、执行步骤和输出约束的能力描述由模型在运行时决定是否调用、如何调用。你可以把它想象成给一个新员工写的“岗位操作手册”。手册里要写清楚这个岗位什么时候介入触发条件、需要哪些输入参数、按什么流程做步骤、做完交付什么输出格式、什么情况下要停下来问人边界与异常。写得好新员工上手就能干活写得烂他要么不知道该干什么要么干到一半卡住。在 Agent 架构里Skill 通常挂在工具调用层之上、编排层之下。编排层负责决定“现在要不要用某个能力”Skill 负责回答“这个能力具体怎么执行”。所以 Skill 的质量直接决定了 Agent 的触发准确率和执行成功率这两个核心指标。2.2 好 Skill 的三个硬指标我后来给团队定了一个简单的验收标准一个 Skill 要上线必须同时满足三条触发准确率在应该调用它的场景里模型能稳定识别并调用在不该调用的场景里不误触发。我们内部要求触发准确率不低于 90%。执行成功率一旦触发模型能按 Skill 描述完成整个流程不需要人工中途纠偏。这个指标我们卡在 85%。输出可用率产出的结果能被下游直接消费不需要二次加工。这个最容易被忽略但恰恰是用户流失的主因。这三条听起来简单但每一条背后都对应着 SKILL.md 里具体的写法约束。下面逐个拆。2.3 为什么“描述越详细越好”是个陷阱新手最容易犯的错是把 SKILL.md 写成一篇长文恨不得把背景、原理、历史沿革全塞进去。我见过一个 3000 字的 Skill 描述模型读完反而不知道该干嘛。原因是模型的注意力是有限的冗余信息会稀释关键信号的权重。正确的做法是用最少的字把触发条件、输入、步骤、输出、边界这五件事说清楚。其他内容要么删掉要么挪到附属文档里。我一般要求单个 Skill 的 SKILL.md 正文控制在 800 字以内超过就要拆。3. SKILL.md 的结构设计五个必填区块和它们的写法3.1 元信息区让模型一眼知道“我是谁、我干什么”元信息区是 SKILL.md 的开头部分通常包含 name、description、version、tags 这几个字段。这里最关键的是description因为模型在决定是否调用时最先看的就是它。我见过太多 description 写成这样“一个智能高效的数据处理工具帮助用户快速完成各种数据任务。”这种描述对模型来说等于没说因为它没有任何可匹配的语义锚点。好的 description 应该包含三个要素动作 对象 场景。比如description: 从 CSV 或 Excel 文件中提取指定列按规则清洗后输出为标准化 JSON。适用于数据导入前的格式统一场景。这样模型在遇到“帮我把这个表格整理一下”这类请求时就能通过“CSV/Excel”“清洗”“JSON”这些锚点判断是否匹配。提示description 里不要用“智能”“高效”“一键”“强大”这类形容词它们不携带任何可匹配信息只会占字数。3.2 触发条件区明确“什么时候该用我”触发条件区是很多 Skill 缺失的部分但它是提升触发准确率的关键。写法上我推荐用正向条件 负向条件的组合正向条件列出应该触发的典型场景用用户可能说的原话或近义表达。负向条件列出容易混淆但不该触发的场景明确排除。举个例子一个“代码审查 Skill”的触发条件可以这样写触发条件 - 用户提交代码片段并询问潜在问题 - 用户要求对某个函数做质量检查 - 用户提到“review”“审查”“看看有没有 bug” 不触发条件 - 用户只是要求解释代码含义应走解释类 Skill - 用户要求直接重写代码应走重构类 Skill负向条件特别重要因为 Agent 平台里 Skill 多了之后误触发是比不触发更严重的问题。误触发会浪费 token、拉长响应时间还会让用户觉得 Agent“不听话”。3.3 输入参数区参数不是越多越好参数设计是 Skill 写作里最考验功力的地方。我的经验是必填参数不超过 3 个选填参数不超过 5 个。超过这个数量模型填错的概率会急剧上升。每个参数要写清楚四件事名称、类型、是否必填、说明。说明里要包含取值示例因为模型对示例的敏感度远高于抽象描述。参数 - file_path (string, 必填): 待处理文件的路径例如 ./data/sales_2024.csv - columns (array, 必填): 需要提取的列名列表例如 [order_id, amount, date] - output_format (string, 选填): 输出格式可选 json 或 csv默认 json这里有个细节默认值一定要写出来。模型在没有明确指令时会倾向于使用默认值如果你不写它就会自己猜猜错就是一次失败调用。3.4 执行步骤区把流程拆成模型能顺序执行的原子动作执行步骤区是 Skill 的“正文”写法上要遵循一个原则每一步都是一个可独立验证的原子动作。不要写“处理数据”这种笼统描述要写“读取文件 → 校验列名是否存在 → 按列提取 → 处理缺失值 → 输出”。我通常用有序列表来组织步骤每步包含三个信息做什么、怎么做、做完的判定标准。执行步骤 1. 读取 file_path 指定的文件。若文件不存在返回错误信息并终止。 2. 校验 columns 中的每一列是否存在于文件表头。若存在缺失列列出缺失列名并终止。 3. 按 columns 提取数据。若某行存在空值用空字符串填充。 4. 按 output_format 转换格式并输出。注意第 1、2 步都带了“终止条件”这是防止模型在异常情况下继续硬跑的关键。没有终止条件的 Skill遇到异常就会产生幻觉输出这是我在实际项目里见过最多的失败模式。3.5 输出约束区定义“什么叫做完”输出约束区经常被忽略但它直接决定了输出可用率。这里要写清楚输出的格式、字段、示例以及什么算合格输出。输出约束 - 输出必须是合法 JSON顶层为数组 - 每个元素包含 order_id、amount、date 三个字段 - amount 为数字类型date 为 YYYY-MM-DD 格式字符串 - 示例[{order_id: A001, amount: 199.5, date: 2024-03-15}]有了这个约束模型在生成时就有了明确的“靶子”下游消费方也能直接按格式解析不需要再做兼容处理。4. 用 skill-creator 把写作流程标准化4.1 为什么需要 skill-creator手工写 SKILL.md 的问题在于每个人写法不一样质量参差不齐评审成本高。我们团队最多的时候一周要评审 30 多个新 Skill光看格式就要花掉大量时间。后来我们基于 skill-creator 的思路做了一套内部工具核心逻辑是用模板约束结构用校验规则卡质量用示例库提供参考。skill-creator 本质上是一个“Skill 的脚手架 检查器”它不负责替你写内容但能保证你写出来的东西结构完整、字段齐全。4.2 skill-creator 的四个核心能力我们内部版本的 skill-creator 主要做四件事模板生成根据 Skill 类型数据处理、文本生成、代码操作、外部调用生成对应的 SKILL.md 骨架五个区块预置好标题和占位说明。字段校验检查 description 是否包含动作和对象、参数是否有类型和示例、步骤是否有终止条件、输出是否有格式约束。示例注入从示例库里匹配相似 Skill把它们的写法作为参考附在草稿旁边。触发测试生成一批正负样本查询跑一遍看触发准确率是否达标。这套东西上线后新 Skill 的平均评审时间从 40 分钟降到了 12 分钟一次通过率从 35% 提到了 70%。4.3 一个最小可用的 skill-creator 校验规则如果你不想搭完整工具至少可以把下面这几条校验规则加到你的 CI 里校验项规则不通过的后果description 长度20-120 字太短无锚点太长稀释信号description 含动作词必须包含动词模型无法判断能力类型必填参数数量≤ 3模型填错概率上升参数示例每个参数必须有示例模型靠猜成功率下降步骤终止条件至少 1 处异常时产生幻觉输出输出格式必须明确下游无法直接消费这几条规则看起来简单但能挡掉 80% 的低质量 Skill。5. 触发准确率怎么提从 60% 到 92% 的实操记录5.1 一次典型的触发失败复盘我们有个“会议纪要生成 Skill”上线第一周触发准确率只有 61%。用户说“帮我整理一下刚才的讨论”它不触发用户说“把这段对话总结成纪要”它才触发。问题出在 description 写得太窄description: 将会议录音转写文本整理为结构化会议纪要“录音转写文本”这个限定词把大量场景排除了。用户手里可能是一段聊天记录、一份手打笔记、一段讨论摘要这些都不匹配。5.2 改写 description 的三步法我后来总结了一个改写 description 的三步法列出所有可能的输入形态录音转写、聊天记录、手打笔记、讨论摘要、邮件往来。抽象出共同的动作和对象动作是“整理/归纳”对象是“讨论内容”。用场景词补充边界加上“会议”“讨论”“纪要”这些场景锚点。改写后description: 将会议讨论内容录音转写、聊天记录、手打笔记等整理为结构化纪要包含议题、结论、待办三部分。改完再测触发准确率直接到了 88%。后来又补了负向条件排除“总结文章”“提炼要点”这类非会议场景最终稳定在 92%。5.3 正负样本测试集怎么建提升触发准确率不能靠感觉要靠测试集。我的做法是每个 Skill 配 20 条正样本 20 条负样本正样本应该触发的用户查询覆盖不同表达方式。负样本容易混淆但不该触发的查询特别是同领域其他 Skill 的典型查询。跑测试时看两个数召回率正样本里触发了多少和精确率触发里有多少是对的。召回率低就放宽 description精确率低就加负向条件。这两个指标要一起看只调一个必然出问题。6. 参数设计的取舍为什么我把 12 个参数砍到了 3 个6.1 参数膨胀的代价我们有个“报告生成 Skill”最初设计了 12 个参数标题、副标题、作者、日期、章节结构、数据源、图表类型、配色方案、字体、页边距、输出格式、语言。设计者的想法是“给用户最大灵活性”但实际结果是模型每次调用平均只填对 5 个参数剩下 7 个要么用默认值要么填错。更糟的是参数一多模型在生成调用时消耗的 token 也上去了响应时间从 2 秒涨到了 6 秒。用户等得不耐烦直接放弃。6.2 参数分层核心参数 配置文件我的解决方案是参数分层把高频变化的 3 个参数留在 Skill 里其余低频参数挪到一个配置文件里由 Skill 在执行时读取。参数 - topic (string, 必填): 报告主题例如 2024年Q1销售分析 - data_source (string, 必填): 数据文件路径 - output_path (string, 必填): 输出文件路径 配置文件 report_config.yaml 提供 - 章节结构、图表类型、配色、字体、页边距等这样模型只需要填 3 个参数成功率立刻上去了同时灵活性也没丢——需要改样式时改配置文件就行。6.3 参数命名的一个小技巧参数名要用领域内的通用词不要自创缩写。我见过一个 Skill 用ds表示 data_source模型十次有三次填错。改成data_source后错误率降到接近零。模型对常见词的语义理解远好于对缩写的猜测。7. 执行步骤的写法终止条件比步骤本身更重要7.1 没有终止条件的 Skill 会怎样前面提过没有终止条件的 Skill 遇到异常会产生幻觉输出。我举个真实例子一个“从数据库查询用户信息”的 Skill步骤里只写了“连接数据库 → 执行查询 → 返回结果”没写“连接失败怎么办”“查询为空怎么办”。结果有一次数据库连接超时模型没有报错而是编造了一条用户记录返回。下游系统拿着假数据跑了一整条业务流程直到人工核对才发现。这个事故之后我们强制要求所有 Skill 必须写终止条件。7.2 终止条件的三种类型我把终止条件分成三类每个 Skill 至少要覆盖前两类前置校验失败输入不合法、文件不存在、权限不足。执行中异常网络超时、外部服务返回错误、数据格式不符预期。业务规则拦截结果为空、结果超出合理范围、触发风控规则。写法上要明确“遇到什么情况 → 返回什么 → 是否终止”。比如3. 执行查询。若查询结果为空返回 未找到匹配记录 并终止不要编造数据。 4. 若查询结果超过 1000 条返回 结果过多请缩小查询范围 并终止。7.3 步骤粒度怎么把握步骤太粗模型会自由发挥步骤太细模型会机械执行、失去灵活性。我的经验是每个步骤对应一个可独立验证的动作步骤之间用明确的输入输出衔接。一个判断标准是如果某一步做完之后你能明确说“这一步成功了/失败了”那粒度就合适。如果做完之后你只能说“好像处理了一下”那就太粗了。8. 输出约束让下游能直接消费你的结果8.1 输出格式的三种选择输出格式无非三种结构化JSON/YAML、半结构化Markdown、自然语言。选择依据是下游怎么用下游是程序用 JSON字段名和类型写死。下游是人用 Markdown结构清晰即可。下游是模型用自然语言但要给出结构提示。我见过最坑的一种情况是Skill 输出 Markdown但下游程序用正则去解析。这种耦合极其脆弱Markdown 格式一改就崩。如果下游是程序一定要输出 JSON。8.2 输出示例的写法输出示例要包含完整的一个样本不要用省略号。模型对省略号的处理很不稳定它可能真的输出省略号也可能自己脑补内容。输出示例完整 { summary: 本季度销售额同比增长12%, highlights: [华东区表现最佳, 新品贡献了30%增量], risks: [华南区连续两月下滑] }8.3 输出校验让 Skill 自己检查一遍如果条件允许在 Skill 的最后一步加一个自检动作按输出约束逐条核对不通过就重试或报错。这一步能挡掉大量格式错误。5. 输出前自检确认 JSON 合法、字段齐全、类型正确。若不合格重新生成一次仍不合格则返回错误。9. 常见问题与排查技巧实录9.1 触发类问题速查表现象可能原因排查方法解决方向该触发不触发description 锚点太窄用正样本测试召回率补充场景词和近义表达不该触发却触发缺少负向条件用负样本测试精确率增加不触发条件多个 Skill 抢触发description 语义重叠对比相似 Skill 的描述明确各自边界加互斥条件触发不稳定description 含模糊词检查是否有“智能”等词替换为具体动作和对象9.2 执行类问题速查表现象可能原因排查方法解决方向参数填错参数过多或命名不直观统计各参数错误率砍参数、改命名、加示例中途卡住缺少终止条件复现异常场景补前置校验和异常处理输出格式错输出约束不明确检查是否有完整示例补格式说明和完整样本结果不可用输出粒度不对看下游如何消费调整格式或字段设计9.3 三个我踩过的坑坑一description 里写“支持多种格式”。模型不知道“多种”是哪几种结果每次调用都随机选一种。改成明确列出“支持 CSV、Excel、JSON”后行为稳定了。坑二步骤里写“根据情况选择合适的方法”。这句话等于把决策权完全交给模型而模型在缺乏上下文时决策质量很差。正确做法是把判断条件写清楚“若数据量小于 1000 行用内存处理否则用流式处理”。坑三输出约束只写“输出 JSON”。模型会输出 JSON但字段名、嵌套结构每次都不一样。必须把字段名、类型、层级全部写死。10. 一个完整 Skill 的写法示范10.1 场景说明假设我们要写一个“竞品分析 Skill”输入是竞品名称列表输出是结构化的对比分析。下面是我实际用的版本做了脱敏处理。10.2 SKILL.md 全文name: competitor-analysis description: 根据竞品名称列表从公开信息中提取产品定位、核心功能、定价策略、目标用户四个维度输出结构化对比分析。适用于市场调研和产品规划场景。 version: 1.2 tags: [market, analysis, competitor] 触发条件 - 用户提供竞品名称并要求对比分析 - 用户提到“竞品”“对标”“市场分析” 不触发条件 - 用户要求分析自家产品走 product-analysis - 用户只要求查单个公司信息走 company-lookup 参数 - competitors (array, 必填): 竞品名称列表例如 [产品A, 产品B] - dimensions (array, 选填): 分析维度默认 [定位, 功能, 定价, 用户] 执行步骤 1. 校验 competitors 数量在 2-5 之间。若超出返回 竞品数量需在2-5之间 并终止。 2. 对每个竞品依次提取四个维度的信息。若某维度信息缺失标记为 信息不足不要编造。 3. 按维度横向对比生成对比结论。 4. 输出前自检确认每个竞品每个维度都有内容或明确标记。 输出约束 - 输出为 JSON顶层包含 competitors 和 comparison 两个字段 - competitors 为数组每项含 name 和四个维度字段 - comparison 为字符串总结关键差异 - 示例{competitors: [{name: 产品A, 定位: ..., 功能: ..., 定价: ..., 用户: ...}], comparison: ...}10.3 这个 Skill 的设计取舍说明竞品数量限制在 2-5太多会导致信息质量下降太少没有对比意义。信息缺失标记而非编造这是防止幻觉的关键宁可输出“信息不足”也不要假数据。输出用 JSON因为下游是分析看板需要程序解析。自检步骤挡掉格式错误减少人工返工。11. 测试与迭代Skill 上线不是终点11.1 上线后的三个监控指标Skill 上线后要持续盯三个数触发准确率、执行成功率、输出可用率。我一般用周维度看趋势如果某个指标连续两周下降就要介入排查。排查顺序是先看是不是用户查询分布变了新场景没覆盖再看是不是模型版本更新导致行为漂移最后看是不是 Skill 本身有 bug。11.2 版本管理的一个实用做法每个 Skill 的 SKILL.md 都要有 version 字段每次修改都要升版本号并在文件末尾附一个简短的变更记录。这样出问题时能快速定位是哪次改动引入的。变更记录 - v1.2: 补充负向条件修复与 product-analysis 的触发冲突 - v1.1: 参数 dimensions 改为选填 - v1.0: 初始版本11.3 什么时候该拆 Skill一个 Skill 如果出现下面任一情况就该考虑拆分了触发条件超过 8 条且场景差异明显执行步骤超过 10 步输出格式有多种且差异大不同用户群体的使用方式完全不同拆分的粒度参考是一个 Skill 只解决一类问题服务一类场景。贪多求全的 Skill 最后往往哪个场景都做不好。12. 我个人在实际操作中的几点体会写了这么多最后分享几个我自己的真实体会都是踩坑换来的。第一Skill 的质量上限取决于你对场景的理解深度而不是你的提示词技巧。我见过提示词写得很花哨但触发一塌糊涂的 Skill也见过描述朴素但极其好用的 Skill。差别就在于作者有没有真正搞清楚“用户会在什么情况下用这个能力”。第二description 值得反复打磨它比正文更重要。我现在的习惯是一个 Skill 的 description 至少改五版每版都拿正负样本测一遍。正文写得再好触发不了等于零。第三终止条件是 Skill 的安全带。没有终止条件的 Skill 就像没有刹车的车平时看着能跑一出事就是大事。宁可多写几个终止条件也不要让模型在异常时自由发挥。第四测试集要跟着 Skill 一起维护。很多人写完 Skill 就不管测试集了结果 Skill 迭代了几版测试集还是老的测出来的数据没有参考价值。我的做法是每次改 Skill 都同步更新测试集保持两者一致。第五别怕砍功能。我砍掉的参数和步骤比加上的多得多。每次砍完成功率都会上升。Skill 的价值不在于“能做什么”而在于“能稳定做好什么”。
返回列表