☰
AI Agent Skills 实战:渐进式披露与按需加载设计指南
2026/10/8 18:34:53 网站建设 项目流程

1. 从"skills"这个词说起:它到底指什么

第一次看到"skills"这个标题,很多人会以为是某个泛泛的概念,或者干脆就是招聘网站上那个"技能"栏。但如果你最近在折腾 Claude Code、Codex 这类 AI 编程助手,就会发现"skills"已经变成了一个非常具体的工程概念——它指的是给 AI Agent 挂载的可复用能力模块。

我最初接触这个概念的时候也懵。传统意义上我们讲"给 AI 加技能",无非就是写个 prompt、调个 API、接个工具函数。但 skills 这套东西不太一样,它更像是一种结构化的能力封装协议:把一段特定领域的知识、一套操作流程、一组工具调用方式,打包成一个可以被 Agent 动态发现、按需加载的单元。你可以把它理解成给 AI 装的"插件",但比插件更轻、更语义化。

为什么这个东西突然火起来?因为大家发现,光靠一个通用大模型 + 一堆工具,做复杂任务时上下文会被撑爆,模型注意力也会被稀释。而 skills 的思路是:平时不加载,用到才加载。Agent 先看到一份 skills 清单(只有名字和一句话描述),判断当前任务需要哪个 skill,再把那个 skill 的完整内容拉进上下文。这个机制在 Claude Code 里叫 Agent Skills,在 Codex 生态里也有类似的设计。

这篇文章我想聊的不是"skills 是什么"这种百科式介绍,而是一个真正在项目里用 skills 的人,会怎么设计、怎么踩坑、怎么把它用出价值。适合已经在用 Claude Code / Codex、或者准备给自己的 Agent 系统加 skills 机制的开发者。如果你只是听说过这个词,看完也能明白它到底解决了什么问题。

2. Skills 的核心机制:渐进式披露与按需加载

2.1 为什么不能把所有能力一次性塞给模型

先说一个我踩过的坑。早期我给自己的 Agent 写了一个超长的 system prompt,把代码规范、部署流程、数据库约定、日志格式全塞进去,大概有八千多 token。结果发现模型在简单任务上表现反而变差了——问它一个简单的函数怎么写,它会莫名其妙地扯到部署流程上去。

这就是上下文污染。模型的注意力是有限的,无关信息越多,真正相关的信息被"看到"的概率就越低。而且每次请求都要带上这八千 token,成本和延迟都上去了。

Skills 机制的核心价值就在这:它把"能力"和"上下文"解耦了。每个 skill 是一个独立文件(通常是一个带 frontmatter 的 Markdown),平时只暴露元数据,Agent 需要时才加载全文。这个设计在 Anthropic 的 Agent Skills 文档里被称为"progressive disclosure"(渐进式披露)。

2.2 一个 skill 的最小结构长什么样

我实际用下来,一个能跑的 skill 至少包含三部分:

--- name: db-migration description: 当需要修改数据库 schema、新增字段或调整索引时使用。包含迁移脚本编写规范和回滚流程。 --- ## 使用场景 当用户要求修改表结构、新增字段、调整索引时触发。 ## 操作步骤 1. 在 migrations/ 目录下创建带时间戳的迁移文件 2. 使用 up/down 双函数结构 3. 本地执行 dry-run 验证 ...

关键在 frontmatter 里的name和description。description 写得好不好,直接决定这个 skill 会不会被正确触发。我见过太多人把 description 写成"这是一个数据库相关的技能",结果模型根本不知道什么时候该用它。正确的写法是描述触发条件,而不是描述内容。

2.3 加载时机:模型自己判断还是人工指定

这里有个容易混淆的点。Skills 的触发有两种模式:

模式触发方式适用场景风险
自动触发模型根据 description 自行判断通用型 skill、任务边界清晰误触发、漏触发
显式调用用户或代码显式指定 skill 名关键流程、高风险操作需要人工介入
混合模式自动推荐 + 人工确认生产环境流程稍长

我个人的经验是:涉及写操作、删除操作、部署操作的 skill,一律走显式调用。让模型自己判断"要不要执行数据库迁移",这个风险太大了。而像"代码风格检查""文档生成"这类只读或低风险的,可以放开自动触发。

2.4 和传统 tool calling 的本质区别

