news 2026/10/14 9:26:22

Agent技能库实战:从Prompt补丁到可复用能力编排

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent技能库实战:从Prompt补丁到可复用能力编排

做Agent应用这两年年,我最大的感受不是模型不够聪明,而是能力太难复用。同一个“查一下客户历史工单”的操作,在不同流程里被我用Prompt写了七八遍,每次写出来行为还不一样——有时模型记得先过滤已关闭工单,有时就忘了。直到我把整套能力按“技能”的方式重新组织,才感觉真正在做一个系统,而不是一直在大模型旁边打补丁。

这篇文章就是我手头项目 agent-skills 的完整复盘。它不是某个现成框架的说明书,而是我自己从踩坑到理顺的过程记录:怎么拆分技能、怎么写技能描述、怎么做路由、怎么维护迭代。如果你也在做 Agent 类应用,或者想把一套大模型能力沉淀成可复用的内部资产,这篇文章应该能给你一些可以直接抄的实践。

1. 先把概念捋清楚:技能、工具与工作流的边界

1.1 技能到底是什么

我见过太多人讨论 Agent,最后都把“技能”等同于“让模型调用某个API”。这是个特别容易掉进去的坑。工具(Tool)和技能(Skill)之间的差异,不是叫法不同,而是抽象的层级不同。

一个工具,通常就是单个原子能力,比如“发送HTTP请求”“读取数据库某张表”“调用某个翻译接口”。它做的事情非常单一,输入输出清晰,不会包含任何场景语义。而一个技能,应该是“面向某个业务目标、可被模型理解和编排的完整行为能力”。

我举个例子你就明白了。假设你们系统里有个“查询订单状态”的API,这是工具。但如果你只是把API丢给模型,模型每次都要自己组织参数、思考要不要查物流信息、要不要附带退款状态,甚至不确定订单号应该传字符串还是数组。而如果封装成一个“订单信息查询技能”,那么这整段行为逻辑就固化了:输入可以是订单号或者客户ID,技能内部负责拆解、查主单、拼装物流信息、处理查不到的情况,最后给模型一个格式干净的结果。

所以我在 agent-skills 项目里给技能下了个定义:

技能 = 意图识别 + 工具调用序列 + 上下文拼接 + 异常处理 + 输出规约

这是一个把“模型智能”和“业务能力”粘合起来的中间层。模型不需要关心技能内部怎么实现,只需要知道这个技能能帮他完成什么目标,在什么情况下该选它,以及它需要哪些输入。

1.2 为什么不能只用函数调用替代技能

现在主流大模型框架都支持 Function Calling,很多人觉得这个就是技能机制了。但我在实际项目里对比过,直接把几十个函数罗列给模型,和把函数组织成技能体系后交给模型,效果差异非常明显。

差异在哪儿?首先是上下文窗口的利用率。一个函数声明可能几百字,二十个函数就是几千字,模型的注意力被摊薄了。而技能机制可以做到两级路由:第一步先根据用户意图粗选出三五个候选技能,第二步再把具体技能的描述和参数Schema喂给模型做精确决策。这不只是省Token的问题,而是让模型在决策时聚焦在真正相关的信息上。

其次是行为一致性。函数是零散约定,技能是完整契约。我在项目里做过对比测试:同样一段“汇总本周客诉热点”的任务,纯函数调用时模型有40%的概率会忘记调用工单分类接口,而用技能封装后,这部分逻辑被固化在技能内部,只要模型正确触发了技能,就一定会执行完整的流程链。

1.3 技能在系统里的位置

如果给 Agent 分个层,从下往上大致是:模型 → 路由与编排 → 技能层 → 工具层 → 外部系统。模型和工具大多数人都知道,容易被忽略的是中间的和技能绑定的一套逻辑:技能注册表、技能路由、技能执行器、技能反馈回路。

技能注册表管理所有可用技能的定义和版本,路由负责根据用户输入挑技能,执行器负责跑通技能内的各个环节,反馈回路把每次执行的成败数据记录下来用于后续优化。这个结构我后面第三节会详细展开。

如果你现在脑子里只有“给模型加几个工具”的概念,我建议你画一张图:把技能层想象成公司里的项目经理——模型是老板,工具是干活的外包团队。老板不需要知道外包团队内部怎么分工,只需要向项目经理下指令。项目经理负责把指令翻译成具体的执行方案,并保证交付质量。这就是技能层存在的价值。

