资讯动态

Agent技能设计实战:从工具调用到能力工程化

发布时间:2026/10/9 19:24:51 来源:尧图企业网站定制
上次复盘 agent 项目时又遇到一个老问题模型推理能力明明已经足够可任务执行结果还是忽好忽坏。排查到最后问题往往集中在同一个环节——技能设计。圈子里聊 agent 的帖子已经够多了但大部分都在谈选哪个模型、用哪个框架、怎么调 prompt真正把技能skills本身当成核心工程问题来对待的很少。我做了大半年 agent 落地觉得有必要把这块拆开讲清楚。如果你也在做 AI 代理、助手、自动化流程这类东西这个主题值得认真看。1. Agent 技能到底是什么先摆脱工具即技能的惯性认知很多项目一开始只会用工具tool这个概念——给模型挂几个函数能调 API 就行。但做着做着就会发现工具只是技能的骨架技能是一个完整的能力单元把模型应该怎么用这个能力也包进去了。1.1 工具是函数技能是函数加说明书加容错机制我在新项目里要求的技能定义必须包含三样东西可执行的动作、模型侧的使用说明description 参数 schema、以及失败时的兜底行为。纯工具函数只解决第一样后两样完全交给模型自己猜。模型猜得对那是运气好猜错了排查起来就是灾难。拆开来看动作层真正的 Python 函数、API 调用、数据库读写负责执行。说明层告诉模型这个技能什么时候用、怎么传参数、参数代表什么含义、返回结果长什么样。容错层技能本身可能失败失败之后应该返回什么信息、模型下一步该怎么处理。很多团队把这三层揉在一个函数签名里注释写两行就完事结果模型在真实调用时根本不知道该传什么。说白了技能设计就是给模型写使用手册手册写得越清晰模型干活的稳定性就越高。1.2 技能粒度从细粒度原子到工作流级技能技能还有一个很容易被忽略的维度——粒度。我把技能分成两类一类叫原子技能Atomic Skill比如查询用户订单、获取天气信息、计算两个日期差多少天这类单步动作参数简单、边界清晰、可复用性强适合被其他技能调用。另一类叫流程技能Workflow Skill把多个原子技能按固定流程编排成一个整体比如完成订单退款需要先查订单、校验状态、计算退款金额、执行退款、记录日志五步——这五步打包成一个技能模型不需要逐步决策只需要一次性调用流程技能就行。这两类技能的比例需要刻意平衡。原子技能太多模型决策负担重、上下文爆炸流程技能太多灵活性差、新场景不好适配。我目前的经验是建模阶段先拆原子技能上线阶段再根据高频路径封装流程技能。1.3 技能和 Prompt、插件的关系不少人问技能跟提示词工程到底什么关系。我的理解是Prompt 是让模型在没有外部工具的情况下生成正确输出技能则是让模型在需要改变现实状态的情况下完成动作。两者不是替代关系而是递进关系——先把 Prompt 调稳再把需要跟外部世界交互的部分抽出来做成技能。插件Plugin这个概念更多是工程部署层面的东西解决的是技能如何分发、加载、更新的问题。技能是逻辑单元插件是部署单元。一个插件里可以包含多个技能也可以只包含一个。2. 技能设计的核心元件声明、逻辑、兜底三件套这一节是整篇文章最硬核的部分我直接给出自己在项目里沉淀的技能三件套设计法配合代码示例说明。这部分内容你可以在自己的项目里直接抄作业。2.1 技能声明名称、描述和参数 Schema 怎么写才不误导模型我见过太多技能声明写成一坨get_order_info(order_id)描述也只有一个单词。这在 demo 里没问题一旦技能数量超过 20 个模型就开始频繁选错技能。我的做法是给每个技能写三段式描述第一段说明技能能做什么第一人称叙述比如获取指定订单的完整信息包括状态、金额、商品明细。第二段说明什么时候用比如当用户查询订单状态、核对订单金额、或者售后需要订单信息时使用。第三段说明什么时候不要用比如不要用本技能判断订单是否可退款退款资格请用 check_refund_eligibility 技能。参数 Schema 方面三个容易踩的细节每个参数必须写 description严禁只写类型。模型不看 schema 类型猜值它看的是描述。描述写订单编号用户在电商平台下单后生成的唯一ID模型就懂该去聊天上下文里翻。复杂参数必须给 enum 或 example。比如状态参数你写 string 类型模型可能给你传已发货、shipped、SENT各种格式。给出 enum [pending, paid, shipped, completed, cancelled]模型就会严格照抄。参数顺序也有讲究必填项放前面可选项放后面。虽然模型理论上不受顺序约束但实测里必填在前、可选在后能减少漏参率。from pydantic import BaseModel, Field from typing import Literal class GetOrderInfoParams(BaseModel): 获取订单信息技能参数 order_id: str Field( description订单编号用户在电商平台下单后生成的唯一ID形如 ORD-2025-0716-001 ) include_items: bool Field( defaultFalse, description是否需要返回商品明细默认不返回以节省 token需要时设为 true ) class GetOrderInfoSkill: name get_order_info description 获取指定订单的完整信息包括订单状态、金额、下单时间。当用户查询订单、核对账单、进入售后流程时使用。不要用它判断退款资格。 async def execute(self, params: GetOrderInfoParams): # 业务逻辑…… return {order_status: shipped, total_amount: 199.00}最后这个不要用它做什么的段落很多开发者会忽略但实际上阻止模型误用某个技能比引导它使用某个技能更重要。因为技能误选的代价不只是该动作没执行还会污染后续所有决策。2.2 技能执行逻辑纯函数优先副作用收敛技能内部的业务逻辑我要求严格遵循纯函数优先副作用收敛原则。什么意思就是技能的输入输出尽可能可预测、无状态所有外部副作用发消息、写数据库、调用第三方 API集中在明确标注的区块里。这么设计有几个好处可测试性大幅提升单测里可以直接 mock 副作用验证核心逻辑。故障定位更快技能报错时能迅速判断是逻辑问题、参数问题还是依赖服务问题。技能可以进行重试、补偿、回滚为构建复杂工作流奠定基础。实现上我常用一个装饰器来统一管理技能执行def skill_runner(retry_times2, timeout10): 技能执行的统一包装超时、重试、日志、异常收敛 def decorator(func): functools.wraps(func) async def wrapper(params): start time.time() try: # 这里可以做参数校验、埋点、限流 result await asyncio.wait_for(func(params), timeouttimeout) return {success: True, data: result, latency_ms: int((time.time()-start)*1000)} except asyncio.TimeoutError: return {success: False, error: skill_timeout, hint: 服务暂时无响应请稍后重试或建议用户等待} except Exception as e: return {success: False, error: f{type(e).__name__}: {str(e)}, hint: ...} return wrapper return decorator注意最后把异常收敛成一个模型能看懂的结构——hint 字段是给模型看的让它知道技能挂了之后下一步该怎么办。很多技能失败后模型就彻底卡住就是因为返回的错误信息全是 Python traceback模型根本不知道该干嘛。2.3 技能返回值的最小足够原则技能返回值直接影响模型下一步的推理质量。我踩过最大的坑就是把执行结果全量塞给模型token 花了一大堆模型反而迷失在细节里。规定技能的返回值只保留模型做下一步决策所需的最小集合同时额外带一个next_step_hint提示模型接下来可以做什么。比如订单查询技能返回{ success: true, data: { order_id: ORD-2025-0716-001, order_status: shipped, total_amount: 199.00, next_step_hint: 用户订单已发货如需查询物流请调用 query_logistics 技能如用户申请退款且订单已发货请先引导用户确认收货后退款 } }这个 next_step_hint 是我后来加上的实测可以让模型的下一次技能调用准确率提高不少因为它相当于给了模型一个决策的路标。而完整数据比如商品明细、地址详情放到另外的字段让模型按需再调详情技能获取不要一次全给。这个设计的核心思想是上下文是珍贵的推理资源不是存储容器。3. 技能路由让模型在几十个技能里选中正确的那一个当技能的粒度已经比较合理、声明也写得足够清楚之后接下来的挑战变成了面对 30 个甚至 50 个技能的时候模型怎么在没有思维短路的情况下做出正确的调用选择这一节讲路由层的设计。3.1 全量注入的选择瘫痪问题第一版技能系统简单粗暴把所有技能定义一股脑注入上下文。模型每次请求都带着几十个技能声明效果如何我只能说技能数量小于 20 的时候还能勉强工作超过 30 个模型的选择准确率明显下滑而且出现了看到某个技能名里有关键词就用的浅层匹配。我做过一个统计技能数量从 15 个增加到 40 个模型选错技能的概率几乎翻了一倍同时首字延迟因为上下文过长增加了约 30%。所以必须做技能路由Skill Routing——在把技能列表交给模型之前先用一个路由模块做预筛把候选集压到 3~5 个。这个路由模块可以是一个小模型、传统检索算法、或者规则系统按需选择。3.2 基于向量召回 规则的混合路由我最终采用的做法是规则前置 向量召回 模型兜底三层路由第一层规则前置根据用户请求里的明显信号做硬匹配。比如请求里出现查一下订单、我的快递到哪了直接绑定相关技能组。第二层向量召回把技能的名称、描述、场景标注做 embedding用户请求也做 embedding算余弦相似度召回 top K。第三层模型兜底将前两层的结果作为候选技能注入上下文由主模型做最终决策。class SkillRouter: def __init__(self, skills: List[SkillDefinition]): self.skills skills self.embeddings self._build_skill_embeddings(skills) # 预计算技能向量 def route(self, user_query: str, top_k: int 5): # 1. 规则硬匹配 ruled [s for s in self.skills if self._match_rule(s, user_query)] # 2. 向量召回 query_vec embed(user_query) ranked sorted(self.skills, keylambda s: cosine(query_vec, s.vec), reverseTrue)[:top_k] # 3. 合并去重 candidates dedupe(ruled ranked) return candidates这套方案落地之后候选技能注入量平均下降 70%技能选择准确率回到 95% 以上。注意这里路由召回的准确性依赖技能描述质量所以前面技能声明的功夫绝对不能省。3.3 技能链从选技能到编排技能流程单技能调用只能解决单个动作真实用户请求往往是多步任务比如帮我退款并且通知我朋友。这就涉及到技能链Skill Chain的概念。技能链有两种实现路径固定编排基于用户请求的模式从预设模板里选择一条链路比如退款流程技能内部按顺序调用多个原子技能每一步由模型填充参数。动态编排不预设链路模型每一步在候选技能里选一个执行后根据结果再选下一个相当于用模型做运行时调度。我一开始追求全动态编排结果链路执行成功率非常不稳定经常在第二步选错技能还不好排查。后来改成高频场景用固定编排低频场景用动态编排成功率反而上来了模型 token 消耗也下来了。这是 agent 系统一个比较反直觉的结论动态能力越强系统越不稳定固定的东西越多成功率越高。真正的智能应该用在该灵活的事上而不是每一步都重新发明轮子。4. 复盘从技能系统 1.0 到 2.0我踩过的三个大坑说完了理想设计讲讲实际踩出来的坑。这些坑几乎都来自同一个认知偏差——把技能当成给模型多一个函数而不是帮模型做对一个决策。4.1 坑一参数 Schema 不给示例模型输出格式漂移技能 1.0 时代我定义参数只写类型和简短描述。很快发现一个问题模型在传日期时间参数时有时传2025-07-16 08:30:00有时传2025/07/16有时传2025-07-16T08:30:00Z。后端解析直接崩溃。排查了很久最终发现是参数描述里没有给出明确的格式示例。修复方案很简单——在每个易错参数的 description 里加上形如...的示例。加完当天日期时间参数的格式错误率从 30% 降到几乎为零。这件事给我的启发是模型对格式的理解依赖于范例而不是规则描述。你写一百遍ISO 8601格式不如写一个2025-07-16T08:30:00Z来得有效。后来我把这个原则推广到所有技能的参数描述中凡是带格式要求的字段一律给出示例值。4.2 坑二返回值过大导致的注意力稀释某个技能返回的是用户近一年的行为记录分页做得很粗糙一次返回几百条。当时觉得数据越全模型判断越准。实测结果完全相反——模型看过多的记录之后反而抓不住最新几条关键信息给出的判断经常拿旧数据说事。我后来把这种大数据量返回改成两层第一层返回最近 5 条摘要 聚合统计总次数、最近活跃时间、偏好标签模型若需要完整明细再显式调用一个新的行为明细导出技能按时间段查询。这样一改模型的决策质量明显提升tokens 也省了。这个坑背后有一个更普适的原理上下文越长模型对局部信息的注意力越容易被稀释。用技能时要刻意控制每个技能的可见输出量把模型当成一个每次只能读一屏文档的实习生一次只给够用的信息。4.3 坑三技能之间的边界模糊导致互抢调用技能多了之后会出现一种烦人的情况两个技能都能处理同一种请求模型随机选择一个导致结果时好时坏。比如下单和预下单两个技能功能相近描述相近模型经常把只想要试算价格、不想真正下单的用户误引导成提交真实订单。这个问题的根治办法不是改描述而是做技能边界审计找出所有描述中包含相同业务实体和相近动作的技能如果边界确实模糊合并为一个技能内部做模式分支如果不能合并在描述里显式写什么时候用 A什么时候绝对别用 A用 B。边界模糊的另一个副作用是评估难做。你根本分不清模型选 B 算不算错误因为 B 从某种角度看也能用。后来我在每个技能定义里强制增加sees_also / 不要用本技能的场景字段从机制上逼着自己想清楚边界。5. 技能治理从 50 个技能到 500 个技能的可控演进技能系统做到后面难点早就不是某个技能怎么写而是整个技能库怎么持续健康地演进。这一节讲治理经验更像系统架构而不仅是agent 技术。5.1 技能注册中心与依赖管理团队协作时不同人开发的技能需要有一个统一的注册中心否则会出现技能重名、参数冲突、互相覆盖的混乱。我用一个简单的注册表来管理每个技能必须有全局唯一名称、版本号、负责人、依赖列表和调用频率统计。技能的依赖关系必须是显式的不允许技能通过隐式全局变量共享状态。这样当某个底层 API 挂掉时可以迅速排查出有哪些技能受影响。# skill_manifest.yaml skill_name: refund_order version: 1.4.0 owner: team_after_sale dependencies: - get_order_info - check_refund_eligibility - payment_gateway domains: - ecommerce - after_sale注册中心的核心价值不是管理而是可观测。你要能随时回答三个问题哪些技能最常用哪些技能几乎没人调哪些技能开始频繁报错5.2 技能版本管理与灰度上线技能本质上是代码所以必须走正经的版本发布流程。技能 1.0 时代我只是改完直接替换线上结果某次一个新版技能改了参数格式导致链路中断了一整天才发现。教训是技能必须有版本向量并且要支持灰度。我现在的做法是每个技能打版本号线上模型默认调用稳定版本新版本先在 5% 流量上灰度对比该技能的成功率、延迟、是否引发链路异常灰度观察 24~48 小时后再切换全量同时保留旧版本作为回滚点。这套流程听起来很重但对于生产环境它省掉的麻烦远超投入。5.3 技能退化检测与自动下线技能库膨胀到一定程度后必然出现部分技能质量退化或者因为业务调整而彻底废弃。定期检测不能靠人肉巡检我做了三档质量指标采纳率候选技能出现后模型最终选用它作为最终行动的比例。成功率技能执行成功不抛异常、返回合规结果的比例。人工接管率某个技能引发的会话转移到人工客服/人工干预的比例。这三个指标合成一个健康分。低于阈值的技能会进入待优化列表优化不了就下线。我把这个机制称为技能的自然淘汰系统——因为只要业务在变化技能库就一直在新陈代谢不清洗只会变成一坨越来越难用的遗产。6. 技能系统再往后走我的三个方向判断技能系统从 1.0 做到 2.0其实已经比较稳定了但这段时间我一直在思考它能往哪走。以下三个方向是我现阶段比较看好的可能对你有参考价值。6.1 技能的自描述与自动化注册现在技能的定义和注册还需要人肉写描述、写参数 Schema、做 embedding 索引。成本不小而且质量因人而异。下一步我觉得可以让技能本身具备自描述能力——根据技能的代码逻辑自动生成描述和参数说明再配合测试用例自动校验描述准确性。这相当于给技能系统做自动化单测描述写得对不对用一组测试请求跑一遍路由看能不能命中目标技能。6.2 跨技能依赖图驱动的自动编排固定编排和动态编排两种模式长期并存但编排规则都是人肉维护的。我想看到的是从技能依赖图出发自动生成候选链路的拓扑排序然后引导模型在合法链路上做选择。这样做的好处是不会出现先退款再校验资格这种明显违规链路的幻觉。实现上需要一套 DAG 约束系统以及链路级的效果追踪。复杂度不小但一旦做出来agent 的执行可靠性与可解释性都会有质的提升。6.3 技能市场与跨团队复用团队里沉淀的高质量技能不妨做成内部技能市场按业务域、场景打标并支持一键引入。这个方向的价值在于组织级知识复用某个团队验证过的售后流程技能另一个团队在构建用户咨询场景时可以直接复用而不必重新设计、重新踩坑。跨团队复用带来的最大挑战是上下文中的语义冲突——同名概念不同定义。这个需要一套统一的领域词表Ontology来对齐也是我接下来准备动手做的事情。做 agent 技能的这大半年我最大的感受是模型能力的天花板比很多人想象的要高决定实际效果的反而是给模型配备的技能体系有多顺手。技能设计不能靠临场发挥它值得有一套像样的工程方法论。这篇帖子把我实战中验证有效的做法和踩过的坑都写出来了如果你也在给 agent 配技能欢迎照着一试有问题评论区交流。

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

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

免费获取报价 →
↑