news 2026/10/14 8:33:39

Agent Skills实战:从技能拆分到路由编排,打造生产级智能体技能库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Skills实战:从技能拆分到路由编排,打造生产级智能体技能库

最近一直在做 agent-skills 方向的东西,说白了就是给智能体搭一套“能干活的技能库”。很多人以为 Agent 的价值全在模型本身,但实际跑过几个项目就会发现,真正拉开差距的是技能体系:你怎么拆技能、怎么描述技能、怎么让模型在你定义的边界内稳定调用技能。这篇文章不聊概念,只聊我在落地 agent-skills 过程中总结出来的设计思路、踩过的坑、以及一套可以直接照抄的实操方法。适合正在做智能体应用的开发者、AI 产品经理,以及想把大模型接进真实业务流程的团队。

1. 先拆开看:Agent Skills 到底在解决什么问题

1.1 从“能聊天”到“能干活”,差距就在技能体系上

大模型的强项是自然语言理解和生成,但“干活”从来不只是说话。查订单、发邮件、改数据库、调接口,这些动作需要模型能够准确理解用户意图,然后调用外部工具,拿到结果,再组织成用户能看懂的回答。这个过程里,模型本身只是“大脑”,真正动手的是技能。

agent-skills 本质上就是把“模型能做什么”和“系统能做什么”之间的桥梁拆成可复用的单元。每个技能对应一个明确的能力边界,有清晰的输入输出、权限约束、超时策略和失败处理。比如你做一个售后客服智能体,订单查询是一个技能,物流跟踪是另一个技能,退货审核又是一个技能。它们各自独立,但可以被同一个 Agent 统一调度。

我见过不少团队第一次搭 Agent 时,什么功能都写在 Prompt 里,让模型自由发挥。结果就是同一句话今天能答对、明天答不对,换了一个用户口音就崩。问题不在于模型不行,而在于你没有一个可控的执行层。Skills 的意义恰恰是让不确定性收敛:模型只负责“决定做什么”,具体的“怎么做”交给注册好、测试过、可观测的技能去完成。

从影响范围来说,这套思路能覆盖的场景非常广。自动化办公、客服问答、数据分析、运维告警处理、内容生产,只要业务流程可以被拆成“输入-处理-输出”的步骤,就能用 agent-skills 的方式承接。它解决的核心痛点是:AI 应用从 Demo 走向生产环境时,必须具备的可维护性、可测试性和可治理性。

1.2 技能拆还是不拆?我用的三个判断标准

很多初学者最容易犯的错是把技能切得要么太粗、要么太碎。太粗的话,技能内部塞了大量条件分支,本质上又变回了一个函数;太碎的话,模型在一个任务里要来回调用七八个技能,上下文转换开销大到离谱。

我一般用三个标准判断一个能力要不要拆成独立技能:

  • 这个能力会不会被多个流程复用?比如“发送邮件”几乎每个业务都会用到,拆出来就是划算的。
  • 它有没有明确的输入输出边界?输入是几个参数,输出是固定结构,技能内不需要理解太多全局上下文,就具备拆出来的条件。
  • 它是否需要独立的权限或成本控制?比如某个能力要调用第三方付费 API,单独封装才能做限流、鉴权和账单隔离。

反过来,如果一个动作只在某个特定流程里出现一次,或者它高度依赖前后几步的状态,那就不要硬拆。我之前在智能客服项目里把“生成回复文案”和“发送回复消息”拆成两个技能,结果每次都要把用户完整对话历史传给“生成文案”,再把生成结果传给“发送消息”,中间多了一倍 token,还经常因为上下文截断导致文案前言不搭后语。后来合并成一个“生成并发送回复”技能,反而稳定很多。

拆技能的核心不是“越小越好”,而是“边界越清楚越好”。一个技能哪怕内部逻辑很复杂,只要对外接口清晰、行为可预期,它就是好的技能。反过来说,一个只做了半件事的原子操作,如果没有完整的输入上下文,模型根本不知道怎么编排它。

2. 一次完整落地:技能清单、注册与编排

2.1 先从业务场景反推能力清单