2. 设计一套技能的核心原则,不只是“把功能封装一下”

2.1 原则一:可编排性要优先于单点能力

我在项目里做的第一个技能库,犯过最蠢的错误:每个技能都做得像一个独立的“小应用”,输入输出定义得死板又封闭。比如“生成周报”技能,它内部直接读取数据库、做统计、生成文案,一步到位。看起来很强,但真到了用的时候会发现:用户今天想先汇总数据再人工审核一遍,明天想只统计某团队的、不生成文案,这时候改技能内部逻辑就特别痛苦,只能不断加大参数开关,技能描述越来越长,模型选择越来越难。

后来我把技能拆成更细的层次,遵循了一个原则:每个技能像一个乐高积木,能被其他技能或流程重新组合。还是周报场景,我不做“生成周报”这种粗粒度技能,而是拆成“数据统计”“结论摘要”“文案排版”“渠道推送”四个技能。模型可以自由组合它们:想生成纯数据周报就前两个,想带排版就加第三个,想发给群里就再补第四个。

要让技能可编排,在设计时就要站在“使用者会怎么组合”的角度着想,而不是只站在“这个功能要完成”的角度。我习惯在设计文档里给每个技能写上“与其他技能的交互关系”这一栏,明确标注它能替代什么技能、它需要什么技能前置、它能不能并发执行。强迫自己把技能当成开放的模块,而不是封闭的程序。

2.2 原则二:失败路径要显式表达,不能只规划阳光大道

大模型调用技能有一个特性:技能的“正常路径”写起来很容易,真正麻烦的是失败分支。大多数开发者在设计技能时只写了“输入什么、输出什么”,很少花时间回答这几个问题:如果模型传了无法理解的参数怎么办?如果技能内部依赖的外部API超时了怎么办?如果返回的数据为空,是报错还是返回“无结果”的占位信息?这个技能是幂等的吗,重复调用会不会产生副作用?

我在某个客服项目中吃过一次亏。当时的“客户标签更新”技能,只定义了正常流程——读数据、算标签、写入系统。上线三天后,模型在一次对话里连续触发了三次这个技能,客户的标签被重复覆盖了两次,还多了一条错误的追加记录。原因就是技能定义里完全没有写入“重复调用的保护”和“参数校验失败时的明确报错”。

现在的我在设计技能时,会强制要求补齐一份“异常契约”:

  • 参数不合法时返回什么错误码;数据为空时返回什么占位符;
  • 外部依赖超时时的兜底策略;
  • 重复调用/并发调用的幂等性说明;
  • 技能对权限和敏感数据的要求。

这些内容不只是给人类开发者看的,也会转化成技能描述里的约束文本,让模型在决策时就知道边界。模型知道“调用该技能若被拒绝会得到什么反馈”之后,它的行为会谨慎很多,乱调用的概率大幅下降。

2.3 原则三:收益边界要清楚,别什么破烂都装进技能库

“做成技能”是有管理成本的。技能越多,模型路由时的候选列表越长,技能维护量越大,内部逻辑的精细度也会稀释。我在项目里一度把技能数冲到60多个,结果模型选错技能的频率明显升高,因为相近技能的区分度不够。

后来我总结了一套判断标准,决定一个逻辑要不要做成独立技能:

  • 这个逻辑有没有被至少三个不同场景复用?如果只有一个业务方在用,那改成普通工具就行;
  • 输入输出是否足够标准化?如果每次调用输入参数都不太一样,说明它更适合写成Prompt模板;
  • 内部逻辑是否至少有一步模型决策?如果完全是无脑API转发,那它就是Tool,不是Skill。

这个判断标准帮我砍掉了三分之一的无用技能,路由准确率反而上升了。技能库不是越大越好,是越精准越好。

3. 从零到一:完整搭建一个技能库的实操记录

3.1 先选定场景,再做技能清单

我建议你第一次做技能库,不要贪大求全,选一个业务边界清晰的场景来练手。我实战的场景是“客服运营智能助手”。它的核心任务是:把用户在服务群里的聊天消息自动处理成结构化工单,推荐给对应负责人,并在每天收盘时生成运营摘要。

