
1. 技能体系Agent能力编排的隐藏基石在做AI Agent应用落地时我踩过最大的坑不是模型选型不是Prompt调优而是把所有的逻辑全塞进一个几百行的系统提示词里让Agent“自由发挥”。结果大家应该都能猜到看起来什么都会实际上什么都做不深。用户让它查个天气它能跟你聊十分钟人生让它调个接口它连参数都拼不对。后来我开始把关注点放在“agent-skills”这个方向上才慢慢摸到门道。所谓agent-skills直译就是“智能体技能”本质上是把Agent能做的事拆解成一棵技能树每个技能对应一组可复用的能力模块包括触发条件、执行流程、输入输出协议、评估标准。这就像给Agent装了一套可编排的“肌肉记忆”让它知道什么场景该调用哪块肌肉、用多大力气、做到什么程度算完成。这篇文章我想把这个方向从底层逻辑到落地细节完整过一遍。不是那种“Agent是什么”的入门科普而是我实际调过技能库、写过技能协议、在线上被真实用户蹂躏之后总结出来的一套方法论。适合已经在做Agent应用、或者准备做复杂Agent编排的团队参考看完可以直接拿来对照自己的方案。2. 为什么“技能”比“意图”更适合做Agent能力边界2.1 从意图识别到技能调用的范式迁移最早做对话机器人核心是意图识别。用户说一句话模型判断这是“查天气”还是“订机票”然后走对应流程。这种方式在单轮、垂直场景下挺好用但到了开放域、多轮任务场景就撑不住了用户一句话可能隐含多个意图意图之间还有依赖关系模型一旦误判整个对话就崩了。而agent-skills的思路是反过来的先把Agent能执行的动作抽象成一个技能注册表每个技能有明确的schema描述然后让Agent在运行时通过推理决定“我该调用哪个技能、按什么顺序调用”。这不只是从“分类”到“检索”的转变而是把Agent从被动响应变成了主动编排者。技能是Agent能力的最小封装单元Agent本身成了一个调度器。我实际测试下来的感受是用技能体系之后系统对表达歧义的容忍度明显变高了。用户说“帮我看看明天北京适合穿什么”如果是意图识别你得把“穿衣建议”单独做成一个意图但在技能体系里这可以拆成“获取天气数据”加“生成穿搭建议”两个技能的组合编排Agent可以自己决定先取天气还是先问偏好灵活性一下子就上来了。2.2 技能树设计顶层规划决定底层复杂度技能体系不是简单列一堆函数名就完事它需要一套层级化的设计。我习惯把技能分成三层原子技能、组合技能、业务技能。原子技能是最小不可拆的能力单元比如“读取文件内容”“发送HTTP请求”“执行SQL查询”。组合技能是把多个原子技能按固定模板串起来的标准化流程比如“获取指定城市的实时天气”就是“地理编码 HTTP请求 数据解析”三个原子技能的组合。业务技能则是面向具体场景的完整闭环比如“智能客服处理退款请求”它内部会串联权限校验、订单查询、退款执行、结果通知等多个组合技能。这层拆分最大的价值是复用性。同一个“地理编码”原子技能既可以被天气技能调也可以被外卖推荐技能调不存在重复开发。而且当某个技能被多个上层场景复用时它的稳定性会自然得到更多的验证和打磨形成了一个良性的质量正循环。2.3 技能描述写给模型看的“使用说明书”技能注册表里最容易被低估的是description字段。很多人觉得description就是给开发者看的注释随手写一句“获取天气数据”就完事。但在Agent场景里这段描述是模型判断何时调用该技能的核心依据重要性不亚于代码本身。我总结了几个写技能描述的经验说清楚“在什么场景下用”不要只写“获取天气”要写“当用户询问当前或未来某天的天气状况、气温、降水概率、是否需要携带雨具时使用本技能”说清楚“不要用什么场景”比如“本技能仅用于查询不做穿衣建议生成”给出输入参数的语义说明“city字段支持中文城市名或行政区划代码不建议传入模糊地理描述如‘南方’”标注前置条件“需要先调用地理编码技能将城市名转为经纬度再调用本技能”这个动作本质上是给模型写“使用说明书”。我见过很多线上事故模型在不该调技能的时候调了、在该传精确值的时候传了模糊值最后排查下来大概率是description写得太含糊。所以我现在每次上线新技能都会安排一整个review轮次专门打磨描述文本。3. 技能间的协作机制让Agent学会“组队打怪”3.1 技能编排的三种范式单个技能即使做得再精能覆盖的场景也有限真正体现Agent价值的是多个技能之间的编排协作。我在项目里总结出三种常用的编排范式可以根据场景灵活选顺序流水线上一技能的输出作为下一技能的输入链路是线性的。适合流程固定的场景比如“商品详情生成”就是“查商品库”到“生成文案”再到“配图推荐”。条件分支Agent根据当前上下文决定走哪个分支技能。适合需要对不同输入做差异化处理的场景比如客服系统里用户身份是VIP就走专属处理技能否则走通用技能。并行扇出一个主技能同时拉起多个子技能最后汇总结果。适合需要多渠道信息汇聚的场景比如“竞品调研”可以同时调“新闻检索”“商品爬虫”“评论情感分析”三个子技能。这三种范式不是互斥的真实场景往往是它们的组合。我们做的一个多功能工作台Agent底层就是一条“入口校验”流水线中间根据用户选择做条件分支再用并行扇出去抓多个数据源最后汇总成一份报告。3.2 技能间通信数据契约才是真正的黏合剂技能能协作起来靠的不是共享全局变量而是一套严格的数据契约。每个技能的输入输出都定义成JSON Schema字段名、类型、允许值范围、默认值、依赖关系全部要写清楚。这样Agent在编排时就能通过校验器提前发现“这个技能输出的字段在下一技能里根本不存在”的断裂问题。我见过不少团队在这里栽跟头。技能各自独立跑都没问题一串起来就开始报奇奇怪怪的错——有的是字段名不一致有的是单位没换算有的是时间格式不统一。这些归根结底都是数据契约没做好。我现在要求所有技能在注册时必须附带完整的输入输出Schema示例并且要提供正常值和边界值两组mock数据方便联调和回归测试。3.3 动态技能发现让Agent知道自己“会什么”前面讲的都是静态技能库技能是预先写好、写死在Agent能力边界里的。但真正进阶一点的方向是动态技能发现让Agent在运行时感知“当前对话场景下我有哪些可用技能”并自主决定加载哪些技能进入推理上下文。这个需求来自一个实际痛点当技能库超过三五十个之后把所有技能的description全塞进提示词里既浪费token又会干扰模型判断效果反而变差。解决办法是做一个两级检索先用一个轻量的embedding模型把用户当前对话内容映射成向量在技能描述库做一次向量检索召回最相关的Top-N个技能再把这N个技能的完整描述注入到推理上下文中。这套机制跑起来之后技能选择准确率大概提升了十多个百分点token消耗也降下来了不少。不过要提醒一句向量检索召回是个概率过程Top-N设太大会有噪音设太小会漏召回。我一般把N设在8到12之间并且规则上兜底用户明确提到某个技能名时直接用规则强制加载对应技能。4. 技能开发与调试的完整实操记录4.1 一个技能从需求到上线的七步流程技能开发虽然比传统功能开发多了Agent调度的维度但只要流程规范不会比普通后端开发复杂太多。我梳理了一套标准流程团队新同学照着走基本不会跑偏需求拆解明确该技能解决的场景识别是否需要复用已有原子技能没有的话先补原子技能协议定义写出输入输出JSON Schema包括字段名、类型、约束、示例值主体实现写核心执行逻辑保证无副作用、可重入、可观测描述撰写编写description字段说明触发场景、参数语义、边界条件单元验证用单测和mock数据验证技能本身功能正确性集成评测把技能接入Agent环境用一组真实对话场景验证调度准确率灰度上线先放量10%观察日志监控误调用率和超时率稳定后全量这里特别想聊一下“可观测”这件事。技能跑在Agent里跟普通API的最大区别是它被调用的原因不是用户直接触发的而是模型推理出来的。所以日志必须完整记录“模型决策链路”——模型看到了什么上下文、选择了哪个技能、传入了什么参数、结果是什么。否则线上出了问题你连“它为什么要调这个技能”都回溯不了。4.2 技能调试工具链跟踪Agent的每一步“思考”调试技能最大的难点是定位问题归属是技能本身的逻辑bug还是模型调用技能时的决策错误我一开始用纯日志方式靠print和log一条条追效率低得让人抓狂。后来搭了一套路演监控面板核心是把每次Agent运行的完整轨迹记录下来包括模型输入输出、token用量、技能调用链、每步耗时等。现在排查线上问题我第一步先看轨迹图确定问题发生在决策层还是执行层。如果轨迹显示模型压根没选对技能优先调description和few-shot示例如果轨迹显示选对了但执行报错才去查技能代码。这套思路能把排查时间从小时级压到分钟级强烈建议做Agent的团队都搞一套。另外多说一句技能调试不要只在模拟环境里跑要多用线上脱敏后的真实对话。我测试时发现模拟环境里表现都正常一上真实用户对话就废掉的情况多半是真实对话里有大量口语化表达、指代消解和多轮省略跟测试脚本差距太大。4.3 热更新与版本管理技能灰度不中断传统后端功能发布可以平滑灰度但技能发布有个额外风险模型可能在灰度期间就调度到新技能了造成行为突然变化。我的做法是给技能做版本号并在技能描述里增加“version”字段。灰度策略是在Agent调度层加白名单只有特定userId或特定对话ID才能命中新版本技能其他的全部走老版本。如果发现新版本行为偏离预期可以在调度层直接把该技能下版本标记为不可用恢复老版本全程不需要重新发版。下线的技能不会立即删除保留在注册表里但标记为deprecated防止历史数据在做轨迹回放时因技能缺失而中断。这条机制帮我们避过好几次线上事故。有过一次新技能上线三天后才发现它在某些边界输入下会返回非常误导性的结果当时就是靠这个灰度开关秒级回滚了。那一周我逢人就推荐技能灰度这个习惯真的能救命。5. 技能评测体系能力有没有变好不能被模型自己说了算5.1 搭建基于真实场景的评测集Agent技能的评测跟传统SLU/NLU评测差别很大只测技能自身准确率远远不够还得测调度准确率、多轮对话中的调用时机、边界情况下的兜底合理性。所以评测集不能全用构造数据必须采样真实用户对话脱敏后做人工标注。我的做法是双维度标注给每个测试样例打“技能选择”标签和“参数填充”标签。技能选择标签包括“应调用技能A”“应调用技能B”“不应调用任何技能直接闲聊回答”三类参数填充标签则看模型填的技能参数是否完整、准确。这套双维标注的好处在于哪怕模型最终返回结果不对你也能区分是哪一层出了问题从而精准修正。比如有一次模型在用户问“今天热不热”时正确调用了天气技能但传成了昨天日期这就属于参数填充问题跟技能调度链路无关。5.2 关键指标不只盯准确率还要盯“不该动的时候不动”技能调度的准确率好定义但真正要命的是“误调用率”——用户根本没想要Agent调技能结果模型多管闲事。这个指标不盯紧用户体验会非常糟。我一般监控三个指标召回率该调技能时是否调了、精确率调技能时是否正确、误调用率不该调时是否调了。前面两个好理解第三个要单独建一个“闲聊/拒绝场景评测集”专测模型在用户问无意义问题、表达情绪或提要求但信息严重不足时会不会乱调技能。娘在AI工程设计里当且仅当功能特性满足研发侧验收标准团队才会把资源投入下一个模块。5.3 回归机制每次改技能描述都要重跑评测集有一次我改了一个技能description的措辞自测觉得没问题就上线了结果技能被调用的频率暴涨了3倍大量原本不该走技能的对话被错误路由进来。后来加了一条规矩凡是修改技能description、编排模板或数据契约必须强制跑全量回归评测集指标回退超过阈值就不允许上线。这条规矩帮我防住了不少隐性回归。特别是技能description这类看似人畜无害的改动实际上对模型行为的影响很大。模型对文本是敏感的哪怕只是把“获取”改成“查询”都可能改变它在某些场景下的调用倾向。所以我现在对技能描述的改动比代码改动还要谨慎每一次变更都当成一次正式发布来对待。6. 线上问题排查实录Agent技能体系的那些坑6.1 模型“过度联想”技能调用的边界防御线上反馈最多的一类问题是用户只是在聊天Agent却莫名其妙调起了技能。比如用户说“我心情不好”Agent直接调了“天气查询”说“明天会下雨别难过”。这属于模型把相关性想过头了它觉得能关联上就调了。边界防御我用了三层策略一是强化description里的负向声明明确写“不要因为用户表达情绪而调用本技能”二是在调度层加一个前置校验器对不满足前置条件的调用请求直接拦截比如用户提到的城市名不在支持列表里就拒绝调用三是在评测集里加入大量边角对话样本反复测试模型在闲聊场景下的“不动”能力。有段时间这三层跑下来误调用率压到了很低的水平。但记住没有任何防御策略可以彻底消除误调用唯一的办法是持续用线上失败样例反哺评测集让系统在迭代中不断压制错误行为。6.2 多技能竞争同一场景时的路由冲突技能库大了以后经常出现多个技能在功能上重叠。比如“查天气”和“穿衣建议”都牵扯到天气数据模型选哪个都说得通。初看没什么问题但实际用户反馈胶水感很强用户先问“明天会不会下雨”Agent查了天气用户接着问“那我穿什么”Agent又只在原技能基础上硬答而不去触发“穿衣建议”技能。这个问题本质是技能边界定义不清。我的解法是对功能重叠的技能做“主从拆分”主技能负责该场景的核心闭环从技能只提供特定维度的辅助信息。模型面对同一场景时优先选中主技能由主技能内部决定是否需要调用从技能。在数据契约层面“查天气”的输出会为“穿衣建议”保留一个挂载点用户接着追问时Agent可以顺滑地切换过去而不是重新跑一遍完整链路。6.3 技能黑盒问题模型把技能参数填废了还有一类高频问题模型技能选对了但参数填得太离谱。最典型的是城市名传了同义词用户说“魔都”模型传成“魔都”而不是“上海”、时间解析错误“明天”解析成了“今天”。这种问题修起来不麻烦但排查路径长因为表面上看是技能执行结果不对容易误以为是模型问题。我现在给关键参数加了一层“参数规范化前置”在技能入口统一做参数映射和清洗同义词映射、时区统一、默认值兜底。同时在技能调试面板把模型原始传参和规范化后的最终参数并列展示一眼就能看出问题在哪一段。另外强烈建议在description里给出参数示例值模型看了示例通常会照着填比干写描述效果好很多。7. 把技能体系做成团队能力资产做agent-skills这大半年我最大的体会是技能体系不是一次性工程项目而是一套需要长期运营的能力资产。它跟代码库一样需要版本管理一样需要review一样需要持续补充测试用例。但它比代码库更特殊的地方在于它的“接口”不是给另一个程序员调的而是给一个模糊计算系统调的——这决定了它永远需要人类来校准边界和兜底。前期搭建技能注册表和处理数据契约确实繁琐但一旦跑通后续新增技能的成本会越来越低。现在我们的平台每接入一个新数据源、一个新工具最快半天就能包装成技能上线Agent就多了一项本领。这个增长速度是过去写死意图流给不了的。最后想分享一个小经验架构师在做技能体系之前可以先带着团队把所有可能涉及的动作列一个完整清单哪怕有些动作当前用不上也先在注册表里占位。这样做有两点好处一是让Agent在规划路径时知道自己“未来会什么”有助于先生成合理的执行计划二是避免后续技能扩张时因字段命名、数据契约不一致而返工。技能系统的地基往往就是从这张不起眼的清单开始的。