资讯动态

Agent技能系统设计:从工具堆砌到可复用技能架构

发布时间:2026/10/21 8:42:27 来源:尧图企业网站定制
提到“agent-skills”这个词很多接触过大模型应用开发的人第一反应是哦给Agent加一堆tools工具让模型能调用外部能力。但如果一个项目被命名为“agent-skills”并且被认真对待它往往做的事情不是简单塞几个函数进去而是在思考一个更深的问题——Agent的技能到底应该怎么构造、怎么管理、怎么被精准触发。我在实际做AI应用落地时最大的感触是大模型本身只是一个“会推理的大脑”但它离真正能干活还有十万八千里。你要让它帮你查数据、发消息、操作业务系统必须有一套机制把“能力”交到它手里。而“简单地把功能写成函数列表”这件事在Demo阶段很爽一旦你的技能数量超过十个、场景开始多样化马上就会变成一场灾难——参数错乱、触发时机不准、技能之间相互干扰、维护成本爆炸。所以当我看到“agent-skills”这个命名角度时我意识到它真正在讨论的是一个可以被复用的、结构清晰的Agent技能体系设计。这套东西如果你只把它当作“工具调用”来理解会错过它最有价值的部分。今天这篇我打算把整个思路拆开揉碎了讲一遍把我做过的东西、踩过的坑、反复调整后沉淀下来的方案全部分享出来。不追求什么宏大框架只求看完之后你能自己搭一套技能系统并且知道每一步为什么这么设计。1. 重新理解Agent与技能的关系1.1 为什么单纯堆工具会出问题先还原一个典型场景。你在做一个客服类的智能体早期只需要查订单、查物流于是给Agent声明了两个function。一切看起来很顺利模型在对话中能自己判断何时调用哪个函数。后来业务方提需求要加退换货申请、优惠券发放、库存查询、客服转人工……两个月后你的tools列表里躺了五十多个函数声明。这时候你会发现几个诡异的现象模型开始“选择性忽视”一些工具尤其当用户问的问题跟多个工具相关时它常常选错。排查下来发现工具描述写得太模糊或者某些工具的触发条件重叠模型根本分不清边界。参数传递也经常出错明明该传整数的地方传了字符串该填枚举值的地方填了自由文本。本质上tools是“平铺”的它们之间没有任何结构关系。而技能是“结构化”的它不仅有“能做什么”的函数签名还包含什么时候该用、什么时候不该用、参数如何校验、执行结果如何反馈等一系列行为约定。把五十个工个平铺给模型相当于让一个新手同时记住五十条办事规矩不懵才怪。1.2 技能的本质是有边界的可复用能力我喜欢的定义是技能是Agent能力的基本单元它有明确的触发条件、输入输出契约、执行逻辑和自我描述。它不同于普通函数的地方在于技能必须为模型提供足够的“上下文友好”的信息让模型能高效且准确决定是否调用、如何调用。举例来说一个“查询订单状态”的技能不仅仅是暴露一个query_order(order_id)的函数接口。它还需要说清楚用户什么时候会需要这个技能当用户询问包裹位置、配送进度时order_id从哪里来从对话中抽取还是需要追问用户如果查不到怎么办返回未找到并引导提供正确单号。这一大段信息如果不结构化地组织好模型就会反复试错而用户看到的就是Agent“抽风”。技能还应该具备可组合性。比如“取消订单”这个技能不应该从零做一套流程而是复用“查询订单状态”和“发起退款接口”它的核心其实是业务规则编排而不是所有逻辑都自己扛。这种分层设计能大幅降低每个技能自身的复杂度。1.3 技能系统解决的三个核心问题被动接需求式地加工具长期看一定会让系统越来越难维护。技能系统真正要解决的至少是这几个问题。能力管理问题。技能不再只是活在代码里的函数而是以“注册表”的方式被管理起来。每新增一个能力需要声明它的名字、描述、版本、参数结构、权限要求、所属领域、依赖关系。这样系统里有哪些能力一目了然该扩展谁、该拦截谁、该下线谁都有迹可循。动态决策问题。模型在每一轮对话中都应该知道“当前这个问题在我的技能库里有没有能接住的”。这需要技能系统提供一种高效的筛选机制把几十上百个技能聚合成较小的候选集减轻模型的判断负担。如果没有这层机制模型面对海量工具时的决策质量下降是必然的。质量保障问题。技能的执行结果需要被持续观测。调用了多少次、成功率多少、平均耗时多少、哪些技能老被误触发。没有这些数据所谓的智能体业务就是盲人摸象。这三个问题展开就是一套完整的设计蓝图。2. 技能系统的内部结构与设计思路2.1 核心模块拆分与协作在我的实践中一个可用的agent技能系统至少包含四个核心模块技能注册中心、技能加载器、技能运行时、意图决策桥。技能注册中心是一个元数据仓库最直白的实现就是一张大表或者一批配置文件。它记录每个技能的所有信息——技能ID、版本、触发关键词和语义描述、输入参数Schema、权限等级、所属领域、执行端点或函数引用、限流配置。它解决了“有哪些技能”的问题。技能加载器负责根据注册中心的配置把技能的执行体加载到内存中。执行体可以是一个Python函数、一个外部HTTP接口、任意可调用的远程能力。加载器需要做依赖检查、版本核验、资源池化避免每个技能重复申请连接资源。技能运行时是真正跑技能的地方。它拿到模型填好的参数后先做参数校验和规范化然后调用技能执行体最后把结果按照约定的结构返回给模型。运行时还要处理超时、重试、熔断、结果截断等容错逻辑。意图决策桥是连接大模型和技能库之间的纽带。它负责把用户的输入、当前对话上下文和技能注册表中的候选技能做匹配把最相关的几个技能声明动态塞给大模型供其选择。这一步是整个系统的灵魂因为它决定了模型能不能在正确的时机看到正确的技能。2.2 为什么需要“动态技能选择”而不是全量塞入早期我图省事把几十个技能全部以JSON Schema的形式写在系统提示词里。结果首先是Token消耗暴涨每个请求都要把那么长的工具列表重复发送一遍成本高得离谱。更麻烦的是模型注意力被稀释明明应该触发技能A它却选成B。后来改成动态选择后情况发生了质变。每轮请求前我先做一次语义召回把候选技能压缩到三到五个再把这些技能的定义交付给模型。这样模型看到的工具列表是短而精的它的判断准确率有了明显提升响应速度也快了因为模型生成的工具调用Token序列更短了。实现动态选择的方式有很多种从基于关键词的倒排索引到用向量模型做embedding相似度召回再到干脆用一个小模型做意图分类。我实际对比下来对绝大多数业务场景用embedding召回加规则修正已经足够稳定了。主题越垂直的小型业务召回准确率越好领域横跨很大的场景规则修正权重就要提高。2.3 设计中的关键取舍整个系统设计中最需要想清楚的一点是技能定义到底面向人还是面向模型。面向人意味着要用清晰的文档目录来组织技能包方便开发人员阅读和维护。面向模型意味着每个技能的描述必须极度语义化要让模型一看就懂、一懂就对。这两者经常矛盾。比如“发起退款”这个技能名字很清晰对人来说一目了然。但对模型来说“退款”和“售后申请”在语义上有重叠如果描述不精确模型极容易混淆。我的解决思路是给每个技能加三层描述文本。第一层是“技能使用场景描述”用一句话说明用户什么情况下会触发它。第二层是“技能行为边界描述”明确哪些情况不应该使用它。第三层是“参数填写指南”逐字段说明含义、取值来源、缺失时怎么办。三层文本一旦写清楚了模型的准确率能上一个台阶有时候比模型本身升级还管用。另一个取舍是关于技能执行体放本地还是放远程。本地函数的优势是延迟低、能直接操作内存中的共享数据缺点是强耦合技能一多代码就变乱。远程服务的方式更利于隔离和规模扩展但会引入网络开销和额外运维复杂度。我个人建议初期阶段用本地函数包等到技能数量超过三五个、涉及跨团队协作再演进成独立服务。3. 从零搭建一个可复用的技能库3.1 技能定义的标准结构先给出一个技能定义的标准结构。这是我在多个项目中沉淀下来的格式它兼顾了人机共读既能被开发人员阅读也能被模型快速理解。每个技能条目包含五个核心字段元信息、触发条件、执行配置、参数契约、返回契约。如果从代码角度来看技能定义一般采用JSON格式存储便于加载器解析和动态下发。一个典型技能定义的骨架大概是这样的{ id: orders.query_status, version: 1.2.0, name: 查询订单状态, domain: orders, enabled: true, when_to_use: 用户询问订单的配送进度、物流位置、签收状态时使用, when_not_to_use: 用户询问退货退款进度时不要使用应使用售后类技能, parameter_schema: { type: object, properties: { order_id: { type: string, description: 完整订单号通常由平台生成。若对话中没有明确给出应询问用户 }, customer_phone_tail: { type: string, description: 客户手机尾号四位数用于身份校验可选 } }, required: [order_id] }, execution: { type: local_function, func_name: biz.orders.query_status }, access_control: { roles: [user, agent], timeout_ms: 3000 } }3.2 技能加载与注册机制技能加载器读取一批这样的定义文件进行校验然后注册到内存中的技能注册表。注册过程不光是简单地把JSON放进字典还需要做很多约束检查。比如检查是否有重复的ID、参数Schmea是否符合JSON Schema规范、执行函数是否存在、版本之间有没有冲突、依赖的其他技能是否都已在注册表中。我一般把技能分为三类来管理基础原子技能、业务领域技能、组合编排技能。原子技能是纯粹的单一动作比如发送短信、查询库存业务领域技能是在原子技能基础上加了业务规则比如“下单前的库存校验与锁定”组合编排技能则是预定义流程比如“处理退款”需要按顺序调用订单校验、库存回补、支付原路退回等多个原子技能。注册中心对每一类技能采用不同级别的校验规则组合技能重点校验依赖路径是否完整。这里特别提醒一个容易出问题的地方技能的id必须稳定不能随便改动。因为技能的调用记录会累积数据id一变历史统计就会断层而且若已有用户或业务进程持有旧id引用改动会导致调用失败。我建议把技能id理解为公共接口一旦发布需要向后兼容。3.3 参数契约与运行时校验的实现技能参数校验这事看起来简单实际坑很多。模型从对话里抽取参数时经常出现类型错误、信息缺失、字段混淆。比如用户说的是“把收货地址改成北京市朝阳区XX路1号”模型可能将“北京市朝阳区XX路1号”解析成order_id这就闹出了笑话。所以参数契约不能只是一纸空文运行时必须做实际校验和修正。我的方案是在运行时安排“参数处理器”这个环节。处理步骤有两步规范化、纠偏。规范化是将模型传入的值转换为执行体实际需要的类型和格式比如字符串数字转int、去除多余空格、格式化日期。纠偏则根据参数语义做一些规则兜底例如发现order_id的值以汉字开头推断模型抽取错误选择清空该字段并触发向用户的追问。运行时校验完毕之后才真正进入执行环节。执行环节最重要的设计是结果的统一封装。无论底层调用成功、失败、超时返回给模型的结构都应该一致不能有时候返回纯文本有时候返回JSON否则模型在下一步推理时会迷茫。我常用的返回结构是{status, code, data, message}后处理简单且模型理解成本低。3.4 技能调用触发链路演示把完整链路串起来的模样是这样收到一条用户消息后决策桥先基于文本召回技能候选集再结合对话历史和业务上下文进行二次过滤。然后决策桥把候选技能的定义动态注入到大模型可使用的工具列表中。大模型在生成回复时判断是否需要调用技能如果需要就输出一条结构化调用指令。运行时拿到指令后执行技能将执行结果作为新的上下文的一部分回复给大模型让模型根据结果生成最终的用户回复。链路看似简单但每个环节都有很多细节。比如候选集生成时不能只看用户当前的一句话还要结合最近几轮的对话内容。用户可能上一句在讲订单这一句突然只说了句“那这个呢”如果决策桥只看当前句召回就会失败因为“这个”没有指代信息。所以我在实现路由时会把最近三轮对话摘要一起参与召回。4. 技能调用的稳定性保障4.1 超时与重试策略技能执行过程中网络抖动、下游服务变慢是家常便饭。如果不设超时一个技能卡住可能导致整个Agent响应节奏被拖垮。超时值需要实测得出不能拍脑袋。我给本地计算类技能设的默认值是3000ms外部API类技能默认6000ms特别重的批量查询会到15000ms。重试策略也讲究轻重分离。对于幂等技能也就是重复执行不会产生副作用的技能比如查询类可以采用“最多重试两次间隔300ms”的策略。对于非幂等技能比如创建订单、发送消息绝对不能盲目重试否则可能导致重复下单、重复发送等问题。这类技能的处理方式是返回失败然后由Agent向用户展示补救选项而不是系统悄悄重试。单一技能超时重试解决后还有更复杂的场景多个技能串行编排时整体链条的耗时预算需要分配好。比如组合技能A调用B和CB最大耗时应被限定在整个预算的40%C最多占60%避免前面环节耗费太多导致后面没有缓冲余量。4.2 并发与资源隔离当Agent服务于多个用户时技能执行就可能并发发生。如果某个技能内部使用了共享的内存缓存变量或者公用的数据库连接池不加控制就会出现数据错乱。我在系统里采用了“技能隔离舱”的思路每个技能执行体跑在独立的执行上下文中拥有自己的资源引用和日志通道。同一技能的多个并发请求共享连接池但请求级别的业务状态不跨请求共享。日志通道里会包含技能ID、请求ID、用户会话ID这样任何一个请求在哪个技能上出了问题都可以快速回溯。这里有另一个容易踩的坑技能内部不要用全局变量做用户级数据传递。就算Python单线程模式看起来不会并发多线程部署一上来全局变量就会变成竞态条件温床。正确办法是数据都挂在请求上下文对象上跨技能传递时显式传递上下文引用。4.3 可观测性设计技能系统的可观测性主要盯三个面调用量、成功率、丝路耗时。调用量能反映业务对技能的依赖度同时能暴露哪些技能常年闲置可以考虑下架。成功率指标要细化到失败原因是参数失败、超时、还是远端业务返回失败排障效率完全不同。链路耗时则按技能自身、技能下游、大模型决策三段拆分哪一段慢优化重点就放在哪一段。实现上不需要第一天就上特别重的调用链追踪系统。简单做法是在技能运行时埋点把每次调用的元信息异步写入日志再定时聚合成监控数据。只要每次调用都写入了技能ID、调用结果、耗时、参数指纹哈希、上下文摘要词事后绝大多数问题都能通过日志查出线索。5. 常见问题与排查技巧实录5.1 模型总是不触发技能怎么办这是碰到过最多的求助模型在那里一通发挥就是不调用工具。排查看不到明显配置问题的话大概率是以下两种原因。第一种原因是技能描述与用户表述之间语义距离太大。比如技能描述写的是“订单状态查询”但用户口语会说“我的快递到哪了”如果决策桥在动态注入技能时没有结合口语化的改写模型根本想不到该用这个技能。解决办法是把用户高频口语说法收集起来写进技能的触发条件里而不是指望模型自动泛化。第二种原因是技能候选集漏掉了该用的技能。如果某种问题恰好没被召回模型再聪明也看不到这项能力。这时需要排查决策桥所有环节的语义匹配分阈值是不是太高了或者向量词典里技能文本是不是太干瘪连示例句式都没写。给技能描述加几种典型问题变体往往立竿见影。5.2 技能参数被填得乱七八糟模型填错参数是高频问题最常见的错法是把对话里任意一个数字当作订单号。排查这类问题首先要检查参数Schema中字段的description是否写清楚了来源。如果描述里只写“订单号”没有强调“必须是系统中存在的完整订单号”模型的发挥空间就太大了。处理手段有两个方向。一是在参数处理器里增加规则校验比如订单号必须有固定的前缀且长度为20位不合规直接丢弃并要求澄清。二是在模型侧给示例就是预设一个“用户说X应当抽取Y”的样例直接放进技能声明中。某些通用模型对少数示例的服从性提升非常明显一个看似简单的例子往往把准确率提高不少。遇到反复纠正还经常错的场景我建议直接在决策桥层动手不要等模型抽完参数再亡羊补牢。可以针对特定技能做一个更小的抽参子模型替换通用模型负责该技能的参数生成。代价是多调一个模型但换来的是实打实的稳定性提升。5.3 技能被误触发行为边界失守技能误触发是比不触发更麻烦的问题因为看起来一切都在正常运作但实际上做了不该做的事。比如用户只是随便问了一句“退款麻烦吗”结果Agent自动发起了退款申请场面就很尴尬。这是典型的边界描述缺失导致的问题。技能声明里的when_not_to_use字段一定要认真写。不能只写“用户问退款时触发”还必须写清楚“仅当用户表达明确退款意愿并提供了订单号时触发用户只是询问流程、抱怨政策时不得调用”。另外动作型技能的调用确认机制必不可少。凡是会产生业务副作用的高危技能在执行前应该生成一个“操作摘要”回传给模型让模型向用户做二次确认“您确认要退款订单123456吗”得到肯定回复后再执行。这个步骤虽然多了来回但能通过防误触发的最后防线。5.4 技能版本升级导致调用异常技能迭代升级是常态但升级过程中经常出现新技能行为与旧调用方式不兼容的问题。我自己吃过这个亏某次给“查询库存”技能加了必填参数warehouse_id结果下游所有调用方因为没传这个字段集体报错。技能升级需要遵循兼容性规则。新版本必须保持老版本可调用可以将新参数设为可选内部用默认值兜底。确实要破坏兼容时应使用新id发布例如stocks.query_v2并在注册表中保留旧技能一段时间给业务侧足够的迁移时间。运行时的版本管理能力越强技能系统的迭代成本就越低。5.5 技能卡死导致整体响应变慢某段时间系统延迟飙升监控发现是有个技能一直阻塞在远程接口调用上因为下游服务性能劣化且超时设置没兜住。查日志时发现所有请求都在等这个慢技能返回其他领域的技能即使可用也被拖到“连带堵车”。解决思路是给每个技能设定独立的超时值并启用熔断。熔断逻辑是当某技能在滑动窗口内连续失败达到阈值就直接进入“快速失败”模式在短暂窗口期内不再真正执行直接返回降级结果。恢复期后放行少量试探请求成功率达到要求就自动回归正常。这样单个技能的问题不会拖垮整个Agent。6. 我踩过坑之后沉淀的几点体会技能系统这个东西做起来不如调模型炫酷但它的扎实程度直接决定Agent能不能从Demo走向生产环境。我个人的体会有几条。第一条技能描述永远值得花时间打磨远比调参影响大。我在内部分享时经常说技能描述就像招聘JD写得越清楚来面试的模型就越精准。JD含糊的后果是垃圾简历连天JD改清楚后匹配率直接翻倍。每一条技能描述开始的几天看起来都“已经够清楚了”但真正用一段时间后总能发现新的模糊点。第二条动态技能选择不是可选项而是必选项。只要技能数量超过十个就必须做召回而不是全量塞给模型。召回机制的建立不复杂但见过太多团队因为起步时工具少没把动态选择框架搭出来后期技能一膨胀头疼无比。框架趁早搭后面持续加技能就不会yq永远能保持添加技能的低成本和高稳定性。第三条技能执行结果一定要做结构化包装。这个看起来是小事但影响模型下一步决策很大。模型生成回复时看到混在一起的文本和JSON经常搞不清楚状态。统一的结构能让模型把注意力放到“结果反馈引发的下一步动作”上而不是解析结果本身。现在这个技能框架已经成了我在多个业务场景中搭智能体的底座。新需求来了多数情况下只是在技能库中新增一条定义写一个执行函数然后在描述里补充足够多的触发示例和边界条件。Agent的整体可靠性能够保持在稳定水位这个思路是绝对绕不开的。如果你正好也在弄Agent方向的东西不用照着全部照搬先从“技能定义标准化”和“动态技能选择”这两个环节切入就好。把这两个点做扎实你的Agent体感提升会非常明显。剩下的细节可以等做的时候再补。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