很多人会问:这不就是 function calling 吗?不是。Function calling 是模型调用一个函数,输入输出都是结构化的参数。而 skill 是模型加载一段知识,它可能包含多个工具调用、多个步骤、甚至一些判断逻辑。

打个比方:function calling 像是给 AI 一把锤子,skill 像是给 AI 一本《木工手册》外加一套工具。前者是原子能力,后者是封装好的工作流。这也是为什么 skills 特别适合那些"步骤多、有约定、需要领域知识"的任务。

3. 在 Claude Code 里落地 Skills 的完整流程

3.1 目录结构与文件放置位置

Claude Code 对 skills 的加载有固定的目录约定。我实测下来,主要有两个位置:

  • 项目级:<project>/.claude/skills/,只对当前项目生效
  • 用户级:~/.claude/skills/,对所有项目生效

每个 skill 是一个独立目录,目录里放一个SKILL.md。注意是目录 + SKILL.md,不是单个 md 文件。这个结构一开始我也搞错了,直接把db-migration.md丢进去,结果死活不加载。

.claude/ └── skills/ ├── db-migration/ │ └── SKILL.md ├── api-design/ │ └── SKILL.md └── release-check/ └── SKILL.md

如果 skill 需要附带脚本、模板文件,也放在同一个目录下,然后在 SKILL.md 里用相对路径引用。这样打包和迁移都很方便。

3.2 description 的写法:决定生死的一行字

我再强调一遍 description 的重要性,因为这是整个 skill 机制里最容易翻车的地方。

反面教材:

description: 帮助处理数据库相关的工作

正面教材:

description: 当用户要求新增/修改数据库表结构、添加字段、创建索引、或编写数据迁移脚本时使用。不适用于查询优化和 SQL 调试。

区别在哪?正面教材明确了触发条件(新增/修改表结构、加字段、建索引、写迁移脚本)和排除条件(不适用于查询优化和 SQL 调试)。模型判断是否加载时,靠的就是这些信号。

我总结了一个 description 的写法公式:

当 [具体触发场景列举] 时使用。不适用于 [容易混淆的场景]。

这个"不适用于"特别关键。因为很多 skill 的边界是模糊的,不写清楚排除条件,模型就会在边缘场景乱触发。

3.3 用 SKILL.md 组织操作步骤的实战模板

下面是我在项目里实际用的一个 skill 模板,做了脱敏处理:

--- name: release-check description: 当用户要求发布新版本、打 tag、或执行上线前检查时使用。不适用于日常提交和本地测试。 --- ## 前置检查 1. 确认当前分支是 main 且工作区干净 2. 确认 CHANGELOG.md 已更新 3. 确认版本号在 package.json 中已 bump ## 执行步骤 1. 运行 `npm run build` 并检查产物 2. 运行 `npm run test:ci` 3. 如果测试通过,执行 `git tag v{version}` 4. 推送 tag 并触发 CI ## 失败处理 - 构建失败:检查 node 版本是否为 18+ - 测试失败:不要跳过,定位到具体用例 - tag 已存在:先确认是否重复发布 ## 注意事项 - 不要在周五下午发布 - 发布前确认回滚方案

这个模板的价值在于:它把"发布"这个动作的所有隐性知识显性化了。新人接手时,不用问老员工"发布要注意什么",skill 里全写着。这也是 skills 除了给 AI 用之外,另一个被低估的价值——它其实是团队知识的载体。

3.4 验证 skill 是否被正确加载

写完 skill 不代表就生效了。我常用的验证方法:

  1. 直接问模型:"你现在有哪些可用的 skills?" 看它能不能列出你刚写的那个
  2. 构造触发场景:给一个明确应该触发该 skill 的任务,观察它是否加载
  3. 构造边界场景:给一个模糊的任务,看它是否误触发

如果 skill 没被加载,排查顺序是:目录结构对不对 → frontmatter 格式对不对 → description 是否够明确 → 是否有语法错误导致解析失败。

4. Codex 生态下的 Skills 与跨工具迁移

4.1 Codex 的 skills 机制差异

Codex 这边的 skills 概念和 Claude Code 不完全一样。Codex 更偏向于配置驱动,很多能力通过配置文件、AGENTS.md 这类约定来定义。但核心思路是一致的:把领域知识从主 prompt 里剥离出来,按需注入。