我搭技能库时不会上来就写代码,而是先拿一沓便利贴,把业务场景里所有“用户可能会提的要求”列成动词短语。比如做一个“订单管理助手”,你可能会得到这么一串:查订单、改地址、催发货、申请退款、开发票、问库存、算运费、找客服…… 这些都是潜在技能。

收敛之后,我会再评估哪些动词是用户高频使用的,哪些是核心流程的关键节点。第一版技能库只保留 10 个以内技能,绝不贪多。技能太多,模型在路由阶段的选择成本会急剧上升,而且彼此间很容易出现描述重叠,导致模型调错。

下面是我常用的技能清单模板:

技能名触发场景输入参数输出内容依赖资源
订单查询用户问订单状态、商品明细订单号、手机号订单状态、商品列表、金额订单库只读权限
物流跟踪用户问快递到哪里了物流单号物流轨迹节点、预计时间物流接口
退款审核用户申请退款订单号、退款原因审核结果、退款金额财务系统权限
发票申请用户要开发票订单号、抬头、税号发票信息或申请回执开票服务

这个表的价值在于它强制你把每个技能的边界写下来。写不出来的技能,说明你还没想清楚,先不开发。

2.2 技能注册表怎么写:元信息、权限与依赖声明

技能落地时,我建议用中心化注册表统一管理,而不是散落在代码里。注册表本身可以是一个 YAML 文件、数据库表或者专门的配置服务。每个技能至少要包含以下字段:技能唯一标识、名称、描述、参数 Schema、权限、超时时间、是否幂等、依赖关系。

描述这一栏最容易被人忽略,但它恰恰是最关键的。因为大部分 Agent 是靠模型理解描述来决定是否调用技能的。描述写得太模糊,模型就会乱选;写得太具体,又会把技能限定死。以前端同事沟通,我会给一句标准:“描述要像一个新同事看这份文档,不需要再问你就知道什么时候该用这个技能。”

举个例子,一个订单查询技能的 YAML 定义:

- name: order_query description: > 当用户询问订单状态、订单内容、下单时间、支付金额等信息时使用。 不要用于查询快递物流轨迹,物流轨迹请使用 logistics_tracking。 parameters: order_id: type: string description: 订单号,通常是 17 位数字,必须来自用户输入或系统会话上下文 mobile: type: string description: 下单手机号后四位,用于二次校验,可空 permissions: - order:read timeout_ms: 3000 idempotent: true dependencies: []

注意描述里明确写了“物流轨迹请使用另一个技能”,这就是在帮模型做路由消歧。参数 Schema 里我特别强调了“必须来自用户输入或系统上下文”,这会显著减少模型编造订单号的情况。

注册表写完之后,还要一个简单的技能引擎去加载它们。引擎启动时校验 Schema、注册路由、建立健康检查,运行时按需执行。这个过程我把它叫作“从代码里的函数到系统里的技能”的转变:技能不再只是方法,而是拥有元数据、权限和监控的独立服务单元。

3. 核心实现:上下文、路由与重试

3.1 技能路由:意图识别与参数抽取

技能路由是 Agent 每轮对话都会发生的动作。我现在的做法是“规则优先、模型兜底”的混合路由。对于高频、固定的表达,直接写正则或关键词匹配;对于长尾表达,再把候选技能列表和用户输入交给模型去选。

def route(user_input, candidate_skills): # 1. 先尝试规则匹配,命中直接返回 hit = rule_match(user_input) if hit: return hit # 2. 规则未命中,交给模型做意图筛选 selected = llm_select(user_input, candidate_skills) return selected

这样做的原因很简单:规则路由成本低、响应快、可预期,能把 80% 的高频问题稳定拉住;模型路由只处理剩下的 20%,即使偶尔选错也在可控范围内。路由完成之后,紧接着做参数抽取。这一步和意图识别我建议分开做,而不是让模型一个动作同时完成。原因在于同时预测两件事会显著增加参数幻觉概率。

参数抽取时,我会把参数 Schema 和示例值一起给模型。比如“查订单”需要订单号,示例就写“订单号一般是 17 位数字,类似 20240315000123456”。一方面让模型知道格式,另一方面让它学会从用户原句中找值。抽出来之后,还要做格式校验,不合格就打回重抽或者要求用户补充。

