ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI编程代理技能驱动工作流:v0.1.5框架实战解析

AI编程代理技能驱动工作流:v0.1.5框架实战解析

最近半年我一直在折腾一个叫"AI-Infra-Auto-Driven-SKILLS"的框架项目,目前迭代到 v0.1.5。老读者可能记得我吐槽过 Codex 和 Claude Code 这类终端 AI 编程代理"脑子不够使"的问题——不是模型笨,而是每次任务进来都像没头苍蝇,要么跳过规划直接写代码,要么无视项目已有的约定。v0.1.5 就是冲着这个痛点去的:它是一套面向 Codex / Claude Code 的技能库加推理工作流,负责把"这个任务该按什么步骤想、该调用哪份技能文档、做完怎么验证"这件事固定下来。如果你也在用 AI 写代码,或者正在搭团队级的 Agent 工作流,这篇内容可以直接当配置参考。

本文会把这套框架的动机、目录结构、推理启动链路、双工具接入差异、实测踩坑全部摊开讲,包括我踩过的上下文膨胀、双 Agent 行为不一致这类问题。下面按我实际迭代的顺序来写。

1. 先说动机:为什么我需要一套"技能驱动"的工作流

1.1 裸奔的 Codex / Claude Code 有多不靠谱

先说个场景。某次我给 Claude Code 丢了一个"给登录模块加个验证码"的需求,它上来就改了三个文件,等我 review 的时候发现:验证码生成逻辑写在了前端组件里、后端接口没加限流、错误提示文案和现有风格完全不一致。代码能跑,但质量一言难尽。

这不是模型能力的问题,是工作方式的问题。默认状态下,这类代理会把"回应对话"当作第一目标,而不是"把项目当回事"。它不会先去看你项目的架构文档,不会主动遵守你代码仓库里的 lint 规则,更不会在改完代码后跑一遍测试再向你汇报。你把所有约束写进 system prompt?那上下文会被撑爆,而且每次对话都要为这些常识付费。

我试过在 CLAUDE.md 里写十几条规矩,试过在 Codex 的 AGENTS.md 里堆注意事项,效果都一般。原因很简单:约束如果不和任务类型绑定,就是一堆噪音。改个 CSS 的任务不需要加载安全评审规则,重构核心模块的任务又必须走完整推理链路。一刀切的约束,要么太松要么太紧。

1.2 "技能驱动"到底是什么思路

v0.1.5 的核心思路其实就一句话:把项目知识和推理步骤拆成一个个小技能包,按任务类型按需加载,而不是一次性全塞给 Agent。

打个比方。默认的 Agent 像一个刚入职的实习生,你给他一份两百页的公司制度手册,他翻了两页就厌了,遇到实际问题还是按自己习惯来。而技能驱动的做法是:给每个岗位配一张"遇到 X 情况就打开 Y 手册"的索引卡,遇到问题先查索引卡,再读对应手册的那几页。

具体到 v0.1.5,它做三件事:

  • 技能仓库:把项目经验、编码规范、领域知识拆成独立的 Markdown + 规则文件,每个技能包只解决一类问题;
  • 推理框架:定义一套标准的任务处理流程,比如"澄清需求 → 拆解任务 → 设计方案 → 执行变更 → 自测验证 → 复盘总结",Agent 拿到新任务先走框架而不是自由发挥;
  • 自动驱动层:根据任务描述、当前目录、git 变更等信息,自动决定加载哪些技能、按什么顺序执行哪些推理阶段。

v0.1.5 是第 15 个小版本,覆盖的技能包从最早的 8 个涨到了 32 个,推理模板从 3 套变成了 6 套。下面我直接把当前版本的内部结构翻出来给你看。

2. 目录级拆解:一套技能包是怎么组织的

2.1 skills 仓库的物理布局

先看整体目录结构。v0.1.5 不再像早期版本那样把所有技能平铺在根目录,而是按推理阶段分成了六个子目录:

ai-infra-auto-driven-skills/ ├── router/ │ └── task-router.yaml # 任务分类路由规则 ├── skills/ │ ├── analyze/ # 需求澄清、影响面分析 │ │ ├── requirement-clarify/ │ │ └── impact-analysis/ │ ├── plan/ # 技术方案、任务拆解 │ │ ├── tech-design/ │ │ └── todo-breakdown/ │ ├── implement/ # 编码规范、模块实现 │ │ ├── coding-style/ │ │ ├── api-standards/ │ │ └── error-handling/ │ ├── verify/ # 自测、lint、测试补充 │ │ ├── self-test-checklist/ │ │ └── lint-verify/ │ └── reflect/ # 变更总结、commit 规范 │ └── review-summary/ ├── templates/ # 推理阶段提示词模板 │ ├── stage-analyze.md │ ├── stage-plan.md │ ├── stage-implement.md │ ├── stage-verify.md │ └── stage-reflect.md ├── scripts/ │ ├── skill-detect.sh # 环境探测脚本 │ └── context-build.py # 生成 Agent 上下文包 └── versions/ └── v0.1.5.changelog.md

这个布局的用意很直接:按推理阶段分目录,Agent 在某个阶段只需要读对应目录下的技能。比如进入 verify 阶段时,它只会加载verify/下面的自测检查单和 lint 规则,不会把 implement 阶段的编码风格又读一遍。

2.2 每个技能包里的三样东西

早期版本每个技能就是一份 Markdown,结果发现文件一多就没法维护。v0.1.5 里每个技能包固定包含三件套:

skill-name/ ├── SKILL.md # 给 Agent 看的操作手册 ├── rules.yaml # 给驱动层看的加载规则 └── examples/ # 正反示例(可选)

SKILL.md是核心,但有个硬性要求:前 100 个字必须说清楚"这个技能解决什么问题、什么时候不用它"。为什么?因为 Agent 是靠语义匹配决定是否加载技能的,开头写不清楚,匹配阶段就容易把不相关的技能拉进来。

rules.yaml是写给程序看的,定义了触发条件。拿 api-standards 技能举个例子:

name: api-standards version: "2.3.0" triggers: - reg: "(add|modify|create|update).*(api|endpoint|route|interface)" - dir: "server/controllers" - dir: "server/routes" conditional: - if: "frontend_code_changed && backend_api_changed" use: ["api-contract-check"] priority: 70

这段规则的意思是:当任务描述里出现"新增/修改接口"这类关键词,或者改动范围落在 controllers / routes 目录,就触发 api-standards 技能。priority用于多个技能同时匹配时决定加载顺序。

2.3 版本与兼容性:v0.1.5 的更新思路

为什么单独搞一个versions/目录?因为这半年我吃够了"技能和项目不同步"的苦头。

技能包和代码仓库是两套生命周期的产物。代码仓库在快速迭代,技能里的编码规范如果三个月不更新,Agent 就会按过时的规矩干活,产出直接被团队打回。v0.1.5 的做法是:

  • 每个技能包独立维护版本号,SKILL.md有修改就 bump 一版;
  • 顶层项目保持统一的 v0.1.x 版本,代表整个框架的对外 API 稳定程度;
  • 每个版本发布时,changelog里必须记录"哪个技能改了、为什么改、对 Agent 行为有什么影响"。

这样做的直接好处是,团队升级 v0.1.5 时能提前知道行为变化,不至于出现"昨天 Agent 还会写单测,今天突然不写了"这种灵异事件。

3. 推理框架的启动链路:从任务进来开始

3.1 第一步:任务分类与技能匹配(路由)

Agent 拿到一个新任务时,第一件事不是写代码,而是跑路由。v0.1.5 里路由由两部分协作完成:router/task-router.yaml负责粗分类,scripts/context-build.py负责按分类结果组装上下文。

路由规则长这样:

categories: - name: bugfix patterns: - "fix|repair|broken|crash|bug" stages: ["analyze", "plan", "implement", "verify", "reflect"] load_skills: ["impact-analysis", "coding-style", "self-test-checklist"] - name: feature patterns: - "add|implement|support|new feature" stages: ["analyze", "plan", "implement", "verify", "reflect"] load_skills: ["requirement-clarify", "tech-design", "api-standards", "self-test-checklist"] - name: refactor patterns: - "refactor|restructure|clean up|rename" stages: ["analyze", "plan", "implement", "verify", "reflect"] load_skills: ["impact-analysis", "coding-style", "lint-verify"] - name: docs patterns: - "documentation|readme|comment|doc" stages: ["plan", "implement"] load_skills: ["docs-style"]

注意bugfix和feature的差异:修复 Bug 不需要走完整的需求澄清,但要加载影响面分析——因为你得先判断这个 Bug 会不会波及别的地方。文档任务则不需要 verify 阶段,它本来就不跑测试。

这一步的实际效果是,一个"修 Bug"的任务进来时,Agent 的上下文里只会有:任务路由规则、impact-analysis 技能、coding-style 技能、self-test-checklist 技能、以及对应的阶段模板。比裸奔时省掉的无关指令至少六成。

3.2 第二步:推理模板的上下文注入

路由决定"走哪些阶段"之后,context-build.py会把templates/下的阶段模板注入到 Agent 的初始上下文里。

每个阶段的模板都遵循同一个格式:目标 → 输入 → 操作步骤 → 产出物 → 验收标准。以stage-plan.md为例:

## 阶段:规划(PLAN) 目标:基于分析结果输出可执行的变更方案。 输入: - 上一阶段的分析结论 - 当前仓库结构 - 相关技能包内容 操作步骤: 1. 列出至少两个候选方案,对比优缺点。 2. 选择方案时遵循仓库既有约定,不要引入新模式。 3. 将任务拆成 5 到 15 个可独立验证的子任务。 4. 标注每个子任务的依赖关系。 产出物: - 一份包含子任务清单、变更文件列表、风险点的方案文档。 验收标准: - 每个子任务都能在 10 分钟内完成。 - 变更文件列表与后续实施阶段一致。 - 方案文档中不存在"待定""再说"类模糊词汇。

这里我最想强调的是验收标准这一格。早期模板只写步骤,结果 Agent 老老实实走完了流程,产出却是一堆没头没尾的半成品。后来在每步后面追加验收标准,情况立刻变了——Agent 会自己对照标准检查产出,不合格就返工,而不是交差完事。

3.3 第三步:结果验证与人工回环

推理链路到 reflect 阶段并没有结束,v0.1.5 还加了一个人工回环机制:Agent 完成变更后,必须生成一份"变更汇报",但汇报不是终点,而是触发人工 review 的起点。

变更汇报模板里包含:

- 改了什么:按文件列出变更点 - 为什么这么改:对应哪个推理阶段、哪个技能约束 - 如何验证:执行了哪些测试/lint,结果如何 - 遗留风险:哪些地方没把握,需要人来看

这套机制解决了一个实际问题:让 Agent 的推理过程可审计。以前它改完代码,你只能通过 diff 猜测它的思路;现在它必须把"为什么这么改"写出来,你 review 的时候一眼就能看出它有没有遵守技能规则,卡在哪个环节。

人工回环的粒度是可以调的。团队刚开始用的时候,可以要求每个任务都走完 review;运行两周后,如果 Bug 修复类任务的通过率高,就可以只抽查,把精力留给 feature 类任务。

4. 接入 Codex 与 Claude Code 的差异处理

4.1 Codex 的命令与技能加载方式

Codex 命令行工具对自定义指令的支持主要靠 AGENTS.md 和自定义命令。AGENTS.md 相当于项目级的长期记忆,Agent 启动时会自动读取。自定义命令则放在配置文件目录下,用户手动触发。

v0.1.5 给 Codex 做的接入方案是:把context-build.py生成的"技能上下文包"写到 AGENTS.md 对应位置,但做了分层处理。AGENTS.md 里只放索引和路由规则,技能全文通过层级引用按需加载。参考结构:

AGENTS.md ├── 项目通用信息(简短) ├── SKILLS 索引(每个技能一句话 + 触发条件) ├── 推理阶段约定(五阶段流程简述) └── 验证规则(测试与 lint 命令)

为什么不全量写进 AGENTS.md?因为 Codex 的上下文窗口虽然不小,但 AGENTS.md 被读入后一直占着位置。我实测过,把 32 个技能全文塞进去后,上下文里光技能说明就占了两万多 token,Agent 回复速度肉眼可见地变慢,而且容易在无关技能里"挑着看",等于回到了一刀切的老路。

4.2 Claude Code 的 Skills 目录与插件机制

Claude Code 的情况和 Codex 不太一样。它原生支持 Skills 目录机制,.claude/skills/下的每个技能包有自己的SKILL.md,Agent 可以根据任务自动选择是否加载某个技能。这比把全部指令塞进 CLAUDE.md 要优雅得多。

v0.1.5 对 Claude Code 的适配,核心是把上面那套rules.yaml翻译成 Claude Code 的 Skills 元信息格式。一个标准的技能包在.claude/skills/里长这样:

.claude/skills/ ├── api-standards/ │ ├── SKILL.md │ ├── metadata.yaml │ └── examples/ └── self-test-checklist/ ├── SKILL.md ├── metadata.yaml └── examples/

metadata.yaml里写了技能的描述和触发关键词,Claude Code 会依据这段描述来决定何时加载技能。描述里必须写清"什么情况下用"和"什么情况下别用",否则 Agent 容易在无关任务里也把技能拉出来。

4.3 一套技能,两份配置的做法

同时维护 Codex 和 Claude Code 两套配置,听起来维护成本翻倍,但 v0.1.5 的实际做法是:源头只有一份,其他全是生成的。

具体流程:

  1. 在skills/目录里用统一格式维护技能内容(SKILL.md + rules.yaml);
  2. 运行scripts/context-build.py --target codex生成 Codex 的 AGENTS.md;
  3. 运行scripts/context-build.py --target claude生成.claude/skills/下的技能包。

两份配置共享同一个内容源,rules.yaml里的触发条件在生成时分别映射到两种机制。Codex 侧映射成 AGENTS.md 里的关键词索引,Claude Code 侧映射成metadata.yaml里的 description。

生成脚本我放在 CI 里跑,每次技能内容有变更,自动重新生成两份配置并提交到仓库。这样团队里用 Codex 的和用 Claude Code 的同事,拿到的技能约束完全一致,不会出现"我用 Claude Code 改的接口格式和你用 Codex 改的对不上"的尴尬。

下表整理了 v0.1.5 在两种工具下的接入差异:

维度Codex 接入Claude Code 接入
配置载体AGENTS.md + 自定义命令.claude/skills/ 技能目录
技能加载按索引语义匹配按 metadata 语义匹配
阶段模板注入通过 AGENTS.md 索引引用通过 skills 目录轮询加载
验证钩子自定义命令触发技能内嵌 checklist
维护方式脚本生成脚本生成

5. 实测三个月沉淀下来的坑

5.1 上下文膨胀与技能文件太啰嗦

v0.1.5 早期版本最大的败笔是技能文件写得像论文。比如 coding-style 技能,我最初写了四千多字,涵盖了命名、缩进、注释、异常处理、数据库访问……应有尽有。结果 Agent 加载这个技能后,生成代码的风格确实符合规范,但整个对话的上下文被占掉一大截,后续修改时它反而"记不住"任务本身的需求了。

后来我把每个技能的 SKILL.md 压到 300 到 800 字,只保留规则 + 正反例 + 验收标准三块。缩进规则这种一句话能说清的绝不展开;异常处理规范直接配一个"好的写法/坏的写法"对照示例,示例比解释省 token 且效果好得多。

压完以后上下文占用降了约四成,任务完成质量反而提升了。这里有个反直觉的经验:技能文件的核心价值不是教会 Agent 怎么做,而是告诉它去哪查、查完怎么核对。细节留给人或者代码仓库里的既有模式去沉淀。

