先说结论:这套叫 AI-Infra-Auto-Driven-SKILLS 的工作流,本质上不是给你塞十几个花哨提示词,而是把 Codex、Claude Code 这类 AI 编码代理从"你说一句它做一步"的被动状态,掰成"按固定推理框架自主拆解、执行、验证、留痕"的主动状态。v0.1.5 是我自己迭代到第五轮的版本号,里面沉淀的是技能包的组织方式、推理协议的编排规则,以及接入两个代理时的踩坑记录。
如果你正在用 AI 写代码、做 Code Review、重构老项目,但总觉得"模型聪明但不听话,答得对但做不全",那这套框架就是冲这个问题去的。下面我把设计思路、技能文件怎么写、怎么接进 Codex 和 Claude Code、以及我踩过的坑,一次说清楚。
1. 为什么需要一套"推理框架工作流"
1.1 裸用 AI 编码代理的三个痛点
先说我最早裸用 Codex 和 Claude Code 的感受。单论单次问答,这俩都很强,复杂逻辑能给你拆得明明白白。但一旦把任务放大到"改完一个模块、跑通测试、再提交 PR",问题就冒出来了。
第一个痛点是步骤漂移。你让代理"重构这个函数",它可能直接开写,不读调用方;也可能读了一堆无关文件,改完才发现破坏了对外的接口。不是模型笨,是它缺少一个"先想后做、做完校验"的强制流程。
第二个痛点是每次对话都是"失忆"状态。同一个仓库,今天问它"这个模块怎么优化",它给一套方案;明天再问,它可能给出完全不同的另一套。没有可复用的技能缓存,等于每次都在让一个聪明但没记性的实习生从头开始摸索。
第三个痛点是产物不可校验。人写代码有自测,AI 写完代码往往直接说"完成了",但它没有跑测试、没有过 lint、没有看 diff 是否符合预期。你作为人类还得重新审一遍,省下的时间又吐回去一部分。
1.2 从"一次性提示词"到"可复用技能"
当时我的第一反应是写更长的提示词。试了几天发现没用——提示词越长,模型越容易在后半段走样,而且同样的内容换个任务就没法复用。
后来我换了个思路:把"提示词"升级成"技能包"。技能包不是一段话,而是一个包含元信息、执行步骤、输出格式、校验规则的结构化文件。模型按需加载某个技能包,就像工人拿到一张标准作业卡:上面写明什么时候用、按什么顺序做、做到什么程度算完。
这背后其实是把"人怎么带新人"的经验搬给模型。你带一个新人不会只说"帮我把代码审一遍",你会给他一张检查清单:先看什么、重点查什么、结论按什么格式写。技能包干的就是这件事。
1.3 这套框架解决了什么
AI-Infra-Auto-Driven-SKILLS 把上面三个痛点对应拆成三个机制:
- 用推理协议约束步骤顺序,解决步骤漂移;
- 用可复用的 SKILL.md 库沉淀经验,解决失忆问题;
- 用强制校验和产物回填保证输出可验收,解决"做完但没做好"。
名字里的 Auto-Driven 不是营销词,而是指技能包的自动触发机制:模型先看任务描述,再匹配技能包里的 when 条件,命中后自动进入该技能的推理流程。你不需要每次手动粘贴提示词,只需要把技能包放进指定目录并要求模型"遇到对应场景必须加载",剩下的由它自己驱动。
2. 整体设计:三层结构与运行机制
2.1 技能定义层:SKILL.md 就是最小单元
这套框架的最小单位是一个技能包。每个技能包是一个目录,里面必须有一个 SKILL.md 主文件,可选的还有 examples/、scripts/、references/ 三个子目录。
SKILL.md 的开头是 YAML Frontmatter,相当于技能的身份证。我常用的字段包括 name(技能名)、description(一段话说明这个技能干什么)、when(什么场景必须触发)、version(版本号)。这些字段不是摆设——description 和 when 是模型判断"要不要加载这个技能"的依据,写得不精确,模型就会在错的时候用、该用的时候不用。
examples 目录放案例,比如一个技能包"code-review",里面可以放一份"好的审查报告示例"和一份"差的审查报告示例"。scripts 目录放可执行脚本,比如自动跑 diff、自动统计变更行数的 shell 脚本。references 放详细规则文档,只在技能主文件说要读时才被加载。
为什么要拆目录而不全塞进 SKILL.md?因为上下文窗口是稀缺资源。模型只要读技能主文件就能开工,细节按需再翻 references,这样每次消耗的 token 是固定的、可控的。
2.2 推理编排层:Plan-Execute-Verify 循环
技能定义层解决"做什么",推理编排层解决"按什么顺序做"。我在框架里内置了一个五步推理协议,所有技能都必须遵守:
- RESTATE先用自己的话复述任务目标和验收标准,不超过三行。这一步看着多余,实际上能逼模型对齐意图,避免自嗨式执行。
- DECOMPOSE把任务拆成子步骤,预估每步产物。比如重构任务拆成"定位调用点、改写核心逻辑、跑测试、更新注释"。
- EXECUTE按拆解顺序逐步执行。每步执行前要声明"我要做什么、读哪个文件、产出什么"。
- VERIFY对照第一步的验收标准逐项检查。没通过就回到第 3 步重新执行,并说明原因。
- RECORD把执行过程、关键决策、已验证的结果写回会话记录或日志文件,供下次复用。
这五步不是口号,我在每个 SKILL.md 里都用代码块把这五步写死,并要求模型"严格按此协议执行,不得跳步"。实测下来,加了这层后,代理的完成率有明显提升,尤其是重构和排查类任务,很少再出现"改完全套测试都没跑就宣布完成"的情况。
2.3 执行与反馈层:产物校验和上下文回填
第三层管的是"收尾"。很多任务失败不是执行时失败,而是收尾时没人把关。所以我在框架里定了一条硬规则:任何技能执行完毕,必须产出三类东西——变更摘要、验证结果、遗留风险。
变更摘要控制在 100 字以内,说明改了哪几个文件、为什么改;验证结果要写明跑了什么测试、结果如何,不许写"应该没问题"这种话;遗留风险是列出当前改动可能影响但没覆盖到的点。
这套要求看着死板,实际价值很大。它把 AI 的输出从"一段话"变成了"一份可归档的记录",你扫一眼就能判断这活儿干得靠不靠谱。同时,RECORD 步骤会把每次执行的关键信息回填到项目目录下的 .ai-infra/state 文件里,下次同一个技能被触发时,模型能读到上次的执行状态,相当于给了它一份短期记忆。
3. 核心细节:技能文件怎么写才不容易翻车
3.1 SKILL.md 的骨架与 Frontmatter
写技能文件最容易犯的错是"把 SKILL.md 写成提示词"。两者的区别在于:提示词是解释给模型听的,技能文件是约束模型执行的。所以技能文件里的每一个指令都应该是"必须做什么、禁止做什么、做到什么程度算完",而不是"你可以考虑""建议"这类模糊表述。
我自己的 SKILL.md 骨架长这样:
--- name: bug-hunt description: 根据报错信息/日志定位根因并给出修复建议 when: 出现异常堆栈、测试失败、线上报错,或用户明确说"帮我排查这个 bug" version: 1.3.0 max_tokens: 8000 --- # Bug 排查技能 ## 执行协议 1. RESTATE:复述 bug 现象与影响范围,附上复现步骤或无复现步骤的说明 2. DECOMPOSE:列出可能的根因假设,按概率排序 3. EXECUTE:逐条验证假设,每验证一条必须给出证据(日志行、代码片段、测试结果) 4. VERIFY:确认根因后,给出修复方案和验证方式 5. RECORD:记录根因、修复点、验证命令 ## 禁止事项 - 禁止在未读取实际日志/报错的前提下猜测根因 - 禁止只给修复建议而不给验证命令 - 禁止在无 P0 证据时同时修改多个文件 ## 输出格式 - 根因结论(一句话) - 证据链(必须带具体行号/文件名) - 修复方案(按优先级排列) - 验证命令(可直接复制执行)注意 Frontmatter 里有个 max_tokens 字段,这是我用来限制单个技能执行预算的。推理框架最怕的是模型在一个技能里无限循环,设一个 token 上限,超了就强制让模型总结中间结果并退出,由人来决定是否继续。这个字段不是标准配置,但我强烈建议加上。
3.2 推理步骤的颗粒度
另一个关键问题是步骤拆多细。拆太粗,模型还是会自由发挥;拆太细,光读步骤就消耗大量上下文,而且模型容易机械执行、失去判断。
我的经验是:步骤数量控制在 3 到 7 步之间;每一步必须是"有明确输入、有明确输出动作"的,不能是"思考一下""分析一下"这种虚词。比如"EXECUTE:先读取 config.json 中的应用名,再根据日志中的 traceId 过滤对应时段请求"就是合格的步骤描述,因为模型知道要读什么文件、处理什么数据、产出什么结果。
判断颗粒度是否合适的标准很简单:如果把每一步截图给你团队里的初级工程师看,TA 能不能不用补充说明就照着执行。能,说明颗粒度合适;不能,说明还要拆细。
3.3 版本 v0.1.5 迭代了什么
版本号这块我说下 v0.1.5 相对前几版的变化,也能帮你看清框架的演进方向。
v0.1.1 是第一版,只有三个技能包(code-review、refactor、test-writer)和一个五步推理协议的说明书,当时还是纯文本约定,模型经常不遵守。
v0.1.2 加上了 Frontmatter 的 when 字段,技能触发率肉眼可见地上来了。这版也第一次验证了"技能是目录不是单文件"的价值。
v0.1.3 引入了禁止事项块。起因是我发现 refactor 技能经常"顺便"改一堆无关代码,加了 explicit 的 RED_LINE 列表之后,这类问题少了很多。
v0.1.4 做了上下文压缩优化,把 references 目录独立出去,主文件控制在 5KB 以内。
v0.1.5 就是当前版本,核心改动是把 RECORD 步骤规范化,增加了 .ai-infra/state 状态文件,让技能之间有状态衔接。这版开始,你可以串起两个技能,比如"先 bug-hunt 定位根因,再 refactor 修复重构",中间的状态传递不需要你手动复制。
4. 实操:把这套技能库接进 Codex / Claude Code
4.1 目录布局建议
接入的第一步是定目录布局。我目前用的是这样的结构:
ai-infra-skill/ ├── SKILLS.md # 技能索引,相当于目录总览 ├── protocol.md # 五步推理协议的完整说明 ├── skills/ │ ├── code-review/ │ │ ├── SKILL.md │ │ ├── examples/good-report.md │ │ └── examples/bad-report.md │ ├── bug-hunt/ │ │ ├── SKILL.md │ │ └── scripts/extract-logs.sh │ └── refactor/ │ ├── SKILL.md │ └── references/scope-rules.md └── state/ └── .ai-infra-state.jsonSKILLS.md 是给模型看的索引文件,里面用表格列出所有技能包、各自的 when 条件、以及一句话说明。这样模型收到任务时,只需要先读这个 2KB 左右的索引,就能快速判断该加载哪个技能,不用逐个打开每个 SKILL.md 去猜。
4.2 接入 Codex 和 Claude Code 的两种方式
两种工具对"全局指令"的加载方式不太一样,但思路一致:把协议文件和技能索引挂到它们的全局配置里,让每次会话启动时自动读入。
Claude Code 这边,依赖 CLAUDE.md 这个约定文件。我在全局 CLAUDE.md 里写了这么一段:
# 全局工作协议 你必须在收到任务后执行以下判断: 1. 读取 ai-infra-skill/SKILLS.md 索引 2. 若任务匹配某个技能的 when 条件,加载对应 SKILL.md 并严格按其执行协议执行 3. 任何情况下,执行顺序必须遵守 protocol.md 中的五步推理协议 4. 执行结束必须输出变更摘要、验证结果、遗留风险Codex 这边则是用自定义指令文件,方式类似,指向同一个目录。关键是别把 SKILL.md 全文塞进全局配置,全局配置只放索引和协议引用,具体技能按需加载。这一个设计决定,能让你的日常会话 token 消耗稳定在一个合理水平。
目录本身放哪都行,只要路径写进全局配置。但如果你的项目里有多个仓库,我建议做一个全局的 ai-infra-skill 目录,而不是每个仓库各放一份,否则版本同步会变成噩梦。
4.3 第一个技能的完整演示
我拿 v0.1.5 里面最常用的 code-review 技能举个例子,方便你照着落地。
触发场景是你要让代理审查一个变更。正常情况下你需要写一大段"请帮我看看这几个文件的 diff,重点检查……",但接好技能库之后,你只需要说一句"review 一下当前分支的改动"。
代理会先读 SKILLS.md,命中 code-review 的 when 条件,加载技能包,然后按协议执行:
1. RESTATE:复述当前分支相对 main 的改动范围 2. DECOMPOSE:列出要审的文件清单,预估变更量 3. EXECUTE: - 读取 git diff --stat 获取变更概览 - 逐文件读取 diff 与上下文 - 按正确性、可维护性、性能、安全四类维度记录问题 4. VERIFY:核对每个问题是否有证据(行号、调用链) 5. RECORD:将审查结论写入 state 文件,标记为待处理最后输出的审查报告里,每个问题都带优先级和证据,P0 是必须堵住的,P1 建议修复,P2 可选项。这套流程跑下来,比裸用代理时稳定得多,基本不用你再追问"这个风险你看了吗"。
5. 常见问题与排查实录
5.1 技能加载了但模型不按步骤走
这是我在 v0.1.1 时期遇到最多的问题,现象是模型明明读了 SKILL.md,但一到执行环节就自由发挥,把步骤顺序打乱。
排查后发现问题出在两个地方。一是 SKILL.md 里用了太多"可以""建议"这类弱约束词,模型默认把它当成参考而非命令。二是全局配置里只写了"请阅读技能"而没有写"必须严格按其协议执行",模型的理解是"读一下就行"。
解决方式是把全文的弱约束词全部替换成"必须""禁止",同时在全局配置里增加一条硬约束:"若技能文件与模型自身习惯冲突,必须优先遵守技能文件。"改完这两个点之后,执行顺序的遵从率明显提升。
5.2 推理链过浅或过深
推理链过浅的表现是模型跳步,比如 bug-hunt 技能里没看日志就猜根因。推理链过深的表现是模型在一个子步骤上反复尝试,甚至在没有新信息的情况下重复读取相同文件。
我针对浅的问题,在技能里加了"禁止在未读取实际日志/报错的前提下猜测根因"这类硬约束;针对深的问题,加上了前面提到的 max_tokens 预算,并且定义了一个"证据充分即停止"标准:当某个假设已有两条以上独立证据支持、且没有反证时,不得继续验证其他假设。
5.3 上下文被技能描述挤爆
接触这套框架的人常有的顾虑是"技能文件会不会吃太多上下文"。实际跑下来,只要保证主文件不超过 5KB、按需加载 references 子目录,上下文开销是可控的。真正容易爆的情况是模型把技能里的长命令输出、大段示例日志也当成了必须读取的内容。
我在 references 目录里加了一条约定:任何 reference 文件开头必须用一行说明"什么场景才需要读我"。同时,技能主文件里的示例只保留结构示意,不放大段真实日志。这样即使模型误读引用,成本也是有限而不是灾难级的。
| 问题 | 现象 | 排查方向 | 解决方式 |
|---|---|---|---|
| 技能不生效 | 模型忽略 SKILL.md | 全局配置是否引用、when 是否匹配 | 强化全局约束、精简单一 when 条件 |
| 执行顺序错乱 | 步骤跳变、先斩后奏 | SKILL.md 弱约束词过多 | 换为"必须/禁止",声明优先级 |
| 推理过浅 | 跳过证据直接下结论 | 缺少禁止项 | 补充 RED_LINE 列表 |
| 推理过深 | 重复读文件、死循环 | 无执行预算 | 设 max_tokens 并定义停止条件 |
| 上下文膨胀 | token 消耗异常高 | 引用了大文件 | 主文件限 5KB,引用按需加载 |
| 结果不可归档 | 输出无法复用 | 缺 RECORD 步骤 | 强制 state 文件回填 |
6. 我在维护这套框架时的一些体会
从 v0.1.1 到 v0.1.5,最大的感受是:给 AI 编码代理做框架,本质是在做"约束设计",不是在做"功能设计"。模型的能力已经够用,真正决定产出质量的是你给它划的那条跑道——在什么情况下必须用什么流程、做到什么程度算完、哪些动作绝对不许做。每一条约束都对应一次踩坑,删掉任何一条都有可能回归到"模型自由发挥"的失控状态。
另一个体会是,技能库的价值会随时间复利。第一周你可能觉得写技能比直接敲提示词还慢,但当你积累了十几个技能包之后,你会发现大部分重复性工作都能一句话触发标准流程,而且每次执行的结果都是可对比、可追溯的。这个"越用越省力"的拐点,大概在技能数量超过十个时出现。
目前 v0.1.5 的下一步,我在考虑给技能之间加一层依赖声明,让一个技能能显式调用另一个技能并传递上下文,而不是像现在这样靠 state 文件做弱衔接。如果你也在折腾 Codex 或 Claude Code 的技能化工作流,建议直接从 v0.1.5 的目录结构开始,别从零写协议——用现成的框架先跑通一轮,再按自己的项目习惯去改,会比闭门造车快很多。