3.2 上下文压缩:别把对话历史全塞给技能

我在早期项目里发现,技能调用的输入如果直接拼接整个对话历史,会带来两个问题:token 消耗暴涨、模型在长上下文里更容易忽略真正重要的字段。技巧是要为每个技能建立独立的“状态槽”,把对话历史里和当前技能相关的信息提取出来,槽位填充完毕后再调用技能。

例如“退款审核”技能需要订单号、退款原因、客服备注。对话历史可能有十轮,但真正需要的可能只在最早两轮里出现过。我会用一个轻量抽取器把这三个槽位从历史里找出来,找不到的槽位再通过追问补齐。这样传给技能的结构化输入通常不超过 200 token,但准确性比塞 3000 token 历史高得多。

上下文压缩还有一个原则:技能不该关心无关上下文。模型需要负责的是“从对话里理解用户要什么”,技能需要负责的是“把用户要的事情办成”。中间需要一个适配层,把用户意图翻译成技能参数。我在工程上把这个适配层叫做“技能前置处理器”,它和技能本身分开维护。

3.3 失败重试与降级策略

技能调用失败是常态,不设计好失败路径,Agent 就会变成复读机。我会把所有失败统一成一个结构化错误对象,里面带错误码、可重试标记、建议动作。

class SkillFailure(Exception): def __init__(self, code, message, retryable=False): self.code = code self.message = message self.retryable = retryable

可重试的失败(超时、网络抖动、上游临时 5xx)使用指数退避重试,最多三次;不可重试的失败(参数非法、鉴权失败、业务规则校验不通过)直接返回给用户,并给出修正建议。降级策略则是在主技能不可用时,自动切换到一个备选技能或者返回缓存结果。比如物流接口挂了,可以先返回订单本身的发货状态,告诉用户“物流明细暂时获取不到,但订单已发货”,而不是让整个对话卡死。

降级方案一定要提前写在技能注册表的 dependencies 或者 fallback 字段里。我在某个跨平台系统里就吃过没有降级的亏:天气查询服务超时后,Agent 直接报错,用户体验极差。后来接了一个离线天气库作为 fallback,虽然数据不是实时,但至少用户不会面对一片空白。

4. 实战中踩过的坑:技能冲突、任务碎片化与参数幻觉

4.1 技能互相抢活,路由优先级怎么定

技能一多,最典型的坑就是两个技能描述重叠,模型随机翻牌。有一次我们的“订单查询”和“物流跟踪”同时能回答“我的快递到哪了”,结果同一句话有时候走订单接口,有时候走物流接口,返回的内容完全不一样。

解决思路有三个,可以同时用:

  • 在技能描述里显式声明“不要做什么”,至少写清楚和容易混淆技能的边界。
  • 在路由层维护一个优先级列表,当模型对候选技能置信度接近时,优先走规则表里指定的那个。
  • 对高频混淆场景做一条规则兜底,比如用户提到“快递”“物流”“到哪了”就直接路由到物流跟踪,不让模型做选择题。

我还发现一个细节:技能描述里的位置会影响模型判断。描述放在注册表靠前位置的技能,被选中概率会偏高。所以不要把冷门技能放在热门技能前面,这也算一个优化点。

4.2 任务被拆太碎,Agent 反而丢掉全局

第二个坑是过度拆分。我们曾经把“生成周报”拆成“读取数据”“总结要点”“排版”“发送”四个技能,理想中模型应该依次调用。实际跑下来经常出现前后割裂:读取数据用的是 A 口径,总结时模型又自己脑补了 B 口径,最后周报里的数字对不上。

后来我把这种强流程型任务改成了“工作流模板”模式。技能仍然是原子能力,但原子能力之间不再由模型自由串联,而是由预先定义的 DAG(有向无环图)编排。模型只需要在入口处判断“用户要生成周报”,然后触发整条工作流。模板会显式定义步骤、每一步的输入来源、输出流向。

