
写 Skill 这件事最让人上头的不是写不出来而是写出来以后 AI 不照做。我最近一个月整理了一套自己的 Agent 技能库前前后后写了二十多个 Skill从会议纪要、周报生成到数据清洗都有。结果测试的时候发现一个特别普遍的现象用户明明说“用周报技能”AI 偏偏自己发挥写了一版有时候它倒是调了但输出格式跟我在文档里定的完全不是一回事还有时候整个流程跑到一半就断掉连个报错都没有。一开始我以为是模型理解能力不够后来排查多了才明白大部分问题根本不在模型而在 Skill 本身的设计。AI 能不能按要求执行不是看你的描述写得有多详细而是看你在几个关键环节有没有做到位。今天就把踩过的坑整理出来遇到“Skill 写好了AI 还是不按要求执行”的情况先查这四件事——技能有没有被 AI 看见、参数接口有没有对齐、执行步骤够不够原子、结果校验有没有闭环。这四条是我实际调试时最常用的排查路径基本覆盖了 80% 以上的失效场景。这篇东西主要写给两类人看一类是在写 Agent 技能时被模型气到的开发者另一类是天天跟提示词打交道、想让 AI 稳定交付结果的产品同学。1. 第一件事AI 到底“看见”你的 Skill 没有1.1 描述不是说明书是“搜索摘要”先说最容易被忽略的一点AI 不是拿到你的 Skill 文件就从头读到尾的。在绝大多数 Agent 架构里模型会先根据用户当前这句话的意图从技能库里挑选几个“可能相关”的技能然后才读取对应的 Skill 内容。那它是靠什么挑的呢靠的就是 Skill 描述字段也就是那个 description。可以把它理解成搜索引擎用户说“帮我把这周工作理一理”你的描述里如果压根没有“周”“工作”“整理”这类词模型就判断这个技能不相关后面内容写得再完美也不会被打开。我见过很多 Skill 描述写的是“这是一个周报生成技能适合需要周报的用户”这种描述基本等于没有。该说的不是这个技能适合谁而是用户那句话里哪些词能命中它。更合理的写法是第一句点明功能、输入、输出后面把用户可能会用的各种自然表述埋进去。比如描述写成“根据聊天记录或项目数据生成结构化中文周报包含本周完成、下周计划、风险与阻塞、数据指标摘要能自动识别日期范围。适用于总结、周报、weekly report、进展汇报、给老板汇报等场景”这样用户说“写周报给老板”时命中概率就高得多。还是那句话描述是给检索用的不是给模型朗读的。1.2 命名和边界让技能库不打架技能多起来以后命名也会影响“能不能被看见”。如果 Skill 的标识是一串无意义编码比如 skill_1234模型就算匹配上了你在日志里也看不出它调的是哪个技能排障的时候两眼一抹黑。更头疼的是同一个 Agent 里塞了太多功能混杂的 Skill描述里全是“总结、翻译、改写、润色”这种高频词模型在选型时就会纠结甚至选错。我的经验是命名尽量让功能词可见比如 document_weekly_report同时一个 Skill 只负责一条职责线。有人喜欢把一个技能写成“万能工具箱”既能总结又能翻译还能生成图片表面看是省事实际是给模型埋雷。多个意图挤在一个 Skill 里描述字段互相干扰调用的参数也无法收敛最后的归宿就是哪个功能都做不深。如果真要支持多个功能不如拆成多个 Skill各自维护触发逻辑清晰测试也好定位。我在实际调试中发现职责边界清晰的技能库比一个庞大的全能技能可靠得多因为模型每次只需要做一道简单的选择题而不是在十几个功能里做复杂的意图消歧。1.3 验证“被看见”的三个办法发现症状以后怎么确认到底是不是触发问题我常用的办法有三个。第一个是看 trace 日志大多数 Agent 框架都会记录工具调用事件里面能看到技能标识和传入参数这是最可靠的证据。第二个是在 Skill 指令开头加一句“执行前先输出‘使用周报技能开始处理’”让 AI 主动声明调起了哪个技能。这个办法简单粗暴适合快速验证尤其是你手头没有完整日志链路的时候。第三个是准备三五个不同表达方式的测试用例比如“写周报”“汇总一下本周进展”“给老板的汇报材料”逐个触发看哪些能命中。如果技能明明匹配了但还是没触发再往描述和命名上找原因。这里我列出不同症状对应的排查方向方便对照症状可能原因优先排查完全没有调用记录描述没命中 / 技能被禁用 / 标识拼写错误检查描述关键词和日志调用了但回答不对参数映射错误 / 步骤模糊检查参数接口和执行步骤时好时坏描述边界模糊 / 多个 Skill 竞争检查命名和职责边界看到“时好时坏”的时候很多人第一反应是模型随机性但我查下来这类问题十有八九是技能描述里的关键词太宽泛同时有好几个技能都能沾边。模型每次选中的技能不一样表现自然就不一样。把技能的描述边界写窄一点把高频词的使用权集中到一个技能上这种现象就会明显减少。2. 第二件事参数接口有没有“对齐”2.1 输入参数要像函数签名一样严谨很多人把 Skill 触发问题解决以后跑了两次就发现技能是调用了但 AI 传进来的参数一塌糊涂。原因很简单你定义参数时只写了“会议内容”“项目进展”这种名称却没告诉模型这些值从哪来、取多少、哪些才符合要求。有一种很典型的错误我写“会议纪要”Skill 时定义了 meeting_content 参数类型是字符串必填。结果用户说“把我们刚才讨论的内容做成纪要”AI 把整个对话历史都塞进来了。为什么因为模型不知道“会议内容”该怎么提取。后来我在参数描述里加了一句“只提取与议题相关的发言排除寒暄、提问铺垫和无关内容”输出立刻干净了很多。所以参数描述不能只写“名称 类型 必填”还要写提取规则和边界。你把参数想象成函数入参只有名称没有类型说明调用方自然会乱来而 AI 这个“调用方”比人更需要明确的说明——它不会像人一样问一句“你说的会议内容是指哪一段”只会默默选择一个自己觉得合理的角度然后直接开干。2.2 缺参数、可选参数怎么办另一个高频问题是“用户没提某个字段AI 怎么办”。有些 Skill 的参数是必填的但用户在对话里并不会一次性说全。比如“生成邮件草稿”这个技能收件人、主题、正文都是字段用户只说“帮我写封邮件向客户道歉”收件人和客户名称都是空的。AI 这时要么编一个假邮箱要么把参数留空导致下游报错最后你看到的结果就是“技能执行了但完全不可用”。我给这类字段补充“缺省行为”后情况好了很多。比如在参数描述里写“收件人可选如果用户没有提供输出中显示[待补充收件人]不要自行猜测邮箱地址”把“不做什么”也写进参数说明。事实证明模型对“不能做”的遵守程度往往比对“应当做”还要高。这个现象很有意思你让它“生成一封道歉邮件”它自由发挥的空间很大但你告诉它“不许编造邮箱地址必须写成待补充”它在这一点上就会很老实。缺省行为本质上是在消灭模型的猜测空间。2.3 输出也要定“交付标准”参数对齐不只是输入输出更关键。很多时候你翻日志发现 AI 确实执行完了但你看到的结果格式不对、字段缺失于是你以为它没执行。实际上问题出在输出定义太松。我见过一个数据总结技能输出要求只写了“整理成报告”结果 AI 有时候输出 Markdown 表格有时候输出纯文本列表有时候又给一段散文下游程序根本没法解析。我给技能写输出规范时固定给三样东西结构模板、示例、校验规则。结构模板规定分成哪几个模块示例让模型知道填好的样子校验规则要求模型输出前检查“哪些字段不许为空、哪些结构必须存在”。比如周报技能里我写了风险项如果为空必须写“无”不能只留个空列表日期范围要精确到月份不能写“本周”每个列表至少一条内容。加了这三样以后输出的一致性完全是两个量级。要记住AI 默认的输出习惯是“能省就省、能概括就概括”你只有把交付标准钉死它才会老老实实按格式走。3. 第三件事执行步骤够不够“原子”3.1 大步骤是跑偏的重灾区有些 Skill 触发正常、参数也对但执行结果就是不对味。这时候要检查技能内部的步骤。AI 在执行一个多步任务时遇到“分析数据并生成结论”这种宏指令往往会选择最偷懒的路径它不分析直接生成一个听起来很合理的结论。所以“看起来是完成了实际上什么都没做”。我的经验是把步骤写成“原子指令”也就是“一个动作 一个对象 一个产出”。拿数据分析技能举例不要写“分析数据生成结论”而要拆成“读取数据 → 计算每列均值、中位数、缺失值比例 → 将这些统计指标整理为表格 → 基于表格指标写结论结论必须引用具体数字”。每一步都有明确的输入对象和输出产物模型就没有自由发挥的空间。这背后其实是在减少模型的不确定性模型在含糊指令下会靠概率补全内容指令越含糊补全的随机性越大指令越具体补全路径越单一。把大步骤拆小本质上是在做“概率收敛”。3.2 别让异常情况把流程卡死技能跑一半停住很多情况是遇到了 Skill 里没定义的边界情况。模型发现数据为空或者某一步没有结果而技能文档没有告诉它怎么办它就会停下来、重复执行甚至编造数据。我遇到过最离谱的一次一个“客户反馈整理”技能输入数据为空AI 硬是编了三段“客户反馈”看起来像真的一样实际上全是幻觉。所以我在写多步骤技能时会明确“异常分支”。比如周报技能里如果输入中没有聊天记录或项目数据就输出“缺少聊天记录请先提供我暂不生成周报”绝不编造。再比如搜索类步骤如果返回结果为空就明确“输出无结果提示而不是给出猜测内容”。把异常行为写成显式规则模型才会在面对分支时走对岔路。本质上你是在给模型画一张路线图标清楚“哪里能走、哪里是悬崖”。没有这张图的模型完全可能选一条看起来近但其实是错的路径。3.3 多轮状态别指望模型记住还有一个隐蔽问题跨轮次状态。如果你的 Skill 需要和用户交互多轮比如先收集信息再生成内容AI 往往会“失忆”——它上一轮已经收集到三个字段了这一轮还继续问你已经给过的字段。这不是模型笨而是技能文档没有告诉它“哪些字段已经拿到、下一步要做什么”。现在我会在 Skill 里增加状态说明比如“收到新消息时先更新对应字段检查是否所有必填字段都已收集完成如果已完成直接进入生成阶段不再提问”。有的框架支持显式的状态变量即便文档里不支持用文字规则也能显著改善多轮体验。重点是让模型知道“当前在哪一步、下一步去哪”而不是每次都从头扫一遍。另外我还会在步骤里加入“完成标志”的描述比如“如果用户说‘开始吧’或‘就这样’则视为信息收集完成进入结果生成阶段”这样多轮对话的结束条件也清楚AI 就不会一直问你问题了。4. 第四件事结果校验与反馈闭环4.1 “执行了”不等于“交付了”这类问题最迷惑人日志显示 Skill 调用了、参数也对、步骤也走完了但最终呈现给用户的结果却是错的。我遇到过几种典型情况一是输出格式不符合下游解析要求程序解析不了就直接扔了个报错给用户二是 AI 生成的内容里有幻觉成分比如周报里写了一个根本不存在的项目进展三是流程图跑完但结果里没有把关键信息带回给用户比如工具执行成功但 AI 忘记了把工具输出拼进最终回答。如果你把这类问题误判成“没执行”就会陷入反复改触发条件的死胡同。正确做法是在 Skill 里补上“输出前自检”和“结果反馈”两个机制。前者让模型自己拦截低级错误后者让失败信息能重新进入处理循环。这两个机制加不加对长链路技能的可靠程度影响非常大尤其是那些包含多个子任务的技能只要中间一个环节断了后面全都会跟着歪。4.2 加一道“输出前自检”我最近给所有长链路 Skill 都加了最后一步要求模型在输出之前按校验规则逐项自查并把自查结果附在输出末尾。哪怕只是写一句“必填项是否齐全是/否风险项是否已标记是/否”也能逼着模型在生成完内容以后再看一眼很多低级错误在这一步就被拦下来了。这个动作尤其适合那种“看起来完成了但仔细一看缺项漏项”的情况。自查的动作本质上是让模型多一次推理路径。模型在第一次生成时可能带了很强的惯性但如果你要求它“检查一遍再输出”它往往能发现自己刚写的内容里缺项或自相矛盾。我在实践里观察到一个规律输出前加了自检步骤以后周报类技能的字段缺失率下降非常明显大概能少一半以上的低级错误。这个技巧成本很低收益却很直接值得作为每个长链路技能的标配。4.3 错误信息要能回传重试最后一个容易踩的坑Skill 里调用其他工具时如果工具报错技能文档没有定义后续动作AI 就会直接把报错原文扔给用户或者假装没看见继续做。这两种结果都很难看。直接扔报错用户看不懂假装没看见后面生成的结论又建立在错误的中间结果上。我现在写的技能会在工具调用步骤后面跟上错误处理逻辑“任何步骤失败时记录错误原因尝试重新执行一次仍失败则向用户返回‘步骤名称 失败原因 已完成的中间结果’不要自行掩盖错误。” 这个规则让 AI 在出错时至少是“可对话”的而不是僵死或胡编。特别是长流程技能一旦某一步失败重试和断点续传的能力比一次跑通更重要。你还应该告诉模型哪些错误可以重试、哪些错误不要重试比如“网络类错误可以重试两次业务逻辑错误不要重试直接返回失败原因”。这样 AI 才不会被一条错误信息卡在死循环里。5. 一个真实案例的完整复盘5.1 场景描述上面四件事说起来抽象我拿一个真实案例把排查过程串一遍。之前同事让我写一个“项目周报生成”的 Skill他反馈的症状是他明明写好指令发给 AI结果 AI 大多数时候不调用技能偶尔调用了生成出来的周报没有风险项格式也乱。“也没有报错它就是不好好按吩咐干活”这是同事的原话。听起来像是模型不行但我把 Skill 文件打开一看问题其实都藏在细节里。5.2 按四件事逐项排查第一步查触发。我在日志里看到同事的常见说法是“给老板写周报”而技能描述里写的是“生成项目周报”关键词命中的权重很低——用户的那句话里包含“老板”“写”“周报”而描述里只有“周报”匹配率自然不高。于是我把描述改成了“根据聊天记录或项目数据生成结构化中文周报适用于写周报、进展汇报、给老板的汇报材料等场景”。第二步查参数。周报技能定义了一个 project_updates 参数但我没有说明提取范围。模型把整段对话全塞进去导致周报里出现寒暄和无关内容。我给参数加了一段“只提取项目进展相关内容排除无关对话”的说明这一处修改的直接效果就是周报正文干净了不会再把“早上好”“好的呢”这种话写进去。第三步查步骤。技能里“分析风险”写得太含糊模型为了省事经常输出“无风险”。我把这一步改成“按时间、人力、外部依赖三个维度逐一检查列出具体风险项如果确实没有则写‘无’不要留空”。这个改动看着不起眼但它逼着模型按维度想一遍风险项漏报的情况立刻就少了。第四步查校验。原技能没有输出自检导致格式漂移。我加了两条规则日期范围必须精确到月份每个板块至少一条内容否则重写。到这里整个技能才算有了一个完整的闭环。5.3 修改后的 Skill 长啥样改完以后基本是这个结构我给同事整理了一个模板你也可以参考name: document_weekly_report description: 根据聊天记录或项目数据生成结构化中文周报适用于写周报、进展汇报、给老板的汇报材料等场景。 input_params: project_updates: type: string required: true description: 从对话中提取的项目进展内容排除无关寒暄。若用户未提供先询问。 steps: - 提取项目进展内容过滤无关对话 - 按时间、人力、外部依赖三个维度检查风险 - 生成周报板块包含本周完成、下周计划、风险项、一句话总结 - 输出前自检日期精确到月份每个列表至少一条内容风险为空必须写“无” error_handling: - 缺少输入材料时提示用户补充不编造 - 单次执行异常时记录原因重试一次这个模板并没有多复杂但每个字段都有了明确职责。同事照着改完以后用五组输入做了回归测试包括“写周报给老板”“这周干了啥帮我总结”“客户想看项目进展”“下周计划是什么”等等。五组里有四组能正确触发技能触发后输出格式也正常了剩下那一组是纯“下周计划”的问题我把它加进描述关键词后也通了。整个过程不到一小时全靠四件事排查清单一步步筛。5.4 排查速查表我把最常用的排查顺序压成了一张表每次 Skill 不听话就先按这个跑一遍顺序检查点关键问题快速验证1触发AI 是否调用了技能描述是否覆盖用户表达查 trace、让 AI 声明技能名2参数输入提取规则是否明确缺省行为是否声明输出格式是否有模板单独传一个测试输入看参数值3步骤大步骤是否拆成原子指令异常分支是否定义多轮状态是否说明走一遍全流程观察卡点4校验是否有输出前自检错误信息能否回传重试故意制造一次失败观察表现这张表我打印出来贴在工位上每次改技能或者调 Agent 的时候都会先对照一遍。别看它简单很多复杂的问题查到最后其实就是表里某一行的细节没做到位。6. 动手写过二十多个 Skill 以后的经验6.1 一次只改一个变量排查时最容易犯的错是同时改好几个地方结果问题修好了也不知道是哪个改动起了作用。我在测试中会强制自己一次只改一个变量改了描述就先只测触发触发没问题再改参数参数没问题再动步骤。这样做虽然慢但每次改动都有了明确的因果证据积累下来的经验才真正可复用。尤其是当你同时在维护十几个 Skill 的时候如果不养这个习惯出了 bug 根本定位不到源头。6.2 用例子代替形容词写步骤描述时少用“仔细”“高质量”“充分分析”这类程度词多用例子来对齐模型的理解。比如“输出一封语气诚恳的邮件”模型不知道什么算诚恳但如果你给出一封示例邮件模型就知道“诚恳”对应什么样的句式、节奏和标点。模型对示例的依赖比对形容词强得多一个例子胜过十句话。这也是为什么我现在给每个 Skill 都配一个示例输出而不是只写规则。规则是抽象的示例是具体的模型天生更擅长从具体样例里学模式。6.3 测试集要留好写完一个 Skill我习惯顺手把测试输入和期望结果存在一个固定目录里下次改动以后直接跑回归。很多人没有这个习惯改完一个技能就上线结果用户换了种说法技能立刻失灵。测试集不用多覆盖主流程、边界情况、异常输入三到五个样例就够用性价比极高。我自己的目录里已经攒了上百条测试用例每次改完技能就跑一遍心里才有底。这看起来费时间其实是在帮你省未来排查问题的几倍时间。6.4 别一上来就给高权限最后说一个有点反直觉的经验Skill 的权限和自由度一开始应该给得越小越好。很多失效问题其实是“太自由导致的跑偏”。先给 AI 严格的步骤、严格的输出、严格的校验确认整个链路能跑通再逐步放宽让它提供更多灵活表达。反过来做的话你根本分不清问题是出在自由度还是实现细节上。我见过不少团队上来就给 Agent 配了全套工具权限结果模型一顿自由发挥出了错都不知道是哪个环节的锅。我个人在实际调试中的体会是Skill 不叫“写好了”而叫“调好了”。写只是第一步真正让它变可靠靠的是按这四件事一遍一遍地查、改、验。如果下次遇到 AI 不听话别急着怀疑模型先按触发的顺序把这一套跑完你会发现大多数问题答案早就在自己的技能设计里了。