agent-skills掰开揉碎讲清楚AI智能体如何从会聊天进化到会干活最近一段时间我一直在折腾一个叫agent-skills的方向。说得直白一点就是给大模型驱动的智能体Agent设计一套可复用的技能体系让它在接到任务时知道自己该调用什么能力、按什么顺序执行、遇到异常怎么兜底。这几个月带着团队从零搭了一套内部用的技能框架跑通了不少真实场景也踩了不少坑。这篇文章不打算讲什么宏大叙事就是把我在设计、实现、验证Agent技能过程中的实际经验摊开来说包括哪些设计决策是拍脑袋拍错了、哪些教训是后来被生产环境打脸才长记性的。适合正在做AI应用开发、或者准备把大模型从聊天框里搬进业务系统里的人读。先明确一个前提这里说的Skill不是那种写几个function让模型调用一下就完事。它是一整套封装好的能力单元包含触发条件、执行逻辑、输入输出契约、异常处理、甚至是该技能的使用说明书。只有当模型能像人翻工具书一样去检索、理解、调用、组合这些技能时Agent才真正开始从演示可以用走向生产中能用。下面我就按这条线展开。1. 为什么Prompt Engineering之后轮到Skills登场了1.1 单体Prompt的天花板前两年大家做Agent主流做法是写超长System Prompt把角色设定、知识库、工具列表、回答规范全塞进去。我最早也是这么干的塞到八千字之后效果非但没有变好反而出现了严重的问题模型开始遗忘中间段的指令每次对话要消耗几千token而且一旦某个业务逻辑要改就得改一整块提示词牵一发而动全身。那时候我们做了一个内部调研工具System Prompt里写了十几个工具的用法。实测下来模型经常把两个相似工具搞混遇到需要按顺序调用多个工具的任务步骤一多就开始乱。后来我意识到问题不在模型而在我们的组织方式——你把一堆能力平铺在一个上下文里等于要求模型自己去做能力路由这根本不是LLM擅长的事。1.2 Skills的本质是给模型一本可检索的工具书Skills模式的核心变化是把所有能力全都平铺展示改成按需检索、动态加载。系统里维护一个技能库Skill Library每个Skill都有独立的描述、参数Schema、执行逻辑、示例。模型在处理用户请求时先通过一个路由层判断当前任务涉及哪些技能再把命中的技能描述动态注入上下文。这个转变带来的直接好处有三个第一上下文不再臃肿模型每次只看到与当前任务相关的技能信息指令遵循率明显提高第二技能可以独立迭代改一个技能不影响其他技能也不用重测全部场景第三技能可以被复用和组合像搭积木一样构建复杂工作流而不用每次从头写Prompt。我用一个生活化的类比来解释单体Prompt就像一本所有知识都印在同一页上的参考手册翻起来累还容易看错行Skills模式则像一本带目录和索引的工具书先查目录、翻到对应章节、只读那几页自然又快又准。1.3 什么场景下Skills是刚需不是所有项目都需要完整的Skills体系。如果你的Agent只是做一个简单的问答机器人固定答案、少量工具那单体Prompt完全够用。但只要你遇到下面几种情况Skills基本就是刚需了工具数量超过10个且彼此之间存在相似功能模型频繁选错工具任务需要多步编排比如查库存→对比价格→生成报价单→发送邮件这类链路同一个Agent需要服务不同业务线不同业务线有各自的专用能力你需要对Agent的行为做精细化管控比如某些技能只允许特定角色调用或者需要记录每次技能调用的详细日志。我们就是在第四种情况上彻底转向Skills架构的——当业务方开始问这个操作是谁触发的、为什么这么执行的时候你就知道单体Prompt的时代结束了。2. Skill的本质拆解一个可复用能力单元的内部结构2.1 一个Skill应该包含哪几层我见过很多团队把Skill做成一个单纯的函数这是远远不够的。经过几个版本的迭代我们最终把Skill沉淀为五层结构每一层都有它存在的必要第一层是元信息层包括技能名称、别名、一句话描述、适用场景、不适用场景。这一层是给路由和检索用的写得越精准模型越不容易误调用。一个典型的反面教材是某个技能描述里写了可处理各种格式的报表结果检索时几乎任何带报表二字的请求都会命中它实际上它只能解析CSV。第二层是输入契约层定义参数名、类型、必填性、取值范围、参数之间的依赖关系。这一层非常关键因为LLM天然不擅长记住复杂的约束如果不在契约层显式声明当mode为monthly时period必须传上月日期范围模型生成的参数就很可能不合法。第三层是执行逻辑层这是实际干活的部分。它可以是一段Python代码、一个API调用、一条SQL查询也可以是多模态的混合操作。执行逻辑层要做的不仅是把事情办了还要把执行结果整理成模型容易理解的格式。我的经验是输出永远要带结构化字段比如execution_status、error_code、data.summary别让模型自己去大段文本里挖信息。第四层是失败兜底层明确这个技能在什么情况下会失败、失败后返回什么错误码、模型拿到错误码后应该怎么处理。没有这一层Agent一旦遇到执行异常就容易开始胡编乱造——它不会承认工具失败了而是会凭空生成一个看似合理的答案。第五层是示例层给模型提供1到3个典型调用样例包括标准输入输出和边界情况。示例层的作用是教模型长什么样才算一次正确的调用比你在描述里写一百句规范都管用。2.2 路由层到底要不要独立关于Skill的路由方式圈子里争论挺多。有人坚持让模型自己从全部技能里选理由是LLM本身就有很强的语义理解能力有人则坚持做一个独立的路由层先用小模型或者规则把候选技能过滤到三到五个再让主模型做最终选择。我的实测结论是当技能数少于15个且命名差异明显时让模型直接从全量技能里选是完全可行的一旦超过这个规模不设路由层就会出现频繁的错误调用。最稳的做法是做一个级联式的路由先是基于嵌入向量的语义检索取Top 10再通过一个轻量的分类器从Top 10里筛出Top 3最后把Top 3的详细描述交给主模型让它做最终决策。这样做的好处是主模型永远只需要在很小的范围内做选择决策负担低准确率也就高。当然加路由层也有代价——延迟变高、链路变复杂、还多了一个需要维护的组件。我当时做了个折中路由层不做成全自动的独立模型服务而是复用任务模型本身在Prompt里先做第一步找出与任务相关的技能编号再做第二步使用技能执行。省了一套部署效果差距也不大。2.3 Skill描述怎么写模型才爱看描述这块我踩过很深很深的坑。早期我自己写技能描述是按人类阅读习惯来的习惯性用本技能用于实现某某功能支持传入某某参数非常礼貌但非常啰嗦。后来发现模型对描述的解析方式和人不一样它对高频动词具体名词的组合最敏感。我总结了一个三段式写法第一段一句话tell the model when to use it用当用户需要……时使用此技能这样的句式。第二段tell the model when NOT to use it明确排除相似场景这一段的防误用效果比第一段还大。第三段tell the model what to expect说明调用后会返回什么以及后续能否串联其他技能。说个真实案例我们有个查天气技能最初描述是查询指定城市的当前天气情况支持摄氏度和华氏度单位转换。后来改成了当用户询问任何地点的天气、气温、降水、风力等情况时使用此技能若用户仅询问季节气候特征或历史气候统计不要使用此技能请使用气候分析技能调用后将返回包含温度、湿度、风速、天气现象的结构化数据。改动之后误调用率直接降了大概四成。区别就在于我把什么时候不能用这个负向边界写清楚了。3. 我把技能库做成能跑的过程从零到生产环境的完整链路3.1 第一步从高频业务场景反向抽取Skill清单很多人的做法是先写一堆技能再想应用场景这是本末倒置的。我当时带着团队先做了两件事第一把过去三个月里用户向Agent提出的真实请求全部拉出来按意图聚类第二统计哪些意图聚类是高频的、哪些是低频但高价值的。然后只针对高频和高价值的意图去设计技能其余先不做。这个决定非常重要。我们一开始贪多求快两周内写了三十多个技能结果一半以上从上线到现在一次都没被调过。反而是当时聚焦做的订单查询物流跟踪退换货申请这三个核心技能承担了绝大多数真实流量。先跑通最小闭环再逐步扩展在技能建设上同样适用。3.2 第二步定义技能基建先搭好脚手架在动手写业务技能之前我建议你先花时间把基础设施定清楚否则后面几百个技能会让你痛不欲生。基建主要包括几部分一是统一的技能注册表每增加一个技能就去注册表里登记元信息、版本号、负责人、依赖项。我曾经因为没做注册表在灰度一个技能时改崩了另一个技能排查了半天才发现两者共享了一个被改动的公共函数。二是统一的参数校验逻辑所有技能的输入参数先经过一层schema校验再进入执行逻辑把模型传错参数从业务代码里隔离出去。我们用的是类JSON Schema的校验规则实测能拦下大概百分之二十的不合法调用这些调用如果直接进业务代码都是要出事故的。三是统一的日志与追踪格式每个技能的调用都要记录调用的Skill ID、输入参数摘要、执行耗时、返回状态、错误信息、后续消费的模型上下文。没有这个追踪体系Agent出问题时你就像在黑箱里摸定位一次事故要半天。四是一个技能调试用的沙箱环境允许开发者在真实Agent语境之外单独调用某个技能看它单独跑是否正常。很多技能在单独测试时一切正常一放进Agent的多轮对话里就开始出现参数继承混乱的问题沙箱和联调环境都得有。3.3 第三步给Agent装上技能使用说明书技能本身写好了不代表模型就会好好用。我发现一个关键问题即使技能描述写得很清楚模型在真正执行时依然会犯三类错误——参数传错、顺序搞反、该调用的技能没调用。后来我们开发了一套技能使用说明书Skill Manifest机制和技能描述平行存在专门指导模型在什么任务流程中使用哪些技能的组合。比如说明书里会写当用户发起退换货请求时先后调用订单查询技能、售后政策匹配技能、生成退货单技能如果订单状态为已签收超过7天跳过售后政策匹配直接调用升级审批技能。这个说明书本质上是把人在业务流程中固化的经验翻译成LLM能读懂的执行路径效果立竿见影——在保障业务合规性方面它对模型行为的一致性提升是单纯靠技能描述远远达不到的。3.4 第四步联调测试与灰度上线的顺序技能开发完成后我们不是直接上线而是走了一条三层验证的路径第一层是单技能验证独立调用每一个技能检查它在各种合法/非法参数下的输入输出确保执行逻辑本身没有bug。第二层是技能链验证把业务场景里需要串行或并行调用的技能组合起来检查参数在多技能之间传递时有没有丢失、格式有没有变形。第三层是Agent端到端验证用真实的任务指令走完整流程重点观察模型对技能的选取是否符合预期、执行失败后能否正确兜底。我印象最深的一个bug就出现在第二层订单查询技能返回的时间字段是2025-03-01 14:23:11这种带时分秒的格式而物流跟踪技能预期的输入是20250301这种纯日期格式。单测都通过一连起来就报错。这种跨技能的字段格式对齐问题不联调根本发现不了。灰度上线时我会按内部账号→种子用户→5%流量→全量的节奏逐步放量同时盯三个指标技能调用的成功率、模型误调用率、端到端任务完成率。其中误调用率是最敏感的指标一旦某次灰度后误调用率上升超过一个百分点立刻回滚该技能版本回归排查不存在先观察观察这种说法。4. 技能设计里的反直觉经验为什么越简单越难做好4.1 技能粒度到底怎么切才合适技能粒度的划分是我和团队争论最久的问题。有人主张细粒度一个技能只干一件最小的事有人主张粗粒度一个技能封装一个完整业务动作。两种方案的利弊都很明显纯细粒度的问题在于调用链太长模型在一次对话里可能要触发七八个技能任何一个环节误判都会导致链路断裂纯粗粒度的问题在于复用性差两个业务场景稍微有点差异就要各自重写一个技能。我最终找到的平衡点是以用户一次不可分割的意图为粒度边界。比如修改收货地址是一个技能修改收货地址并重新计算运费就需要拆成两个技能并通过说明书进行组合。判断粒度合不合适有一个简单标准如果一个技能在执行过程中会调用另一个技能的子步骤说明粒度太粗了应该把它拆开如果一个技能必须依赖调用方给它传一大堆前置上下文才能执行说明粒度太细了应该把它收拢一点。这个规则听起来简单但执行起来需要大量的业务梳理。我们组织过一次技能粒度评审会把已有技能全部列出来逐一回答它是否代表了一次不可分割的意图。当时砍掉了五个、合并了三个技能库的误调用率下降得非常明显。4.2 相似技能怎么共存不打架技能库里最头疼的问题之一是如何处理一批看起来很像的技能。比如查询订单和查询物流是两个技能它们都要接收订单号作为参数描述里有一段高度相似。模型在调用时经常混淆——用户明明想知道包裹到哪了模型却调了订单查询并返回订单状态。我们最后用的是互斥声明机制在路由检索和模型选择两个层面同时做处理。路由检索层面我们把相似技能的向量表示做负样本处理训练嵌入时让它们互相保持距离模型选择层面在每个技能描述里显式声明如果你要查询物流轨迹请使用物流跟踪技能该技能不负责订单状态查询。这个方法虽然看起来笨但效果非常实在相似技能的混淆率可以降低将近一半。4.3 别让技能变成黑盒还有一个容易被忽视的经验技能内部可以复杂但它的行为边界必须透明。我们需要让Agent知道这个技能用了什么数据、做了什么处理、哪些事情它做不了。比如一个报价计算技能内部可能有十几条计价规则但如果模型无法理解它的输出含义用户追问为什么这个价格是这么多时模型就答不上来只能敷衍。为了解决这个问题我们要求每个技能的执行结果里除了业务数据之外必须附带一个执行说明字段把关键处理逻辑浓缩成一段人话级别的解释。模型在向用户答复时可以拿这个字段作为依据来组织自然语言效果比让模型自己推理技能内部逻辑要可靠得多。5. 从几十个到几百个技能库的治理才是长期挑战5.1 技能重复建设与技能债务技能一多新问题就来了。团队里不同人各自为战A在项目里写了一个汇率换算技能B在另一个项目里也写了一个功能几乎一样的只是参数风格不同。这种重复建设的后果是技能库膨胀、语义检索时出现语义冲突、维护者不知道该改哪个版本。我把这类问题叫做技能债务——和代码债务类似它不会立刻让系统崩溃但会持续侵蚀系统的可维护性和准确率。为了应对我们建立了一个技能评审委员会式的机制任何新技能的立项都要先检索现有技能库评估是否存在可复用的旧技能再决定是新建、扩展还是收缩。审批流程虽然增加了一点时间成本但从全局来看它把技能库的数量增速控制住了避免了无政府式的膨胀。5.2 技能版本管理与回滚策略技能是要随业务迭代的不可能一成不变。我们内部给技能版本制定了语义化规则主版本号代表行为契约的变更比如新增了必填参数次版本号代表执行逻辑的调整但对外契约不变补丁版本号只修bug。主版本号的技能是不允许不经灰度直接替换的因为它可能改变下游依赖方的行为预期。版本回滚的策略我也要强调一下无论当时改得多么自信都要保留上一个版本的技能代码和描述文本。有一次我们把销售预测技能的模型调用从A模型切到B模型上线后发现B模型对某些数据分布的理解有明显偏差预测结果波动很大用了不到十分钟就立刻回滚到A模型。因为提前保留了完整的旧版本快照整个回滚过程非常丝滑。5.3 技能的可观测性你不知道它在为什么样AI打工最后一个治理层面的问题是技能的使用情况到底怎么度量。我强烈建议从第一天就明确埋点每次技能调用记录调用方、调用时间、输入输出大小、延迟、成功率、被模型的采纳情况。这套数据后面有大用你可以分析哪些技能是热点优先保障它们的性能和稳定性你可以发现僵尸技能连续一个月零调用要么下架要么和别的技能合并你可以做技能路由效果的A/B实验同一个技能描述A和描述B哪版的路由准确率更高你甚至可以基于调用记录反向优化模型——如果某个技能经常被模型错误的相似技能取代说明它们的描述边界还没划清。我见过太多团队把精力全放在写新技能上对技能上线后的运行情况毫不关心。最后的结果就是技能库越建越大但整体准确率却在下滑。可观测性不是可有可无的锦上添花而是技能体系能否长期健康运行的基础设施。6. 评估技能好坏除了准确率还要盯住这三个容易被忽视的指标6.1 误调用率跟你以为的准确率不是一回事很多团队评估Agent技能只盯着任务完成率或者回答正确率这远远不够。真正影响体验的是误调用率——模型调用了错误的技能或者在不该调用时调用了技能。这两个指标看起来都在准确率的覆盖范围内但实际统计口径完全不同。举个例子用户问昨天下午那个订单发货了吗Agent调用了订单查询技能但查询技能默认填补的当前时间范围没覆盖昨天下午于是返回了空结果模型接着自己编了一句该订单尚未发货。从任务完成率角度看这个回答部分是错的但更本质的问题其实是技能实现没有处理历史时间范围参数。这种问题只有通过误调用率加参数覆盖率一起看才能暴露出来。6.2 技能内部执行时延和Token消耗技能的执行时延直接决定了Agent对话的流畅度。用户问一个需要调用三个技能串行处理的问题如果每个技能消耗两至三秒整个对话就是七八秒起步用户基本等不了。我们做了两轮优化第一轮把所有可并行的技能从串行改成并行时延降了一半第二轮给高频技能做结果缓存对相同参数的请求直接返回缓存结果时延又被砍掉了一大截。Token消耗也不容忽视。每一个技能的描述、Schema、示例、执行结果都会占据上下文空间一旦上下文被撑满Agent的指令遵循能力、多轮记忆能力都会直线下降。我们有专门的分析师定期统计每个技能在上下文中占用的Token占比对占比异常高的技能做描述精简处理。6.3 失败后的翻盘率这是我自己定义的一个指标但我认为它比任何指标都重要。所谓翻盘率是指技能执行失败后Agent能否通过合理的兜底机制最终仍然完成任务。比如订单查询技能因为系统维护返回了失败模型能否主动告知用户稍后再试而不是编造一个查询结果物流跟踪技能缺少某平台接口模型能否引导用户通过其他渠道查询。翻盘率过低说明技能设计中的失败兜底层没有发挥作用。我们在每次技能联调时都会人为制造故障测试Agent在技能失败、参数非法、接口超时等各种场景下的应对表现。这些故意找茬式的测试暴露的问题比常规功能测试多得多。我建议任何一个技能在上线前都要过一遍这样的故障注入测试别让Agent在真实用户面前表演一本正经地胡说八道。6.4 建设一套自己的技能评测集所有指标的评测都离不开一套稳定的评测集。我们维护了一个专门的技能评测集包含三类case正常业务case、边界case、坑人case故意包含与技能描述相似但不应调用本技能的表述。每轮技能迭代后都要在这个评测集上跑一遍全量回归对比新版本的通过率和旧版本的差异。这个评测集是动态更新的凡是在生产环境让Agent犯错的新case我们都会补录进去。随着评测集越来越大技能迭代的底气也会越来越足。我自己最深的一个体会是没有评测集的技能迭代就像在雾里开车你永远不知道这次改动到底是进步还是退步。三个月的快速迭代之后评测集积累的价值会超过任何单一技能本身。7. 写在最后关于Agent技能这件事我目前最真实的几个判断我不敢说自己已经掌握了Agent技能设计的终极答案这毕竟是一个快速演进的方向。但有几个判断是在反复被打脸之后逐渐坚定下来的分享给同路人参考。第一个判断是技能描述的文字质量对最终效果的影响远超代码质量本身。一个技能的执行逻辑再严谨如果模型在路由阶段压根没选中它一切都白搭。我见过太多团队把时间花在优化执行代码上对描述却随手一写这是捡了芝麻丢西瓜。第二个判断是不要迷信让模型自己学会一切。给模型足够的技能描述和示例确实能学会很多东西但涉及业务合规、强顺序、参数约束严格的场景更有效的做法是提前把说明书写好用结构化的Manifest约束住模型的行为边界该绑的规矩一定要绑。第三个判断是技能的演化是一个持续工程不是一次性建设。业务变了、模型换了、数据分布漂了技能都要跟着调整。我把整个技能系统的运行比作养一座花园——你可以把花种下去但不能指望它自己就一直好好长你每次引入一个新技能都要像种下新苗一样给它标记、浇水、观察、修剪还要时不时拔掉枯死的废枝。我在实际项目中最满意的一个改动是把所有技能的版本变更都纳入到统一的变更日志里每次发布都写清楚改了什么、为什么改、影响哪些下游场景。一开始团队觉得多余到后面排查问题、做回归时所有人都在感谢这个决定。如果你也正在搭建自己的Agent技能体系我建议你从最小的闭环开始选三个最高频的业务场景设计对应的技能把路由、描述、执行、兜底、追踪这套链路完整跑通然后再去扩展规模。先把地基打牢让上面的楼盖多少层都不怕。根据我这几月的经验地基和楼之间最大的坑通常是在技能描述和失败兜底这两层——这两个地方多花时间打磨回报率远高出你的预期。