围绕这个场景,我拉了一张技能清单。我习惯用表格管理,列出技能名、目标、输入、输出、依赖,下面这是我当时的原始清单(节选):

技能标识技能目标关键输入预期输出
extract_issue从聊天记录中抽取用户问题主体原始消息、用户ID结构化问题描述
classify_topic判断问题属于哪类业务分类问题描述、分类枚举分类标签及置信度
find_history检索该用户的历史工单与处理记录用户ID、问题描述命中历史记录列表
recommend_owner根据业务规则推荐处理负责人分类标签、问题描述负责人列表
weekly_insight聚合本周工单数据生成运营总结时间范围运营摘要文本

清单定下来后,你会发现技能之间天然有依赖关系。比如 recommend_owner 依赖 classify_topic 的分类结果,weekly_insight 依赖 extract_issue 之后的所有数据。这个依赖关系我直接画成了一张有向图,每个节点是技能,边是数据流向。这张图最终沉淀成了技能路由表的核心依据。

3.2 写好技能描述和参数Schema,这一步决定模型能不能用好

技能描述是整个 agent-skills 项目里投入产出比最高的一part。我对比过不同写法的效果,一份粗糙的描述和一份精细的描述,模型选对技能的比例能差25个百分点以上。

一份好的技能描述,我认为至少包含六块信息:

  • 技能做什么,用一两句话说清楚;
  • 什么场景下应该调用它,列举触发它的典型用户表达;
  • 什么场景下不应该调用它,列举容易混淆的边界情况;
  • 输入参数的解释,尤其是那些容易填错的枚举值;
  • 输出格式的约定;
  • 调用失败或数据为空时的行为提示。

下面是我为 extract_issue 写的中文描述模板。注意它不是给用户看的话术,是给模型看的路由说明书。

skill_id: extract_issue name: 聊天消息问题抽取 description: > 从一条或多条客服聊天记录中抽取用户的核心问题主体。 适合输入原始对话文本,输出精炼的、可编辑的问题说明。 当用户只是想闲聊、或者消息本身不包含问题的场景下不要调用。 input_text 字段需要传入去除敏感信息后的消息内容。 parameters: type: object properties: input_text: type: string description: 需要抽取问题的原始聊天消息,越长越接近原文越好 user_id: type: string description: 用户唯一标识,可用于关联历史工单,可为空 required: [input_text] output: type: object properties: issue_summary: type: string description: 提炼后的问题描述,大约30-80字 issue_type: type: string enum: [故障, 咨询, 投诉, 建议, 其他] description: 根据问题语义推断出的初始类型 required: [issue_summary, issue_type] error_policy: empty_input: 返回错误码 NEED_INPUT sensitive: 若输入包含手机号、身份证等字段需先脱敏处理

写完之后我做了一个有点笨但很有效的验证动作:把每个技能描述打印出来,假装自己是大模型,用五条真实用户提问做模拟路由。如果模拟时自己都拿不准该不该调某个技能,说明描述写得还有歧义。这个方法比任何自动化测试都先发现问题。

关于参数Schema,我有一条强烈建议:尽可能给枚举值加上“语义锚点”。别只写「枚举值:故障、咨询、投诉、建议、其他」,要写「故障:用户报告系统不可用、报错、超时等问题;投诉:用户表达不满、要求补偿等」。模型对语义丰富的描述理解程度会明显更高。我在项目里甚至给每个枚举配了两到三个典型示例短语,效果非常好。

3.3 实现技能注册表与路由机制

技能定义文件写好了,需要一个运行时来承接。以 Python 为例,我搭了一个轻量的技能注册表,代码量不大,但结构很清晰。

from dataclasses import dataclass, field from typing import Callable, Any, Dict @dataclass class Skill: id: str name: str description: str schema: Dict[str, Any] handler: Callable[..., Any] version: str = "0.1.0" tags: list[str] = field(default_factory=list) class SkillRegistry: def __init__(self): self._skills: Dict[str, Skill] = {} def register(self, skill: Skill): self._skills[skill.id] = skill def get(self, skill_id: str) -> Skill: return self._skills[skill_id] def list_skills(self) -> list[Skill]: return list(self._skills.values()) def search_by_semantics(self, query: str, top_k: int = 5) -> list[Skill]: # 这里接入你的向量检索,将技能描述向量化后做相似度排序 pass

