news 2026/10/13 8:22:32

Agent Skills实战:从工具调用到可复用技能,让行为收敛

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Skills实战:从工具调用到可复用技能,让行为收敛

1. 先搞清楚一个问题:Agent到底缺什么

过去两年我一直在折腾大模型应用,从简单的对话机器人做到能调用外部工具的智能助手,越做到后面越觉得,主流Agent框架给的“工具箱”模式越来越不够用。你给Agent塞一堆函数、接口,它确实能调用,但每次调用都像第一次见面,完全没把之前“学会的东西”沉淀下来。而“agent-skills”这个概念,坦白说,就是冲着这个痛点来的:把Agent干活的“经验”封装成可复用、可管理、可进化的技能模块。

一开始接触这个方向的时候,我最大的困惑是:这不就是把Prompt写得更详细一点,再挂上工具吗?真的上手之后才发现,完全不是一回事。Skills强调的是把“完成某类任务”的整体流程、约束、判断逻辑、输出规范打包成一个独立单元,让Agent在面对同类问题时直接整套复用,而不是每次都靠大模型现场推理、现场发挥。

这个标题看起来就两个词,但背后牵扯到的核心问题其实不小:Agent的行为稳定性怎么保证?经验怎么沉淀?技能多了之后怎么路由、怎么避免互相打架?版本迭代之后怎么保持兼容?这些都不是靠堆Prompt能解决的。

所以这篇文章我会从问题本身出发,把Skills这个设计到底解决了什么、是怎么从Tools进化过来的、实际开发中怎么封装一个能用的技能、以及多技能管理时的工程化经验,全部摊开来讲。适合谁看?如果你们团队已经在用LangChain、LangGraph或者类似的Agent框架做应用,而且已经开始觉得“函数注册表”不够用了,那这篇文章应该能帮你省不少试错时间。

1.1 指令即代码?这种思路的天花板

先说一个很常见的做法。早期我帮某公司做的内部知识库助手,第一版就是把所有规则写成System Prompt,里面列了一堆“如果用户问天气就调用XX接口,如果用户问库存就查XX表”的指令。刚上线的时候效果还行,因为场景少,就二三十条规则。但两个月后场景扩到一百多个,Prompt已经膨胀到一次性塞不进去了,而且更尴尬的是——新规则和旧规则开始互相覆盖。

举个例子。有一条规则说“用户提到耗材要引导去商城下单”,另一条规则说“用户问库存时要给出实时数字”。结果用户问“这个耗材还有库存吗”,Agent就卡住了,它不知道应该走商城引导还是走库存查询。这种冲突在大模型眼里不是逻辑错误,它会随机挑一个执行,然后用户体验就变成抽奖。而且你没法靠肉眼在一万字Prompt里找出所有可能冲突的规则。

这就是“指令即代码”思路的天花板:你把所有东西都堆在同一个上下文里,让模型自己掂量哪个优先级高。短期能跑,长期必崩。本质原因是:规则之间没有任何边界,A规则和B规则不知道对方的存在,冲突不可避免。

Skills的思路是完全不同的。每个技能是一个独立模块,它自己带触发条件、执行逻辑、输出格式,互不干扰。Agent要做的是先判断“这个请求属于哪个技能”,再进入那个技能的上下文去执行。规则集从“一锅炖”变成了“分门别类放好的抽屉”,冲突面天然就小了很多。

从工程上看,这也让测试和维护变得舒服多了。一个技能可以单独抽出来测,单独发版,甚至单独回滚。这跟写代码时做模块化、组件化是同一个思路,只是把对象从函数换成了“大模型行为单元”。

1.2 从Tools到Skills:把“经验”变成可执行资产

再看第二层问题:Tools为什么不够用。主流Agent框架里都有“工具注册”机制,定义几个函数,把函数名、参数描述、返回值说明告诉大模型,模型在需要的时候生成调用请求。这在单一功能场景下很好用,比如查天气、算个数学题。但问题在于,一个工具只负责“一步操作”,而真实业务里大量任务是需要多步协作才能完成的。

