前两天有个朋友来找我吐槽,说团队里明明已经接入了AI助手,日常问答、资料整理都挺能打,可一到处理具体业务就翻车,要么答非所问,要么流程走到一半就卡住。我问他是不是直接把一段需求说明甩给了AI让它自由发挥,他点了点头。我说问题就出在这儿——你缺的不是一个更聪明的AI,而是一份写得合格的Skills。
这几年AI Agent的概念被炒得火热,但真正决定一个智能体能不能在真实工作里扛活的,往往不是底层模型多强,而是你给它配了哪些“技能”。所谓Skills,你可以把它理解成给AI发的“岗位说明书+操作手册+工具箱”三合一。它把一类任务拆解成清晰的步骤,配上可执行的脚本和限定条件,让AI从“什么都懂一点的聊天机器人”变成“能稳定干成一件事的员工”。这篇文章会把Skill从设计、编写、测试到踩坑修复的完整链路讲透,特别适合正在给助手写技能的同学,也适合想从零搭建一套内部AI工作流的小伙伴参考。
1. 先把“Skills”这件事掰开揉碎
1.1 一个Skill到底长什么样
很多人第一次接触Skills时有个误解,以为它就是一段写得很详细的提示词。其实提示词只是Skill的一部分,甚至不是最关键的那部分。一个完整的Skill通常是一个目录,里面有说明文件、资源文件和可执行脚本。说明文件负责告诉AI“什么时候该用这个技能、用的时候按什么步骤走、哪些事绝对不能做”,脚本则负责做那些AI本身不擅长或者不稳定的计算和处理。
举个例子,我之前带团队给客服场景写过一套“订单问题诊断与售后工单生成”的Skills,目录结构大致是这样的:
order-diagnosis-skill/ ├── SKILL.md ├── assets/ │ ├── exception_keywords.txt │ └── answer_templates.json └── scripts/ ├── analyze_order.py └── generate_ticket.pySKILL.md是核心入口,AI会优先阅读它来决定是否调用这个技能以及如何调用。assets目录里放着辅助参考材料,比如异常问题关键词表、答复模板,AI在生成话术时可以参考。scripts目录存放真正干活的代码,比如从订单数据里提取特征、判断异常类型、自动填单。这三层各司其职:说明负责“知道怎么做”,资源负责“知道参考什么”,脚本负责“把事真正落地”。
1.2 为什么不能把需求一股脑塞给AI
我见过很多团队的第一个Skill是这么写的:让AI充当售后专家,分析订单数据并生成工单。听起来没问题,但实际跑起来就会出现大量幺蛾子。比如AI自己编造订单号,因为它其实没有权限访问数据库,只是凭借训练记忆“脑补”了一个;再比如它把“物流超时”和“商品破损”两种完全不同的售后类型揉在一个工单里,因为它分不清流程分支的判断标准。
根因在于:大模型是一个概率推理器,不是状态机。你给它一个开放目标,它会沿着最可能的语义路径走,但不会严格按业务规则去执行。Skill的价值就是把这些不确定性收敛住。它用明确的步骤约束AI的行为路径,用脚本接管需要精确计算的部分,用约束条件划定AI的自由度边界。一句话总结:Skill不是让AI更聪明,而是让AI更好用。聪明是模型的事,好用是工程的事。
这个观念如果没转过来,后面写多少Skill都会觉得别扭。
1.3 什么场景适合写Skill,什么场景不该写
动手之前先判断需求合不合适,能省下大量无用功。以我的经验,适合写成Skill的任务有三个特征:
- 任务流程相对固定,可以拆成若干个有序步骤,比如“先查库存-再算时效-后出方案”。
- 任务包含AI不擅长但规则能搞定的环节,比如精确计算、大小比较、格式校验。
- 同一个任务会被反复执行,且对输出的一致性有要求,比如定期生成报表、批量审核文案。
反过来,有些需求就不适合硬做Skill。比如高度依赖灵感和创意的头脑风暴,你给AI设太多条条框框反而压制输出质量;再比如一次性临时任务,花一两个小时写Skill还不如直接对话来得快。Skill是投资品,只有当你确定这个事会被反复干、而且干法相对稳定时,这份投资才划算。
团队里经常有人问我:“是不是所有事都能做成Skill?”我的回答是:凡是你能写出一份可执行SOP的事,都有变成Skill的潜质;凡是连你自己都说不清楚怎么做的事,AI更没法替你干。
2. 写Skill之前的准备工作
2.1 明确边界:哪些事归Skill管,哪些事不归
这是最容易被跳过的环节,也是决定Skill生死的一步。正式下笔之前,你必须先回答几个问题:这个Skill的输入是什么,输出是什么?哪些场景归它管,哪些场景它一定要拒绝处理?
拿我们当时做的订单诊断Skill来说,提前就划清了边界:只处理“已付款但未完成”状态的订单,只诊断“发货超时、缺货、地址异常、物流停滞”这四类问题,其他问题一律转到人工客服。这个边界极其重要,因为AI的默认行为是“有问必答”,如果你不给它划出拒绝处理的范畴,它就会自信地把超出能力范围的事情也硬接下来。
实操中我习惯用一个小表格来记录边界条件:
| 维度 | 定义 |
|---|---|
| 触发条件 | 订单状态为已付款且未完成,或用户主动表达售后诉求 |
| 输入范围 | 订单号、用户描述文本 |
| 处理范围 | 四类标准异常:发货超时、缺货、地址异常、物流停滞 |
| 拒绝处理 | 退款金额争议、商品质量问题(需人工质检)、投诉升级 |
| 输出形式 | 诊断结论 + 建议动作 + 结构化工单内容 |
把这张表贴在SKILL.md的显眼位置,相当于提前给AI立了规矩:能干什么、不能干什么,一目了然。很多Skill翻车就是因为边界没立住,AI啥都敢接。
2.2 场景剧本:把工作流画出来再谈写代码
边界确认之后,下一个动作是梳理工作流。这个过程我不建议直接开写,而是先在纸面上把流程画出来。哪怕你不画图,至少也要把步骤一条一条列出来。一个合格的Skill流程通常包含四个阶段:理解输入、查证信息、做出判断、生成输出。
以订单诊断为例,当时的流程是这样拆的:
- 从用户对话中提取订单号,并确认订单状态符合预设边界。
- 调用脚本查询订单当前状态、支付时间、发货时间、物流轨迹。
- 根据数据判断异常类型:如果支付后超过48小时未发货,判定为发货超时;如果库存记录显示缺货且补货时间未知,判定为缺货;如果收件地址省市区为空或格式非法,判定为地址异常;如果物流轨迹超过72小时未更新,判定为物流停滞。
- 针对异常类型,从答复模板库中选取话术,并生成工单草稿。
这里有一个关键认知:流程拆得越细,AI的自由发挥空间越小,输出就越稳定。反过来,如果只给AI说“分析订单问题并给出建议”,它大概率会在判断异常类型时漏掉某个分支,或者在话术里自由发挥出与业务口径不一致的内容。
2.3 工具盘点:哪些环节需要脚本兜底
流程理完之后,逐个环节问自己:这件事AI凭语言能力能不能稳定完成?如果答案是不确定,那就需要脚本兜底。
我总结了一套简单的判断标准:凡是涉及数值计算、数据查询、格式校验、正则匹配、时间比较的环节,统统交给脚本;凡是涉及语义理解、内容生成、情感判断、话术选择的环节,留给AI。这样分工的好处是让AI把算力花在它真正擅长的地方,同时把业务规则牢牢握在代码里。
比如订单诊断里,“支付时间是否超过48小时”这种判断虽然AI勉强能做,但它可能因为不同时区、日期格式等问题算错,对吧?就算它算对了,你也没法保证每次都对。同样的事用Python脚本三行搞定,精确到秒。这不是AI笨,而是这类精确计算根本不该交给语言模型去做。再比如,从用户输入里提取订单号这件事,AI可以做,但脚本配合正则表达式会更稳。两边结合:AI先做语义理解和用户意图判断,脚本再做精确的参数提取和格式校验。
所以筹备阶段就要把脚本清单列出来,标注每个脚本负责的输入、输出和处理逻辑。宁可脚本多设计一个,也别把关键环节裸奔交给AI去猜。
3. 核心文件实战:SKILL.md从零到一
3.1 写好“触发条件”:决定AI何时出手、何时沉默
SKILL.md开头部分最重要的内容就是触发条件。它解决“这个技能什么时候该被调用”的问题。写得太宽,AI会在不合适的场景下强行调用,导致答非所问;写得太窄,AI该用的时候却不知道用,技能就白写了。
触发条件的写法核心是“场景化描述+正向条件+负向条件”。比如订单诊断Skill的正向条件可以写:当用户询问订单状态、发货进度、物流异常,或明确表达对订单进展不满时。负向条件要单独写一段:当用户仅询问商品规格、价格优惠或售后政策时,不得调用本技能,而应转交通用客服流程。
这里有个经验:不要只依赖“关键词命中”这种低级方式。AI理解语义,你可以写“如果用户提到物流不动了、好几天没人管,这些表达也属于触发范围”。把真实用户会说的口语放进去,比干巴巴的关键词列表有效得多。
还有一个容易忽视的细节:触发条件里要定义“优先级”。如果用户同时触发了多个技能,AI该选谁?我的做法是在SKILL.md开头就声明:“当本技能与通用回复逻辑冲突时,以本技能为准,但用户明确表达退款投诉等拒绝范围内的意图时,本技能主动让位给人工升级流程。”优先级写清楚了,后面能少吵很多架。
3.2 工作流步骤怎么写才不会被误解
我见过最多的失败案例,是工作流步骤写得太像“愿景声明”。比如“分析订单状况并给出合理建议”,这种话AI看了等于没看,它不知道具体动作是什么。好的步骤描述要具体到“在什么条件下做什么判断,输出什么格式的结果”。
拿订单诊断的步骤来说,当时写的是:
- 步骤一:从用户输入中提取订单号。提取成功后,调用
scripts/analyze_order.py获取订单信息;提取失败时,向用户索要完整订单号,不得猜测。 - 步骤二:根据脚本返回的状态字段判断处理分支:订单状态为
paid时进入异常判断流程;为completed时直接告知用户订单已完成,后续不进入诊断逻辑;为canceled时如实告知用户订单已取消,并提示联系客服处理退款。 - 步骤三:在异常判断流程中,依次检查四个判定条件,任一条件命中即锁定对应异常类型,并联合相应的答复模板生成诊断结果。
- 步骤四:如果四个条件均不命中,输出“订单当前正常”的结论,不生成工单。
每一步都有明确的动作和条件分支,AI不需要“思考”只能“照做”。为了让它更稳,我给每一步还加了一个“完成标准”字段,比如步骤一的完成标准是“拿到合法格式的订单号并通过脚本接口校验”。这样AI在执行完一步之后能自查有没有做对。
写步骤有一个心法:把AI当成一个记性不好但执行力强的新员工。你不能说“处理一下这个订单”,你得说清什么叫“处理”、先干什么后干什么、干到什么程度算完。
3.3 约束与禁忌:给AI上紧箍咒
如果说工作流定义了“该怎么做”,那么约束与禁忌就定义了“绝对不能怎么做”。这部分写少了、写模糊了,Skill的质量就没了下限。
约束包括三个层面:数据隐私约束、操作范围约束、措辞风格约束。数据隐私层面,要明确“订单号、用户手机号、地址等敏感信息只能在脚本内部处理,不得写入对话日志之外的地方,不要向用户复述完整的隐私信息”。操作范围层面,要声明“本技能只能诊断和生成工单,不具备改单、退款、取消订单的权限”。措辞风格层面,要约定“面向用户的答复需要简洁、有礼貌,并且必须在结尾提供下一步指引”。
禁忌部分我会直接列一个负面清单:不得编造订单数据;不得在脚本返回异常时自行猜测数据填充;不得在内部信息缺失时拒绝回答,而应采取替代方案向用户说明情况;不得讨论与售后无关的话题。这些条款每一行都来自真实事故。比如“编造订单数据”这条,早期版本没有写,AI在脚本接口偶发超时时,竟然自己编了个“订单已发货”的假结果安抚用户,差点酿成重大客诉事故。
约束语气的选择上,尽量用“必须/不得”这种强指令,不要用“尽量/建议”这种软表述。模型对强指令的遵循率显著高于软性建议。
3.4 元数据与版本管理:让Skill可维护
不要小看SKILL.md头部那几行元数据。它看似没什么用,但在实际团队协作、多版本迭代、问题追溯时能省大量时间。我会在每个Skill的头部固定记录以下信息:
| 字段 | 示例 | 作用 | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| name | order-diagnosis | 唯一标识,便于检索 | ||||||||||||||
| version | 1.3.0 | 版本号,配合变更记录 | ||||||||||||||
| description | 诊断订单异常并生成售后工单 | 一句话说清用途 | ||||||||||||||
| author | >{ "order_id": "A20250315001", "user_text": "我的订单好几天没动静了" } 脚本输出约定是: 这个协议必须在SKILL.md中完整写清楚。怎么强调都不过分——AI只有看到字段说明和示例,才知道怎么调用脚本、怎么解析返回结果。我见过有人在脚本注释里写“返回数据结构在函数docstring里”,AI根本不会去看那个代码文件。正确的做法是把返回示例直接粘贴到SKILL.md对应的步骤描述后面,AI在决策时才会有效参考。 4.2 异常处理与兜底逻辑:脚本挂了,Skill也不能摆烂脚本是程序,程序就会出错。接口超时、数据库连不上、数据字段为空,这些不可控因素时刻存在。问题在于,Skill的执行链条不能因为一个脚本报错就整个崩溃,更不能让AI在脚本报错时“自由发挥”。 我给订单诊断脚本设计了三层兜底: 第一层是参数兜底:脚本在入口处校验输入字段,缺失的字段给出明确的错误码和提示信息,而不是贸然执行导致更深的错误。比如order_id格式不对时,脚本返回 第二层是业务兜底:当某个数据源查询失败时,脚本返回部分结果并明确标注 第三层是逻辑兜底:当脚本全部不可用时,SKILL.md里预设一条“降级话术”,AI直接向用户说明系统正在升级、已记录问题并转人工处理。这条路径保证了最坏情况下Skill也不会给出虚假答复。 这套兜底逻辑写起来并不复杂,但很多人从没想过。他们默认“脚本只要写得对就不会挂”,现实当然不是这样。任何生产环境里的Skill,都必须把“系统不稳定”当成常态来设计。 4.3 脚本测试的三种方式脚本写完不是扔给AI就完事了,你得先确保它本身经得起考验。我习惯按三个层次来测试脚本。 第一层是纯脚本测试,不调AI,直接拿模拟数据跑。这一步主要验证输入输出协议是否稳定、异常分支是否正确处理。对于 第二层是带AI的局部测试。把SKILL.md的前半段(触发和工作流)加载给AI,人工给几个用户问题,看AI能不能正确理解步骤并调用脚本。这一步主要看SKILL.md的描述是否清晰,有没有让AI产生误解的表达。那些“模棱两可”的措辞,大多数在这一步暴露出来。 第三层是端到端联调,模拟真实对话场景,从用户输入开始一路看到最终输出。这层测试关注的是整体体验,比如AI调用了脚本之后能不能正确解读JSON结果、生成的话术是否自然、边界场景下能不能合理拒绝。 三层的执行顺序不能乱,先保障脚本质量,再逐步扩大测试范围。很多时候Skills出问题,不是AI笨,而是底层脚本本身就有bug,结果全让AI背了锅。 5. 测试、调试与迭代的完整闭环5.1 单点测试:先把每个环节打穿端到端联调之前,我强烈建议你先做“单点测试”。什么意思?就是针对Skill里的每一个关键环节单独做验证,先把环节本身打通,再连起来跑。 比如订单诊断Skill,我需要分别验证:用户说“订单还没到”能不能触发技能;提取订单号的正则能不能命中A20250315001这种格式; 单点测试的价值在于快速定位问题发生在哪一环。如果你直接跑完整流程发现输出不对,还得花大量时间排查是触发问题、脚本问题还是模板问题。而先做单点测试,哪个环节挂了直接修哪个,效率翻倍。 为了做单点测试,我给每个Skill都准备了一个测试用例清单,大概长这样:
这个表既是开发时的验收标准,也是后续回归测试的用例库。每一次改代码、改SKILL.md,拿这张表重新跑一遍,确保没引入新问题。 5.2 端到端联调:用上帝视角看表现单点测试通过后,进入端到端联调阶段。这时要模拟尽可能真实的用户输入,观察整个链路的表现。我的习惯是把AI的原始思考过程拉出来仔细看一遍,不要只盯着最终输出。 有一次联调就发现了一个隐蔽问题:AI在决策分支时选择了错误路径。用户输入“我的订单被退回了”,按设计应该进入人工升级流程。但AI先触发订单诊断技能,因为用户输入里提到了订单,而且诊断结果也返回了一个异常类型,最后AI顺着诊断逻辑输出了一条“我们正在为您处理”的话术。这个问题单点测试发现不了,因为每个环节单独看都没问题,只有连起来才发现分支优先级设计有缺陷。 解决方案是在SKILL.md的触发条件里增加一条优先级规则:当用户表达“退款、取消、投诉、已退回、少件”等强诉求时,不执行诊断流程,直接转交人工。同时把规则放到SKILL.md靠前的位置,确保AI先看到再往下执行。 联调时还要注意次数积累。一种输入跑通了不算数,至少要覆盖正常场景、边缘场景和异常场景各若干次。一个Skill的稳定运行,靠的就是这类大样本联调把隐藏问题一个个逼出来。 5.3 上线与灰度:Skill也是产品,要有人管Skill写完调完,还不能立刻全员使用。我见过太多团队把Skill写出来就扔给全公司,结果一个AI生成模板里的标点符号问题都能引发用工风险。Skill上线也要讲究节奏。 先从“受控模式”开始:只允许少数测试用户使用,收集真实场景下的表现。抽样看输出质量、触发准确率、用户反馈。达到预期标准后再逐步放开。 灰度期间我会特别关注两类指标:一是触发率,用户提到相关需求时AI有没有漏激活;二是无效触发率,用户明明没这个需求AI却误调用。这两个一高一低就说明触发条件写得有问题。 另外上线不代表结束。要让Skill有负责人。业务规则会变,脚本依赖会变,用户语言习惯也会变。我见过一个Skill用了半年还没人维护,功能已经和业务现状脱节了,AI还在拿旧规则给用户开药方。这是比技术故障更隐蔽的风险。每季度至少过一遍所有线上Skills,确认业务逻辑、边界条件、话术模板仍然有效。 6. 常见翻车现场与排查速查表6.1 六个高频问题实录做Skills这段时间,我把团队和自己踩过的坑做了个记录,你会发现大部分问题不是模型能力不够,而是工程细节没到位。 第一个高频问题:AI不按步骤走,跳步执行。原因是步骤描述不够有约束力,AI看到结果可直接生成,就自作主张省略了中间检查环节。解决办法是在SKILL.md里写明“严格按照以下流程执行,不得跳过任何步骤”。每步完成后再加一句“确认完成后进入下一步”。 第二个高频问题:脚本输入输出对不上。脚本明明接收订单号,AI传了个对话文本进去。根源是SKILL.md里没有给脚本输入格式的示例,AI只能靠猜。解决方法是把JSON示例直接贴在调用脚本的那一步描述里。 第三个高频问题:AI在脚本返回异常时自行编造数据。这个前面已经反复提到。解决方法是写死“当脚本标记data_complete为false时,必须使用预设降级话术”。 第四个高频问题:触发条件有严重漏召回。用户说方言口语或者换个说法,AI就识别不出来。解决方法是多收集真实用户表达,扩充同义触发样例,并在触发条件里增加“用户表达某种意图的短语包括但不限于...”的枚举。 第五个高频问题:多技能冲突。用户的问题同时触发两三个Skill,AI不知道选哪个,最后乱套了。解决方法是给每个Skill定义明确的优先级,并在共享的规则文件里统一协调。调度的逻辑应当独立于单个技能存在。 第六个高频问题:SKILL.md写得过长过复杂。有人把几十个业务规则全部塞进去,AI根本顾不上全部遵循。解决办法是分层写:核心执行步骤简明扼要,详细规则放在参考文件里,并明确告诉AI“仅在冲突或边界场景时参考详细规则”。 6.2 排错思路第一步:先分锅遇到Skill表现不对,第一件事不是急着改提示词,而是先判断问题出在哪个层面。是触发环节没激活,还是执行环节走错分支,还是脚本层计算错误,还是生成环节话术不对?不同环节的排错思路差异很大。 触发问题要看“AI有没有看到这个Skill、有没有被激活”;执行问题要看“AI有没有理解步骤、有没有正确调用工具”;脚本问题要看“代码本身有没有bug、数据源有没有异常”;生成问题要看“模板选择和话术拼接逻辑对不对”。 很多时候你以为的“AI不听话”,深挖下去其实是脚本bug导致AI拿到的数据就是错的,它只是顺着错误数据往下走罢了。所以出问题先查链路各层的输入输出记录,看看是哪一层开始出现偏离的。我把这个排查顺序记成了一句口诀:先看触发,再看流程,然后查脚本,最后审话术。 6.3 避坑清单:几条拿时间换来的经验第一条经验:脚本输出越结构化越好。AI擅长文字,不擅长解读一段冗长的日志文本。能让脚本输出JSON的就不要输出自然语言。 第二条经验:给AI看的任何指令里,示例比抽象说明更有效。你说“输出工单内容”不如直接给它一个工单样例模板,让它照着填。 第三条经验:负面约束要写“如果...则...”,不要只写“不要...”。因为AI可能知道不能做什么,但不知道该怎么做代替动作。比如“不要编造数据”,后面最好接上“当数据缺失时,使用默认话术模板并标记需要人工补充”。 第四条经验:Version历史记得留。每次改Skill前把旧版本归档。你永远不知道哪次改动会让线上效果变差,留一条退路永远不会错。 第五条经验:Skill不要设计成“一次调用干所有事”。真正常用的好Skill,往往是那种“只处理一个窄场景,但处理得特别稳”的模块。把复杂系统拆成多个小Skill各管一摊,远比一个超级Skill可控。哪怕中间需要AI做链路调度,多基层的颗粒度也更利于排查问题、复用小能力。 我自己在写完第一版订单诊断Skill的时候特别自信,觉得功能都有了,结果灰度第一个星期就收到N条工单异常,全是因为边界条件没守住。后来老老实实把边界分析、触发管理、降级策略这些基础做扎实,业务数据才终于稳定好看。Skills这个东西,写多了你会产生一种感觉:它不是给AI写说明书,而是给AI搭脚手架。脚手架搭得密、搭得稳,AI就能高效发挥;脚手架漏一块板,翻车就是早晚的事。 如果你手头也正打算写一个Skill,强烈建议先从最不起眼的边界分析开始,找一个窄场景,拆透流程,把脚本和模板准备好再动笔。第一版做得窄一点没关系,跑顺了再逐步扩展。后面有新的业务场景需要沉淀,你会越写越顺,团队里那些重复劳动的活也会被一点点消化掉。这就是Skills真正值钱的地方。 |