最近团队里开始大规模用 AI 编程 Agent 写代码,大家吐槽最多的反而不是“它不会写代码”,而是“写出来的东西一股 AI 味”:命名风格东一榔头西一棒子、依赖随手乱加、Git 提交信息写得像机翻、明明团队内有统一的技术栈和约定,它偏要用自己训练数据里的那套来。说白了,一个会写代码的 Agent 和一名能直接加入项目干活的同事之间,差的不是代码能力,而是对团队规范的理解和遵守。
Skills 机制就是补上这段差距的关键。它相当于给 Agent 预置了一套“岗位手册”,把你们项目里的代码规范、提交规范、架构约定、常用方案全部转换成 Agent 能读取、能执行的操作规程。这篇文章我会从实战角度拆解怎么把 Skills 用起来,让 Agent 从“会写代码的工具”变成“按规范干活的同事”。
1. 先搞清楚 Skills 到底解决了什么问题
1.1 通用 Agent 的“能力幻觉”和“规范盲区”
很多人第一次用 Claude Code、Codex 这类工具时,会觉得它“什么都会”。但实际上,它会的只是“写代码”这个泛化能力,对你们团队的具体约定一无所知。举个最常见的例子:团队后端统一用 Java 17 + Spring Boot,接口返回结构固定是{ code, message, data },可你让 Agent 生成一个查询接口,它很可能会按照自己训练语料里最常见的写法,给你返回一个直接丢实体类的结构,甚至用上 Java 8 的LocalDate处理逻辑,和团队里的工具类完全脱节。
再比如前端,团队已经定了用 Vue 3 + TypeScript + unplugin-auto-import,组件里不允许手动import { ref } from 'vue'。但通用 Agent 生成的代码大概率会把这些 import 全部写上,你还要花时间一行行删。这些小问题叠加起来,写代码的时间是省了,Review 的时间反而变长了。
Skills 解决的就是这种“规范盲区”。它的核心思路不是教 Agent 更多编程知识,而是把你们项目里那些“默认大家都该知道”的事情,显式地写给 Agent 看。
1.2 Skills、Prompt 和 Rules 三者的边界
刚开始接触 Skills 的人容易把它和普通的 Prompt 指令、Rules 规则混淆。我自己的理解是这样:
- Prompt 是一次性的对话上下文,告诉 Agent“这一次任务怎么干”,不持久,换个会话就失效。
- Rules 是全局的行为约束,相当于公司的“员工手册”,规定哪些能做、哪些不能做,通常放在项目根目录的规则文件里,每个会话都会加载,但它偏“禁止性条款”,不适合承载太长的操作细节。
- Skills 是可复用的“岗位操作手册”,围绕某一个具体任务封装完整的步骤、模板、示例和脚本,Agent 遇到相关任务时再动态调用,相当于“遇到这种情况,按这个流程走”。
用团队来类比:Rules 是“上班不能迟到、代码必须过 Lint”;Prompt 是“今天把登录模块改一下”;Skills 则是“新同事入职后,给他一份怎么提 PR、怎么写 commit message、怎么跑测试的标准化流程文档”。三者配合,Agent 才算真正融入团队。
2. 项目级 Skills 适配的整体设计思路
2.1 先盘点团队里有哪些“隐性规范”
做 Skills 适配的第一步,不是急着写文件,而是先盘点。我建议把团队里大家约定俗成、但从未写进文档的规范都列出来,至少包括这些维度:
- 代码风格:缩进、命名、注释语言、是否强制类型标注、Lint 规则。
- 技术栈约束:规定使用的框架版本、UI 库、HTTP 客户端、序列化方式、数据库访问层。
- 架构模式:分层方式、目录结构、依赖注入风格、异常处理策略。
- 工程流程:Git 分支命名、commit message 格式、PR 描述模板、测试要求、构建命令。
- 业务约定:接口返回结构、错误码规范、日志格式、敏感信息脱敏要求。
有一个很实用的做法:找团队里代码 Review 最严格的那个同事,问问他平时都会挑出哪些问题。我当初做适配的时候,就是从几个“Review 狠人”的评论里提取出高频意见,然后逐个转成 Skills。这样出来的适配目录,基本就是团队真实痛点的映射。
2.2 确定 Skills 的目录和命名规范
目前各家 Agent 对 Skills 的目录约定不完全一致,但主流形式大同小异,通常是在项目根目录创建一个skills文件夹(有的工具是.claude/skills,有的是./skills),每个 Skill 一个子目录。
我建议命名全部用小写字母加连字符,例如backend-api-handler、git-commit-convention、vue3-component-style。每一个 Skill 目录下必须有SKILL.md文件,这是 Agent 读取的核心入口。其他辅助资源可以包括模板文件、示例代码、可执行的校验脚本等。
这里有一个关键点:目录名要能体现“场景”,而不是“知识点”。比如python-coding-style就太泛了,Agent 不知道该什么时候用它;改成python-backend-api-implementation就更明确——当需要写 Python 后端接口时使用。Skills 的一个重要特性就是按需加载,描述越精确,Agent 判断“该不该用”的准确率越高。
2.3 分层适配:团队级、项目级、个人级
Skills 不一定都要塞在项目里。我实际工作中是分三层的:
- 团队级 Skills:放在一个独立的 Git 仓库里,统一管理,项目通过 submodule 或复制方式引入。这类 Skills 包含团队的通用规范,比如 Git 提交规范、代码 Review 检查清单。
- 项目级 Skills:放在具体项目仓库里,包含和这个项目强相关的模式,比如“这个项目特有的分页返回结构”、“用户权限校验的写法”。
- 个人级 Skills:放在你的用户目录下,是个人偏好,比如你习惯用什么测试框架写单测、喜欢在代码里加什么注释风格。
分层的好处是避免把团队规范复制到几十个仓库里,改一处其他不同步。我当前的做法是团队级和项目级分开维护,个人级基本不用,因为既然是希望 Agent “按团队规范干活”,个人偏好最好别混进来,否则输出又变得不稳定。
3. SKILL.md 写作要点:把规范翻译给 Agent 听
3.1 SKILL.md 的标准结构
一个能被 Agent 准确理解的 SKILL.md,我一般按下面的结构来写:
--- name: backend-api-implementation description: 当需要实现一个后端 HTTP API 接口时使用,包括 Controller、Service、Mapper 的代码生成和异常处理。不要在处理非接口任务时使用。 --- # 后端 API 接口实现规范 ## 适用场景 - 新增一个 RESTful 接口 - 修改已有接口的返回结构 ## 技术栈与依赖 - 使用 Spring Boot 3.x,Java 17 - HTTP 响应统一为 ResponseResult<T>,禁止直接返回实体类 ## 实现步骤 1. 先阅读 `src/main/resources/api-schema.yaml` 中的接口定义 2. 在 controller 包下新建类... 3. ... ## 验收清单 - [ ] 所有接口都有 @Validated 参数校验 - [ ] 使用项目内的 BizException 抛出业务异常 - [ ] 新依赖有正当理由并更新 dependencies.md ## 示例代码 参考 `examples/user-controller.example.java`注意,YAML frontmatter 里的name和description是 Agent 判断是否加载这个 Skill 的重要依据,可以写得详细,但不要讲废话。特别是 description 里要写清楚“什么时候不该用”,这能明显减少误触发。
3.2 用“验收清单”代替“讲道理”
我踩过最大的坑,就是在 SKILL.md 里试图给 Agent“讲道理”——“代码应当具有良好的可读性”、“注意边界情况”。这种大而化之的话对 Agent 约等于没说,它不知道你的“可读性”具体指什么。
后来我把所有规范全改成可以打勾的验收项。比如“具有良好的可读性”改成:
- 方法长度不超过 80 行,超过时拆分
- 禁止使用魔法数字,常量统一放在
Constants.java - 不允许出现逻辑与(&&)超过两层的嵌套条件,如有需要提前 return
这种清单式写法有两个好处:一是 Agent 能在完成代码后自行对照检查,二是你在 Review 时拿同一份清单去核对,人机标准一致,扯皮概率大幅下降。
3.3 在 SKILL.md 里嵌入“反面示例”
只有正面示例是不够的。Agent 很擅长模仿格式,但容易忽略哪些写法是被禁止的。我建议每个 Skill 里都加一个“反面示例”小节,展示团队代码里经常出现的坏味道,并写明为什么不推荐。
举一个实际的例子,我们的前端 Skill 里有这么一段:
## 反面示例 ❌ 在组件里手动导入 Vue API: ```ts import { ref, computed } from 'vue'✅ 正确做法:项目已配置 unplugin-auto-import,直接使用ref和computed即可。
这个技巧的效果非常明显。Agent 生成代码时,只要在上下文里看到反面示例,就很少再踩同一个坑。我甚至觉得反面示例比正面示例更值得写,因为大部分 Agent 的“基础编码能力”已经不错了,缺的是对团队禁忌的了解。 ## 4. 实操:把高频场景做成 Skills 套件 ### 4.1 场景一:Git 提交规范适配 Git 提交信息是 Agent 最容易“放飞自我”的地方。我见过它提交 “update code” 这种毫无信息量的信息,也见过它写一整段英文散文。后来我写了一个 `git-commit-convention` Skill,内容很简短: ```markdown --- name: git-commit-convention description: 在生成 Git commit message 时使用。团队采用 Conventional Commits 规范。 --- # 团队 Git 提交规范 - 格式:`<type>(<scope>): <subject>` - type 使用:`feat` / `fix` / `docs` / `style` / `refactor` / `test` / `chore` - scope 使用模块名,例如:`feat(user-service): 增加用户注销接口` - subject 用中文描述,不要用句号结尾,不超过 50 个字 - 禁止使用 “update”、“modify” 这类无意义动词这个 Skill 很短,但价值很高。它配合 Agent 工具的auto-commit功能,基本能保证每一条提交信息都符合团队规范。写这类 Skill 的秘诀就是:只列规则,不要长篇解释,Agent 提取规则的能力很强,反而是大段文字会稀释重点。
4.2 场景二:后端接口代码规范适配
如果你们团队有比较严重的接口风格不统一问题,可以写一个backend-api-implementationSkill。这个 Skill 通常是最复杂的,因为它往往和项目的具体技术栈绑定。我在工程里是这样组织的:
目录结构:
skills/ backend-api-implementation/ SKILL.md templates/ Controller.java.tpl Service.java.tpl Mapper.java.tpl examples/ user-controller.example.java user-service.example.javaSKILL.md 重点写三部分:接口处理流程、统一响应结构、异常处理规则。模板和示例代码则给出骨架和标准写法。这样 Agent 生成时相当于“照着模板填业务”,生成结果非常稳定。
整个团队收益最大的地方在于:以前不同人写出来的接口,参数校验有的用@Validated,有的手写 if;异常有的抛BizException,有的直接返回 null;现在所有 Agent 生成的接口都是同一套结构,Review 成本直线下降。
4.3 场景三:前端组件开发适配
我还写过一个vue3-component-implementationSkill,解决的是组件库使用不规范的问题。我们的项目引入了 element-plus,但团队内部又封装了一些通用组件,比如ProTable、ProDialog,有些 Agent 不知道这些封装的存在,直接去用原生 table 和 dialog 拼。
Skill 里我写明了:
- 优先使用团队封装的 Pro 组件,不直接使用 element-plus 原生组件实现表格和弹窗
- 组件样式统一使用 scoped + CSS 变量,不用
!important - 通用状态用 Pinia,不要用组件间事件总线
- 所有表单必须有
rules校验,校验规则集中在validate.ts
写这个 Skill 时,最好附带 Pro 组件的 props 说明文档和最小示例。Agent 有了参考文档后,生成的组件代码基本可以直接用,不再需要你一遍遍提醒“用 ProTable 啊”。
4.4 场景四:数据库访问层规范适配
数据访问层的规范通常和具体 ORM 绑定。比如我们团队禁止在 Mapper XML 里写复杂的动态 SQL,复杂查询必须走 QueryWrapper 或者在 Service 层用 Java 代码处理。这个规则如果不写进 Skill,Agent 很容易生成一长串<if>标签的 SQL,维护起来非常痛苦。
数据库访问层 Skill 里我还会写明表和实体类的命名规则、字段类型映射约定、逻辑删除字段的处理方式。这类规范如果在代码 Review 时逐条讲给 Agent 听,效率太低,写成 Skill 一次配置,后面所有会话都能稳定生效。
5. 把 Skills 接入日常工作流的几种方式
5.1 最简单的方式:项目根目录加说明
对于 Claude Code 这类工具,官方支持自动发现项目里的skills目录。其他 Agent 工具也大多支持类似的机制。你在项目根目录放好 Skills 目录之后,新建会话时 Agent 就会先扫描可用的 Skills,然后在对话中根据用户请求自动匹配。
用起来之后你会发现,Agent 在响应任务前有时会主动说一句“我会参考项目里的 xxx Skill”。如果没看到这句话,而你确定当前任务应该匹配某个 Skill,可能就是因为 description 写得不够精确,或者目录没放对位置。
5.2 把 Skills 和 Rules 串起来用
Rules 通常只适合写一些全局性的、不依赖具体场景的硬约束,比如“禁止将敏感配置硬编码在代码里”“所有对外接口必须记录日志”。具体到某个场景怎么做,再扔给对应的 Skill。
我的经验是:Rules 里写“不做什么”,SKILL.md 里写“应该怎么做”。两者配合最大的好处是,Agent 先通过 Rules 守住底线,再通过 Skills 把活干到符合团队的期望,效果比只用一种好很多。
5.3 用脚本自动校验 Skills 是否生效
Skills 不生效是常见问题,单纯靠聊天确认不够。我在工程里加了一个很轻量的 Node 脚本,每次 Agent 生成完代码后会自动执行项目已有的 lint 和测试。前端跑 eslint + vue-tsc,后端跑 mvn test。只要有一项不过,就要求 Agent 必须修复到通过为止。
这个机制虽然不复杂,但能倒逼 Agent 认真读取 Skill 里写的内容。尤其当我在 SKILL.md 里写了“代码必须通过以下命令校验”之后,Agent 会在生成时主动检查自己有没有违反规范,出错率骤降。
5.4 不同 Agent 工具间的通用化
我知道很多团队不止用一种 Agent 工具,有人用 Claude Code,有人用 Codex,还有人用 Cursor。好消息是 Skills 的理念已经非常通用,很多工具都支持,只是加载方式略有差异。
我的做法是维护一份标准的skills目录,然后在不同工具里做适配。比如 Cursor 圈定规则的方式是.cursor/rules,我可以在里面写一个很瘦的规则文件,内容只有一句“遇到前端组件开发任务时,阅读skills/vue3-component-implementation/SKILL.md”。这样不同的工具最终都指向同一份权威文档,避免各搞一套导致口径不一致。
6. 常见问题与排查技巧实录
6.1 Skills 完全没被触发
这是我被问得最多的问题。经过排查,大部分情况出在 description 写得不够具体,Agent 判断不了当前任务属于哪个 Skill。比如我有一个 Skill 的 description 写的是“处理前端相关任务”,结果 Agent 几乎从不加载它,因为“前端相关”太宽泛了,连 Agent 自己都不知道什么时候该用。
后来我把 description 改成“当需要实现或修改 Vue 3 组件时使用,包括新增页面组件、通用组件,不适用于样式调整、工具函数编写”,触发率就正常了。另外还要确认 Skill 目录有没有被正确扫描,有些工具要求skills目录放在项目根目录,有些则需要在配置文件中显式声明路径,这一步很容易被忽略。
还有一个细节:如果你某个 Skill 加了 external 依赖或者引用了本地脚本,要确保这些资源路径是相对目录写的,不要用绝对路径。否则复制到别的机器上,就会因为路径失效导致 Skill 加载失败。
6.2 SKILL.md 太长导致 Agent 执行到一半“失忆”
刚开始我把 SKILL.md 写成了一篇几千字的百科全书,想覆盖所有情况,结果 Agent 在处理任务时上下文被大量挤占,反而忽略了关键步骤。后来我学乖了,每个 SKILL.md 尽量控制在 200 行以内,只保留必须的步骤和验收项,那些更细节的内容放到同目录下的参考文档里,需要时再让 Agent 读取。
你可以把 SKILL.md 理解成一个目录索引,它告诉 Agent “先去读哪个文件、按照什么顺序操作”,而不是把所有信息都塞进去。这个调整之后,Agent 的执行稳定度提升非常明显。
6.3 多个 Skills 之间产生冲突
当项目里的 Skills 数量变多以后,冲突是难免的。比如一个backend-api-implementation里要求所有接口使用POST方法,另一个restful-api-design里又说查询接口应该用GET。Agent 同时加载两个 Skill 时就会左右为难,生成结果随机性很大。
我处理冲突的原则是:每个场景只设置一个唯一权威的 Skill,其他 Skill 引用它而不是重复定义。如果确实需要例外,就在对应的 SKILL.md 里显式写“本规范优先于 xxx Skill”。这种“唯一权威”的策略能让 Agent 在做判断时有明确的优先级依据,不会出现两套标准打架的情况。
6.4 生成的代码仍然不完全符合预期
Skills 能大幅提升一致性,但不可能保证 100% 符合预期。遇到这种情况,我的处理方法是先把部分正确的结果收下,然后针对具体的偏差补充 SKILL.md 里的示例或验收清单,下一次生成就会好很多。这其实是一个持续迭代的过程,Skills 的质量是在一次次 Review 中越磨越好的。
另外一个容易被忽略的点是:任何 SKILL.md 里写的指令,都要确保 Agent 有足够的工具和权限去执行。比如你要求它跑测试,但它所在的执行环境没有安装测试依赖,那这个验收项永远过不了。所以 Skill 里的每一个操作步骤,都必须在真实环境里手动跑一遍验证。
7. 关于 Skills 适配我最后的几点个人体会
做 Skills 适配这件事,最难的其实不是技术,而是梳理出团队“真正在用的规范”。很多规范连团队成员自己都没意识到,比如代码风格、命名习惯、模块划分逻辑,它们分散在不同的代码和 Review 记录里。把这一层隐性知识显性化,无论对 Agent 还是对新入职的同事,都是巨大的效率提升。
我也建议别想着一口气把所有场景都适配完。先挑两三个最高频、最痛的点,比如 Git 提交规范和接口代码规范,做出效果给团队看,然后慢慢扩展。搞得太重太全,一方面维护成本高,另一方面 Agent 加载时也会犯选择困难症。
最后一个小技巧:每次让 Agent 干活时,可以在对话里显式提一句“先参考项目里的 xxx Skill”。这个动作能帮你快速验证 Skill 是否能被正确触发,同时也能给 Agent 一个明确的行为锚点。用久了你会发现,Agent 不再像是“一个外部的生成器”,而更像一个熟悉你们项目、知道分寸感的协作者。