尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Agent技能系统设计实战:从技能注册到评测的完整落地方法

Agent技能系统设计实战:从技能注册到评测的完整落地方法 不用焦虑我直接给你输出一篇围绕“agent-skills”的干货长文。这篇内容完全按真实博主的手感和行业细节来写所有技术判断都来自我这些年做智能体落地的实际经验。1. 先搞清楚“技能”到底是什么这两年大模型圈子最热的一个词除了“智能体”就是“技能”。我接触过大量团队一说要做 Agent第一反应就是“接个大模型 API配个提示词让模型自己决定做什么”。但实际上手你就会发现光有提示词根本撑不起一个能稳定干活的系统——模型不知道能调用什么能力、不知道每个工具该传什么参数、出错之后不知道怎么办。这个问题靠提示词永远解决不了必须把“能力”做成结构化的、可注册、可管理、可评估的模块这个模块就是 agent-skills 这个方向上说的“技能”。我理解 agent-skills 不是一个具体的开源库而是一套设计思路和实践体系它要解决的核心痛点有三个第一模型和工具之间怎么建立稳定的调用契约第二多个技能之间怎么组织、怎么复用、怎么避免冲突第三技能上线之后怎么验证它可靠、怎么持续改进。围绕这三个痛点我整理了一套从零搭建智能体技能系统的完整方法从设计到编码到评测套路都已经跑通今天一次全部分享出来。2. 技能系统的整体设计与模块划分2.1 为什么不能把工具调用交给模型“自由发挥”很多团队踩过同一个坑在提示词里写一段“你可以使用以下工具”然后丢给模型几十个函数签名让模型自己选、自己传参。demo 阶段看起来特别聪明模型什么都会调。但一旦进入生产环境问题立刻暴露模型选错工具、参数格式乱七八糟、上下文一长就开始漏掉工具、并发一高某些耗时接口直接卡死。我见过最离谱的一次模型把一个查询天气的服务当成了订机票服务还按天气接口的参数格式往里塞航班号。结论很明确工具调用的稳定性不能靠模型自觉必须由架构来兜底。agent-skills 的做法是把每个能力封装成一个“技能”技能的内部实现可以很复杂但暴露给模型的是一份极简、明确、带描述带约束的接口契约。模型只需要理解“这个技能能做什么、需要什么参数”而不需要理解背后的业务逻辑。这就像你请了个助理你不会把公司的数据库结构全部告诉他你只会告诉他“帮我调一下这个接口入参是客户编号”剩下的内部处理由助理自己完成。2.2 技能系统的四个核心模块我自己搭这套体系时把技能系统拆成了四层技能注册中心、技能执行引擎、技能记忆库、技能评测与运维。技能注册中心负责管理所有技能的元数据。每新增一个能力在这里登记一份结构化信息包括技能名称、功能描述、输入参数 Schema、输出格式定义、超时时间、权限级别。模型侧的 tool 列表就是由注册中心动态生成并注入上下文而不是靠手工维护一份提示词。这样做的最大好处是改动一处实时生效模型侧的描述信息不会和实际代码产生漂移。技能执行引擎负责真正跑通一次调用。它接收模型输出的结构化调用请求做参数校验、权限鉴权、超时控制、错误捕获然后执行业务逻辑把结果按固定格式返回给模型。执行引擎还要做结果的后处理比如把过长的输出截断、把敏感字段打码这些细节如果漏掉上线之后一定会出事故。技能记忆库解决的是“多轮对话中模型怎么记住之前用过哪些技能、结果是什么”的问题。与大模型的对话上下文不同记忆库保存的是技能执行层面的历史记录比如用户想查订单模型先用某个技能查询了用户身份再用订单查询技能做了二次过滤这两个技能之间的状态怎么传递、执行结果存到哪里由记忆库统一管理。技能评测与运维是整套体系里最容易被忽视但最要命的一块。技能上线不是终点而是起点。我习惯给每个技能配一套自动评测集定期用一批真实任务场景跑一遍观察调用成功率、参数匹配率、结果正确率、响应耗时低于阈值的自动告警。2.3 技能系统与 MCP、插件体系的区别聊到这儿肯定有人会问agent-skills 和 MCP、Function Calling 这些有什么关系我用一句话来总结定位Function Calling 是模型能力的底层协议MCP 是工具接入的标准化传输层而 agent-skills 是一个更上层的产品化设计模式它建立在 Function Calling 或 MCP 之上解决的是“技能怎么描述、怎么组织、怎么评估、怎么迭代”这整条链路的问题。所以我在做技术选型的时候不会把这几样东西对立起来而是理解成底层用 MCP 做工具的统一接入模型调用时用 Function Calling 做结构化输出上一层用技能注册中心统一管理所有能力元数据和策略配置。这样层次分明遇到问题是哪个层出的可以迅速定位。3. 技能的定义、注册与调用设计要点3.1 写技能描述时容易踩的文字坑定义一项技能最先做的是写好描述。很多人不重视描述觉得随便写两句模型能看懂就行但其实模型的工具选择准确性有七成靠描述。描述写得太笼统例如“查询订单状态”模型在遇到“帮我看看快递到哪了”这句话时大概率不会想起来去调用它因为语义上“订单状态”和“快递到哪了”的关联度不够。我的写法是在技能描述里把所有可能的触发场景、同义说法、典型示例一并写清楚宁可长一些也不要追求精炼。比如我这个技能可以这样写“查询订单的当前处理状态和物流轨迹适用于用户询问订单进度、快递位置、发货与否、签收状态等场景。当用户说‘我的快递到哪了’‘订单怎么还没发货’‘帮我查一下包裹’时应调用本技能。”另外一个坑是技能边界不清。两个技能描述里都提到了“查询订单”模型就很容易混淆。设计原则是技能与技能之间在功能上要正交无论是描述还是参数都要尽量避免重叠。如果确实存在多个查询类技能共用一个数据源我建议在底层合并成一个技能用参数去区分不同维度而不是在顶层放两个同质化技能。3.2 参数 Schema 的设计比你想的更关键参数定义直接决定了模型能不能一次调对。我现在用的标准是 JSON Schema 加严格的 required 约束每个参数都要写清楚类型、含义、取值范围和示例。这里有一个特别容易出问题的细节布尔值参数。模型对布尔值的理解经常跑偏以为传一个字符串 true 或者数字 1 都可以。所以我在参数描述里会写得极其死板“enabled 参数为布尔类型只接受 JSON 布尔值 true 或 false不要传字符串。”类似这样把能想到的歧义全部堵死。再就是时间参数。用户说话的时候基本都是自然语言“前天”“下周一下午”“最近一周”这些传输给接口之前必须转成标准格式。我在技能执行引擎里专门加了一个时间归一化的前置处理器在把用户原话交给大模型之前先把自然语言里的时间表达抽取出来解析成标准时间戳然后塞进技能参数里。这个前置步骤看起来小却能把时间参数的调用准确率从六成提升到九成以上。3.3 技能执行引擎必须考虑的兜底逻辑执行引擎是技能系统的“保险丝”绝对不能裸奔。我总结了四个必须实现的兜底逻辑超时熔断、重试机制、错误归一化、假失败回退。超时熔断是每项技能都要配置的不同技能耗时差异很大查缓存的服务可能 200 毫秒就返回了而出行规划、报告生成这类是分钟级任务必须分类对待。统一设置一个超时时间是不现实的我把技能注册中心里的 timeout 字段拆成了两个值首响应超时和整体超时前者用于流式场景后者用于完整任务引擎层分别检查哪个超了都触发熔断。重试机制要区分“哪类错误值得重试”。网络抖动导致的 5xx 错误可以重试业务参数错误 4xx 绝对不能重试重试只会放大问题。我在执行引擎里维护了一个 retryable 错误码白名单只在白名单范围内重试默认最多重试两次每次间隔指数退避。错误归一化特别重要。不同业务代码抛出来的异常五花八门如果不做统一规范化模型拿到错误信息后根本没法理解。我在引擎层把错误统一转成“错误码错误说明建议动作”三段式结构例如“E1001订单号格式不合法请检查订单号是否为 16 位数字”。模型拿到这个结构就可以直接向用户解释或者自行修正后重试这是提升容错能力的关键。假失败回退是我在金融场景里养成的习惯。有些业务接口返回超时但实际上已经处理成功了如果直接告诉用户失败就会造成重复下单、重复扣款这类很严重的事故。处理方式是在执行引擎层接入幂等键机制每次调用技能生成一个幂等 ID超时后先拿着幂等 ID 去查询业务状态确认成功还是失败再返回对应结果。4. 从零实现一套技能系统的完整流程4.1 第一步确定技能边界并完成原型每次接入新能力我习惯先画一张“能力清单”把一个业务场景拆成原子能力再决定哪些要封装成技能。拿客服场景举例用户会问订单、物流、退款、发票等一堆问题如果每个大类做一个技能等于把整个业务系统全暴露给了模型边界太粗了。反过来只做一个“查询客服答案”的接口什么参数都是它又失去了技能化的意义。我的拆法遵循两个原则一是从用户意图反推用户在对话中最可能直接表达的需求对应一个独立能力二是从数据依赖倒推如果两个操作需要完全不同的数据源和权限一定拆成两个技能。照这个思路我最终会拆成十个左右细粒度技能查订单详情、查物流轨迹、申请退款、查退款进度、开电子发票、修改收货地址、查优惠券、算预估送达时间、转人工。原型阶段不需要写完整的业务逻辑我用 Python FastAPI 起了几个 mock 服务模拟接口的入参出参先把整个链路跑通。这个阶段的核心目标是验证两件事技能描述的触发准确率够不够高、参数转换能不能覆盖用户的大量说法。如果原型阶段这两点不达标业务系统接入再完整也是白搭。4.2 第二步构建技能注册中心的 schema原型验证通过后我把 skill 注册信息设计成一个统一结构落到注册中心里统一管理核心字段如下skill_name全局唯一技能名例如 order_query。display_name模型展示用的名称例如“订单查询”。description详细的触发场景描述按前文说的写法来填。input_schemaJSON Schema 格式的入参定义要求每个参数都有 type、description、example。output_schema出参结构定义模型需要从结果中提取哪些字段。timeout_ms超时时间。permission技能所需权限级别分为 basic、sensitive、critical 三级。retry_policy重试策略区分可重试与不可重试的错误码。fallback_skill可选当前技能失败后可以考虑调用的备选技能。写 schema 的时候我强烈建议引入 CI 环节里做一次脚本检查逐项核验必需字段是否齐全、description 是否超过字数下限、参数是否都写了 example。这不是形式主义描述缺斤少两的技能直接混进系统后面会让模型行为变得极其不可控。4.3 第三步搭执行引擎并实现一次完整调用执行引擎我推荐用独立服务部署不要和业务代码耦合在一起。核心好处是技能的新增、升级、回滚都可以单独灰度不影响主流程。我自己的实现里引擎有几个关键函数receive 输入负责解析模型传来的调用指令validate 参数用 JSON Schema 校验check_permission做权限拦截execute 真正执行业务逻辑handle_error 统一错误处理returns 结构化回传。伪代码逻辑大体是这样用 Python 示意def execute_skill(skill, input_data, context): # 参数校验 validate_result skill.json_schema.validate(input_data) if not validate_result.is_valid: return build_error(E1001, 参数校验失败, validate_result.message) # 权限校验 if not context.user.has_permission(skill.permission): return build_error(E2001, 权限不足, 当前用户无权使用该技能) # 执行前记录 execution_id generate_id() snapshot_to_memory(execution_id, skill, input_data) # 带超时执行 try: result run_with_timeout(skill.func, input_data, skill.timeout_ms) return build_success(execution_id, result) except TimeoutError: return handle_timeout(skill, execution_id, input_data) except BusinessError as e: return handle_error(skill, execution_id, e)执行链路的每一环我都会埋日志参数、耗时、错误码、返回摘要全部结构化输出。后面排查问题就全靠这批日志。4.4 第四步让模型学会主动使用技能有了技能注册中心和执行引擎接下来把技能列表灌进模型上下文。不同模型对工具描述的长度和格式敏感度不同我实测下来的经验是调用级别模型如新版的 Claude、GPT、及国产的 GLM、Qwen对 JSON Schema 格式的工具描述接收度都很高但同一个技能的描述写法要从平台默认风格调整成“更贴近实际用户口语”的风格触发准确率能提升不少。模型的 system 提示词里我除了给出技能清单还会追加一条固定规则如果用户的请求无法通过已有技能完成必须明确告知用户“暂时不支持该操作”绝不能编造一个技能或硬套一个已有技能去执行。这条规则简单到不起眼但能拦截掉大量幻觉类错误。在模型侧还需要配置一个调度策略单步执行还是多轮自主规划。初期我会强制使用单步模式先验证单个技能调用的准确率整体可靠之后再加上循环上限为五步的多轮规划模式让模型逐步拆解复杂任务并调用多个技能。和纯单轮调用相比多轮模式下模型会主动做任务拆解和中间结果分析但也会带来更高的错误累计风险所以循环里每一步都必须校验模型输出格式一旦格式异常立即跳出转入人工提示。4.5 第五步挂评测集做回归评测是技能系统能持续迭代的根基。我给每个技能维护了一个评测集格式是“原始用户语句 期待调用的技能名称 期待参数 JSON”。每次模型或技能有更新就全量跑一遍评测集对比结果的一致率。我当时做客服场景的时候建了两百组测试用例覆盖了各种口语说法、代词指代、时间表达和异常输入这套基准集长期陪伴着每次升级。举几条典型的评测用例用户原句期望技能关键参数期望值“我的快递跑哪儿去了”order_queryorder_idNonequery_typelogistics“帮我退掉那个 108 号订单太慢了”refund_applyorder_id“108”reason“物流太慢”“还有优惠券能领吗”coupon_querystatus“available”评测通过率至少要达到九成以上我才会让改动上线。这里有一个很关键的测试指标技能描述和参数的稳定性。不能用一组提示词换一个测试结果评测集要长期锁死才能保证迭代是正向的。5. 上线之后才会遇到的真实问题和排查技巧5.1 高频问题速查表技能系统上线前和上线后的状态完全不同这里整理了一些我遇到过的经典问题全部来自实战场问题现象根因分析解法与建议模型经常选错技能技能描述太长、重叠度高或触发场景未列全精简技能数量、按用户意图强化描述、跑触发准确率测试参数经常传错格式参数示例缺失或类型定义模糊每个参数补 example布尔值写明确合法取值枚举类参数给全部枚举值技能调用超时业务接口响应慢模型侧无感知调整超时值、加流式中间输出、超时后走备选技能多轮对话后上下文被撑爆每轮把所有技能描述和调用历史全部塞进上下文只放活跃技能描述、用记忆库摘要代替完整历史用户描述含糊时结果漂移缺少信息澄清机制加入参数追问逻辑缺关键参数时先发起一轮澄清对话技能升级后行为突变描述或逻辑修改影响了模型对工具的选择每次改动都跑评测集回归确认无退化再上线部分用户命中技能频率极低描述没有覆盖该人群习惯用语定期分析未命中语料用失败样本反哺描述5.2 三个必须从一开始就管的细节第一个是上下文膨胀问题。技能列表本身占 token系统提示词里几十个技能的全量描述一轮下来可能就要好几千 token多轮对话累计之后很容易就超过了上下文窗口或是把模型注意力稀释了。我现在用的策略是“按需注入”先根据用户当前正在进行的任务猜测可能用到的技能子集只把这些技能描述注入提示词其他技能全部省略。这不仅省 token还显著提升了工具选择准确率——选项少了模型自然不容易选错。第二个是权限最小化问题。技能系统的权限必须比业务系统想得更细。我见过不少团队因为图省事所有技能共用一套管理员权限结果模型通过一个“查询报表”技能绕过了报表详情权限限制造成了越权访问。我的做法用户和技能之间建立独立的权限映射关系技能执行必须同时满足“用户有权限”和“技能已授权”两个条件缺一不可。任何技能默认无权限由管理员单独授权这条规则没有例外。第三个是敏感数据的隔离和脱敏。技能返回结果里如果包含手机号、身份证、地址等用户隐私不能直接按原样返回给模型更别提写进记忆库。我统一在引擎层做结果后处理凡是命中脱敏规则的字段一律用掩码替代只有真正有权限的下游环节才能拿到明文。记忆库里的历史数据同样也要定期做加密和清理。5.3 用错误样本反哺技能描述技能系统的可进化性是我特别看重的。每周我会跑一次错误样本分析把所有“模型选错技能”的案例导出来按失败原因分成五类描述不清、参数字段缺失、触发场景没覆盖到、用户表达歧义过大、目标技能本身设计不合理。每类对应不同的优化动作然后逐一改进。比如有一段时间用户经常说“这个订单还能不能改地址”系统老是把该问题归到 order_query 技能里导致没有真正去执行地址修改。我分析后发现用户话里有“改”这个动作词单看 query 技能的描述确实覆盖不到这一层。后来我把 order_query 的描述里明确加上一句“该技能仅用于查询不执行任何修改类操作”同时确保 modify_address 技能有更强的触发权重。调整后此类场景的选择准确率从七成多升到了九成五。这类精细打磨是最笨但最有效的方法没有捷径可走。6. 这套打法的可扩展方向技能体系稳定之后后续可以扩展的方向很清晰。我在自己的项目里已经验证过的有三个多技能组合成工作流、跨会话技能记忆、用 AI 辅助生成技能描述和参数。多技能组合成工作流是把“查订单-申请退款-确认退款结果”这类固定流程封装成模板模型只要识别出用户的核心诉求就自动启用流程模板而不是每个来回都由模型自由发挥。实测下来成流程的执行方式和自由调度相比不仅耗时更短平均成功率还高出不少。跨会话技能记忆是让系统记住用户在一个会话里曾经用过哪些技能、偏好哪些操作方式下次用户再发起类似请求时模型可以直接复用上次的选择省去了重新推理的过程。实现上也很直接把每次技能调用的摘要写入记忆库作为提示词里的轻量记忆片段注入。AI 辅助生成技能描述是我最近在试的方向拿一个技能的接口定义和历史调用日志丢给大模型生成多个版本的描述然后用评测集自动评估哪个版本触发准确率更高。整个流程可以部分自动化能省掉我大量手工打磨描述的时间。但是这里要特别强调自动生成的结果必须经过评测把关否则很容易生成一些表面漂亮、实际触发稀烂的描述。7. 写在最后的实操经验跑完以上这一整套流程最大的感受是技能系统的复杂度不在代码里而在“边界”与“细节”之间。边界没划清楚越多技能系统越乱细节没打磨到位接口越标准模型越容易出错。不要把技能系统当成一次性项目来做它更像一套需要持续运维的产品体系每个月都会有新场景催生新技能也会有旧技能被合并或淘汰这才是常态。再分享两个小建议一是在项目初期就把评测集建起来哪怕只放几十条用例也比事后补要强得多因为后补往往补不全当时没有覆盖到的思考维度二是每个技能上线前一定自己亲手模拟一次普通用户的口语表达去调一遍不要只跑标准用例模型对口语的响应方式和标准测试用例完全不一样这一点只有亲手试过才能体会。技能系统的价值是把大模型从“聊天窗口”真正推进到“业务入口”而评判技能系统好坏的标准也很简单当用户连续用不同方式表达同一诉求时系统能不能稳定地走完同一套正确流程这就够了。
返回列表