☰
Agent Skills 实战:把通用大模型调教成专业行家的方法论
2026/9/24 23:26:09 网站建设 项目流程

前阵子有个做 AI 应用的朋友找我吐槽,说他搭的 agent 总像个"什么都懂一点的实习生"——写代码也行、查资料也行、整理文档也行,但每一件事都做得不够专业,稍微往深了问就露怯。他想让 agent 在特定任务上达到"老手"的水准,却不知道该从哪下手。我当时就告诉他,你缺的不是更聪明的模型,而是一套成体系的agent-skills机制。

这句话不是随口说的。过去大半年,我一直在折腾 agent-skills 这套思路,把原本堆在 system prompt 里的"一坨"通用指令,拆成了一个个独立、可复用、可单独测试的技能单元。做完之后最直观的感受是:agent 不再是一个靠临场发挥的"通才",而是变成了一个带着一堆专业工具书、知道什么场景该翻哪本书的"行家"。这篇文章我就把这段时间的完整实践串一遍,包括 agent 和 skills 之间到底隔了什么、一个 skill 文件该长什么样、怎么写才能让模型稳定调用、多技能共存时怎么调度、以及怎么测试才能保证上线不翻车。如果你正在做 agent 应用,或者只是好奇"让模型干专业活"这件事到底怎么落地,这篇文章应该能给你点实在的东西。

1. 先搞清楚一个前提:agent 和 skills 之间到底隔了什么

1.1 为什么要把指令"拆开",而不是"堆进去"

很多人做 agent 的第一反应,是把所有要求写进一个巨大的 system prompt:你是我的助手,你要做 A,做的时候注意 B,遇到 C 情况要 D,输出格式要 E……写到后面,prompt 三千字起步,模型的表现却越来越飘。为什么?因为模型的注意力是有限的,指令太多、优先级不明确的时候,它只能抓主干、丢细节,而那些细节恰恰是你最在乎的专业要求。

agent-skills 的核心逻辑恰好相反:不追求一个全能的 prompt,而是把每一个专业任务封装成一个独立的 skill,每个 skill 只负责一件事,只有被触发时才进入上下文。这样做有三个立竿见影的好处:一是单个 skill 的指令可以写得很细、很专,不用担心稀释模型注意力;二是不同任务之间的指令不会再互相干扰;三是每个 skill 可以单独迭代、单独测试,哪个出了问题就修哪个,不用动整条链路。

1.2 工具、技能、工作流,三个概念别混在一起

开始设计 skill 之前,还有一个特别容易踩的概念坑:把工具(tool)、技能(skill)和工作流(workflow)当成一回事。实际上它们是三个层次的东西,混在一起会直接导致你的 skill 目录设计得一团乱。

拿一个做数据分析的 agent 举例。工具是"能做什么":比如有 execute_python、read_csv、visualize 这些函数,它们给 agent 提供了操作能力。技能是"知道怎么做":比如"做探索性数据分析"这个 skill,它包含一套步骤——先看数据形状、再查缺失值、然后看分布、最后做相关性分析,这套步骤是可以沉淀下来反复用的。工作流则是"什么时候做什么":比如"每周一自动拉取上周的销售数据,跑一次 EDA,出一份周报",它把多个技能和决策条件串成了一个完整流程。

很多人的 skill 目录之所以越用越乱,就是因为在设计 skill 时不小心把工具定义和工作流逻辑也塞了进来。我的原则很简单:skill 里只写"怎么做好一件事",不写"用什么函数",也不写"什么时候该做这事"。工具是底座,工作流是编排,skill 是中间那层可被排列组合的专业能力单元。

2. 一个 Skill 的标准解剖:从入口描述到执行指令

如果你去看各种开源 agent 框架里的 skill 实现,会发现格式五花八门,但核心部件都差不多。我自己用下来,一个成熟的 skill 文件至少应该包含四块:name、description、params、instruction。前两块决定"模型什么时候想起它",后两块决定"模型调起它之后能不能干好活"。

2.1 模型靠什么判断"该不该用这个技能"

