Skill 不是装得越多越好。不少开发者在 Claude Code、Cursor、Codex 这类编码 Agent 里一口气塞了二十几个 Skill,结果发现 Agent 的响应开始变得“犹豫”:该调接口的时候不调,不该用工具的时候乱用,推理速度也明显下降。这不是模型变弱了,而是 Skill 的管理方式出了问题。
这篇文章不聊“Skill 该怎么写”这种单点教程,而是看一个更核心的工程问题:当 AI Agent Skill 数量膨胀之后,系统为什么会变“笨”?我会从加载机制、上下文占用、技能路由三个层面拆原因,再给出一套“减负”和排查的实操方法。如果你正在给 Agent 堆技能,或者已经在维护一个越来越乱的 Skill 目录,这篇可以直接收藏。
1. 核心现象速览
| 观察项 | 说明 |
|---|---|
| 核心现象 | Skill 数量增加后,Agent 出现误选工具、上下文被稀释、回复质量下降、响应变慢 |
| 本质原因 | 技能全部加载进提示词后,上下文被无关内容挤占,路由判断出现歧义 |
| 主要触发条件 | 把所有 Skill 塞进 System Prompt、技能描述不清晰、技能与技能职责重叠 |
| 受影响场景 | 编码 Agent、个人知识库助手、批量自动化任务、多工具 API 聚合场景 |
| 常见平台 | Claude Code、Cursor、Codex、OpenCode,以及各类自研 Agent 框架 |
| 与 MCP 关系 | Skill 影响的是“怎么想”,MCP 解决的是“能调什么”,两者不能互相替代 |
| 最直接的对策 | 精简技能数量,按需加载,给技能写清晰的触发条件,用日志和评估集验证命中率 |
这张表是全文的结论,也是我给大多数团队做 Agent 工程优化时的判断框架:问题往往不是模型不行,而是提示词和工具的组织方式超出了模型的有效决策范围。
2. 这个问题的适用场景与边界
先说清楚,不是所有 Agent 都会“技能越多越笨”。
如果你只是把 3 到 5 个 Skill 放在固定的工作流里,每个技能描述写得很清晰,且任务之间没有交叉,那么多一个 Skill 通常影响不大。问题容易出在以下三种场景:
- 通用型 Agent:同一个 Agent 既要写代码,又要查资料,还要处理文档、发邮件、分析数据。技能之间的边界模糊,模型很难在任务一开始就确定正确路径。
- 编码 Agent:Claude Code、Cursor、Codex 这类工具允许用户把开发规范、测试框架、部署流程都做成 Skill,一旦数量超过十几条,Agent 在文件读写时容易把无关技能也带入推理过程。
- 批量任务系统:Agent 需要根据输入自动路由到不同 Skill。技能描述相似度越高,路由失败的概率越大。
不适合用“堆技能”解决的问题也要讲清楚:当任务本身依赖外部数据源或工具时,比如读取数据库、调用第三方 API,应该优先考虑 MCP 或独立工具服务,而不是把这些操作强行包装成“技能”。Skill 适合解决“怎么做”的问题,不适合解决“能连什么”的问题。
涉及版权、隐私和数据安全的内容也要注意:如果 Skill 里包含公司内部代码规范、客户数据字段或隐私策略,部署到云端 Agent 前必须确认服务商的权限隔离和加密策略;如果你把 Skill 分享到公开仓库,先检查里面是否暴露了密钥、内部域名或敏感路径。
3. 先看 Skill 的加载方式:三种典型机制
要理解“技能越多越笨”,先要知道 Skill 是怎么进入模型视野的。目前主流 Agent 框架的 Skill 加载方式大致有三种:
3.1 全部注入 System Prompt
这是最简单的实现:启动服务时读取 Skill 目录下的所有 Markdown 文件,把它们的名称、描述、指令全部拼进 System Prompt。模型每一次请求都能看到完整的技能列表。
优点是实现简单、可控性强;缺点是上下文占用随技能数量线性增长。假设每个 Skill 的描述平均 500 token,50 个 Skill 就会额外消耗 25000 token,这条路径同时挤占了用户输入、历史对话和模型输出的空间。常见表现是:Agent 开始丢三落四,早期任务要求被遗忘。
3.2 目录扫描加动态检索
这类实现只在需要时把相关技能片段拉到上下文里,典型的做法是“技能描述 + 嵌入检索”。系统把所有技能的描述生成向量,请求进来后先做相似度检索,只把 Top-K 个技能注入上下文。
这个方案在技能数量较多时明显更省 Token,但引入了一个新问题:检索本身可能出错。如果两个技能的描述都包含“处理日志”,模型或者检索器就分不清到底该用日志分析技能还是日志清洗技能。结果就是技能越多,检索结果越不稳定。
3.3 通过 MCP 工具注册
MCP(Model Context Protocol)把外部能力暴露成标准工具,Agent 通过工具调用的形式使用。Skill 在这里更像“人在回路中的提示词资产”,MCP 工具本身不参与技能选择,但 Agent 需要结合工具列表和 Skill 描述一起规划任务。
这种模式下,技能膨胀不会直接压低推理质量,但会增加 Agent 在“到底该调用哪个工具”这个问题上的决策成本。
从工程角度看,前两种加载方式最容易出现“越装越笨”,第三种更多表现为“工具列表太长导致选择困难”。但不管哪种方式,只要技能数量超过模型在这种任务上的判断上限,性能都会下降。
4. Skill 过载,具体“笨”在哪里
下面拆开讲五个具体表现,你可以对照自己的项目排查。
4.1 上下文被无关技能稀释
假设一个 Agent 的任务是“读取 PDF,提取表格,导出 Markdown”。如果系统里还有“OCR 图片识别”“批量压缩图片”“生成海报文案”这些无关技能,它们在上下文里占据了大量 token,模型在处理 PDF 时也可能把“图片识别”的手段混进来。
这种稀释的直接影响是:核心指令在 token 中的相对占比下降,模型更容易“忘掉”用户的精确要求。你可能会看到 Agent 明明指定了“表格导出 CSV”,它却输出成 Markdown。
4.2 路由选择困难
当你有 20 个技能时,模型必须在每次任务开始时推断“应该调用哪个技能”。这本质上是一个分类问题,技能描述越模糊、数量越多,分类准确率越低。
典型例子是“阅读”类技能: “阅读 PDF”“阅读网页”“阅读文档”三个技能如果描述高度相似,Agent 很可能选了 PDF 阅读技能,却读不了网页内容,然后开始瞎猜或报错。
4.3 技能冲突与顺序覆盖
技能 A 说“遇到代码错误先分析日志”,技能 B 说“遇到代码错误直接尝试修复”。两个 Skill 同时存在时,Agent 可能反复横跳,行为不稳定。
更麻烦的是配置覆盖:有些 Agent 框架会按目录顺序加载技能,后加载的技能可能覆盖同名字段,导致你写的规则没生效,而你自己并不知情。
4.4 基本行为退化
Skill 过多之后的另一个典型现象是 Agent 的“常识行为”被削弱。原本一个不挂任何 Skill 的 Agent 面对“读取 config.yaml 并输出 JSON”能直接完成,但挂了 30 个技能后,它可能先调用“配置文件解析专家”技能,再尝试“代码评审”技能,把简单问题复杂化。
这是因为模型把过多的技能当作决策依据,过度依赖“技能卡片”反而遮盖了自身的推理能力。你可以把这种现象理解为 Agent 的“能力恐慌”:技能范式太强,模型默认走技能流程,不再按通用能力处理问题。
4.5 性能与成本上升
技能全部加载时,每次请求的输入 token 都会增加,直接带来两个后果:响应变慢,推理成本上升。在自部署场景里,显存和算力消耗也会增加;在 API 调用场景里,Token 费用线性增长。
这一点在长对话里尤其明显。假设一次会话有 20 轮,每轮多消耗 10000 token 的重复技能描述,总增量就是 20 万 token,成本完全不可忽视。
5. 怎么判断你的 Agent 已经“Skill 过载”
不要靠感觉判断。给一套可操作的检查方法。
5.1 观察清单
先回答下面四个问题:
- 每次系统提示词里注入的技能描述是否超过 10 个?
- 技能列表里是否存在超过两个职责重叠的技能?
- 同一个任务在重复执行 10 次时,模型选择技能的结果是否稳定?
- 去掉部分技能后,任务正确率是否反而上升?
如果四个问题有两个答案是“是”,大概率已经过载。
5.2 用日志记录技能命中率
在 Agent 框架里加一个简单的日志,记录每次请求命中了哪些技能、实际调用了哪些工具、输出是否正确。有了数据再决定删哪些技能。
import json import time from collections import defaultdict # 简单技能命中统计,实际使用中可替换成项目内的日志系统 skill_hit = defaultdict(int) skill_fail = defaultdict(int) def log_skill_usage(skill_name: str, success: bool, extra: dict = None): record = { "skill": skill_name, "success": success, "ts": time.time(), "extra": extra or {}, } # 输出可被日志采集的 JSON 行 print(json.dumps(record, ensure_ascii=False)) if success: skill_hit[skill_name] += 1 else: skill_fail[skill_name] += 1 def report(): for skill in set(skill_hit) | set(skill_fail): hit = skill_hit[skill] fail = skill_fail[skill] print(f"{skill}: hit={hit}, fail={fail}, rate={hit / max(hit + fail, 1):.1%}")把这个统计表跑一周,优先删除“零命中”和“高调用但低成功率”的技能。
5.3 做最小对比实验
更严谨的方式是控制变量:准备 20 个标准测试用例,分别用“全量技能”和“精简技能”跑一遍,对比正确率与平均响应时间。如果你的 A/B 测试显示精简后正确率上升,那就不是玄学,是工程结论。
6. Skill 与 MCP 的区别,别再混着堆
很多人把 Skill 和 MCP 混在一起处理,这是技能目录混乱的原因之一。
Skill 本质上是一段结构化的指令包:它告诉模型“遇到哪类问题时,按照哪些步骤来思考”,它不会直接调用外部系统。MCP 则是一个协议,它把文件系统、数据库、API、浏览器等外部资源封装成标准可调用工具。两者的关系是:Skill 负责设计问题求解策略,MCP 负责提供执行能力。
可以在自己的 Agent 里这样分化:
| 维度 | Skill | MCP |
|---|---|---|
| 核心作用 | 提示词层面的方法论 | 工具能力接入 |
| 是否消耗上下文 | 会,需按量控制 | 会,工具描述也会进入模型 |
| 典型文件形式 | SKILL.md / prompt 文件 | server 配置 / 可执行服务 |
| 排错思路 | 检查描述、触发条件 | 检查服务端口、鉴权、响应格式 |
| 合理的数量 | 越少越好,按任务域收敛 | 按真实能力需求,宁缺毋滥 |
这意味着你在做“技能瘦身”时,不要简单地把一堆 MCP 工具改写成 SKILL.md。那样只是把“工具列表过长”换成了“技能列表过长”,问题并没有消失。
7. 优化实操:把 20 个 Skill 缩到 5 个
下面给一套可落地的优化流程,目标是把技能目录收敛到“够用、干净、可维护”。
7.1 按任务域合并
先列出当前技能实际对应的任务类型,合并成五个左右的大类。举例:
- 编码:代码生成、代码审查、Debug、重构、测试编写,统一为一个“编码助手”技能。
- 文档:PDF 解析、Word 转换、Markdown 格式化,统一为“文档处理”技能。
- 数据分析:日志分析、JSON 提取、表格统计,统一为“数据处理”技能。
- 内容产出:周报、摘要、文案生成,统一为“内容生成”技能。
- 运维:命令检查、服务器状态、部署说明,统一为“运维助手”技能。
合并后,每个技能里用“分支指令”区分具体场景,而不是一个场景单独一个技能。
7.2 给每个 Skill 写清楚触发条件
模糊的 description 是 Agent 误路由的元凶。写 SKILL.md 时,重点不是把操作步骤写多细,而是写清楚“什么情况触发”和“什么情况不要触发”。
--- name: code-review description: | 用于代码评审任务。当用户要求检查代码质量、发现潜在 bug、 给出重构建议时,使用本技能。 不适用于:解释代码逻辑、生成新功能的场景,这类场景请使用 code-generation。 triggers: - 检查代码 - 代码评审 - code review - 找 bug - 重构建议 ---注意把“什么时候不触发”也写进去,这一步能有效降低相似技能之间的路由冲突。
7.3 把大技能拆成“入口 + 子流程”
合并不是把内容堆成一个巨型 Markdown。更好的做法是保留一个入口文件,子流程按步骤编号或按参数分支调用。
# Document Processing Skill ## 触发条件 - 用户需要读取或转换 PDF、Word、Markdown 文件 - 用户要求提取表格、导出结构化内容 ## 处理流程 1. 判断输入文件类型 2. 如果是 PDF,使用 pdf-parse 提取文本 3. 如果是 Word,使用 pandoc 转换为 Markdown 4. 如果包含表格,按用户指定格式输出(CSV / Markdown) 5. 输出前检查字段是否完整这样既合并了数量,又保留了每个分支的可执行细节。
7.4 只保留经过验证的规则
很多技能里写的是“我认为应该这样做”的规则,而不是“验证过有效”的规则。要定期清理那些没有实际执行过的指令。可以用前面提到的命中率统计:一段时间内零调用的技能直接下线,调用多但成功率低的技能重写它的触发条件。
7.5 用评估集防回退
优化完技能后,维护一个 20 到 50 条的标准任务集。每次改技能都跑一遍,防止“优化”变成“回归”。评估集不需要自动化得很复杂,手动截图记录也可以,关键是稳定可重复。
EVAL_CASES = [ {"task": "读取 a.pdf 提取表格并导出 csv", "expect": "输出 csv 文件且表格字段完整"}, {"task": "解释这段 Python 代码的异常处理逻辑", "expect": "不调用任何代码生成技能"}, {"task": "总结这篇文章为 5 条要点", "expect": "不调用编码技能"}, ] def evaluate(agent_run_func): passed = 0 for case in EVAL_CASES: result = agent_run_func(case["task"]) ok = judge(result, case["expect"]) passed += int(ok) print(f"{case['task'][:20]}... {'PASS' if ok else 'FAIL'}") print(f"total: {passed}/{len(EVAL_CASES)}")注意评估时要同时看“任务完成度”和“技能选择是否合理”,因为 Agent 的“笨”很多时候体现在错误技能选对了结果,这种假成功同样要拦截。
8. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Agent 经常选错技能 | 技能描述模糊或职责重叠 | 打印每次请求的命中技能日志 | 重写 description,增加“不触发”条件 |
| 响应速度明显变慢 | 技能全部注入上下文,token 膨胀 | 查看每次请求的 prompt token 数 | 改为按需加载或精简技能数量 |
| 输出质量不稳定,同一任务结果忽好忽坏 | 存在技能冲突或覆盖 | 检查加载顺序,看是否有同名配置 | 统一目录加载规则,保留唯一入口 |
| 去掉部分技能后,运行反而更稳定 | 技能过载导致路由混乱 | 做 A/B 对比测试 | 保留核心技能,维持最小化原则 |
| MCP 工具描述太长,Agent 调用异常 | 工具列表超长,决策成本过高 | 检查工具注册数量 | 精简 MCP server,合并工具参数 |
| 技能更新后旧任务失败 | 新技能规则覆盖了旧行为 | 用评估集回归测试 | 先跑评估集再上线 |
| 批量任务卡在某个技能调用上 | 技能内部指令死循环或缺少退出条件 | 查看日志中的调用链 | 给技能增加最大重试次数和失败出口 |
| 技能里包含敏感信息,外发到云端 API | 权限与合规隐患 | 扫描 SKILL 目录中的密钥和内部路径 | 删除敏感信息,使用环境变量引用 |
9. 最佳实践与工程化建议
把技能从“放进去就能用”升级成“一套可持续维护的提示词资产系统”,建议从下面几点入手。
9.1 目录结构标准化
不要把所有技能文件平铺在一个目录里。建议按领域分目录:
skills/ ├── coding/ │ ├── SKILL.md │ └── examples/ ├── document/ │ ├── SKILL.md │ └── templates/ ├── data/ │ └── SKILL.md ├── content/ │ └── SKILL.md └── ops/ └── SKILL.md这样 Agent 框架可以按目录做检索,也方便后续按模块做权限控制。
9.2 把技能当作代码来管理
技能文件要进 Git,要有变更记录,要有人 Review。技能描述和提示词属于“可运行资产”,改坏了会影响全部下游任务。更新技能时遵守:先写评估用例,再改技能,跑评估,通过后才合入。
9.3 控制加载粒度
尽量不要做到“全量加载”。在框架支持的情况下,优先用“技能检索 + 按需注入”的方式。如果检索方案不稳定,可以先维护一份人工映射表,把常见任务和技能绑定,减小模型自行分类的压力。
9.4 重视日志与可观测性
记录每个任务的技能调用链、模型决策过程、输出质量,才能定位“变笨”的根因。没有日志的 Agent 优化,基本等同盲调。
9.5 合规与安全边界
- Skill 目录里不要出现明文 API Key、Token、内部服务器地址。
- 涉及人脸、声音、私人文档处理时,必须先获得授权,并在部署环境做访问限制。
- 把 Skill 分享到公开平台前,检查是否包含公司内部规范或个人隐私数据。
- 在批量任务中,如果技能调用第三方服务,要注意输出内容的版权归属。
10. 总结与下一步
“Skill 越多,Agent 越笨”这个现象的核心原因不是模型变笨,而是你把过多决策压力放到了模型身上。技能的价值在于提供精确的方法论,而不是堆积数量。每增加一个 Skill,实际是在增加一次路由决策、增加一段上下文占用、增加一次冲突可能。
最值得做的三件事:把当前技能目录按任务域合并,给每个技能写清楚触发和排除条件,然后跑日志统计看命中率。最容易踩的坑是“技能不够就再加一个”——这只会让问题在数量层面继续累积。
如果你现在维护的 Agent 已经出现选错技能、输出不稳定、响应变慢的现象,先不要换更大的模型,先检查你的 Skill 目录,这通常比换模型省成本,也更直接。后续可以继续探索的方向包括:基于向量检索的技能路由、技能自动评估集、多 Agent 分工替换超大技能包,以及 Skill 与 MCP 工具链的职责再划分。