最近在好几个 AI 编程助手和 Agent 工具里,Skill 都是一个高频词。Claude Code 支持把一套固定工作流写进 SKILL.md,Codex 也有自己的 skill 目录,Trae、Cursor 这类编辑器也在跟进。功能本身挺好,可我发现一个很实际的怪现象:Skill 越装越多之后,AI 反而越来越难用。
这不是错觉。我把同一份日志分析任务分别放在只装了 3 个 Skill 和装了 20 多个 Skill 的环境里跑,前者的回答更稳定,后者经常出现答非所问、输出格式变化、甚至两个 Skill 互相打架的情况。原因并不复杂:Skill 不是插件越多越好,它本质上是塞给模型的“说明书 + 工具包”,装得越多,模型要做选择和吸收的信息就越多。
这篇文章就直接拆这个问题:Skill 是什么、为什么装多了会变乱、我平时怎么规划和管理 Skill,以及已经装乱之后怎么恢复。里面不会把所有细节都写成固定答案,因为不同工具的加载方式和目录结构略有差异,但总体的治理思路是通用的。
1. 先搞清楚 Skill 到底装给谁看的,它和 Agent 有什么区别
很多人对 Skill 的第一印象是“像软件里的插件包”,装完就有了一个新功能按钮。实际在主流 AI 编程工具里,Skill 更接近一组结构化说明,它是给模型看的,不是给用户点的。
1.1 Skill 本质上是给模型看的“操作说明书”,不是给用户看的“功能按钮”
一个 Skill 通常是一个目录,比如.claude/skills/xxx/或.codex/skills/xxx/,里面包含一个主文件,一般是SKILL.md,顶部有 frontmatter,常见字段是 name 和 description,下面是一段正文,说明这个 Skill 适用什么场景、按什么步骤执行、有什么注意事项。目录里还可以放脚本、模板、示例文件、参考文档和输入样例。
模型读取 Skill 时,读到的不是一段“可直接执行程序”,而是文本描述。它需要根据描述里的步骤去查文件、跑脚本、组织输出。所以 Skill 写得好不好,直接影响模型选不选、用不用得好。
这里有个容易被忽略的点:你装了很多 Skill,等于同时给模型发了厚厚一沓说明书,但模型并不保证每一份都翻对。真正起作用的不是文件数量,而是描述质量和触发条件。
1.2 Skill 和 Agent 的区别:一个等调用,一个自己跑
热门搜索里经常出现“skill 和 agent 的区别”,这确实是入门时最容易混淆的地方。我的理解比较简单。
Skill 是一组“被动的”工作流程说明。场景出现时,模型根据描述判断是否调用,然后按说明执行。它不会主动运行,也没有自己的循环和退出机制。
Agent 是一个“主动的”执行单元,通常有自己的运行循环、工具调用权限、结束条件。Agent 可以调用多个 Skill 和工具,在运行过程中根据中间结果不断调整下一步。
如果任务本身就是“先分析,再决策,再循环执行,直到验收通过”,那更适合设计成 Agent。如果你只是希望“遇到某一类输入时,按固定步骤给一份标准化输出”,那 Skill 就够用。装 Skill 不能替代 Agent 设计,反过来,给 Agent 挂一堆 Skill,也只是放大了模型的选择负担。
1.3 Skill 的触发通常是“描述匹配”,不是“命令匹配”
还有一点必须理解:很多 Skill 不是用户敲命令才生效,而是模型看到当前输入后,根据每个 Skill 的 description 判断是否相关。这意味着两个 Skill 描述写得太接近,模型就会随机选一个,甚至同时参考两个。
这就是为什么“日志分析 skill”和“运维排障 skill”容易打架。用户说“帮我看看这个日志”,两个 Skill 的描述都匹配,模型要么选错,要么把两个流程拼在一起,最后输出格式不伦不类。所以要管理 Skill,先得理解它的启动机制是语义匹配,而不是文件名匹配。
2. Skill 装多了变难用,问题基本出在这四个地方
2.1 上下文被大量占用,回答质量最先下降
不同工具加载 Skill 的方式不一样。有的是把常驻 Skill 直接放到对话上下文中,有的是按相关性动态加载。不管是哪种,Skill 越多,上下文里被占用的空间就越大。
如果常驻,30 个 Skill 的说明可能会占掉几万 token 甚至更多,留给用户指令和推理的空间变少,长任务尤其明显。如果是动态加载,模型每次都要翻目录、读文件,短期还好,任务一旦涉及多个步骤协作,推理轮次和延迟都会明显增加。
我实测时,同样一个订单日志排查任务,Skill 超过 15 个以后,模型走流程的稳定性开始下降,偶尔会跳过中间校验步骤,直接给结论。这个现象单独看某个 Skill 时会觉得很奇怪:每个 Skill 单独用都挺好,放在一起就变笨。原因就是上下文被分散了。
2.2 描述相似导致错误触发,输出来回横跳
这是最常见的“难用”来源。装了多个领域相关但边界不清的 Skill,比如:
- PPT 制作 skill
- 文档排版 skill
- 汇报材料生成 skill
三个描述里都有“报告、排版、PPT、汇报”这些词。当用户说“把这个项目周报整理一下”,模型会犹豫到底调用哪个。有些情况下,模型会先按第一个 Skill 的步骤生成,发现不合适,又改成第二个的格式,反复横跳。
结果就是回答的可重复性没了。同一个输入,两次跑出来的流程和格式完全不一样。这种不稳定比“不会做”更让人头疼,因为你很难判断模型下一步会给出什么。
2.3 多个 Skill 之间流程冲突,格式不统一
Skill 如果只描述“做什么”,不描述“输出长什么样”,到输出环节就会乱。比如“日志分析 skill”输出 JSON 摘要,“故障定位 skill”输出 Markdown 表格,单独用都没问题,可当用户需求同时跨两个 Skill 时,模型很可能生成一个混排结果:前半段是 JSON,后半段是表格,关键字段还对不上。
更麻烦的是,Skill 里如果带脚本或模板,不同 Skill 之间还可能出现路径引用、命名约定和依赖版本冲突。我自己就遇到过两个 Skill 都要求创建output/目录,一个往里面写 JSON,一个往里面写 CSV,第二次运行时其中一个直接把目录清空了。
这种问题不会在安装时暴露,只会在某个真实的批量场景里突然出现。所以管理 Skill 的时候,不能只看“能不能跑”,还要看“多个 Skill 一起跑时会不会互相踩”。
2.4 没人维护的 Skill 会变成“僵尸资产”
Skill 使用不是一次性的。环境、输入格式、依赖版本、团队规范都会变。装的时候很顺手,两个月后可能就发现:参考文档过时了、脚本依赖的接口变了、示例数据也不再匹配当前业务。
更隐蔽的是,有些 Skill 是通过录制工具或 Skill Creator 批量导出来的。录制本身没有问题,问题是录制产物往往带有大量一次性上下文,比如某次特定任务的字段名、临时目录、旧接口路径。这套东西留在一个 Skill 里,每一次被触发都是在教模型用旧流程处理新问题。
如果你发现某个 Skill 装了之后几乎没被触发过,或者触发后效果不如直接让模型自由发挥,那它大概率已经变成了负担。
3. 我建议这样管理 Skill:先规划、再安装、后淘汰
3.1 第一步:把使用场景拆成“高频固定流程”和“低频随机任务”
不要先到处找“skill 推荐”,先列自己的真实场景。我会先把高频固定流程标记为适合做成 Skill 的对象,比如:
- 日志分析:固定输入是日志文件,固定输出是问题摘要和根因列表
- 代码评审:固定输入是 MR diff,固定输出是风险点、建议、阻塞项
- 周报整理:固定输入是 Git 提交记录,固定输出是周报段落
低频随机任务不要急着做成 Skill,先让模型用通用能力处理。同一个任务稳定跑通三次以上,再固化成 Skill。这样能避免把一次性需求变成永久噪音。
3.2 第二步:一个 Skill 只做一件事,描述写清楚“能触发”和“不能触发”
一个 Skill 只解决一个场景,是降低冲突成本最有效的办法。描述里不能只写“能做日志分析”,还要写“当用户只是闲聊报错概念时不要触发”。
我一般习惯在 SKILL.md 的 description 里把触发条件和排除条件都写上。示例:
--- name: log-analysis description: 分析日志文件、报错堆栈和请求 trace,输出问题摘要、根因分析和修复建议。仅当用户提供具体日志内容或日志文件路径时使用;不处理没有日志素材的通用故障概念讨论。 ---这样会让模型的选择压力小很多。模型判断“该不该调用”时,靠的就是这段描述,描述越准,误触发越少。
3.3 第三步:按项目级、全局级、临时级分开存放
Skill 应该分级管理,而不是全部塞在同一个目录里。
- 项目级:只对当前项目有意义,比如某个业务模块的编码规范、测试规范
- 全局级:跨项目通用,比如日志分析、周报整理、代码评审
- 临时级:正在试用的 Skill,放在独立目录,试用通过再升到全局
这样做的好处是控制影响范围。一个项目特有的规范不会跑到别的项目里干扰判断,试用中的 Skill 也不会污染稳定环境。很多人觉得 Skill 目录很乱,其实就是缺了这层分级。
3.4 第四步:设置验证样例,把“回答得好”变成可检查的步骤
判断 Skill 有没有用,不能靠感觉。我会给每个重要 Skill 准备一小段验证输入和预期输出。
- 输入:一份固定样例日志
- 预期输出:问题根因、影响范围、修复建议,格式为 Markdown 表格
- 验证标准:步骤完整、没有跳过校验、格式与预期一致
每次改 Skill 之后,先跑验证样例,再放到真实任务里。你会发现很多问题根本不是模型能力不足,而是输出格式被某个描述带偏了。有了验证样例,改动是否有效就一目了然。
4. 已经装乱了,按这个顺序恢复
4.1 先全部禁用,再逐个放行
如果整个环境明显变难用,不要急着删文件。先把所有非必要 Skill 禁用,只保留最核心的一两个,重新测试同一条任务。这时候通常就恢复稳定了。
然后每次只放行一个 Skill,跑同一条验证输入。哪个 Skill 放进去后输出变差,就说明它和当前环境冲突。这个方法虽然慢,但能避免“一次全开,不知道谁在捣乱”的困境。
如果核心任务本身没问题,只是某些场景不稳定,那大概率不是模型问题,而是 Skill 环境和输入条件变了。
4.2 从日志和输出格式判断冲突源
大部分主流工具都会输出模型调用了哪些 Skill、读取了哪些文件、执行了哪些脚本。遇到输出异常时,先看调用日志:
- 是不是一次输入触发了多个 Skill
- 是不是读取的 Skill 文件与目标场景不匹配
- 是不是某个 Skill 里的脚本报错了,但模型没停下来继续走
这样才能快速定位是“描述冲突”“流程冲突”还是“资源损坏”,而不是反复改提示词。
4.3 保留最小集合,不常用的放进归档目录
恢复稳定后,把用得少的 Skill 从活动目录移到 archive 目录,而不是直接删除。归档之后模型读不到,但以后需要时可以快速找回。
一个我常用的标准:过去两周没有被触发过,且未来场景不确定,就归档。这个标准看起来简单,但对控制规模很有效。否则你永远不知道当前环境里到底有哪些 Skill 在“潜伏”。
4.4 合并同类项,用“编排”而不是“叠 Skill”
如果确实是“日志分析 + 故障定位 + 告警通知”这种强关联流程,更适合做成一个完整的“故障排查 Skill”,或者做成一个 Agent 工作流,而不是三个互相独立的 Skill。
多个 Skill 靠模型自己拼装,不如把拼装逻辑写进同一个流程文档里。这样既减少了上下文里的冗余描述,也避免了模型在步骤之间跳来跳去。
5. 写自己的 Skill 时,这几个地方最容易被忽略
5.1 触发条件(description)决定了模型会不会用你
很多人写 SKILL.md 只写“这个 Skill 能做什么”,不写“什么时候不该用”。模型的选择依据主要就是 name 和 description。描述越泛化,误触发概率越高。
我给团队的建议是 description 写两句:第一句说清适用场景,第二句说清边界。前端页面还原的 Skill 可以写成这样:
--- name: frontend-page-restore description: 根据设计稿图片生成 React 页面代码。仅用于前端页面还原,不处理设计规范说明、交互逻辑规划或后端接口设计。 ---虽然不同工具的字段格式略有差异,但核心原则一样:让模型容易判断“用”和“不用”。
5.2 输入输出模板决定了结果能不能直接用
Skill 正文里一定要给出输入示例和输出模板,特别是结构化输出。输出模板越明确,模型生成时越不会自由发挥。比如日志分析 Skill 的输出模板可以写成:
## 问题摘要 - 发生时间: - 影响范围: - 根因等级:高 / 中 / 低 ## 根因分析 - 现象: - 可能原因: - 验证方法: ## 修复建议 - 建议方案: - 操作步骤: - 回滚方案:没有模板时,模型每次生成的结构都可能不同。有模板后,后续无论是人工阅读还是自动化处理,都能稳定依赖同一个结构。
5.3 边界和禁止项决定了安全下限
我会在 Skill 正文里单独写“禁止项”。比如:
- 禁止在未确认格式化范围时直接执行批量修改
- 禁止在日志分析时忽略时间戳排序
- 禁止把未经验证的命令直接写入生产环境脚本
这些禁止项会明显降低模型“激进执行”的概率。尤其是带脚本的 Skill,如果没有边界说明,模型为了完成目标,可能做出超出预期的操作。写禁止项不是为了限制能力,而是为了把行为的确定性拉高。
5.4 版本与测试:SKILL.md 也要能回滚
Skill 文件本质上是代码和文档的组合,应该有版本意识。我会在目录里维护一个变更记录,或者在文件名里保留日期。每次改动只改一个点,然后用验证样例测试,确认没问题再提交。
这里不要求引入多复杂的流程,但至少要保证“如果改坏了,能马上回到上一个能用版本”。否则 Skill 会越调越乱,最后连最开始为什么装它都忘了。
6. 不同阶段的人,对 Skill 的态度不一样
6.1 新手:先空手跑通,再装两三个高频 Skill
如果你是第一次接触 Claude Code、Codex 或 Trae 这类工具里的 Skill,我的建议是别一上来就复制一份“80 个常用 Skill 合集”。先保持默认配置,把基础任务跑通。然后选两三个自己每天都做的场景,比如代码评审、日志分析、周报整理,逐个装、逐个验证。
等你真正理解一个 SKILL.md 下面哪些描述会影响触发、哪些步骤会影响输出,再考虑扩展。否则你只是把一堆别人写的说明文件堆进环境里,出了问题连定位都很难。
6.2 进阶:把 Skill 当成团队流程资产管理
如果已经进入团队协作阶段,Skill 就不该只是个人文件。我会用类似代码仓库的方式来维护:
- 每个 Skill 一个目录,结构统一
- 有明确的负责人,改动后要通知相关人
- 有验证样例和输出模板
- 有归档和淘汰机制
这样 Skill 才真正变成团队能力的一部分,而不是个人收藏夹里的“好物”。团队里出现“某个 Skill 明明很实用,但没人敢改”的情况时,往往就是因为缺少版本和验收机制。
6.3 回答变奇怪时,先按这个链路排查
最后留一个我自己的排查顺序:
- 看输入是否满足预期格式:缺日志、缺上下文、路径错误最容易被忽略。
- 看调用日志:确认这次到底加载了哪个 Skill。
- 看输出模板:模型有没有严格按照模板生成,还是自由发挥了。
- 看 Skill 的 description:是不是有多个 Skill 同时匹配。
- 看资源冲突:脚本、目录、依赖版本有没有被其他 Skill 改动过。
- 最后再考虑调整模型参数或改提示词。
按这个链路走,绝大多数“Skill 越多越难用”的问题都能定位到具体原因。工具本身通常没坏,往往是说明书的描述、边界和输出模板出了问题。
Skill 的价值不在数量,而在于能不能让模型稳定地按一套可靠流程完成特定任务。装之前多花五分钟想清楚使用场景和触发边界,比之后再花半小时排查冲突要省事得多。如果你的 Skill 列表也已经膨胀到不知道谁在起作用,不妨先全部停掉,从最小集合开始恢复。