5.2 双 Agent 行为差异导致的"同一套技能两个结果"

这是最让我头疼的一个坑。同一套技能配置,Codex 和 Claude Code 跑出来的结果经常不一样。Codex 倾向于严格遵守 AGENTS.md 里的步骤清单,按部就班地走流程;Claude Code 则更"灵活",经常跳过非强制的步骤,直接跳到实现阶段。

发现这个问题的方式很偶然——团队里两个同事用不同工具改同一个模块,一个人交上来的代码带了详细的方案文档,另一个人只改了代码没写方案。一查才发现,Claude Code 把"输出方案文档"当成可选项跳过了。

解决办法是在技能规则里增加强制级别字段:

requirements: - id: plan-doc action: mandatory check: "存在 plan/ 目录下的方案文档" - id: lint-pass action: mandatory check: "lint 命令 exit code = 0" - id: commit-prefix action: recommended note: "提交信息建议按约定前缀"

生成阶段模板时,mandatory级别的条目会写到"验收标准"区块并明确标注"缺少此项视为任务未完成";recommended级别则写明"在条件允许时执行,未执行需在汇报中说明原因"。加了这个区分之后,双 Agent 的行为一致性明显提升。

5.3 更新策略:别让技能变成技术债

技能库最隐蔽的成本不是创建,而是维护。项目代码风格变了、依赖框架升级了、团队约定改了,任何一个变化都可能导致技能内容过时。v0.1.5 里我踩过的具体坑是:某个技能里写死了旧的 ORM 用法,结果 Agent 每次改数据库相关代码都按旧规范来,生成的代码直接编译不过。

现在我的维护策略有三条:

  • 每次技能使用后留反馈:Agent 完成一个任务后,在汇报里标注"本次使用了哪些技能、哪些规则对结果无帮助"。攒够反馈就删掉无用的规则;
  • 每周做一次技能审计:把技能内容里涉及 API 名、命令路径、目录结构的部分抽出来,和当前仓库实际情况比对,不一致的立即改;
  • 技能变更走 PR 流程:技能文件的修改不直接 push,要像改代码一样经过 review。因为技能变更会同时影响 Codex 和 Claude Code 两份配置,改错了等于让所有 Agent 同时犯错。

这三条执行下来,技能库从"越用越脏"变成了"越用越精准"。目前 v0.1.5 的 32 个技能里,大约每个月会调整五六个,但整体结构保持稳定。

6. 适合谁,不适合谁,以及下一步想做的事

先说结论:这套 v0.1.5 的推理框架工作流,最适合的是手里有一批模式固定、重复度高、修改频繁的代码任务的个人开发者或小团队。比如接口联调、Bug 修复、写测试、补文档这类任务,技能驱动能明显减少你反复交代同样要求的次数。你的项目约定越清晰,这套体系收益越大。

不适合的场景我也踩过:如果你主要用 Agent 做探索性的、一次性的研究任务,或者代码仓库本身没什么约定可循,技能库反而会变成束缚——Agent 花在匹配技能上的时间比实际干活还长,性价比很低。另外,如果团队里没人维护技能库,那就不如别上这种重方案,老老实实用 CLAUDE.md 写三条最硬的规矩更实际。

v0.1.5 下一步我打算做两件事:一是给context-build.py加一个"技能使用统计"输出,跑完任务能自动记录每个技能被加载次数和引用次数,帮我把没用的技能揪出来;二是支持按项目目录做技能版本锁定,让老项目继续用旧技能、新项目用新技能,别让一次升级波及全部历史仓库。

最后分享一个我自己的体会:做这套东西最难的永远是"克制"。我一开始什么规范都想塞进去,结果证明全是噪音。技能驱动真正的价值不是让 Agent 变聪明,而是让你把项目里那些"默认大家都知道"的知识显性化——写进技能包的那一刻,才是它们真正开始发挥作用的时候。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进