
1. 从“agent-skills”说起为什么我们需要给AI编码代理装上一套技能系统第一次看到agent-skills这个项目名的时候我脑子里蹦出来的不是某个具体工具而是一个很朴素的问题我们天天在说 AI coding agents说 Claude Code、说各种 CLI 代理可这些代理真正干活的时候靠的到底是什么是模型本身够聪明吗显然不是。模型再强如果没有一套结构化的“技能”去约束它、引导它、给它提供可复用的操作范式它就是一个知识渊博但手脚笨拙的实习生。agent-skills这个项目本质上就是在解决这个问题。它是一套面向 AI 编码代理的技能定义与组织方案配套一个 skills CLI让开发者能够把“怎么让代理做某件事”这件事本身变成可管理、可复用、可版本控制的资产。你可以把它理解成给 AI 代理写的“操作手册 工具箱 测试用例”三合一。我接触这个方向是因为在实际项目里反复遇到同一个痛点每次让代理去完成一个稍微复杂点的任务比如“给这个模块补一套测试”“按 TDD 流程重构这段逻辑”“把这份配置迁移到新格式”我都得在对话里重新解释一遍流程、重新强调一遍约束、重新纠正一遍它跑偏的地方。这种重复劳动极其消耗精力而且每次结果还不稳定。agent-skills这类方案出现的意义就是把这些“重复解释”沉淀下来变成代理可以直接加载和执行的技能单元。这篇文章适合几类人看一是已经在用 Claude Code 或者类似 AI coding agent 做日常开发的工程师想把自己的使用方式从“聊天式”升级到“工程化”二是对 skills CLI 这类工具好奇想知道它到底解决什么问题、值不值得投入时间三是团队里负责制定 AI 辅助开发规范的人需要一套可落地的思路来统一大家的代理使用方式。不管你之前有没有写过所谓的“提示词工程”只要你会写代码、会用命令行这篇内容都能给你一套可以直接抄作业的路径。2. agent-skills 的整体设计思路把代理能力拆成可组合的技能单元2.1 核心问题代理的“能力”为什么难以沉淀先说清楚一个背景。现在主流的 AI coding agent不管是 Claude Code 还是其他 CLI 形态的工具它们的交互模式基本都是“你给指令它执行你反馈它调整”。这个模式在单次任务里没问题但一旦任务重复出现问题就暴露了。我举个自己的例子。有一段时间我频繁需要给不同的 Python 模块补 pytest 测试每次我都会在对话里写类似这样的话“请用 pytest 写测试遵循 AAA 模式每个测试函数只测一个行为mock 外部依赖覆盖率尽量到 80% 以上。” 前几次还行到第十次的时候我就烦了——不是烦写这句话而是烦每次都要写而且代理有时候会漏掉其中某条约束导致我还得回头纠正。这就是“能力无法沉淀”的典型表现。代理的能力是临时的、会话级的关掉窗口就没了。你没法像管理代码一样管理它没法 review 它的变更没法在团队里共享更没法给它写测试。agent-skills的设计出发点就是把这个“临时能力”变成“持久资产”。它的核心抽象是 skill一个 skill 就是一段结构化的描述告诉代理在什么场景下、按照什么步骤、遵守什么约束、产出什么结果。这个描述不是随便写的自然语言而是有约定格式的可以被 CLI 解析、校验、加载。2.2 为什么选择“技能”这个抽象层级这里有个设计上的取舍值得说。你完全可以把代理的引导做得更粗比如直接写一个巨大的系统提示词把所有规则都塞进去也可以做得更细比如给每个函数级别的操作都定义一个模板。agent-skills选择“技能”这个中间层级我认为是有道理的。太粗的话提示词会膨胀到难以维护而且不同任务之间的约束会互相干扰。太细的话管理成本会高到没人愿意用你不可能为每个小操作都写一个 skill。技能这个层级刚好对应“一类可复用的任务模式”比如“写测试”“做代码审查”“迁移配置”“生成文档”。它足够具体能承载有意义的约束又足够通用能在多个项目里复用。从工程角度看这个层级还有一个好处它可以被测试。你可以给一个 skill 定义输入和预期输出然后验证代理加载这个 skill 之后的行为是否符合预期。这就把 AI 代理的使用从“玄学调参”拉回到了“可验证工程”的范畴。test-driven-development 这个热搜词出现在相关列表里我觉得不是偶然——skills 和 TDD 的结合是这个方向最有价值的实践之一。2.3 skills CLI 在整条链路里的位置skills CLI 是这个方案的操作入口。它的职责大概包括几块初始化技能目录结构、校验技能定义是否符合规范、把技能加载到代理的上下文里、以及管理技能的版本和依赖。我自己的理解是CLI 的存在让这套东西从“概念”变成了“工作流”。没有 CLI 的话你得手动把技能文件放到某个位置手动告诉代理去读手动处理格式错误。有了 CLI这些步骤就标准化了。你可以像用 git 管理代码一样用 CLI 管理你的技能库。这里要提醒一点不同工具对技能加载方式的支持程度不一样。Claude Code 有自己的配置机制其他代理可能走不同的路径。agent-skills这类项目的价值在于它试图提供一个相对通用的技能描述格式让同一套技能能在不同代理之间迁移。当然实际迁移时还是会有适配工作这个后面会细说。3. 核心细节解析一个 skill 到底由哪些部分组成3.1 技能元数据名称、触发条件与适用范围一个 skill 的第一部分是元数据。这部分决定了代理“什么时候该用这个技能”。我见过不少人写 skill 的时候忽略这块结果就是代理要么不用要么乱用。元数据里最关键的是触发条件。你不能只写一个名字叫“写测试”然后指望代理知道什么时候该调用它。你需要描述清楚当用户请求涉及“为现有代码补充测试”“验证某个函数的行为”“重构后确保测试通过”这类意图时加载这个技能。触发条件写得越具体代理的匹配就越准。适用范围也很重要。有些技能是语言相关的比如专门针对 Python 的测试技能就不应该被用在 JavaScript 项目上。你需要在元数据里标注清楚语言、框架、项目类型等约束。这样代理在加载技能前可以先做一次过滤避免用错工具。我自己的经验是元数据里的描述要写成“给代理看的”而不是“给人看的”。什么意思就是你要用代理能理解的方式表达条件而不是用人类习惯的模糊表述。比如“当代码变更涉及数据库迁移时”就比“当需要处理数据库相关的事情时”要好得多因为前者有明确的判断依据。3.2 执行步骤把“怎么做”拆成可跟随的序列技能的主体是执行步骤。这部分是真正干活的地方也是最容易写砸的地方。写步骤的核心原则是每一步都要有明确的动作和明确的产出。我见过一些技能定义步骤写得很笼统比如“分析代码结构然后生成测试”。这种写法对代理来说等于没写因为它不知道“分析”具体要做什么“生成”要遵循什么格式。好的步骤应该像这样第一步读取目标文件识别所有公开函数和类方法列出清单第二步对每个函数分析其输入参数类型和返回值类型判断需要 mock 的外部依赖第三步按照 AAA 模式为每个函数生成至少一个正常路径测试和一个边界测试第四步运行测试并检查覆盖率报告如果覆盖率低于阈值则补充测试。你看这样的步骤代理是可以逐步执行的而且每一步都有可验证的产出。这就是“可跟随”的含义。这里有个细节步骤之间要有依赖关系的说明。有些步骤可以并行有些必须串行。如果你不说明代理可能会用错误的顺序执行导致结果不对。比如“先运行测试再生成测试”显然是错的但如果你不写清楚顺序代理未必能自己推断出来。3.3 约束与禁忌告诉代理“不要做什么”约束这部分我觉得是区分一个技能好不好用的关键。大多数人写技能的时候只写“要做什么”忽略了“不要做什么”。但实际使用中代理跑偏往往不是因为没做该做的而是因为做了不该做的。举个真实的例子。我写过一个代码审查的技能本意是让代理检查代码风格和潜在 bug。结果有一次它自作主张地把它认为“不好”的代码直接改了而且改错了。从那以后我就在技能里加了一条硬约束只报告问题不修改代码除非用户明确要求修改。约束要写得具体、可判断。像“不要做危险操作”这种就是废话代理不知道什么算危险。你要写成“不要执行任何删除文件、修改数据库、推送代码到远程仓库的操作”。这样代理才能准确遵守。禁忌部分还要考虑边界情况。比如一个技能在正常输入下工作良好但遇到空文件、超大文件、编码异常的文件时会怎样这些都需要在技能定义里说明处理方式否则代理可能会崩溃或者产生奇怪的行为。3.4 产出格式让结果可预期、可校验产出格式这块很多人觉得不重要反正代理生成什么就用什么。但如果你要把技能用在团队协作或者自动化流程里产出格式就必须固定下来。我自己的做法是对每个技能都定义清楚产出的结构。比如测试技能产出应该包括测试文件路径、测试函数列表、覆盖率数值、未覆盖的分支说明。这些信息用固定的格式组织方便后续处理。产出格式的另一个作用是便于校验。你可以写一个简单的脚本检查代理的产出是否符合预期格式。如果不符合说明技能执行出了问题可以及时干预。这就把技能的使用纳入了可观测的范畴。4. 实操过程从零搭建一套可用的技能库4.1 环境准备与 skills CLI 的获取动手之前先把环境理清楚。我假设你已经在用某个 AI coding agent并且它支持加载外部技能定义。如果不支持那这套东西的价值会打折扣你可能需要先解决代理的接入问题。skills CLI 的获取方式通常是通过包管理器或者直接从项目仓库拉取。我建议先看项目的官方文档确认它支持的代理类型和版本要求。不同版本的 CLI 对技能格式的支持可能有差异用错版本会导致校验失败。安装完成后先跑一下 CLI 的帮助命令看看它提供哪些子命令。一般来说会有 init、validate、load、list 这几类。init 用来初始化技能目录validate 用来校验技能定义load 用来把技能加载到代理list 用来查看当前可用的技能。提示在正式使用前先用一个最简单的技能做一次完整的 init-validate-load 流程确认工具链是通的。不要一上来就写复杂技能否则出问题的时候你分不清是工具问题还是技能定义问题。4.2 初始化技能目录结构跑 init 命令之后你会得到一个标准的技能目录。这个目录的结构通常长这样根目录下有一个配置文件然后是 skills 子目录每个技能一个文件夹文件夹里放技能定义文件。我建议在初始化之后先不要急着改结构。按照工具约定的结构来能省掉很多麻烦。如果你有特殊需求比如想把技能按语言分类可以在 skills 目录下再建子目录但要确认 CLI 支持递归查找。目录命名上用短横线连接的小写英文比如python-testing、code-review、config-migration。不要用中文或者空格避免在不同系统上出现兼容问题。4.3 编写第一个技能以测试驱动开发为例我拿 test-driven-development 这个场景来演示因为它是热搜词里出现的也是实际价值最高的技能之一。先建一个目录叫tdd-workflow。然后在里面创建技能定义文件。文件内容大致分几块元数据、触发条件、执行步骤、约束、产出格式。元数据部分名称写tdd-workflow描述写“按照测试驱动开发流程先写失败测试再写实现最后重构”。触发条件写“当用户要求以 TDD 方式开发新功能或要求先写测试再写实现时”。执行步骤我一般写五步。第一步理解需求把功能拆成可测试的行为单元列出清单。第二步为第一个行为单元写一个失败的测试运行确认它失败。第三步写最少的实现代码让测试通过不要过度设计。第四步运行全部测试确认没有破坏已有功能。第五步重构代码保持测试通过然后回到第二步处理下一个行为单元。约束部分写三条。第一不要跳过失败测试这一步必须先看到测试失败再写实现。第二每次只处理一个行为单元不要一次性写多个测试。第三重构阶段不要改变外部行为只调整内部结构。产出格式写清楚每个行为单元对应一个测试函数测试函数命名遵循test_行为_条件_预期的格式最后给出测试通过的报告。写完这个技能定义后跑 validate 命令校验。如果有格式错误CLI 会告诉你哪里不对。改到通过为止。4.4 把技能加载到代理并验证效果校验通过后用 load 命令把技能加载到代理。加载方式取决于你的代理类型。有些代理是启动时读取技能目录有些是运行时动态加载。你需要确认加载是否成功通常 CLI 会给出反馈。加载成功后做一次实际验证。找一个小的功能需求让代理用这个技能来完成。观察它的行为是否符合技能定义有没有先写失败测试有没有控制每次只处理一个行为单元有没有在重构后重新运行测试。如果代理的行为不符合预期先检查技能定义是不是有歧义。很多时候问题出在步骤描述不够具体代理理解偏了。把描述改得更明确重新加载再试。注意不要指望一次就写出完美的技能。技能定义是需要迭代的就像代码一样。每次使用后记录下代理跑偏的地方然后针对性地补充约束或细化步骤。5. 常见问题与排查技巧实录5.1 技能不生效或代理忽略技能这是最常见的问题。表现是代理完全没有按照技能定义的行为执行就像没加载一样。排查思路分几步。先确认技能是否真的加载成功了用 list 命令查看当前可用技能列表。如果列表里没有你的技能说明加载环节出了问题检查目录路径和文件格式。如果列表里有但代理不用检查触发条件是不是写得太窄或太模糊。太窄的话代理匹配不上太模糊的话代理可能匹配到别的技能去了。我一般会把触发条件写得稍微宽一点然后在执行步骤里做具体的场景判断。还有一种可能是代理的上下文窗口被其他内容占满了导致技能定义被挤出去了。这种情况在长对话里容易出现。解决办法是开新会话或者把技能定义精简一下。5.2 技能执行到一半跑偏有时候代理开始是照着技能做的做到一半就偏离了。这通常是因为某个步骤的描述有歧义或者步骤之间的依赖关系没写清楚。我的排查方法是把代理的实际执行过程逐步对照技能定义找到第一个偏离的步骤。然后看那个步骤的描述问自己如果我是代理我会怎么理解这句话往往问题就出在某个词有多个解释。解决办法是把那个步骤拆成更小的步骤或者补充具体的判断依据。比如“分析代码”改成“读取文件内容识别所有函数定义输出函数名和参数列表”。5.3 不同代理之间的技能迁移问题如果你想把同一套技能用在不同的代理上会遇到格式和加载机制的差异。有些代理支持的技能字段多一些有些少一些。有些代理的技能加载是静态的有些是动态的。我的建议是把技能定义写成相对通用的格式把代理特定的配置抽出来单独管理。这样迁移的时候只需要改配置部分技能主体不用动。另外不同代理对同一个技能的理解可能有差异。迁移后一定要重新验证不要假设行为一致。5.4 技能库的版本管理与团队协作当技能多起来之后版本管理就成了问题。我建议把技能库当成代码库来管理用 git 做版本控制。每次修改技能都提交写清楚改了什么、为什么改。团队协作方面可以约定一个技能 review 流程。新技能或者技能的重大修改需要至少一个人 review 后才能合并。review 的重点是触发条件是否准确、步骤是否可跟随、约束是否完整。还可以给技能写测试。虽然不能像测试代码那样自动化但可以记录下典型场景下的预期行为作为回归验证的依据。问题类型典型表现排查方向解决手段技能不生效代理完全忽略技能加载状态、触发条件检查 list 输出放宽触发条件执行跑偏中途偏离技能定义步骤描述歧义拆分步骤补充判断依据迁移失败换代理后行为异常格式差异、加载机制抽离代理特定配置重新验证版本混乱不知道哪个版本在用缺乏版本管理用 git 管理建立 review 流程6. 技能设计中的经验与避坑要点6.1 从最小可用技能开始不要追求大而全我一开始犯的错是想写一个“万能开发技能”把所有可能的开发场景都覆盖进去。结果就是技能定义长得离谱代理加载后反而不知道该关注什么执行效果很差。后来我改成每个技能只解决一类问题而且从最小的场景开始。比如先写一个只处理“给单个函数补测试”的技能跑通之后再扩展到“给整个模块补测试”。这样迭代速度快问题也容易定位。技能之间可以组合。一个复杂的任务可以由多个小技能串联完成。这比写一个大技能要灵活得多也更容易维护。6.2 约束要写成“可判断”的不要写成“感觉”前面提过约束的重要性这里再强调一下写法。“代码要写得优雅”这种约束是没用的因为代理没法判断什么算优雅。“函数长度不超过 50 行”就是可判断的代理可以数行数。可判断的约束还有一个好处就是你可以写脚本自动检查。如果代理的产出违反了约束脚本能发现你就能及时纠正。这就把技能的质量控制部分自动化了。6.3 给技能写“反例”帮助代理理解边界除了写“应该怎么做”我还会在技能里写一些“不应该怎么做”的例子。比如在测试技能里写“不要写这样的测试def test_all(): assert True这种测试没有验证任何行为。”反例对代理来说是很强的信号。它比单纯的规则描述更能让代理理解边界在哪里。我实测下来加了反例的技能代理跑偏的概率明显降低。6.4 定期回顾和清理技能库技能库用久了会积累一些不再需要的技能或者有些技能已经被更好的版本替代了。我建议每隔一段时间做一次清理把废弃的技能归档或者删除。清理的时候顺便检查一下现有技能是否还符合当前的项目规范。项目在演进技能也要跟着更新。一个过时的技能比没有技能更糟糕因为它会引导代理做出不符合当前规范的行为。6.5 把技能和实际项目结构对齐技能定义里的路径、命名、格式最好和实际项目的结构保持一致。比如你的项目测试文件都放在tests/目录下测试文件命名是test_*.py那技能里就应该写清楚这些约定。这样做的好处是代理生成的产出可以直接融入项目不需要额外调整。如果技能里的约定和项目实际不一致代理生成的东西你还得手动改就失去了自动化的意义。7. 技能库的扩展方向与个人实践体会7.1 从单点技能到技能流水线当你有了一批基础技能之后可以考虑把它们串成流水线。比如“需求分析 → 写测试 → 写实现 → 代码审查 → 生成文档”这样一条链。每个环节对应一个技能代理按顺序执行。流水线的好处是整个开发流程都被结构化了每一步都有明确的产出和约束。你可以清楚地看到哪个环节出了问题然后针对性地优化那个技能。实现流水线的方式可以是在技能定义里声明前置和后置技能也可以用一个编排脚本来控制执行顺序。具体选哪种取决于你的代理支持什么机制。7.2 技能与项目规范的联动技能库不应该孤立存在它应该和项目的编码规范、测试规范、文档规范联动。比如项目规定所有公开函数必须有 docstring那测试技能和文档技能里就应该包含检查 docstring 的步骤。联动的方式可以是把项目规范文件作为技能的输入让代理在加载技能时同时读取规范。这样规范更新了技能的行为也会跟着更新不需要改技能定义。7.3 我个人在实际操作中的体会用了这套东西一段时间后我最大的感受是AI 代理的使用方式正在从“对话”转向“配置”。以前我们花时间想怎么把话说清楚现在我们花时间想怎么把技能定义写清楚。这个转变的本质是把一次性的沟通成本转化为可复用的资产。另一个体会是技能定义的质量直接决定了代理的上限。一个写得好的技能能让普通模型表现出色一个写得差的技能再强的模型也发挥不出来。所以在这上面投入时间是值得的。最后分享一个小技巧每次代理执行技能后不管结果好坏都花一分钟记录一下它的表现。好的地方记下来作为正面例子不好的地方也记下来作为改进依据。积累一段时间后你会发现技能定义越来越精准代理的表现也越来越稳定。这个记录习惯是我觉得投入产出比最高的一件事。