☰
agent-skills:为AI编程代理构建可复用技能体系
2026/10/28 4:24:56 网站建设 项目流程

1. 从"agent-skills"说起:为什么AI编程代理需要一套技能体系

第一次看到agent-skills这个项目名的时候,我脑子里冒出来的第一个念头是:这不就是把散落在各个项目里的提示词、脚本、工作流给收拢到一块儿吗?但真正翻完它的结构、跑通几个技能之后,我发现事情没那么简单。它解决的是一个很具体、很痛的问题——AI coding agents 每次开新会话都像失忆一样,你得反复告诉它"这个项目用 pnpm 不用 npm""测试必须先跑 lint""提交信息要遵循 Conventional Commits"。这些规则你写在 README 里它不一定读,写在系统提示里又太臃肿,而agent-skills的思路是把这些"项目常识"拆成一个个可复用、可组合、可版本管理的技能单元。

说白了,agent-skills是一套面向 AI 编程代理的技能封装规范 + CLI 工具链。它让你把"怎么在这个仓库里干活"这件事,从口头约定变成可执行的资产。你写一个 skill,它就能被 Claude Code、Cursor、各类支持 skills 协议的 agent 读取和调用。适合谁来参考?三类人:一是天天用 Claude Code 写业务代码、被重复指令烦到不行的开发者;二是团队里负责搭工程规范、想让 AI 输出更稳定的 Tech Lead;三是想把自己的一套工作流沉淀下来、跨项目复用的独立开发者。

我自己的使用场景很典型:手上有五六个仓库,技术栈各不相同,有的是 Next.js + pnpm,有的是 Python + uv,还有几个是纯脚本工具。以前每次切项目都要重新给 AI 交代一遍上下文,现在每个仓库根目录放一个.skills/目录,agent 一进来就知道该干嘛。这篇文章我会把agent-skills的设计思路、核心机制、实操流程、踩坑经验全部拆开讲,尽量做到你照着做就能跑起来。

2. agent-skills 的整体设计与核心思路拆解

2.1 为什么是"技能"而不是"提示词"

很多人第一反应是:我直接写一个超长的 system prompt 不就行了?我试过,结论是不行,至少不好维护。原因有三个。

第一,上下文预算有限。你把所有规则塞进一个 prompt,agent 每次调用都要吃掉大量 token,真正干活的空间被压缩。而 skills 是按需加载的——agent 判断当前任务需要哪个技能,才去读那个技能的内容。这就像你不会把整本员工手册背下来,而是需要报销的时候去翻报销那一章。

第二,复用性差。提示词是绑在会话上的,换个项目就失效。skills 是文件,可以放进 git,可以跨仓库复制,可以做成模板。我现在的做法是把通用技能(比如"写测试的规范""提交信息格式")抽成一个私有仓库,新项目直接 submodule 引进来。

第三,可测试、可迭代。提示词改了就改了,你没法验证它是不是真的生效。skills 因为是一个个独立文件,你可以针对性地改一个、测一个。这一点在test-driven-development这类技能上体现得特别明显——TDD 的流程是有明确步骤的,写成 skill 之后,agent 每次都会按"先写失败测试→再写实现→再重构"的顺序走,而不是随机发挥。

2.2 目录结构与技能发现机制

agent-skills的核心约定其实很朴素:在项目里放一个约定好的目录,里面每个子目录或文件就是一个技能。常见的布局是这样:

.skills/ ├── test-driven-development/ │ ├── SKILL.md │ └── examples/ ├── commit-convention/ │ └── SKILL.md └── project-setup/ └── SKILL.md

每个SKILL.md里包含技能的元信息(名称、描述、触发条件)和具体内容(步骤、规则、示例)。agent 启动时会扫描这个目录,把技能的名称和描述加载进上下文(这部分很轻量),当它判断当前任务匹配某个技能时,再去读完整的SKILL.md。

这个设计的关键在于描述要写得准。描述写得太宽泛,agent 会到处乱触发;写得太窄,该用的时候又用不上。我的经验是描述里要包含"什么时候用"和"解决什么问题"两句话,比如:

当需要为新功能编写代码时使用。本技能强制先写测试再写实现,确保每一步都有验证。

2.3 与 Claude Code 等 agent 的协作方式

