给 AI 配了一堆 Agent Skills 之后,你有没有这种感觉:它没变聪明,反而变笨了?确切地说,更迟钝了——回复前要想半天,明明该调用技能的时候不调用,不该调用的时候疯狂调用,而且上下文一长就"失忆"。我几个月前把一套精心整理的 Skills 挂到某主流智能体平台上,满怀期待地看它表演,结果实测跑下来,回答质量不仅没提升,连基础问答都开始吞吞吐吐。一开始我以为是模型抽风,后来把 Skills 一个个摘掉,问题瞬间消失。那一刻我才意识到:Agent Skills 不是越多越好,配置不当不仅毫无作用,还真会拖后腿。
这篇文章我不打算讲那些"如何三分钟创建一个 Skill"的入门教程,重点聊机制和坑:为什么技能会失效、会拖后腿,怎么判断一个技能到底有没有用,以及真正"能打"的 Agent Skill 应该怎么配。内容偏实操,适合已经在玩智能体、但感觉效果不对劲的人。
1. 先把 Agent Skills 的机制盘清楚:它到底在做什么
1.1 一个技能的本质是"可调用的外部能力"
Agent Skills(在部分平台也叫 Tools、Plugins、Actions,叫法不同,本质一致)就是一组你事先定义好的、可被大模型按需调用的外部能力。它通常由两部分组成:
- 描述部分:告诉模型"这个技能是干什么的、什么时候用、怎么用、有什么限制"。这部分是纯文本,会进入模型的上下文窗口,不影响代码,但影响模型对工具的选择。
- 执行部分:真正跑的动作,可能是调用某个 API、运行一段代码、抓取网页内容,或者读取某个数据库。这部分由平台或你自己的后端执行,执行结果会作为一个消息片段返回给模型。
换句话说,Agent Skills 让大模型从"只会说"变成"能动手"。用户提问之后,模型先判断"这个问题需不需要动工具",如果需要,就从技能清单里挑一个匹配的,生成调用参数,执行完成后再把结果整理成自然语言回复。
这套机制在单技能场景下很完美,但它有一个隐藏前提:模型必须准确判断"什么时候该用"和"该用哪个"。这个前提一旦被破坏,后面全是连锁反应。
1.2 为什么大家忍不住给 Agent 装一堆技能
因为新鲜感,也因为"看起来很强"。我见过一个朋友在某开源框架里一口气挂了 17 个 Skills,从天气查询到论文润色,从订阅源解析到周报生成,五花八门。问他为什么挂这么多,他说"反正不占地方,多挂几个总能用上"。
这就是大部分人的心理:技能列表长 = 能力全面 = Agent 更厉害。尤其是看到别人分享的"一套 Skills 让 Agent 变成全能助手"的截图,很容易产生"我也可以"的错觉。还有一些平台本身就提供了技能市场,一键安装非常顺滑,装完一时爽。但这些技能可不是"不占地方"——它们每一行描述都在占用模型有限的注意力资源。
1.3 从提问到技能调用,链路比你以为的长
一个完整的技能调用过程是:用户输入 → 模型解析意图 → 在候选技能中做语义匹配 → 生成调用参数 → 执行动作 → 返回结果 → 模型整合结果并回复。每一步都有出错的可能:
- 意图解析错了,该调用技能的时候,模型直接凭记忆瞎编;
- 语义匹配错了,想分析 PDF 却调用了网页抓取技能,返回一堆乱码;
- 参数生成错了,技能被正确选中,但传入的日期、关键词、筛选条件不对,结果没用;
- 执行返回错了,API 超时或报错,模型又不会承认失败,只好硬着头皮编。
很多技能"看起来装了,实际没起作用",本质就是链路中某一环悄悄断了,而你又没有可观测的手段。这也是我后来花大力气做调用日志和回归测试的原因。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 为什么你的技能清单在拖后腿:三层根因
2.1 上下文窗口被悄悄吃光,注意力被稀释
先算一笔账。主流大模型的上下文窗口动辄几十万 token,听起来很多,但你要知道:系统提示词、所有已挂载技能的描述、对话历史、当前问题、模型正在生成的回复,全部共享这一个窗口。
假设你挂了 10 个技能,每个技能描述平均 400 个 token(这已经是非常精简的写法了),光技能描述就占掉 4000 token。表面上看,4000 对 128k 窗口不算什么,但问题在于模型处理长上下文时,注意力是"摊薄"的。技能描述区塞得越长,模型在真正处理用户问题和历史信息时的有效注意力就越少。
我用一个不太严谨但很形象的类比:这就像开会时有一个总爱插话的人,每次发言内容不多,但每次都在关键时刻打断真正重要的讨论。你很难说"他说的不对",但他确确实实在分散你的注意力。技能描述也是一样——它们不一定错,但它们存在本身就干扰了模型对重要信息的聚焦。
更要命的是长对话场景。当上下文长度接近窗口上限,系统会开始丢弃最早的消息。如果你每次开启对话都有 4000 token 的固定技能描述占位,那么被挤掉的其实是更早期的真实对话历史。很多 Agent"聊到后面就失忆",不一定是模型记忆机制的问题,而是你的技能描述把历史信息挤出去了。
2.2 模型的技能选择机制,远比你想的粗糙
LLM 做技能选择靠的是语义匹配,不是精确检索。它的工作方式是:把用户问题和一个技能的描述放在一起算相似度,觉得"差不多"就选。这就带来两类问题。
第一类是模糊描述导致误触发。我看过一份技能描述:"解析网页内容,提取关键信息,支持多种格式"。听起来没问题对吧?问题是"多种格式"这种表述和 PDF、Word、图片解析的描述高度重叠。当你上传一份 PDF 让它解析时,模型可能同时匹配到"网页解析技能"和"PDF 解析技能",然后在两者之间反复横跳,最终选择了错误的那一个,返回一堆没用的东西。
第二类是技能之间互相打架。两个技能描述如果存在大量重叠词汇,它们就会在语义空间里挤在一起,模型很难分开。我实测过一组案例:一个是"生成周报",另一个是"生成日报",描述里都写了"总结工作内容""统计任务进度""输出结构化报告"。结果用户只是说"帮我写个总结",模型居然随机选择其中一种来调用,两种报表结构完全不同,输出效果自然一塌糊涂。
这不是模型能力不行,而是你没有在描述里替模型做好"选路"的工作。模型可以做到精确匹配,但前提是你给它足够清晰、足够有区分度的文本描述。
2.3 执行链的错误放大效应
就算技能被正确选中、正确调用,执行过程本身也会引入新问题。
首先是工具返回质量问题。API 超时、接口返回空值、网页反爬返回验证码页面——这些实际发生的异常,模型往往不会处理。它只会把返回结果当成"真实信息"硬编进回答里。如果返回的根本是一堆广告页文本,模型甚至会一本正经地基于它写出一段"分析报告"。我能理解模型为什么这样:它的核心训练目标是生成连贯文本,而非检测上游数据的可信度。但作为使用者的我们,就成了受害者。
其次是多技能级联调用。有些平台支持技能之间互相调用:技能 A 的结果作为技能 B 的输入。听起来很酷,但每一步都会引入新的延迟和新的出错可能。三级链式调用如果每级耗时 5 秒、出错率 10%,总耗时轻松超过 15 秒,综合错误率接近 30%。用户问了一个本来两秒就能答的问题,结果等半天还拿到一个污染过的答案。
第三个问题是结果污染上下文。即使技能执行成功并返回了正确结果,这个结果也会占据上下文空间。如果这个结果本身很长(比如抓取了 5000 token 的网页正文),而后面的对话完全用不上它,那它就成了新的"注意力垃圾",继续稀释后续生成质量。很多时候 Agent 回答越来越跑题,就是因为开场误触发了一个技能,返回了一堆无关内容,而这些内容成了后续生成的"模板",越带越偏。
3. 判断一个技能到底有没有用:三个硬指标
与其靠感觉判断"这个技能好用/不好用",不如建立一套定量的评估方式。我用了几个月后,沉淀出三个指标,分享给大家。
3.1 调用率:装了不等于用了
最直接的问题:这个技能在过去一段时间里,到底有没有被调用过?
从智能体平台的日志里,你能看到每次对话的完整调用记录。统计方式很简单:连续记录 20 次真实用户对话,看每个技能被调用的次数。我见过一个很典型的案例:用户挂了 6 个技能,其中 3 个在 20 次对话里只被调用过 0 次或 1 次。这就叫"白占地方"——它们不仅没帮上忙,还在一直消耗上下文预算。
需要排除两种误判:一是触发条件极端(比如"仅在用户明确要求生成季度财报时"),这类技能虽然调用次数少,但该用的时候必须存在,属于"低频高价值"型,可以保留;二是描述存在歧义导致模型压根没意识到它的存在,这类技能就该重写描述或者直接删掉。
3.2 净收益:省下的 token 是否大于吃掉的 token
这是很多人忽略的一个指标。技能的原理是"用一点固定开销,换取部分场景下的效率提升"。那这笔账得算清楚。
举一个实测的例子。某开发者写了一个"查询任务状态"的技能,描述占 300 token。每次调用时,技能会从后端拉取一个 JSON 数据,大概 200 token,模型基于它做格式整理。如果用户平均每周问 3 次任务状态,那这个技能的收益是:每次少翻 5000 token 的历史记录(因为状态是动态的),而且准确率高。虽然占用 300 token,但收益远大于支出,这是划算的。
反过来,另一个场景:某开发者写了一个"文本润色"技能,描述占 400 token,但用户让模型润色时,模型直接就能做,根本不需要调用任何工具。结果每次对话,这 400 token 白白消耗,收益为 0。这就是典型的负资产技能。
建议给每个技能建立一个简单的收益账本:平均每周调用次数 × 单次节省的 token > 技能描述占用 token × 对话次数。凡是长期算不平的,直接删。
3.3 输出质量对比:同题对照测试
最笨但最有效的测试方法:准备一组固定的测试问题,分别在挂载技能前后各跑一遍,对比输出质量。
我自己的做法是准备 5 个问题,覆盖三类场景:技能应该被触发的、不应该被触发的、触发边缘的。例如:
- 明确该用技能:"帮我查一下昨天服务器 CPU 峰值。" → 观察是否调用、返回格式、回答准确性。
- 不该用技能:"帮我写一段产品介绍。" → 观察模型是不是误调用了无关技能、回答有没有被工具结果带偏。
- 边界试探:"这个东西怎么样?" → 观察模型会不会因为意图模糊而做出奇怪的选择。
对比维度可以做成一张表,我自己用久了就固定下来了:
| 评估维度 | 挂载前 | 挂载后 | 结论 |
|---|---|---|---|
| 回答准确率 | 直接答,靠训练知识 | 调用技能后是否更准 | 是否值得挂载 |
| 响应速度 | 基准耗时 | 是否明显变慢 | 延迟是否可接受 |
| 回答相关性 | 是否贴合问题 | 是否被工具结果带偏 | 输出质量 |
| 关键信息保留 | 重点是否覆盖 | 是否遗漏核心信息 | 是否有副作用 |
这个测试不用太频繁,每次新增或修改技能后跑一轮就够。但一定要跑,因为很多"看起来没问题"的技能,实际在边界场景下很容易出错,只有固定测试集能帮你稳定发现问题。
4. 亲手做一个"能打"的 Agent Skill:从设计到落地
4.1 第一步永远是做减法:先审计你的技能清单
在写任何新技能之前,先把你现有的技能全部过一遍。我自己列了一个检查清单,每项都对应着真实的坑:
- 这个技能在过去 20 次对话中,被调用了几次?
- 调用后返回的内容,是否真的帮助模型给出了更好的回答?
- 如果把它摘掉,有哪些场景会明显变差?
- 有没有两个技能描述存在语义重叠?
- 技能描述有没有包含过时的信息(比如旧的 API 端点、旧的数据格式)?
做完这个审计,你大概率会发现至少三分之一技能是可以直接删掉的。我自己的清单从 12 个减到了 5 个,效果不降反升。原因就是:少掉的技能释放了上下文预算,也让剩余技能的语义空间更清晰,误触发率直线下降。
提示:删技能不是删了就完事,最好把删除前的调用日志留一份。万一后续发现某类问题变多,可以快速判断是不是删错了技能,而不是又从零排查。
4.2 描述怎么写出"高区分度"
技能的描述是决定模型能不能正确调用的核心,但很多人把描述写得像产品说明书,啰嗦而没有重点。我实践下来比较好用的结构是五段式:
- 角色声明:一句话说明这个技能是干什么的,越具体越好。"一个用于从 PDF 文档中提取表格数据的技能"比"一个文档处理技能"强十倍。
- 触发条件:明确列出"当用户想让 AI 做以下事情时"的清单,尽量覆盖同义表达。例如:"当用户提及 PDF 解析、提取表格、读取扫描件时"。这一步是降低误触发和漏触发的关键。
- 输入要求:告诉模型调用时需要哪些参数,参数格式务必具体,例如"日期格式 YYYY-MM-DD"这种。
- 输出格式:告诉模型返回结果该如何整理,是直接返回原始工具结果,还是需要加工成自然语言。
- 禁忌:明确说明什么情况下不要调用。例如"仅当用户上传 PDF 文件时调用,纯文本文件直接用文本解析,不要调用本技能"。
我拿一个真实案例做对比。
反面写法:"本技能用于处理文档,支持多种格式的文件解析和内容提取,包括但不限于 PDF、Word、Excel、图片。"
正面写法:"本技能用于解析 PDF 文件内容并提取其中的表格数据。触发条件:用户要求从 PDF 中提取表格、读取扫描 PDF 内容、将 PDF 表格转为 Excel。输入要求:需要提供 PDF 文件路径或上传文件。输出格式:返回 Markdown 格式的表格。禁忌:仅处理 PDF,其他格式不调用本技能,若用户提供的是 Word 或图片,请选择其他合适技能。"
看到区别了吗?前者会让模型在面临多种文档类型时犹豫不决,后者把边界划得清清楚楚,模型只需要做匹配,不需要"思考"。这对大模型来说是最友好的。
4.3 控制体积与定期维护
技能描述不是写论文,越短越好。我自己的经验法则:单条技能描述尽量控制在 300 词以内。超过 500 词,模型在长上下文里会逐渐"丢失"对后半段描述的关注,效果反而更差。
原因还是注意力。描述太长,模型要在大量文字里找到关键触发条件,这是一件困难的事。精简到 300 词以内,触发条件放在中间偏前位置,模型匹配的成功率会明显提升。
另外就是定期维护。技能描述里如果包含 API 地址、接口参数、日期时间等动态信息,建议设置一个提醒,每 1~2 个月检查一遍。有一次我的一个数据查询技能突然失效,排查了半天,发现是上游接口的返回结构改了,但描述还在按旧格式引导模型解析,模型拿到的数据对不上,自然输出一塌糊涂。这种问题很难靠模型自己发现,只能人工维护。
4.4 用回归测试代替玄学调优
技能写完之后不要直接上线,先跑一轮回归测试。我固定用刚才说的那套 5 问题测试集,每次增加或修改技能后跑一遍,对比挂载前后的输出。测试结果要记录,最好按日期归档。
如果测试中发现技能误触发,不要急着改描述,先做"语义冲突排查":把当前所有技能描述打印出来,用不同颜色标出重复的词汇。你会发现一半以上的误触发,根源不是某个技能描述写得差,而是两个技能描述里的关键词重叠太严重。
我做过一次很典型的修复:两个技能分别负责"提取图片中的文字"和"提取 PDF 中的文字",描述里都反复出现"提取文字"四个字,导致模型频繁选错。解决办法很简单:把其中一个改成"提取扫描图片中的文字",并明确写上"仅在用户提供图片文件时调用"。改完之后,误触发率从 40% 降到了接近 5%。
5. 我踩过的那些坑:问题排查与速查表
从几个月折腾 Skills 的经历里,我把最常见的故障整理成一个速查表,方便你直接对照排查。
| 现象 | 典型原因 | 排查思路 | 解法 |
|---|---|---|---|
| 技能完全不触发 | 描述里缺乏明确的触发条件,模型语义匹配失败 | 检查描述是否包含"当用户提及……时"这类条件 | 重写描述,用用户口语表达方式重新列出触发短语 |
| 技能该用的时候没用,不该用的时候乱用 | 描述和其他技能语义重叠 | 把所有技能描述打印出来对比关键词 | 精简重叠词汇,给每个技能补充互斥的边界说明 |
| 加了技能后,回答反而变差 | 上下文被技能描述占据,注意力被稀释 | 统计技能描述总 token 数和调用次数 | 删减低频技能,压缩描述篇幅 |
| 技能调用成功但输出胡说八道 | 工具返回了空值/错误,模型选择"硬编" | 查看执行日志里工具返回的原始内容 | 在技能描述中增加"当返回结果为空时,告知用户查询失败"的说明 |
| 长对话后期技能不工作 | 上下文窗口被早期技能描述和工具结果挤满 | 检查上下文占用统计 | 精简技能数量,控制工具结果长度,必要时使用摘要 |
| 技能逻辑没问题,但调用后延迟很高 | 工具执行本身慢,或存在链式调用 | 分步测速:单独调用工具是否在预期时间内返回 | 拆掉链式调用,改用单技能完成;缓存高频结果 |
除了这个速查表,还有两条经验我认为值得特别提出来。
一条是二分法定位故障技能。当你不确定是哪个技能拖累了整体表现时,不要一个个试,效率太低。直接把所有技能全部摘掉,跑一遍测试集确认"裸模型"是正常的,然后一次挂回一半,跑测试。如果效果变差,说明问题在这一半里;再对折,缩小范围。通常两三轮就能精确定位肇事技能。
另一条是用"问法变体"测触发率。同一个功能,用户可能有十种不同的问法,技能描述里只写一种,必然漏触发。我在测试时会刻意换着说法问:"查一下昨天的数据""把昨天的报表给我""帮我看看昨晚指标""昨天的统计结果怎么样",看技能能不能正确触发。如果这几种问法里有一种不触发,说明描述里缺少对应的同义词表达,直接补进触发条件里。
最后再分享一个细节。如果你发现某个技能在部分对话里表现稳定,在另一部分对话里却不稳定,先别急着改描述,重点检查一下触发该技能前,用户问题和当前上下文的相似度。我遇到过一次:同一个技能,在短对话里非常可靠,但在长对话里频繁误触发。后来发现是因为技能描述里有一个词和用户长对话里反复出现的一个专有名词高度相似,把模型"勾"过去了。把那个词改成更冷门的表述,问题就解决了。这种问题极其隐蔽,没有日志的话几乎不可能发现。
我现在的技能清单只有 5 个,每个的描述都控制在 300 词以内,每月固定检查一次调用日志和上下文占用。至少在配了这些东西之后,我的 Agent 表现比之前"挂 17 个技能"的时代明显更稳定。技能这东西,本质是杠杆,而不是仓库。你往仓库里堆再多的工具,真正用得上的只有那么几个,其他都是灰尘。关键不是你会不会往里塞,而是你会不会往外扔。