很多人在 skill 的 description 上敷衍了事,写一句"用于代码审查"就完事了。结果是什么?模型在真正需要它的时候想不起来,或者在不该用的时候强行调用。这是因为在大多数 agent 架构里,模型决定是否激活某个 skill,靠的就是读 description 然后做语义匹配。它不看你的 instruction 写得有多精彩,只看你那几句话能不能和当前用户请求挂上钩。

所以 description 的写法,核心就一句话:把"什么时候该用本技能"的触发条件写清楚。我个人的习惯是三段式:第一句说这个 skill 是干什么的;第二句列举哪些说法应该触发它,最好是用户原话级别的例子;第三句明确哪些情况不应该触发,把边界画出来。举个例子,一个"代码审查"技能,如果 description 里写"用户要求审查代码、检查代码质量、做 code review 时使用,不要用于 debug 场景",触发准确率会比一句话描述高出一大截。

2.2 参数声明:给模型的输入边界

params 是容易被新手忽略的部分。skill 不是凭空运行的,它需要输入,这些输入从哪里来?在 agent 场景下,通常是模型根据对话内容自主抽取。如果 params 定义得不清晰,模型要么抽错,要么漏抽,skill 拿到的数据就是残缺的。

这里有一个很实用的建议:给每个参数写清楚它的含义、类型、是否必填,以及从哪类信息里提取。比如一个"会议纪要整理"的 skill,输入参数可以定义为 meeting_transcript(必填,字符串,用户粘贴的会议文字记录)和 attendees(可选,字符串列表,会议参与人)。模型读到参数说明后,才知道该从对话里找什么。另外,参数不要设计得太多。我见过有人一口气定义十几个参数,结果模型光是抽取参数就耗尽了大半上下文预算,skill 本身的执行质量反而下降。参数数量控制在 3~5 个是比较健康的范围。

2.3 执行指令的三种写法与适用场景

instruction 是 skill 的灵魂,也是写法差异最大的地方。我总结了三种常见写法,各有各的适用场景。

第一种是步骤式,适合流程固定的任务。比如"数据清洗":第一步检查重复值,第二步处理缺失值,第三步统一字段类型,第四步输出清洗报告。这种写法胜在稳定,模型照着走基本不会跑偏,缺点是灵活度低,遇到特殊情况容易僵化。

第二种是原则式,适合需要判断力的任务。比如"内容审校":不要逐字逐句改稿,先看逻辑结构再看措辞;对事实类错误必须标注来源;修改要保留作者语气。这种写法不告诉模型具体怎么走,而是给它几条必须遵守的底线,让它自由发挥的同时不越界。

第三种是示例式,也就是 few-shot,适合输出格式复杂、难以用规则描述的任务。比如"生成结构化周报",给出两三个标准的输入输出对,模型会照着模仿,比写十行"你必须怎么怎么样"有效得多。

这三者也可以混用。我的经验是:核心流程用步骤式兜底,专业性要求用原则式围栏,复杂输出用示例式做示范,三层组合起来,skill 的质量就有了基本保障。

2.4 版本号与元信息:容易被忽视的两样东西

最后聊一个很多人不重视、但后期会救命的东西:版本号和元信息。skill 是会迭代的,今天你改了 description,明天你调整了输出格式,如果不记录版本,两周后 skill 表现异常,你根本不知道是哪个改动引起的。我现在的习惯是每个 skill 顶部都维护 version、changelog、owner 三个字段,改动一次就更新一次。这不是形式主义,是在多技能、多协作场景下做问题回溯的唯一线索。

3. 手写一个实用 Skill:从代码审查到完整落地

讲完了理论,用一个实例把整个流程走一遍。我选"代码审查"这个任务,因为它是典型的"看起来简单、做好很难"的技能:人人都能说两句,但说出来的话必须专业、有依据、可执行,才称得上 skill。

3.1 选一个值得做成 skill 的任务

不是所有任务都适合做成 skill。判断标准有三条:第一,任务是重复出现的,至少每周都会碰到几次;第二,任务有相对稳定的方法论,不是每次都不一样;第三,任务做得好不好有明确的评价标准。代码审查三条全占,所以特别适合。