agent-skills本身不是一个 agent,它是给 agent 用的素材库。以 Claude Code 为例,它读取项目上下文时会把 skills 目录纳入扫描范围,然后在对话中根据任务动态引用。这里有个容易误解的点:skills 不是自动执行的脚本,而是给模型看的结构化指令。它影响的是模型的决策,不是直接跑代码。

所以你会看到两种技能:一种是流程型(比如 TDD 的步骤),一种是知识型(比如"这个项目的 API 约定")。前者约束 agent 的行为顺序,后者补充 agent 的背景知识。两者配合,才能让 agent 真正像一个熟悉项目的同事,而不是一个每次都要重新培训的实习生。

2.4 方案选型:为什么不用 MCP 或纯脚本

有人会问,MCP(Model Context Protocol)不是也能给 agent 提供能力吗?区别在于定位。MCP 更多是连接外部工具和数据源,比如让 agent 查数据库、调 API。而 skills 是内化的知识和流程,它不需要外部服务,就是一堆 markdown。两者不冲突,我现在的项目里 MCP 负责"能做什么",skills 负责"该怎么做"。

至于纯脚本方案(比如写个 shell 脚本让 agent 调用),问题在于脚本是死的,agent 只能执行不能理解。skills 是活的,agent 可以读懂意图、根据上下文调整。举个具体例子:一个"部署"脚本只能按固定参数跑,而一个"部署"skill 可以告诉 agent"先检查测试是否通过,再确认版本号,最后执行部署命令",中间任何一步出问题它都能停下来问你。

3. 核心细节解析与实操要点

3.1 SKILL.md 的写法:结构比文采重要

一个能用的SKILL.md,我总结下来要包含四块:元信息、触发条件、执行步骤、示例。元信息用 YAML front matter 写,触发条件和步骤用正文写。下面是我实际在用的一个 TDD 技能模板:

--- name: test-driven-development description: 当需要实现新功能或修复 bug 时使用。强制先写失败测试,再写实现,最后重构。 --- ## 何时使用 - 新增任何业务逻辑 - 修复有明确复现步骤的 bug ## 执行步骤 1. 先写一个会失败的测试,运行确认它确实失败 2. 写最小实现让测试通过,不要提前优化 3. 运行全部测试,确认没有破坏其他功能 4. 在测试保护下重构,每次重构后重跑测试 ## 禁止事项 - 禁止先写实现再补测试 - 禁止一次写多个测试再一起实现

注意description那一行,它是 agent 决定要不要加载这个技能的唯一依据,所以必须写清楚触发场景。我踩过的坑是描述写成了"关于测试的技能",结果 agent 在写文档的时候也去加载它,纯属浪费上下文。

3.2 技能粒度:太粗和太细都是坑

粒度控制是这套东西里最考验经验的地方。我一开始把"前端开发规范"写成一个巨大的技能,结果 agent 加载之后被几千字淹没,反而不知道该关注什么。后来拆成"组件命名""状态管理""样式约定"三个独立技能,效果立刻好转。

反过来,拆得太细也不行。我曾经把"写 import 语句"都单独做成一个技能,结果 agent 每次写代码要加载七八个技能,上下文直接爆掉。我的经验法则是:一个技能对应一个完整的、可独立描述的"动作单元"。比如"写测试""提交代码""初始化项目"都是合适的粒度,"写 import"就不是。

3.3 触发条件的写法:用场景不用关键词

新手最容易犯的错是把触发条件写成关键词匹配,比如"当用户提到 test 时使用"。这样做的后果是 agent 变得机械,用户说"帮我验证一下这个函数"它就不触发了。正确的做法是描述场景:

  • 差的写法:当出现"测试"这个词时使用
  • 好的写法:当需要验证代码行为、新增功能、或修复 bug 时使用

场景描述让模型自己去判断语义,而不是做字符串匹配。这背后其实是利用了模型的语义理解能力,你给它一个清晰的意图边界,它就能在边界内做判断。

3.4 版本管理与团队协作

skills 一定要进 git,而且要像代码一样 review。我们团队现在的流程是:任何人改 skill 都要提 PR,说明改动的动机和预期效果。因为 skill 直接影响 agent 的输出质量,改错了会导致整个团队的 AI 辅助开发体验下降。

还有一个细节:skills 要跟着项目走,不要跟着人走。我见过有人把 skills 放在自己的 home 目录,结果换台机器就没了,同事也用不上。放在项目仓库里,clone 下来就能用,这才是正确姿势。对于跨项目通用的技能,我用 git submodule 或者 npm 包的方式分发,保证一处修改、处处生效。