这个改变让我得出一个结论:agent-skills 体系里,“技能”负责原子动作,“工作流”负责流程编排,两者必须分开。模型擅长的是从一个候选清单里选一个技能,而不是在小步快跑的流程里做几十次决策。每多一次决策,就多一次出错的机会。

4.3 参数幻觉的排查思路

参数幻觉是 Agent 落地中最恼人的问题之一,典型表现是模型“一本正经”地编出订单号、日期、金额。排查时我会按顺序检查三件事:

  • 参数有没有可能从系统上下文里拿到?如果能,就做“上下文回填”,优先覆盖模型生成值。
  • 参数校验规则是不是太宽松?比如订单号应该包含数字和特定前缀,那就不能只校验非空。
  • 模型是否被要求在同一个步骤里做了太多事情?如果它在一次调用里既要选技能又要抽 5 个参数,幻觉概率会大增。

我见过一个案例,用户说“帮我查一下上周的订单”,模型把“上周”当成了一个日期参数,生成了一个根本不在任何时间区间里的具体日期。后来我们把所有时间类参数都改成相对时间解析器,由代码去算日期范围,模型不再负责生成具体日期。参数幻觉的根因,很多时候是让模型做了本该由代码完成的事。

4.4 问题排查速查表

现象可能原因处理办法
模型不调用任何技能技能描述不清晰或候选列表未传入检查路由上下文,确认技能注册表已加载
调用技能但参数格式错误参数 Schema 缺少示例在参数描述里补充示例值
多个技能返回冲突结果描述边界重叠增加“不要使用”说明和路由优先级
任务执行一半中断技能超时或未设置重试检查超时时间,配置失败补偿动作
技能执行成功但回答错误技能输出没有被正确映射增加前置处理和后置格式化层

这张表我一般贴在项目文档最前面,出现问题时先对照排查,而不是盲目调 Prompt。

5. 可测试性与可观测性:让技能库能持续演进

5.1 为每个技能建一个“最小验证集”

技能库不是写一次就完了,它会随着业务变化不断改。改技能最怕的是改完一个,影响了另一个。所以我会给每个技能维护一个最小验证集,一般包含三类用例:正常场景、异常场景、边界场景。

以“订单查询”为例:

TEST_CASES = [ {"input": "我的订单 20240315000123456 到哪一步了", "expected_skill": "order_query", "expected_params": {"order_id": "20240315000123456"}}, {"input": "订单状态看不了", "expected_skill": "order_query", "expected_params": {"need_more_info": True}}, {"input": "快递送到哪里了", "expected_skill": "logistics_tracking", "expected_params": {"logistics_no": None}}, ]

这些用例会被跑在一个回放环境里,使用 mock 接口,不请求真实上游。每次修改技能描述、参数 Schema 或者路由逻辑后,一键回放所有验证集。一旦有用例没通过,就说明这次的改动引入了回归。这个习惯救了我很多次,因为技能类改动不像传统 Bug 那样有堆栈报错,很多问题是静默的,只有回放才能发现。

5.2 观测指标怎么埋:成功率、调用链、资源消耗

技能上线后,必须能回答三个问题:技能跑得稳不稳?用户的问题有没有被正确路由?哪些技能正在消耗最多的成本和时间?

我会给每个技能记录结构化日志,字段固定为:技能名、参数摘要、返回码、耗时、重试次数、调用来源、模型版本。然后按天聚合以下指标:

指标名含义目标
技能调用成功率成功次数 / 总调用次数核心技能需 > 98%
路由命中率正确技能被选中次数 / 总次数需持续监测趋势
参数抽取错误率参数校验失败次数 / 总调用次数新技能上线后重点观察
技能平均耗时每次调用的响应时间超过阈值触发告警
模型路由占比规则路由 vs 模型路由的次数比例模型路由占比过高时优化规则

这些指标不止是看板,更要设置告警。比如某技能成功率连续 10 分钟低于 95%,就立刻切到 fallback 方案,同时通知对应负责人。没有告警的可观测性,等于没有可观测性。因为技能链路的错误往往不表现为系统崩了,而是表现为用户默默流失。