以“写周报”为例。工具如果拆成“查工时”“查项目进度”“汇总文本”,那Agent得自己决定先调哪个、中间怎么加工、输出长什么样。每一次都让大模型现想,就意味着每一次的输出都可能不一样。今天它先查工时再查项目,明天可能先查项目再查工时;今天周报分三段,明天分六段。行为不稳定是这种模式最大的硬伤。

一个“周报技能”应该是什么样?它要把整个流程固化下来:第一步查工时数据,第二步查项目里程碑,第三步按照“项目进展、风险、明日计划”的固定结构生成周报,第四步检查输出长度和格式,然后直接产出。大模型在里面干的活不是重新设计流程,而是在给定的结构里做填充和微调。这就是Skills和Tools的本质区别:Tools是零件,Skills是装配好的流水线。

我后来在某个跨平台系统的项目里试着把常用的十几种业务流程全部技能化之后,最直观的感受是:Debug的难度下降了一个数量级。以前Agent出Bug,你根本不知道它是哪一步想错了,现在你直接锁定是哪个技能内部的问题,然后把那个技能单独拎出来调就行。

2. Skills这个设计,核心到底在解决什么

聊完了“缺什么”,再进一步拆一下Skills这套架构核心解决的四个问题:行为收敛、经验沉淀、依赖管控和可评估性。每一个都对应我在实际开发中踩过的坑,一个一个说。

2.1 行为收敛:让Agent不再每次都“临场发挥”

“临场发挥”这个词,用过Agent的人应该深有体会。同一个任务,上下文稍微变一下,输出结构可能就差了八百里。我见过有Agent在给客户写邮件的时候,今天用“尊敬的”开头,明天直接“Hi”,今天正文三段式,明天五段式。如果你做的是对外输出型应用,这种不稳定性是非常致命的,因为品控没法做。

技能化之后,输出结构是被“锁”在技能定义里的。模型的自由发挥空间被收敛到了“结构内的表达”,而结构本身不会漂移。举个例子,我做的邮件技能里规定了Opening必须有称呼、Body必须控制在200字以内、Closing必须包含联系方式,模型只能在给定字段里发挥措辞创意,但骨架是稳定的。

这背后其实用到了大模型一个很重要的特性:给定约束越明确的上下文,输出越稳定。当然这不是百分之百的,所以技能内部还需要在关键环节加上校验逻辑。比如字段缺失就自动补全,格式不对就重新生成。这一套下来,Agent的行为方差可以压到非常低。

有人可能会问:这样会不会让Agent变得死板、不够智能?我的回答是:业务系统需要的是“可控的智能”,不是“薛定谔的智能”。你要灵活性,那就在技能定义的时候给出口子,比如设置自由模式参数,而不是让整个系统行为完全不可预测。

2.2 经验沉淀:技能是带状态的“熟手”

大模型本身不记事儿,你上一次教它的做事偏好,这轮对话结束就全忘了。即便是长对话,也就是多撑一会儿的窗口记忆,换个会话照样从头再来。这就导致一个很蠢的现象:团队花了很多精力调出来的最佳实践,存在PPT里、飞书文档里,但Agent每次干活的时候完全用不上。

Skills的另一个价值就是把“经验”落地成可执行资产。你今天发现做竞品分析时用某个特定框架效果特别好,就可以把整个分析框架固化成一个“竞品分析技能”。下次Agent接到同类任务时直接套用。注意,这跟普通的few-shot示例有本质区别:few-shot给的是几个孤立的参考输出,但技能给的是完整的行为流程、判断规则、输出模板、兜底逻辑。

我自己的习惯是,每做完一个高价值的Agent任务,都会复盘一遍“哪些步骤如果固化下来,下次能少走弯路”,然后把这些步骤写成一个新技能。时间长了,技能的积累本身就是团队的竞争壁垒。因为Prompt可以被抄走,但经过业务打磨的技能集,别人很难一次性复制。