第一步是把这个任务的方法论沉淀下来。我当时回顾了自己做过的几十次 code review,梳理出了一个固定框架:先通读理解整体设计,再按正确性、安全性、性能、可维护性四个维度逐项检查,最后按严重程度分级输出问题清单。这套框架就是 skill 的核心资产。

3.2 Skill 文件的完整示例

下面是我实际用过的一个代码审查 skill 的简化版,格式是 YAML,字段按照前面说的四件套来组织:

name: code_review description: > 对给定的代码片段进行系统性审查,输出结构化审查报告。 当用户说"帮我看看这段代码"、"做一下 code review"、 "检查代码有没有问题"、"审查这个 PR"时使用本技能。 不要用于单纯的语法报错排查,也不要用于 debug 类问题。 version: 1.3.0 params: code: type: string required: true description: 待审查的代码文本,可以直接从对话内容中提取 focus: type: string enum: [correctness, security, performance, readability] required: false description: 审查重点,缺省时四个维度全查 instruction: | 1. 通读全部代码,先建立整体认知,不要看到第一个可疑点就下结论。 2. 如果指定了 focus,优先审查对应维度;未指定则按正确性、安全性、 性能、可维护性的顺序逐项检查。 3. 判断每个问题的严重级别:blocker(会导致功能错误或安全漏洞)、 major(明显影响质量)、minor(一般性改进建议)、nit(风格类小问题)。 4. 按以下格式输出报告: 【概览】代码行数、函数数量、主要职责 【问题清单】按严重级别从高到低排列,每条包含: - 位置(行号/函数名) - 问题描述 - 为什么是问题 - 建议修改方案 【总体评价】2-3 句话,涵盖代码质量和改进优先级。 5. 规则:没有充分依据不下结论;每条问题必须给出位置和理由; 如果代码行数超过 300 行,按函数为单位分批审查,不要试图一次看完。

3.3 第一次运行后的迭代方向

写完 skill 文件,千万别直接投入使用,先跑三轮测试。第一轮拿一个你知根知底的旧代码来测,因为你清楚里面埋了什么问题,能判断 skill 有没有找到;第二轮拿一段故意"写得很烂"的代码,看它会不会过度报告;第三轮拿一段高质量代码,看它会不会为了凑数而硬报问题。

我第一版 code_review skill 跑下来的问题非常典型:它会报告一些"看似是问题、其实不是"的东西,比如对局部变量的命名提出风格修改,而这种建议对团队项目毫无价值。后来我在 instruction 里加了一条规则:"nit 级问题如果数量超过 5 条,只报告最有代表性的 3 条",并强调对团队既有代码风格要克制。这就是 skill 迭代的常态——不是一步到位,而是通过真实反馈一点点调优。

4. Skill 编排与路由:多技能共存时的调度细节

单技能跑通只是第一步。当你的 agent 里挂了十几个甚至几十个 skill 时,真正头疼的问题才开始出现:模型能不能在正确的时机选择正确的技能?两个技能描述相似时怎么办?技能之间能不能互相调用?

4.1 描述冲突:两个 skill 都觉得自己该上场

我踩过的最痛的一个坑,是有一次同时维护了"周报生成"和"项目进展总结"两个 skill,前者负责把零散工作记录整理成周报,后者负责从长篇讨论中提炼项目状态。结果模型经常在用户说"帮我写周报"时反而激活了"项目进展总结",输出一份文不对题的东西。

问题出在 description 的语义边界不够清晰。解决方式有两个层面。第一,在编写阶段就刻意做差异化描述,每个 skill 的 description 里都明确写出"本技能不适用于什么场景",把重叠区域提前隔离。第二,在路由阶段引入优先级机制,如果两个 skill 的匹配分数都很高,优先选择 description 更具体、更长的那一个——因为描述更具体往往意味着它更贴近用户的真实意图。我后来干脆把两个技能合并成一个,在 instruction 里用条件分支处理两种场景,反而更清爽。同类技能能合并就合并,合并不了的才靠描述区分,这是减少路由冲突的治本方法。

4.2 技能链:A 技能里调用 B 技能