这个注册表提供了三个能力:注册、精确获取、语义检索。语义检索是路由的关键,我通常把每个技能的描述文本向量化存储,在用户请求进来时先做一次粗筛,找到top_k个候选技能,再把这些候选技能的详细描述一起交给模型做最终选择。

路由策略我建议用“两段式”:

  • 第一段是规则加向量检索的粗筛,成本低速度快,把技能匹配范围从60个缩小到5个;
  • 第二段是让大模型精排,把候选技能描述完整给出,让模型结合对话上下文选一个最合适的。

很多框架默认的做法是单段式的“所有技能描述一股脑塞给模型”,我用两段式之后Token消耗降低了大约60%,路由准确率还提升了。原因很简单,模型在少数几个相似技能之间做选择比在多而杂的技能堆里做选择要稳得多。

3.4 实测一轮,用数据说话

技能库搭完,不能凭感觉说“能用”。我习惯做一轮偏向性的能力测试。我会准备一套覆盖所有技能的测试用例,每条用例记录目标技能、真实用户表达、路由结果、执行结果。下面是一小段真实的测试数据示例:

测试用例用户表达期望技能实际选中执行结果
TC-01“看一下这个用户之前有没有报过网络问题”find_historyfind_history成功,命中2条工单
TC-02“这个客户说是你们产品有问题,要退费”classify_topicclassify_topic成功,分类为投诉
TC-03“今天大概来了多少单呀”weekly_insightextract_issue失败,路由错误
TC-04“把昨天南区的客诉整理个报告”weekly_insightweekly_insight成功,摘要生成正常

TC-03的失败很有代表性。模型把“今天大概来了多少单呀”理解为要抽取问题主体,而不是做数据聚合。我当时的处理不是改代码,而是去调整 weekly_insight 的技能描述,加入了一句“当用户询问统计数据、趋势或总量时优先调用本技能,即使消息中没有明确的问题描述”。一轮测试下来,这个错误的复现率就清零了。可见路由问题大多数时候是描述问题,不是模型问题。

4. 我在真实业务里踩过的坑与排查记录

4.1 技能描述写得太花哨,反而误触发率飙升

我在项目早期有一种误区:为了让模型更“懂”技能,把描述写得很丰富,加入了各种业务背景、行业术语、边界案例。结果模型对各种模棱两可的表达都往这个技能上靠,误触发率飙升。

后来我想明白了:模型的意图推断能力会放大描述中的“语义面”。如果你把描述里写上“本技能适用于客户情绪激动的情况”,那模型遇到任何情绪词都会优先尝试这个技能。正确的做法是,用严格的触发条件加反例来收窄边界,而不是用场景修饰词来扩展边界。

我现在的写法偏好是:描述开头用一句中性的事实陈述,再用“当且仅当”式的条件列表说明触发条件,最后总挂一句“不要调用的情况”。测试下来,误触发率下降了50%以上。

4.2 参数校验宽松,下游数据一片混乱

技能内部执行成功,不代表整个链路成功。我的教训来自 recommend_owner 技能。它在输出时只返回了负责人ID,没有校验负责人ID是否仍然在岗。结果有一周时间,系统把工单推荐给了两个已离职的同事。因为技能执行器只检查了“返回值非空”,没有检查“返回值的业务有效性”。

这个问题本质上是技能内部缺少业务校验。我的排查办法是在每个技能执行器里增加一层“业务检查断言”,专门负责对输出结果做业务合理性判断。比如负责人ID必须存在于当前在职员工表中、分类标签必须是运行中业务线定义的枚举,否则主动抛出业务异常而不是返回空值。这个习惯帮我挡住了一系列后续的数据质量事故。

4.3 技能版本被覆盖,旧会话行为漂移

技能不是写一次就永久不变的。在我项目的持续迭代中,经常发生:今天改了一个技能的参数格式,明天有同事反映“昨天的历史会话回放出来行为不对”。原因很简单——旧会话保存的执行记录是旧技能的输入输出,而技能执行器已经升级,旧数据用新逻辑处理自然对不上。