这也是为什么Skills的设计里,非常看重“技能描述”和“适用场景”这两个字段。它们决定了这个技能在什么条件下被激活,以及如何在多技能环境中被检索命中。如果描述写得不清楚,技能再多也是废的,因为Agent根本不知道什么时候该用它。

2.3 Skills和Prompt模板、RAG的区别

很多刚接触这个概念的人都会混淆这三样东西。我简单区分一下。

Prompt模板是把固定句式和变量占位符组合起来,解决“问法很多但底层意图一致”的问题。但它没有执行链路,没有多步流程,也没有结果校验。它本质上是“一段话”,不是“一个行为”。

RAG是做知识注入的。它解决的是“模型不知道某个特定信息”的问题,靠检索把相关资料塞进上下文。但RAG不会告诉模型“怎么处理这些资料”,检索回来的东西怎么加工、怎么落成最终结果,还是要靠模型现场决定。RAG是“喂料”,Skills是“定流程”。两者经常配合,但不是一回事。

Skills的定位是“行为层”。它封装的是“面对某类任务时,Agent应该怎么行动”的整套逻辑。你可以把一些RAG检索步骤内嵌在技能里,也可以把Prompt模板作为技能内部的一个环节,但Skills本身远大于它们任何一个。如果把Agent比作一个餐厅,Prompt模板是做菜的配方,RAG是食材仓库,而Skills是整个后厨的SOP手册。

3. 实操:从零封装一个能用的AgentSkill

理论说再多,不如直接上手。这一节我用一个我实际做过的“周报生成”技能来演示,怎么从零封装一个可用、可测、可迭代的Agent Skill。

3.1 技能结构:先定骨架再补血肉

一个标准的技能我建议至少包含五块:描述与触发条件、输入模式、执行链路、输出规范、异常兜底。这五块缺一不可,缺了任何一块,技能都会在某个场景下出幺蛾子。

描述与触发条件是给Agent看的,它决定了路由系统在什么时候激活这个技能。这一块要写得像搜索引擎的关键词,既要覆盖用户的各种问法,又不能过度泛化把不该接的任务接进来。输入模式决定了这个技能需要哪些结构化参数,比如周报技能需要“用户名、时间范围、目标格式”。执行链路是这个技能的核心,规定了模型先做什么、再做什么、每一步的输入输出是什么。输出规范锁定了结果的格式、长度、字段结构。异常兜底则负责处理“链路里某一步失败时怎么办”。

这五块定义好之后,技能的骨架就算立住了。剩下的就是往里面填实际的Prompt内容、接入数据源的逻辑、校验规则。

3.2 代码示例:一个“周报生成”技能的实现

先上结构定义。我用YAML来写,因为可读性好,方便非技术同事一起维护。实际运行的时候会把它解析成结构体。

name: weekly_report_generator description: | 根据用户提供的工时数据和项目里程碑,生成结构化周报。 适用于用户说“写周报”“生成周报”“总结本周工作”等场景。 不适用于数据分析、非周报类文档生成。 triggers: keywords: ["周报", "weekly", "本周总结", "工作汇报"] intent_match: "generate_weekly_report" inputs: user_name: type: string required: true description: "汇报人姓名" time_range: type: string required: true description: "周报覆盖的时间范围,格式YYYY-MM-DD ~ YYYY-MM-DD" focus_areas: type: list[string] required: false description: "本周重点关注的领域,默认自动识别" workflow: - step: fetch_work_hours tool: internal_timesheet_api params: user: $user_name range: $time_range - step: fetch_project_milestones tool: project_management_api params: user: $user_name range: $time_range - step: draft_report llm_prompt: | 你是一名资深项目助理,请基于以下原始信息生成周报。 数据: 工时记录:{{work_hours_data}} 项目里程碑:{{milestone_data}} 要求: 1. 按“本周进展、风险预警、下周计划”三段式组织内容 2. 每条内容必须包含具体数据和结论,禁止空话 3. 总字数控制在300~500字 4. 风险部分必须给出建议动作 output: report_draft - step: validate_output validator: | 检查report_draft是否包含三个章节,是否包含数据引用。 如果缺失,回到draft_report步骤重新生成一次。 output_schema: title: string sections: - name: "本周进展" - name: "风险预警" - name: "下周计划" rollback: - if: fetch_work_hours fails action: "提示用户工时系统暂时不可用,提供上周缓存数据作为降级方案" - if: validate_output fails twice action: "进入手动模板模式,按模板字段生成最小可用周报"