有些复杂任务天然需要多个技能协作。比如"写一份竞品分析报告",可能需要先调用"网页信息采集"技能抓取资料,再调用"数据分析"技能做对比,最后调用"报告生成"技能输出文档。这就涉及技能链的设计。

技能链有两种实现思路。一种是在 skill A 的 instruction 里直接写"本技能执行第三步时,需要调用 skill B,调用方式是……",把依赖关系硬编码进去。这种方式简单直接,但耦合度高,A 一改,B 被影响的概率就大。另一种是解耦思路:让每个 skill 只输出结构化中间结果,由上层 agent 根据中间结果决定下一步调用哪个技能。比如"竞品分析"技能只负责输出"竞品功能对比表",至于这张表是拿去生成报告还是生成 PPT,它不关心。

我个人强烈倾向第二种。因为第一种做法本质上还是在写死流程,违背了 skill 设计的初衷——可复用、可组合。把中间结果结构化,等于把技能之间的耦合点变成了数据,这条数据流比任何硬编码都更稳定。

4.3 上下文与预算问题

多技能共存还有一个隐性问题:上下文窗口。每个 skill 一旦被激活,它的 instruction 就会占据上下文空间;如果 agent 在一个长对话里连续激活四五个 skill,光是指令就吃掉不少 token,留给实际内容的就不多了。

我的做法是给 skill 的 instruction 设定一个400~600 token 的预算上限。写的时候如果超了,就砍掉非核心的细节,或者把细节挪到外部知识库里,skill 里只留关键路径。另外,agent 框架最好支持"技能用后即焚"——完成当前任务后,该技能的指令就从后续上下文中移除,避免污染下一步操作。这个机制看起来很基础,但没有它,长会话场景下技能越多,模型越容易精神分裂。

5. 测试 Skill 的三种方式:单测、集成验证与回归

很多团队把 skill 写完就直接上线,然后靠用户反馈来发现问题。这是最被动的做法。Skill 本质上是代码资产,它应该享受和代码一样的测试待遇。

5.1 单测:验证单个 skill 的输出结构

单测的核心目标是回答一个问题:给定固定输入,这个 skill 能否稳定产出符合要求的输出。对 code_review 这个 skill 来说,单测就是准备几段已知问题的代码,断言输出里是否包含问题清单、是否标注了行号、严重级别是否符合预期。

具体执行时,我会维护一个 golden set——一组精心挑选的测试用例,每个用例都有人工标注的"标准答案"或"关键断言"。跑单测时把输入喂给 skill,检查输出是否满足断言。这里要强调一点:单测检查的是结构和关键内容,不是逐字匹配。LLM 的输出天然有随机性,要求它每次一字不差,既不现实也没必要。断言设计得宽松一点,只抓住"必须有的内容"就够。

5.2 集成测试:放进真实 agent 里看表现

单测过了,不代表真实场景里能用。因为单测是"直达"的——直接给 skill 喂输入,跳过了模型判断"该不该调用它"这一步。真实场景里,模型要先从用户的话里识别出意图,再决定是否激活这个 skill,这里就可能出岔子。

集成测试就是把 skill 装进完整的 agent 链路里,用接近真实的用户提问去测。重点观察两件事:一是触发率,用户提到相关需求时,模型有没有正确激活这个技能;二是端到端质量,从用户提问到最终输出,整条链路跑下来的结果是否令人满意。我见过太多 skill 单测全绿、一进 agent 就失灵的例子,基本都是死在触发环节——description 写得不行,模型根本想不起来用它。所以练好集成测试,就是在练好 description 的"翻译能力"。

5.3 回归测试:改了 A 技能怎么知道没弄坏 B

技能之间不是孤岛。改了 A 技能的 description,可能让原本归 B 的场景流向了 A;改了 B 技能的 instruction,可能影响它在技能链中输出的格式。这种"连锁破坏"只有回归测试才能兜住。