后来我把每个技能都加上了版本号,并在执行记录里保留触发时的技能版本。同时做了一层“兼容层”:对旧版本的已知调用方式做输入适配。这样一来,即便技能升级,旧会话的复盘也能保持行为稳定。这个治理动作在团队协作场景下尤为重要,不然每个人在本地改完技能,一上线就互相踩踏。

4.4 一个我自己觉得很好用的小技巧:黄金样例回归集

最后分享一个让我省了很多心的方法:为每个技能维护一个“黄金样例集”,里面存放五到十条该技能在真实业务里的最佳输入输出对,以及两到三条明确的负面样例(不应该触发该技能的输入)。每次更新技能描述或者内部实现后,我先把这些样例跑一遍,看有没有回归问题。

这听起来有点像测试驱动开发,但在一套技能体系里,它的价值被放得特别大。技能的对错很难用静态代码检查发现,只能靠业务样例来感知。这个黄金样例集我每个月花两小时更新一次,我敢说它帮我省下的排错时间至少是十倍以上。

写在最后

在我实际折腾 agent-skills 这套机制的过程中,最深的体会是:技能库不是设计出来的,是“长”出来的。你不可能一开始就规划出完美的技能边界,更合理的节奏是先搭一个最小闭环,然后跟着业务需求不断增删、合并、拆分技能。既要做加法,也要有勇气做减法——我砍掉二十多个低价值技能后,整体效果反而是明显变好的。

如果你的项目也到了Prompt越来越臃肿、模型行为越来越难预测的阶段,我建议你真的可以试试把能力用技能的方式重新组织一遍。先挑一个最常复用的流程,从写好一份技能描述开始,再配上一个简单的注册表和路由,很快你就能感受到结构带来的力量。后面如果有多智能体编排、技能自动发现这些方向的新体会,我再来接着分享。

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

商业卫星星座爆发增长与太空交通管理挑战

1. 太空竞赛新篇章:商业卫星星座的爆发式增长上周日本凯洛斯通信卫星的意外解体事件,再次将公众视线聚焦到近地轨道日益拥挤的现状。这颗价值数亿日元的卫星在轨解体后,产生的数百块碎片使得附近轨道区域的碰撞风险系数骤增30%。这已是今年第…

作者头像 李华
网站建设 2026/10/14 9:25:56

主动配电网中源-荷-储协同优化调度技术解析

1. 项目背景与研究意义 在能源转型的大背景下,电力系统正经历着从传统集中式供电模式向分布式、智能化方向的深刻变革。这种变革带来的最显著特征就是配电网中出现了大量分布式电源(如光伏、风电)、柔性负荷和储能装置,使得传统单…

作者头像 李华
网站建设 2026/10/14 9:25:01

Agent-Skills 技能模块化实战:从架构设计到工程化管理的完整指南

刚开始接触 agent-skills 这个概念时,很多人会误以为它只是给智能体堆一堆功能函数。真正动手把技能模块拆出来后,我才意识到这东西的本质,其实是把“智能体能力”这件事,从代码层面上升到了工程化管理的层面。我最初是在一个内部…

作者头像 李华
网站建设 2026/10/14 9:24:33

Tesseract 5.0 编译实战:解决中日韩OCR乱码与DPI崩溃

简介:本资源为OCR-Tesseract 5.0编译完成的开箱即用版本,面向计算机视觉开发者、文档数字化工程师及AI工程实践者,解决OCR引擎本地部署难、依赖配置复杂、多语言识别支持不足等实际痛点。压缩包含496个文件(62.38MB)&a…

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

逆向工程入门练习:从汇编基础到实战分析的系统训练

1. 逆向工程入门练习的整体设计思路 1.1 为什么选择逆向工程作为进阶方向 逆向工程这个方向,在安全圈子里一直是个绕不开的话题。很多人学编程学了一两年,写了不少业务代码,但总感觉对程序底层的理解隔着一层纱。你知道代码能跑,…

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

SpringBoot+Vue电影推荐系统架构与实战

1. 项目概述这个电影推荐系统项目采用了当下最流行的前后端分离架构,前端使用Vue.js框架,后端基于SpringBoot技术栈。作为一名经历过多个推荐系统项目的开发者,我深知这类系统在设计和实现过程中会遇到哪些"坑"。今天就来详细拆解这…

作者头像 李华