这里有一个很关键的设计,异常兜底里我写了“如果取工时失败,用上周缓存数据降级”。这是实际踩坑之后的经验:一开始技能里没有兜底逻辑,某天内部系统接口超时,Agent直接罢工不产出了,用户体验极差。加上降级缓存后,即使数据不是最新,至少能出一版让用户手动改的草稿。

3.3 触发条件与动态变量注入

触发条件这块特别容易踩坑。之前我写过一版技能,触发关键词里漏了“工作汇报”这个说法,结果用户明明是想写周报,Agent却给当成写邮件技能处理了,整段偏题。后来我把触发条件拆成两层:一层是关键词匹配,一层是意图分类模型兜底。只要有一层命中,就进入技能候选列表。

再提醒一下动态变量注入。技能里的工作流步骤经常会用到用户输入,但你不能直接把用户原话塞进Prompt里,因为它可能带无关信息。我一般是先做参数抽取,从用户会话中提取结构化的user_name、time_range等参数,再注入到工作流中。这样技能内部的Prompt就干净很多,不会夹带乱七八糟的闲聊内容。

这个技能实现完毕之后,总体上讲,你可以看到它跟单纯的“把指令写在System Prompt里”的差别,就是——流程是显式的,校验是强制的,失败是预判过的。这三点合起来,技能才真正配得上“可执行资产”这个说法。

4. 技能多了以后:注册、路由与版本管理

技能不是越多越好。当你本地攒了二三十个技能之后,新的问题会冒出来:Agent到底该用哪个?两个技能会不会搞混?旧版技能还敢不敢用?这节的实操经验是从我管理一个含三十多个技能的技能库中踩出来的。

4.1 让Agent正确选技能的机制

在“技能路由”的问题上,我第一种方案试过“把所有技能描述塞给模型一次性排序”。这种方式在小规模时是可行的,但技能超过二十个之后,光是把描述喂进去就占了大量上下文,而且模型的选择准确率肉眼可见地下降。后面我换成两阶段路由架构:第一层用元数据粗筛,第二层用语义向量排序。

先说元数据粗筛。每个技能在注册的时候就带一批结构化标签,比如领域(开发、运营、销售)、任务类型(生成、分析、提取)、依赖工具(工时系统、项目系统、CRM)。路由模块先按这些标签缩小候选范围。比如用户的问题是“这周的销售数据总结下”,那直接过滤掉开发类和生成文档类的技能,候选可能只剩三四个。

再说语义向量排序。把用户问题和剩余候选技能的描述都做embedding,然后算相似度排序。这一步效果还不错,但有个细节:embedding模型对中英文混合的短文本很敏感。我一开始用的通用embedding模型,排序结果飘忽不定,后来换了专为中文优化的版本,准确率才上来。这块之所以重要,是因为Agent选错技能,后面每一步都是白费。

4.2 检索与路由的工程化做法

如果你想把路由这套做得更稳健,我建议不要让大模型直接生成“技能名”就完事,而是让它先输出一个候选技能列表和理由,再交给规则层做最终裁决。这里“理由”很关键,因为它给Debug留了抓手——Agent选错了技能,你看理由就知道它是被哪个描述误导了。

这就像一个菜鸟点单员,你不只让他报菜名,还要求他解释为什么客人想点A菜,这样他点错了,你才知道是菜单描述误导了他,还是他对菜系的理解有问题。