回归测试的做法不复杂:把之前所有 skill 的 golden set 串起来,每次有任何技能变更,就全量跑一遍,对比每个用例的结果是否还在可接受范围内。我用的是一个很笨但很有效的办法——每次迭代都记录"基线输出",把跑得不错的输出归档,下一次跑的时候做对比,看有没有出现明显的质量滑坡。这个流程坚持下来,团队里就没人敢改完 skill 不打招呼就走,因为周一的全量回归会把你所有偷懒暴露得干干净净。

5.4 评测指标别只盯着"成功率"

最后说评测指标。做 agent 的人很容易只盯一个数字:任务成功率。但 skill 评测单一成功率远远不够。我自己会额外看三个指标:token 消耗(同一个任务,优化后有没有更省)、平均迭代轮次(agent 多少次操作之内完成,轮次越多说明 skill 指引越不清晰)、人工修正率(输出有几成需要人工改,这是质量最真实的镜子)。

这四个指标放到一起看,才能全面判断一个 skill 的健康度。成功率 100% 但人工修正率 60%,说明 skill 只是"看起来能跑",实际上并没有真正理解任务;成功率 80% 但 token 消耗比别人高一半,说明 instruction 写得啰嗦,还有压缩空间。指标齐全了,迭代才有方向。

6. 我在这套体系里踩过的坑和最终沉淀的设计准则

6.1 坑一:描述写得太泛,模型什么都往这里塞

我最早写一个"数据分析"技能时,description 只有一句"用于数据分析相关任务",结果用户说"帮我把这个 Excel 整理一下",模型也把它激活了。整数据的、做可视化的、跑统计模型的,全被一网打尽。这个技能实际上什么都没分析好。

后来我把"数据分析"拆成"数据清洗""探索性分析""统计建模"三个技能,各自的 description 都写清楚了自己的适用边界和不适用场景,触发准确率立刻上了一个台阶。描述的具体程度,直接决定路由质量,这句话我后来写进了团队的 skill 编写规范。

6.2 坑二:规则堆砌,把 skill 写成了"法典"

还有一个反向的坑。有时为了把 skill 做"专业",我会忍不住往 instruction 里堆规则,一条两条五六条,写到后面 skill 的核心流程被淹没在大量"不要这样""必须那样"的禁令里。模型的执行效果反而更差——它把精力花在遵守禁令上,忘了自己最该做的是完成主任务。

这个教训让我明白了一个道理:规则是护栏,不是剧本。护栏两三道就够,多了反而妨碍执行。核心流程要清晰,边界规则要精简,这俩得分开写,别搅在一起。

6.3 坑三:版本升级没有兼容策略

另一次踩坑是升级了"报告生成"技能的输出格式,第二天发现下游接它的"周报推演"技能全乱了——上游换了接口格式,下游还在按旧格式解析。因为没有版本兼容机制,一次升级引发了一连串连锁故障。

所以我现在对 skill 的升级设了一条规矩:破坏性变更必须和大版本号绑定,并且要提前通知所有下游消费方。非破坏性的优化,比如补充规则、优化措辞,走小版本号;改了输入输出格式、改了核心流程的,必须按大版本走,并附迁移说明。这条规矩看着简单,能省下大量排障时间。

6.4 我最终沉淀下来的五条设计准则

踩了这些坑之后,我把经验收敛成了五条准则,每次做新 skill 之前都会过一遍:

  • 单一职责:一个 skill 只做一件事,描述里说清边界,宁可多拆几个也不要硬塞。
  • 流程与规则分离:核心步骤用清晰的流程化语言写,约束规则单独成段,别混排。
  • 触发描述具体化:description 必须包含"什么说法该触发"和"什么情况不该触发"。
  • 参数少而精:参数数量控制在 3~5 个,每个参数说明来源和类型,不给模型增加抽取负担。
  • 测试先行:每个 skill 必须配套三个测试用例以上,才能进入生产环境。

这五条不是理论推演出来的,是从一个个翻车现场里爬出来的。你说它多高深?真没有。但就是把每个 agent 项目做扎实的基本功。如果你也在做自己的 skill 库,不妨拿这几条去对照一下手头的 skill,再看一眼最近的 agent 输出质量是不是有明显改善。磨刀不误砍柴工,把技能这块地基打稳,agent 的上限才能真正被你拉起来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询