另外,每次升级模型版本(比如换了一个新的底座模型),都必须在完整验证集上跑一轮回归。模型能力变化会影响技能路由的表现,哪怕只是模型“更聪明”了,也可能导致它不按描述的边界走。这个坑我踩过一次后才开始把模型版本纳入测试矩阵。

6. 按我的经验,搭建技能库最容易上手的顺序

如果你现在准备从零开始搭一套 agent-skills,我建议不要急着铺开几十个技能,而是按这个顺序走:

第一步,选第一个技能时,不要选“发邮件”“写代码”这类写操作,优先选一个只读、低风险、结果容易验证的技能。比如“查订单”“查天气”“查文档”。只读技能的好处是即便调用错误,也不会对业务数据造成不可逆影响,非常适合用来跑通注册、路由、执行、反馈的完整链路。

第二步,用中心化注册表把这一个技能定义好,包含描述、参数 Schema、超时和权限。然后接一个最简路由:规则优先,模型兜底。这个阶段的目标不是“智能”,而是“确定”。

第三步,跑通三到五个只读技能,建立一套最小验证集,然后才开始加写操作类技能。写操作类技能必须有更严格的权限校验、操作前确认、操作审计。我在模拟项目 X 里就是这样:前两周全部在做只读技能,流程稳定后第三周才接了“创建工单”和“发送通知”,出错率明显低很多。

第四步,每增加一个技能,就回到验证集跑一遍全量回归,并且把新技能和已有技能的边界写清楚。技能库最忌讳一次性扩张,一旦路由准确率滑坡,排错的复杂度会指数上升。

最后,用前面说的结构化日志和指标把系统跑起来。你会发现 agent-skills 的开发重点很快就从“写 Prompt”转向“做治理”:怎么让技能列表清晰、怎么让失败有章法、怎么让每一次调用都有迹可循。

我个人在实际操作中一个很深的体会是:不要把技能体系设计得过于复杂。注册表、路由、校验、重试、观测,这五件事做好,已经足够支撑大多数生产级应用。很多团队一上来就想做可视化编排、多智能体协作、自进化技能,结果连最基础的技能稳定性都没达标。先把一个技能做到 100 次调用不出错,再谈一百个技能怎么协同,顺序千万不能反。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 8:33:16

PHP大文件分片上传与断点续传实战方案

1. 项目概述:为什么大文件上传不能“一锤子买卖”你有没有遇到过这样的场景:用户在后台要上传一个2GB的工程视频,刚拖进浏览器窗口,进度条卡在5%不动了;刷新页面重试,系统提示“文件已损坏”;换…

作者头像 李华
网站建设 2026/10/14 8:32:44

Android音频隐私敏感模式开发指南

1. Android音频隐私敏感模式解析 在移动应用开发中,音频采集功能的隐私保护一直是开发者需要重点考虑的问题。Android 16引入的AudioRecord.Builder.setPrivacySensitive()方法,为音频采集场景提供了更精细的隐私控制能力。这个功能特别适合那些需要临时…

作者头像 李华
网站建设 2026/10/14 8:32:37

Python生成器与动态属性管理实战解析

1. Python动态特性深度解析 在Python开发中,生成器(Generator)和迭代器(Iterator)是处理大数据集的核心工具,而动态语言特性则赋予了我们运行时修改对象结构的强大能力。这些特性共同构成了Python区别于静态类型语言的独特优势,也是中高级开发…

作者头像 李华
网站建设 2026/10/14 8:32:06

单机处理亿级DataFrame:HyperFrame并行架构解析

搜索"hyperframes"这个词,多半不是想找某个花里胡哨的框架名,而是被一个很现实的问题逼到了墙角:数据表的规模已经大到单机Pandas跑不动,而迁到Spark又总觉得动静太大。这篇文章不聊概念,直接把这套架构拆开…

作者头像 李华
网站建设 2026/10/14 8:31:46

巨量算数X-Bogus、-signature、msToken三重校验原理解析与工程化实现

简介:本资源聚焦巨量算数平台核心安全参数(X-Bogus、_signature、msToken)的加密机制逆向分析与工程化复现,面向爬虫开发者、Web安全研究员及逆向初学者,解决高频 encountered 的参数动态生成与请求鉴权绕过难题。压缩…

作者头像 李华