路由层还有一个很重要的设计——置信度阈值。当用户问题的语义与所有候选技能的相似度都低于某个阈值时,不要强行选一个技能,而是启用一个“通用对话技能”来兜底,或者直接问用户澄清。这个设计救过我很多次,因为每个技能都有覆盖盲区,硬选的结果往往比不选还糟。

注意:技能名称本身一定要起得“有描述性”,尽量包含任务类型和对象。比如weekly_report_generator比helper_tool_01强一万倍,模型的语义匹配能力真的会通过名称来调动。

4.3 版本管理:别让你的技能悄悄变异

技能上线之后不是一劳永逸的,你需要持续迭代。但版本管理这关很容易被偷懒跳过,我自己就吃过亏。有一版把周报技能的输出模板改了,结果用户反馈“周报看起来不像周报了”,排查半天发现是另一个同事在调试时顺手改了模板没提交说明。

我的方案是给每个技能都配上语义化版本号,同时在技能的changelog字段里记录每次改版的原因和影响范围。不是让你像写论文一样维护文档,但至少要把“谁在什么时候改了哪里改了为什么”记下来。否则一旦线上出问题,你连回滚都不知道该回到哪个版本。

版本管理还有个进阶玩法:灰度发布。比如一个技能的新版本只在10%的会话中生效,如果效果稳定再逐步放大比例。具体做法不复杂,在路由层加一个版本分配器,通过随机数决定走新版还是旧版。做一次之后你会发现,这个机制比什么预验证都靠谱,因为真实流量的多样性是测试集永远覆盖不了的。

5. 调试实录:几个坑和排查思路

讲了半天架构和设计,接下来分享一些我在实际跑Agent技能时遇到的典型故障,以及我常用的排查思路。这些坑不一定每个团队都会踩,但踩到任何一个都是要命的,知道怎么排查,能帮你省下好几个下午。

5.1 Agent“忘了”调用技能怎么办

最常见的问题是:Agent明明应该调用技能去干活,但它偏不,它选择用自己那点通用知识硬编一个答案。比如问“帮我生成本周周报”,模型直接自己写了一份通用周报,完全没用技能系统,自然也没去拉取真实工时数据。

排查思路第一步不是改Prompt,而是先看路由日志,确认技能是否被召回。如果路由层压根没把技能放在候选里,那问题出在触发条件描述上;如果技能在候选里但模型没用,那问题出在“提示词对模型行为的引导不够”。

这个问题的有效解法是:在System Prompt里加一行“当系统判定有匹配技能时,必须激活技能,禁止自行生成结果”。也可以给每个技能配备一个“激活示例”,让模型在Few-shot示例中看到“当用户说出类似这句话时,你应该激活哪个技能并调用”。实测下来,激活示例比抽象描述效果显著得多。

5.2 技能检索被覆盖、路由串台怎么解

第二种情况是路由串台:用户明明在问A技能的事,系统却命中了B技能,输出牛头不对马嘴。最典型的原因就是技能描述写得太泛,两个技能之间语义相似度过高。比如我开发过一个“项目总结技能”,另外一个“个人总结技能”,描述里都用到了“总结”这个高频词,结果用户一提“总结”,两个技能都被召回了,排序又飘,就经常选错。

我的解法是给技能描述增加“负面声明”。比如在“个人总结技能”的描述末尾加一句“本技能仅处理个人工作汇报类总结,不处理项目整体复盘,项目复盘请走项目总结技能”。这相当于给路由层更强的区分信号,大模型对“负面清单”的理解能力通常比纯正向描述要好。

另一个排查思路是打开路由日志,查看语义排序的分数差。如果Top1和Top2的分数只差了0.01,说明这两个技能在语义上确实不好分,这时候不是继续调embedding模型,而是老老实实去改技能描述,拉开它们的区分度。

5.3 技能内部生成结果不稳定怎么调