4. 实操过程与核心环节实现

4.1 从零搭建一个 skills 目录

假设你有一个现有的项目,想接入agent-skills。第一步是在项目根目录建目录:

mkdir -p .skills

然后创建第一个技能。我建议从最痛的那个点开始,通常是"项目怎么跑起来"。新建.skills/project-setup/SKILL.md:

--- name: project-setup description: 当需要安装依赖、启动开发服务器、或运行构建时使用。 --- ## 环境要求 - Node.js >= 20 - 包管理器使用 pnpm,禁止使用 npm 或 yarn ## 常用命令 - 安装依赖:pnpm install - 启动开发:pnpm dev - 运行测试:pnpm test - 构建:pnpm build ## 注意事项 - 首次安装后需要复制 .env.example 为 .env - 数据库迁移用 pnpm db:migrate

写完这个,你在 Claude Code 里问"这个项目怎么跑",它就会去读这个技能,然后给出准确的命令,而不是瞎猜。

4.2 用 skills CLI 管理技能

agent-skills配套的 CLI 主要做三件事:初始化、校验、列出。初始化就是生成目录骨架:

npx agent-skills init

校验是检查所有SKILL.md的 front matter 是否合法:

npx agent-skills validate

这个命令我强烈建议加进 CI。因为 front matter 写错(比如少了description)会导致技能静默失效,agent 不报错,只是不加载,你根本发现不了。加进 CI 之后,PR 阶段就能拦住。

列出命令用来查看当前项目有哪些技能:

npx agent-skills list

输出大概是:

技能名触发场景文件路径
project-setup安装依赖、启动服务.skills/project-setup/SKILL.md
test-driven-development新增功能、修复 bug.skills/tdd/SKILL.md
commit-convention提交代码.skills/commit/SKILL.md

4.3 在 Claude Code 中验证技能生效

搭好之后怎么确认 agent 真的在用?我的方法是故意问一个只有技能里才有答案的问题。比如技能里写了"包管理器用 pnpm",我就问"这个项目用什么装依赖",如果它答 pnpm 而不是 npm,说明技能加载成功。

如果没生效,排查顺序是:先看SKILL.md的 front matter 格式对不对(YAML 对缩进敏感),再看description是不是写得太模糊,最后看目录名有没有拼错。我遇到过最隐蔽的一个问题是文件编码带了 BOM,导致 front matter 解析失败,agent 直接忽略整个技能。用file命令一看就露馅了。

4.4 一个完整的 TDD 工作流实录

拿一个真实场景走一遍。我要给一个工具函数加参数校验,先确保.skills/tdd/SKILL.md存在。然后在 Claude Code 里说:"给 parseConfig 函数加上参数校验,非法输入要抛错。"

agent 加载 TDD 技能后,行为是这样的:

  1. 先写测试文件parseConfig.test.ts,包含非法输入的用例
  2. 运行pnpm test,确认新测试失败(红)
  3. 修改parseConfig.ts,加校验逻辑
  4. 再跑测试,确认通过(绿)
  5. 检查是否有重复代码,做小重构
  6. 重跑全部测试

整个过程我没有额外提醒它"先写测试",因为技能已经约束了流程。这就是 skills 的价值——把规范从"需要人盯"变成"自动执行"。

4.5 参数与配置的取舍

skills 本身没有复杂参数,但有几个配置项值得说。一是加载策略:是全部预加载还是按需加载。默认是按需,但如果某个技能特别常用(比如 project-setup),可以在 agent 配置里设成常驻。二是优先级:当多个技能冲突时(比如两个技能都规定了提交格式),需要指定优先级。我的做法是在技能名里加前缀,比如00-project-setup、10-commit,用命名约定解决冲突。

三是技能的作用域。有些技能只对特定文件类型生效,比如"React 组件规范"只该在写.tsx时触发。这个可以在description里写清楚,比如"当编辑 .tsx 文件时使用"。

5. 常见问题与排查技巧实录

5.1 技能不生效的排查清单

这是被问得最多的问题。我整理了一张速查表:

现象可能原因排查方法
agent 完全无视技能目录名不对确认是.skills不是skills
技能偶尔生效description 太模糊改成明确的场景描述
front matter 报错YAML 缩进或 BOM用file查编码,用在线 YAML 校验
技能冲突多个技能规则矛盾加命名前缀定优先级
上下文爆炸技能太大或太多拆分技能,精简内容

5.2 描述写得太宽泛导致的误触发

我踩过最典型的一个坑:写了个"代码质量"技能,描述是"当需要改进代码时使用"。结果 agent 在几乎每个任务里都加载它,因为"改进代码"这个描述太宽了。后来改成"当需要重构已有代码、消除重复、或优化性能时使用",误触发率立刻降下来。

判断描述是否合适的标准很简单:你能不能举出一个"不该触发"的反例。如果举不出来,说明描述太宽。

5.3 技能内容过长导致上下文被挤占

一个技能写超过 2000 字,基本就该拆了。因为 agent 加载技能是要占 token 的,技能越长,留给实际任务的空间越小。我的做法是技能正文只放"必须知道"的,细节放到examples/子目录里,agent 需要时再读。这样主文件保持精简,细节又不丢失。

5.4 团队协作中的技能冲突

多人维护 skills 时,最容易出现的是规则打架。比如 A 写的技能说"提交信息用中文",B 写的说"用英文"。解决办法有两个:一是建立技能命名规范,按领域划分前缀;二是定期 review,把冲突的规则合并到一个技能里。我们团队现在每月做一次 skills 清理,删掉过时的、合并重复的,保持目录干净。

5.5 与 test-driven-development 结合的实战心得

TDD 技能是我用得最顺的一个,但一开始也翻过车。问题出在测试粒度上——agent 有时候会写一个巨大的测试覆盖所有情况,然后一次性实现,这就违背了 TDD 的小步快跑原则。后来我在技能里加了一条硬性规定:"每个测试用例只验证一个行为,实现后立即运行。" 加上这条之后,agent 的行为就规范多了。

还有一个心得:TDD 技能要和项目的测试命令绑定。如果技能里只说"运行测试"而不说具体命令,agent 可能猜错。所以我在技能里明确写了pnpm test,并且注明"不要用 watch 模式,用单次运行"。这些细节看起来琐碎,但正是它们决定了技能好不好用。

6. 技能库的扩展与长期维护

6.1 从单项目到跨项目的技能沉淀

当你在一个项目里攒了五六个好用的技能之后,自然会想复用到其他项目。我的做法是建一个私有技能仓库,把通用技能放进去,各项目通过 submodule 引用。这样一处修改,所有项目同步更新。

但要注意通用技能和项目技能的边界。像"提交信息格式""TDD 流程"这种是通用的,而"这个项目的 API 约定""数据库表结构"是项目专属的。混在一起会导致通用仓库越来越臃肿。我的划分标准是:换个项目还能用的,就是通用技能。

6.2 技能的效果评估与迭代

技能写完不是终点,要持续观察效果。我的评估方法是记录agent 需要人工纠正的次数。如果一个技能上线后,相关任务的纠正次数明显下降,说明它有效;如果没变化甚至上升,说明技能写得有问题,要么描述不准,要么步骤不合理。

迭代的时候要小步改,一次只改一个点,改完观察几天。因为技能的影响是间接的,一次改太多你根本分不清是哪个改动起了作用。

6.3 面向未来的技能设计思路

AI coding agents 的能力在快速演进,技能的设计思路也要跟着变。我现在的判断是:越具体的技能越容易被模型内化,越通用的技能越容易被模型自己学会。所以未来技能的价值会更多体现在"项目专属知识"上,而不是"通用编程规范"。换句话说,与其教 agent 怎么写测试,不如告诉它"这个项目的测试文件放在哪、用什么框架、有哪些约定"。

这个判断也影响了我现在的技能布局:通用规范类技能尽量精简,把篇幅留给项目特有的上下文。毕竟模型本身越来越聪明,它缺的不是通用知识,而是你这个项目的具体情况。

最后分享一个我最近在用的技巧:给技能加"反例"。在SKILL.md里专门写一段"不要这样做",比只写"要这样做"效果好得多。因为模型对边界的理解往往比对规则的理解更准,你告诉它哪里不能碰,它反而更清楚该往哪走。这个技巧在 TDD 技能上尤其明显,加了"禁止先写实现"之后,agent 的违规率几乎降到零。

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

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

立即咨询