我实测下来,Codex 里比较实用的做法是:

  • 用AGENTS.md定义项目级的通用约定
  • 用独立的 skill 文件定义特定任务的流程
  • 通过显式的引用让模型加载对应 skill

差异点在于,Codex 对 skill 的自动发现能力相对弱一些,更多依赖显式引用。所以如果你从 Claude Code 迁移过来,会发现"自动触发"没那么灵,需要调整使用习惯。

4.2 一份 skill 能不能同时给两个工具用

这是很多人关心的问题。答案是:核心内容可以复用,但元数据要适配。

我的做法是维护一份"源 skill",然后写个小脚本生成两个版本:

字段Claude Code 版本Codex 版本
元数据格式YAML frontmatter配置项或注释
触发方式description 自动匹配显式引用为主
文件位置.claude/skills/项目约定目录
正文内容完全一致完全一致

正文部分(操作步骤、注意事项)是纯 Markdown,两边通用。真正需要适配的只有头部元数据。这样维护成本就降下来了。

4.3 跨工具迁移时最容易丢的东西

迁移时最容易丢的不是内容,而是触发上下文。在 Claude Code 里,description 写得好,模型会自动加载;迁到 Codex 后如果还是靠自动触发,很可能就不灵了。

我的经验是:迁移时把自动触发改成显式引用,同时在项目文档里写清楚"什么任务该引用哪个 skill"。虽然多了一步人工判断,但稳定性反而更高。毕竟 skill 的价值是"知识封装",不是"自动魔法"。

5. 设计一个好 Skill 的几条硬经验

5.1 粒度控制:一个 skill 只干一件事

我见过最夸张的一个 skill,把"代码审查 + 单元测试 + 部署 + 监控配置"全塞在一起,两千多行。结果就是:模型加载它之后,注意力被分散,每个环节都做得马马虎虎。

正确的做法是按任务边界拆分。判断标准很简单:如果这个 skill 的 description 里出现了"和"或者"以及",就该考虑拆了。

  • 差:code-quality(代码质量,涵盖审查、测试、格式化)
  • 好:code-review、unit-test-gen、format-check三个独立 skill

拆开之后,每个 skill 的 description 更精准,触发更准,加载的上下文也更小。

5.2 写"什么时候不用",比写"什么时候用"更重要

这一点我在前面提过,但值得单独拎出来说。因为误触发的代价往往比漏触发大。

漏触发:模型没加载 skill,按通用能力处理,可能做得不够好,但不会出大错。 误触发:模型加载了不该加载的 skill,按错误的流程操作,可能造成实际损害。

所以每个 skill 的 description 里,我都会认真写"不适用于"部分。比如一个"数据库迁移"的 skill,我会明确写"不适用于查询优化、不适用于数据修复、不适用于生产环境直接操作"。

5.3 把隐性知识显性化

Skills 最大的价值,其实是把老员工脑子里的隐性知识写下来。比如:

  • 为什么这个字段要用text而不是varchar?
  • 为什么发布前要先跑一遍 dry-run?
  • 为什么这个接口不能加缓存?

这些"为什么"平时没人写文档,但新人踩坑时又特别需要。把它们写进 skill,AI 用得上,人也能看。这是我觉得 skills 机制最被低估的地方。

5.4 版本管理:skill 也要进 git

Skill 是代码资产,必须进版本控制。我见过有人把 skill 放在本地不提交,结果换台机器就没了。

我的做法是:项目级 skill 跟着项目走,用户级 skill 单独建一个 repo 管理。每次修改 skill 都走正常的 PR 流程,这样能追溯"为什么这个步骤是这么写的"。

6. 踩坑实录:那些让我熬夜排查的 skills 问题

6.1 skill 死活不加载:从目录结构开始排查

有一次我写了个 skill,怎么都不生效。排查了半小时,最后发现是目录名和 frontmatter 里的 name 不一致。Claude Code 加载时以目录名为准,但我在 SKILL.md 里写的 name 是另一个,导致索引混乱。

排查链路是这样的:

  1. 先确认目录存在且拼写正确
  2. 检查 SKILL.md 文件名是否大小写正确(Linux 下大小写敏感)
  3. 检查 frontmatter 的---是否成对
  4. 检查 name 和目录名是否一致
  5. 检查 YAML 缩进是否有 tab(YAML 不允许 tab)