第三类是技能内部生成结果不稳定。比如周报技能里,让模型写“本周进展”,它有时候写三条,有时候写五条,结构也不固定。技能整体走了,但细看产出还是随机。

这种情况要区分是两个原因:一是技能里的Prompt约束不够具体,二是输出校验器没有起到纠偏作用。我当时的方式是:把“本章节最多三条,每条必须包含百分比进度”这类硬约束直接写进Prompt,然后在输出校验器里做正则匹配检查。不满足就直接触发重新生成。这里的教训是:不要指望大模型读一遍要求就每次都遵守,你要用代码去兜住它。代码才是真正的确定性保证,大模型的“听话”只是概率事件。

在稳定性调优上还可以尝试把温度参数调低,但这只适合结构化要求高的输出,如果是创意生成类技能,温度太低反而会让内容变得索然无味。这个分寸,要根据技能类型反复试。

6. 关于“agent-skills”的一点个人体感

折腾了大半年,我最大的感受是:技能化的核心不是写技能本身,而是建立一套“让技能能被正确发现、可靠执行、安全迭代”的机制。单独写一两个技能很简单,但要把技能做成一个体系,让它能抗住真实业务的复杂度和持续变化,这才是真正有挑战的地方。

把这个方向做扎实以后,你会发现团队讨论Agent问题的方式也会跟着变。以前大家争论的是“这个Agent怎么不听话”,现在讨论的是“这个技能的触发条件是不是该加个负向样本”“这个技能的输出校验是不是该更严格一些”。话题从玄学变成了工程,这就是技能化带来的最大的价值。

最后分享一个每次实战都管用的小习惯:给每个技能配一个“一句话验收标准”。周报技能的验收标准不是“生成了周报”,而是“生成了包含进展、风险、计划三部分、且有数据支撑的周报”。写下来你就知道这个技能合格没有,该不该改版,改完之后有没有退步。这一点微小但有用,建议你一定试一次。

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

从零构建知识工作插件:让采集、整理、检索自动化流转

一个知识工作者的日常,表面上看是“读读写写”,实际上密集地分布在十几个工具之间:看到一篇有价值的文章要复制关键段落,开会时随手记下的想法要归到某个主题下,数据库里的片段要反复回查,写文档时又要到处…

作者头像 李华
网站建设 2026/10/13 8:21:54

基于微信小程序的社区养老管理系统设计与实现

社区养老的话题这些年一直没冷过,但聊到具体落地,最缺的往往不是床位和护工,而是信息怎么管。养老服务站有没有空闲人力、哪位老人该上门回访了、家属想看看服务做到什么程度——这些问题靠台账和电话确认,效率极低。“基于微信小…

作者头像 李华
网站建设 2026/10/13 8:21:09

代码结构与模块化设计:从混乱到可维护的工程实践

代码结构这件事,我最近感触特别深。团队里来了个新人,接手一个跑了两年多的老项目,看代码的时候眉头皱得能夹死蚊子。不是说他水平不行,而是项目里到处都是“看起来能跑但根本不敢动”的代码——一个函数五六百行,模块…

作者头像 李华
网站建设 2026/10/13 8:20:55

OpenMontage:开源蒙太奇自动化剪辑工具,重塑视频剪辑节奏与重组流程

如果你做视频剪辑已经有一阵子,大概率会撞上同一个瓶颈:素材拍了一大堆,单看每个镜头都觉得能用,可一旦放上时间线,怎么组、怎么接、节奏怎么定,就是找不到感觉。说得再直白一点——剪辑软件的按钮你都熟了…

作者头像 李华
网站建设 2026/10/13 8:20:13

IEC 60417-2020图形符号数据库解析与工程化集成指南

简介:本资源为国际电工委员会(IEC)官方发布的《IEC 60417-2020 设备用图形符号数据库快照(2020-03-06)》PDF标准文件,面向电气/电子设备设计师、工业产品UI工程师、技术文档编写人员及认证合规工程师&#…

作者头像 李华