前阵子看到一篇关于技能开发的文章,标题特别戳我——《Skills开发技能指南:OpenClaw也好,Skills也好,都别脱离具体场景谈方案》。说实话,最近半年各种智能体开发框架和技能库如雨后春笋,讨论的声音很多,但能像这句话一样把我拉回地面的不多。作为一个在实际项目里被“工具瘾”坑过好多次的开发者,我太明白“脱离场景谈方案”意味着什么了。
这篇文章我不想复述原文内容,只想借这个标题把自己的实操经验捋一捋。我会从“Skills”到底是什么、为什么场景比方案重要,到一个完整会议纪要技能的开发实录,再到我踩过的那些坑,一条线讲清楚。只要你手头有任何一个智能体开发框架,不管是不是类似OpenClaw这种开源Agent套件,下面的思路都能直接搬过去用。
1. 从标题说起:当“技能开发”成为一种新咒语
1.1 一个让我警惕的标题
好的标题有两种:一种让你觉得“学到了新东西”,一种让你觉得“被戳中了”。这个标题属于后者。它最狠的地方在于“别脱离具体场景谈方案”这半句。我见过太多团队,拿到一个Agent框架,第一反应是“框架提供什么能力,我就用什么能力”,而不是“我的业务到底需要什么能力”。这两者看似差不多,实际上差了十万八千里。
举一个真实发生在我身边的例子。某团队拿到开源的智能体开发包,兴奋得不行,用了两天时间做出来一个“无所不能”的超级助手。这个助手既能写代码,又能做PPT,还能订机票。结果业务方试用了一周,反馈就一个字:乱。写代码的时候还凑合,做PPT的时候格式完全不受控,订机票更是压根不接第三方接口。什么问题?不是框架不行,不是模型不行,是团队成员压根没想清楚这门技能的使用场景是什么。
标题里那句“OpenClaw也好,Skills也好”,我理解为一个更宏观的提醒:不管是底层Agent框架,还是上层技能模块,只要脱离了具体场景,它们就只是一堆文档和示例代码,不会产生业务价值。框架有框架的边界,技能有技能的目标,而场景是连接两者的唯一桥梁。
1.2 先搞清楚“Skills”到底指什么
业内对Skills的称呼很多,有人叫工具、有人叫函数调用、有人叫技能包。为了不绕晕,我可以这样定义:Skill是一个可以被智能体按需加载的可复用能力单元,它由一个明确的触发条件、一个输入输出契约、以及若干执行逻辑组成。
这句话有点学院派,但拆开就很好懂。触发条件解决“什么时候用”的问题;输入输出契约解决“对话和外部系统之间怎么对齐”的问题;执行逻辑解决“具体怎么做”的问题。三者缺一不可。很多开发者的误区是只写了执行逻辑,比如“帮我调用一个API”,却不定义触发条件和输出格式。结果模型在根本不合适的场景下也强行调用,然后输出又不符合下游系统的预期,系统就变得非常不可控。
再往深一层讲,Skill不是给模型看的,是给使用者看的。模型的智商再高,也不知道你的业务流程里有哪些坑,更不知道你希望它以什么形式交付结果。因此,Skill的设计本质上是一种业务逻辑的程序化表达。所以它绝对不能是“千篇一律”的模板,而必须扎根到具体场景里去设计裁剪。
1.3 为什么“场景”比“方案”重要
有一段时间我很喜欢研究各种最新发布的Skill模板,看到人家写的“定时提醒”、“智能摘要”就觉得很高端。后来我发现自己做了一个“定时提醒”技能,结果团队里根本没人用。为什么?因为大家用的是企业微信,提醒要发到企业微信群里,还要带上具体责任人,而这个技能只支持邮件提醒。这就是典型的方案很好、场景没对齐。
场景这件事,包含的维度远不止一问一答。它至少要回答这几个问题:谁在用这个技能?他目前的流程是什么?他希望技能产出什么形态的结果?如果技能拿不到上游数据,有没有备用方案?一次执行最多允许花多少时间?这些问题没搞清楚之前,任何好看的方案都只是空中楼阁。
从技术层面看,场景决定了Skill的复杂度和技术选型。一个内部知识库问答技能,可能只需要检索和生成;一个工单自动分类技能,可能需要结构化输出和规则兜底;一个电商客服技能,则可能还需要情感分析、多轮状态管理。场景复杂度上去了,你自然知道该在哪里下功夫。所以我会把“场景定义”当作整个Skills开发的第一步,也是最重要的一步。
2. 场景化第一课:从需求到技能的定义
2.1 用5W2H把一个模糊需求压缩成可执行的场景描述
很多开发者写Skill上来就写代码,这不对。第一步应该是写场景描述,而且要写得极其具体。我的习惯是用5W2H来压自己:
- What:我需要这个技能完成什么任务?任务边界在哪?
- Why:不直接人做,为什么要模型来做?它比人做有什么优势?
- Who:谁会调用这个技能?是终端用户还是另一个系统?
- Where:这个技能主要跑在什么环境里?比如网页、飞书、微信生态?
- When:什么时候触发?是每天定时,还是问答时实时?
- How:它的核心处理流程是什么?
- How much:有没有性能要求?比如必须三秒内返回,或者必须支持并发。
不要小看这些粗糙的问题。我见过一个团队要做一个“合同风险分析”Skill,所有人都以为用户想要“AI自动阅读合同并给出风险提示”。但用5W2H一问才发现,真正的使用者是法务专员,他们根本不缺风险点分析,他们缺的是“自动比对最新法律条款并生成改法务批注”。前者是问答,后者是生产工具。差之毫厘,谬以千里。
写场景描述的时候,建议用一个表格固定下来。一方面逼自己思考,另一方面也为后续的测试用例提供依据。你可以把这张表当作Skill的需求规格说明书,代码还没写,边界和指标已经有了。
2.2 技能边界:把不做的清单写出来
这是最容易被忽略的一步。Skill设计里,大家忙着写“做什么”,很少有人写“不做什么”。但不做的清单恰恰能救命。
举一个亲身经历。我曾给一个团队做“订单异常提醒”Skill。最初的版本里,我把“判断订单是否异常”交给了大模型,结果模型经常判断错误,把正常退款的订单也标成异常。后来我在指令里明确加了一条:“只有满足以下三种条件的订单才判定为异常:支付成功但超48小时未发货;物流停滞超过72小时;用户投诉中明确提到未收到货。不满足任意条件的订单一律标记为正常。”加了这条边界之后,误报率直线下降。
模型本身没有“常识”,它的所有判断都来自你的指令和示例。你给它越清晰的边界,它就越接近一个可靠的工具。所以我在每个Skill里都会专门写一个“不处理”的部分,甚至把它提到输出格式之前。这不仅让模型的准确率提高,也让后续维护者知道当初设计这个Skill时的考虑,不会乱加功能。
2.3 输入输出契约:比模型聪明更可靠的标准
Skill要接入外部系统,输入输出就是它和世界之间的约定。我一般把输入输出设计成JSON Schema,这样即使不用代码强校验,也可以让模型按照固定结构输出。然后再由一段很薄的代码做最终的校验和兜底。
为什么强调“契约”而不是“自由发挥”?因为大模型天生适合生成创造性文本,但在对接业务系统时,创造性反而是灾难。下游系统不可能接受“有时候返回数组、有时候返回对象”的输入,更不会欢迎多余的字段。所以你的Skill输出必须稳定、可解析、无歧义。
举个例子,一个“发票信息抽取”Skill,它的输出契约应该长这样:
{ "invoice_code": "string", "invoice_number": "string", "issue_date": "date", "total_amount": "number", "seller": { "name": "string", "tax_id": "string" }, "items": [ { "name": "string", "quantity": "number", "unit_price": "number", "amount": "number" } ] }模型也许可以写出更精美的描述,但我只需要它严格按照这个Schema输出。确定性带来的收益,远大于那些花哨的自由发挥。
3. 实操实录:从一个“会议纪要Skill”看完整开发流程
3.1 场景与约束定义
所有的技能开发都从场景开始。这一次我们以“会议纪要Skill”为例,把它完整走一遍。很多人觉得会议纪要简单,无非是转写、总结、输出几条行动项。但实际一深挖,你会发现坑很深。
我的目标用户是某互联网公司的项目经理,每周要开四次跨部门会议。他的痛点不是记录,而是会后的任务拆解。每次会议结束,他都要把讨论内容转成任务,再分配给不同的人,还要设置截止日期。人工整理一份纪要大概花四十分钟,他希望这个Skill能在十分钟内完成,并且输出格式符合公司的项目管理软件导入标准。
约束条件是这样的:输入来自在线会议软件的转写文本,可能有漏字、口语化严重;输出必须包含议题列表、结论、待办事项三大部分,待办事项的负责人必须是公司内部系统里已有的员工花名;有争议的议题不能强行下结论,要标记为“待定”。这些约束写下来,Skill的开发目标就非常清晰了。
3.2 技能结构设计与参数选择
结构上,这个Skill分为三层:预处理层、分析与抽取层、格式化输出层。预处理层负责清理转写文本中的停顿词、无效语气词、多段重复内容。分析与抽取层负责识别议题、关键决策和行动项。格式化输出层负责把结果转换成公司项目管理软件能识别的结构。
参数选择上,必须控制模型输出长度。我给这个Skill设定的最大令牌数是1200,同时设置了温度参数为0.1。温度太高会产生含糊的表达,不利于任务提取,所以尽量低。但是也不能完全设为0,否则遇到错别字或口语化表达时,模型缺乏一点纠错弹性。
这里顺便说下“工具”的使用。在这个Skill里,我没有让模型直接去读转写文本,而是先由一段脚本把文本按说话人切分,并做了分段标记。这样模型拿到的是“说话人A在1分20秒说:……”这样带上下文的块,比直接给它整篇乱章更容易生成结论。看似多了一步,但实测准确率提升非常明显。
3.3 关键实现:指令模板与函数调用
指令模板是Skill核心中的核心。我因为踩过很多次坑,现在已经形成了自己的最小指令模板框架,内容大致如下:
你是一个会议纪要整理助手,你的输入是经过预处理的会议转写文本。 请严格按以下步骤处理: 1. 将文本划分为议题,用“议题1:xxx”的形式列出。 2. 对于每个议题,提取结论性语句。如果说话人之间有分歧,不要强行概括,标记为“待定”。 3. 识别所有行动项,包括“负责人”、“任务描述”、“时间节点”。如果转写中未明确提及这三个要求,统一填“待确认”。 4. 输出格式必须为JSON,格式如下: {...示例JSON...} 不相关的文本不要写入输出。 注意:行动项负责人只能从以下名单中选择:张三、李四、王五、赵六。不在名单中的名字视为无效,填入“待确认”。这里面最精髓的一句话是“不在名单中的名字视为无效”。模型从口语转写里识别出的人名可能是昵称、错字,比如把“张珊”识别成“张山”。你不能指望模型自己纠错,直接给它一个白名单更可靠。这算是我的独家技巧之一。
函数调用部分,我用Python写了一个轻量的校验函数。收到模型的JSON输出后,先解析,再校验必填字段,最后把待办事项批量导入项目管理软件。如果校验失败,我会返回一个清晰的报错信息给模型,让它重新生成一次。这个重试机制看似简单,但能扛住模型偶尔的字段遗漏。
3.4 测试与迭代:至少跑通三遍真实场景
很多技能开发者测完一个“完美案例”就上线了,这是大忌。我的习惯是准备三个梯度共九个测试用例。第一梯度是干净文本,几乎没有口语和错字,用来检查基本流程通不通;第二梯度是带口语化表达、有打断、有话题跳跃的文本,用来检查模型抗干扰能力;第三梯度是最混乱的真实转写,里面甚至还有几个人同时说话的乱码。
但是我更想强调的是“真实场景跑通”。光靠离线测试不行,我还会模拟真实调用链,比如从会议平台拉取转录文件、调用技能、再写入内部系统。这一步能暴露很多规划时根本想不到的问题。拿这个会议纪要Skill来说,我的第一版跑真实转写时,发现段落标记脚本在一条超长文本上会产生很大的计算消耗,整个上传接口直接超时。后来被迫给脚本加了分段上限,一批处理四千字,分批完成,才算把这个问题压下去。
还有一个很容易忽略的是模型版本升级导致的“行为漂移”。同一个Skill,在旧版模型上输出很稳定,换了新版模型的API后,JSON格式偶尔会有字段缺失。所以每次模型版本更新,我都会把九个测试用例完整跑一遍再上线,绝不因为API兼容就直接升上去。
4. 常见问题与排查技巧实录
4.1 场景定义不清导致技能“什么都干不好”
这是出现频率最高的问题。症状是模型经常“答非所问”或输出无用信息;病因是Skill的System Prompt里没有写清楚触发条件,导致模型在不适用场景下也调用了它。
排查方法其实很简单,把一次完整的请求日志打出来,看用户问了什么、Agent选了哪个Skill、最后返回了什么。如果用户只是问了一句“今天天气如何”,结果Agent调用了你的“数据分析Skill”,那大概率是技能描述写得不够精确。你可以把Skill描述里的“天气”和“数据分析”两个语义距离拉大,或者把触发条件写成“仅当用户问题中包含日期、关键字查询意图时”,这样Agent就不会乱选。
4.2 过度设计参数与模型能力的错配
有的团队喜欢在Skill里塞入十多个输入参数,期望模型一次性精准填完。但模型在自然对话中能提取的信息是有限的,参数越多,出错概率越高。根治办法是“最小充分参数原则”:只保留当前场景下不可省略的参数。
举个例子,做一个“休假审批”Skill,你只需要知道申请人、假期类型和日期范围。如果此时你再加一个“审批人评语”,而对话里根本没有这个信息,模型硬生成出来就会污染数据遇到这类情况,我会直接删掉非必要参数,或者把非必要参数设置为可选字段,并让模型在信息不足时填“无”。这样下游系统解析起来干净很多。
4.3 依赖外部工具时的稳定性问题
Skills经常要调用其他系统,最怕的就是外部系统抖动。我经历过的典型情况是:模型已经把待办事项正确解析出来了,但写回项目管理软件时接口超时,导致用户以为技能没生效。后来我加上了一个异步重试队列,接口失败先存本地,间隔三十秒重试一次,最多三次,全部失败再告警。这点在处理真实业务时非常重要,因为外部系统不可能永远稳定。
此外还有第三方API限流问题。很多Skill在小流量时跑得很顺,一上线就被限流。所以我会提前查询调用配额,并给Skill配置一个“熔断开关”:一旦连续调用失败超过五次,就直接返回固定提示,而不是把自己的出错信息打包发给用户。
4.4 我总结的三条避坑经验
第一,不要迷信大模型的能力边界。相信自己手写的规则兜底,而不是信任模型“总会理解”。一个带白名单校验的Skill,永远比一个靠模型自觉的Skill可靠。
第二,输出格式越严格越好。哪怕系统只需要一个字段,也给它一个JSON Schema。模型也许会觉得繁琐,但它输出的稳定性会因此呈指数级提升。
第三,测试集要留存。每次迭代后跑同一批回归用例,才能知道改动是提升了还是退化了。我见过太多人把骰子盲目调一圈,最后模型表现却变差了。留存测试是唯一能让你有“手感”的东西。
最后再分享一个很多人没注意到的小技巧:给Skill的每条指令都要有明确的优先级。当多个约束条件发生冲突时,写清楚哪个才是最高优先级的。我的经验是,如果输出格式和内容正确性发生冲突,那可解释的格式永远比内容正确性优先级高,因为格式错误会直接让下游系统崩掉,内容错误还有机会补救。
Skill开发这件事,说难也难,说简单也简单,关键就是肯不肯在下笔前先花时间把场景想透。工具和模型只是马,场景才是路。你自己心里有路,再普通的马也能跑赢方向感缺失的千里马。