做AI编码代理相关工作的朋友最近应该都在琢磨同一件事怎么让代理不是“偶尔超神、经常智障”而是稳定地把活干完。我自己的体会是换更大参数的模型只是其中一条路真正拉开差距的往往是你怎么组织代理可复用的经验。这也是 Skills 工程的核心思路——把一次性的正确操作沉淀成可长期调用的行为模板让编码代理在碰到同类任务时不是重新“猜”而是直接照着成熟流程走。这套方法论最早是被一位知名 AI 研究者带火的我看着圈子里讨论了大半年自己也在几个真实项目里跑了几轮今天把能直接落地的部分整理出来。1. 为什么行为优化比换个“更聪明的模型”优先级更高1.1 一次“看似正常”的翻车现场先说个真实场景。某开发者在做一个模拟项目X一个跨平台桌面待办应用后端接了个简单的 REST API。之前代理帮他写第一版接口时统一错误格式用的是{code, message, data}三字段结构代码里也写了注释。过了一个月要加“批量删除待办”功能代理拿到需求后完全没有沿用之前的错误约定而是自己定义了一套{error: {type, detail}}的新格式。前端同学一接直接崩了。问题出在哪不是模型能力不够也不是上下文太短。代理当时已经读到相关代码文件了但它没有形成一个“遇到接口改动就必须遵守统一错误格式”的行为习惯。它只是凭概率在生成代码看到哈希里可能存在的注释并不会自动把它当作强约束。换句话说代理缺的不是知识是“行为规范”。1.2 编码代理的“经验断层”问题大部分编码代理本质上还是“每轮对话独立工作”的。虽然有上下文窗口但上下文不等于长期记忆。你调过一次的封装方式、踩过的坑、团队约定的命名规则如果不显式写下来下一次代理启动时它对这些内容一无所知。这就带来两个很讨厌的现象一是“越改越乱”每次生成的结果风格不一致代码库变成一个多风格拼接现场二是“同样的错反复踩”上次明明因为某个坑重写了接口这周换个会话它又踩一遍。你让代理写单点功能它表现很好你让它在一套既有体系里接着干活它就经常暴露经验断层。1.3 skills 的本质给代理一本可复用的“操作手册”Skills 工程的核心就是把“应该怎么干活”从模型的隐式概率里抽出来变成一组显式的、可维护的操作手册。每遇到一类典型任务就沉淀一条 skill里面写清楚什么时候用、按什么顺序做、做到什么程度算完成、哪些动作绝对不能做。类比一下你带新人不会只丢给他一个 IDE 让他自由发挥你会给 SOP、给代码规范、给他一个“上次大家怎么解决这个问题的记录”。Skills 就是给编码代理配的这套东西。它不是提示词工程那种“临时哄模型”而是一份能被反复加载、持续迭代的工程资产。2. 搭一套可落地的 Skills 工程骨架2.1 目录结构与命名规范Skills 工程的第一步不是写 skill而是先把仓库结构定下来。我建议把 skills 目录放在项目仓库的根目录和代码目录平级这样代理在扫描项目结构的时候一定能看到它。推荐一个通用的目录骨架skills/ ├── index.md ├── frontend/ │ ├── react-hooks-best-practice/ │ │ ├── SKILL.md │ │ └── examples/ │ │ └── demo.jsx │ └── api-error-format/ │ └── SKILL.md └── backend/ ├── rest-api-error-handling/ │ └── SKILL.md └── database-migration-check/ └── SKILL.md命名规范我踩过不少坑这里直接给出我现在的约定目录名用小写短横线命名法格式是“动词对象场景”比如rest-api-error-handling一眼就能看出来这个 skill 是干嘛的。不要用utils这种泛目录也不要在一个 skill 文件里塞十几个场景一条 skill 只解决一类任务这是铁律。2.2 一条 Skill 的标准模板SKILL.md 用 Markdown 写但要在开头放一段 YAML 格式的元信息方便索引和自动加载。我目前用的模板长这样--- name: rest-api-error-handling description: 新增或修改 REST 接口时统一错误响应格式与错误码 when_to_use: 任务涉及创建/修改后端 REST 接口且请求或响应结构发生变化 version: 1.3.0 last_reviewed: 2025-03-14 --- ## 背景 本项目的 REST API 统一使用 {code, message, data} 作为错误响应结构。 不要在业务代码里各自发明错误格式。 ## 核心步骤 1. 阅读现有 controller 层代码确认已有统一错误处理中间件。 2. 新接口的失败分支必须返回 ErrorResponse结构如下 java { code: PARAM_INVALID, message: 待办ID不能为空, data: null }所有业务异常先映射为业务错误码禁止直接抛 500。更新对应接口的 OpenAPI 文档。验证清单[ ] 新接口的错误响应结构与旧接口一致[ ] 没有新增自定义异常类绕过统一包装[ ] 文档已同步[ ] 走一遍前端调用确认前端能正常解析禁止事项不要在 controller 里手写 try-catch 拼 JSON不要出现{error: ...}之类的临时结构为什么要有 YAML 头因为你要让代理在加载时快速判断“这条 skill 是否适用于当前任务”。when_to_use 是触发条件version 和 last_reviewed 是维护信号。正文里的“禁止事项”很多人会忽略但它对行为约束特别重要代理在看到明确禁令之后自由发挥的概率会显著下降。 ### 2.3 把 Skills 真正“接进”代理的工作流 目录建好了文件也写了问题来了代理怎么知道要用它 我见过不少团队skills 目录建了半年代理一次都没读过——因为没有加载机制。我的做法是在代理的全局配置里加一条系统级指令大意是 text 项目根目录的 skills/index.md 是团队行为规范索引。开始任务前 必须检查索引判断当前任务是否命中某条 skill 的 when_to_use。 如果命中先完整读取对应 SKILL.md再开始编码。如果是用支持自定义工具的文件型代理还可以让代理自动做目录遍历把skills/*/SKILL.md的元信息在启动时加载进上下文。以支持函数调用的代理为例我会写一个轻量的读取脚本让代理在任务开始时先调用它而不是靠“记得去看看”。这一步是整套体系的地基没有加载机制的 skills 文件只是摆设。3. 写出高可用 Skill触发、步骤、验证三件套3.1 触发条件要能被“判断题”式命中写when_to_use最忌讳的是写得太抽象。比如你写“当需要处理接口问题时”代理看了等于没看正确写法是“当需要创建或修改后端 REST 接口且请求或响应结构发生变化”。这样代理在执行时能用一道判断题来决定是否加载。我自己的检查方法是把描述念给团队里另一个开发听看他能不能在 10 秒内判断出“这个 skill 适不适用于当前任务”。如果不能就继续收窄。触发条件写得越像“规则匹配”行为越稳定。触发条件里还可以加上“排除项”比如“前端 mock 接口不算”避免代理在不该用的时候乱加载。3.2 步骤必须能复现而不是“此处应有优化”很多 skill 文件里写的是“优化接口性能”“完善错误处理”这种正确但没用的话。代理读到之后仍然不知道具体该怎么做。Skill 的价值在于把隐性经验显性化所以每一步都要写到“另一个新人照着做能做出来”的程度。举个例子不用写套话“检查代码质量”而要写成“检查所有公共方法是否补了表单校验注解缺失的补上在本地执行npm test确保测试覆盖新增分支”。步骤中的关键参数、类名、库名、甚至路径都尽量写死。这里有个平衡点要把握好步骤太细场景一变就废了步骤太粗代理又无从下手。我的建议是“骨架写死细节留档”核心流程严格可复现但具体技术选型上留一两个合规选项。3.3 验证清单与退出条件防止代理自由发挥代理最危险的行为是“做完”之后自信心爆棚明明只跑通了 happy path就说全部完成。验证清单就是为了堵这个口子。清单里每一项都要是可执行的检查动作而不是“确保没问题”这种模糊表述。还要加一条“退出条件”比如当前任务涉及的范围之外的问题只记录不改动避免代理顺手重构了别人的代码。没有退出条件的代理很容易在修 bug 的时候把整个文件风格都改掉看起来工作量很大实际上给 review 制造了巨大负担。退出条件是你对代理行为边界的一种声明它和触发条件一样重要。4. 从单条 Skill 到体系化迭代4.1 索引文件与版本管理当 skills 多起来之后管理成本开始出现。不能每个工程都自己乱写需要index.md做总览。我的一张典型索引表是这样的Skill 名称适用场景版本最后维护日期负责人rest-api-error-handling新增/修改 REST 接口1.3.02025-03-14某开发者Adatabase-migration-check任何数据库结构变更0.9.02025-02-28某开发者Bfrontend-component-review前端组件提交前自查1.0.12025-03-01某开发者C代理启动时可以只读索引表来做粗筛命中后再读对应 SKILL.md。这能显著减少上下文占用。索引表本身不要放在项目根我习惯把它放在skills/index.md让代理用同一个扫描路径找到全部信息。4.2 用两个指标判断行为是否真的变好接手 Skills 工程之后最怕的是“写了很多 skill但行为没变化”。我自己会盯两个指标一个是“命中率”也就是代理实际调用 skill 的次数除以应该命中的任务数另一个是“返工率”也就是 review 时被打回修改的比例。命中率长期很低说明加载机制有问题代理根本没意识到 skill 的存在。返工率高说明 skill 的内容和实际场景脱节或者步骤写得不够约束力。我一般按周统计连续两周没问题再考虑加大范围。没有指标就迭代容易变成自我感动。4.3 常见问题速查与排查思路这套方法落地过程中问题集中在下面几类我整理成了一张速查表现象可能原因排查方向代理从不读取 skill加载指令没写进系统级配置检查全局指令是否包含“启动先读 index.md”读取了但行为没变化触发条件写得太宽代理无法匹配收窄when_to_use增加排除项按 skill 做了但还是错步骤里技术栈和项目实际不一致拿最近一次失败案例去反向校正步骤多个 skill 互相打架职责边界不清、重复覆盖做一次去重同一场景只保留最具体的一条步骤太死换个场景就失效参数细节写得太绝对把“必须写死”的部分和“可选项”分开列代理在清单外自由发挥缺少退出条件在模板末尾明确“任务范围外只记录不改动”这里的排查思路核心就是“看命中的链路”索引有没有读到触发条件有没有匹配步骤有没有执行验证有没有卡住。链路里任何一个环节断了行为都不会变好。4.4 我踩过的几个坑第一个坑是贪多。一开始我一次性写了二十几条 skill结果一半没人用。后面改成“从痛点出发”团队最近两个星期反复被哪类问题困扰就先写哪一条一个月沉淀三到五条就够。第二个坑是追求“完美文档”。skill 写得像周报背景写了三大段真正的操作步骤只有一行。后来我给自己立了个规矩写完一条 skill找团队另一个人按步骤走一遍走不通就改。这一步能筛掉绝大多数不可执行的废话。第三个坑是没人维护。skill 里的技术栈升级了没人更新代理照着旧步骤干活反而出错。现在我把last_reviewed字段当成硬指标超过两个月没动过的 skill 直接标记“待复核”避免它变成负资产。我个人现在最舒服的用法是新项目开工前先花半天沉淀三条核心 skill——项目规范、接口风格、提交检查。之后所有代理任务都往这三条上面挂。等代码库风格稳定了再逐步补充场景化 skill。这个节奏不激进但效果很实在代理生成代码的一致性肉眼可见地变好了。