这个顺序建议你存下来,能省不少时间。

6.2 description 写得太泛导致误触发

我写过一个api-design的 skill,description 是"当涉及 API 相关工作时使用"。结果发现,只要任务里出现"接口"两个字,它就被加载,哪怕只是让我改个接口的注释。

后来改成:"当用户要求设计新的 REST 接口、定义请求响应结构、或规划接口版本策略时使用。不适用于修改现有接口的注释、调试接口报错、编写接口测试。"

改完之后误触发率大幅下降。description 的精度,直接决定 skill 的可用性。

6.3 多个 skill 冲突时的优先级问题

当两个 skill 的触发条件有重叠时,模型可能同时加载两个,然后按哪个执行就不确定了。我遇到过db-migration和db-schema-design同时被加载,结果模型在"改字段"这个任务上左右横跳。

解决办法有两个:

  • 在 description 里划清边界:明确写"涉及实际执行迁移用 A,只做设计讨论用 B"
  • 在 skill 正文里加互斥说明:比如"如果同时加载了 X skill,以本 skill 为准"

我倾向于第一种,因为边界清晰是设计问题,不该靠运行时打补丁。

6.4 skill 内容过长反而拖慢响应

有个 skill 我写了三千多字,包含大量示例代码。结果每次加载它,响应都明显变慢,而且模型经常"抓不住重点"。

后来我做了两件事:

  1. 正文精简到核心步骤,把详细示例移到同目录的examples.md,需要时再引用
  2. 用表格和列表替代大段文字,信息密度更高

改完之后,加载速度和执行准确率都上来了。skill 不是越长越好,是越准越好。

7. 从 skills 到 Agent 能力体系:我的整体思路

7.1 分层设计:基础约定、领域 skill、任务 skill

用了一段时间之后,我慢慢形成了一套分层思路:

层级内容加载方式例子
基础层项目通用约定常驻代码风格、目录结构、命名规范
领域层某类任务的通用流程按需数据库操作、API 设计、测试编写
任务层具体任务的执行步骤显式发布流程、迁移脚本、故障排查

基础层放AGENTS.md或 system prompt,领域层和任务层放 skills。这样既保证了通用约定始终生效,又避免了上下文被撑爆。

7.2 用 skills 承载团队规范

我们团队现在有个约定:任何"口口相传"的规范,都要沉淀成 skill。比如"提交信息怎么写""分支怎么命名""review 要看哪些点",全部写成 skill。

好处是双重的:AI 用得上,新人也能看。而且 skill 进 git 之后,规范变更有了历史记录,比散落在 wiki 里的文档靠谱多了。

7.3 持续迭代:skill 是活的

Skill 不是写完就完事的。我每个月会回顾一次:哪些 skill 从没被触发过(可能 description 有问题)?哪些经常误触发(边界没划清)?哪些内容已经过时(流程变了)?

这个过程有点像维护测试用例,需要持续投入。但回报也很明显:你的 Agent 会越来越懂你的项目。

8. 一些实用建议和后续可以做的事

如果你刚开始接触 skills,我的建议是从一个小场景切入。别一上来就想着把整个项目的知识都 skill 化,那样容易半途而废。先挑一个你每周都要重复做、步骤又比较固定的任务,把它写成 skill,跑通整个流程,感受一下效果。

跑通之后,再逐步扩展。我自己的节奏是:每周沉淀 1-2 个 skill,一个月下来就有了一套能覆盖主要工作流的能力库。

后续可以探索的方向,我个人比较感兴趣的是skill 的自动化测试——怎么验证一个 skill 在给定输入下会正确触发、正确执行。目前这块还比较手工,如果能做成 CI 的一部分,skill 的质量会更有保障。

另外就是skill 之间的组合。单个 skill 解决单点问题,但真实任务往往是多个 skill 串联。怎么让 Agent 自动编排多个 skill,这是个值得琢磨的问题。我试过在 skill 里显式引用其他 skill,效果还行,但还不够优雅。

最后分享一个我踩坑后总结的小技巧:写 skill 的时候,把自己想象成在给一个刚入职的同事写操作手册。这个心态一换,写出来的东西立刻就不一样了——你会自然地写清楚"为什么"、写清楚"什么时候别用"、写清楚"出错了怎么办"。而这些,恰恰是 skill 最有价值的部分。

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

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

立即咨询