
如果你同时用 Codex 和 Claude Code 跑过真实项目八成会跟我有同样的感受同一个任务有时候一遍过有时候来来回回改上十几轮还是错的。一开始我也以为是模型脑子不够用直到我把大量时间花在“帮 Agent 擦屁股”上才反应过来——问题不在推理能力而在我们交给它的工作流实在太粗糙了。过去大半年我一直在折腾一套叫 AI-Infra-Auto-Driven-SKILLS 的技能库框架目的很直接把平时散落在文档里、聊天记录里、代码注释里的“项目经验”变成 Agent 可以自主读取、按条件触发、逐步执行的显式技能文件。目前迭代到了 v0.1.5配合 Codex 和 Claude Code 的上下文机制在跨文件重构、测试补全、回归检查这几类任务上效果比裸用模型稳定得多。这篇文章不打算讲什么宏大理论就聊聊这套推理框架工作流到底长什么样、我在 v0.1.5 这轮里改了什么、落地时会踩到哪些坑。1. 先说清楚这套技能框架解决的到底是什么问题1.1 两个 Agent 用久了之后最让人头疼的几种“犯蠢”先说几个我反复遇到的场景你看完肯定有共鸣。第一个场景是“重复造轮子”。项目里明明已经有一个写好的工具函数负责统一处理时间格式转换。结果某次我让 Agent 在一个新模块里加日志它非常自然地又写了一个几乎一模一样的函数只是参数名换了。问它为什么不用现成的它的回答是“未在上下文中检索到该项目已有该工具函数”。第二个场景是“改一处崩三处”。我给 Claude Code 一个重构任务要求把某个核心接口从同步改为异步。它一口气改了十几个文件然后信心满满地告诉我完成了。结果编译一跑五个调用方还在用旧签名。问题不是它不会改而是它改的时候没有系统性地把“所有受影响调用方”纳入检查范围完全靠上下文里残留的信息猜。第三个场景是“不遵守项目内既定约定”。某个仓库里有一套严格的错误处理规范要求所有外部调用必须用特定的包装类型返回错误。Agent 写新代码的时候总是按自己习惯来写得倒很整齐但跟项目风格完全不一致。事后我一条条跟它讲规范、让它重写返工成本高得离谱。这三个场景表面看是“模型不够聪明”但细究下来其实是一类问题模型对项目的理解是碎片化的、短期的它没有“项目经验”这种长程记忆。你指望它每次开对话都从代码里自动归纳出全部约定不现实。1.2 本质原因模型没有“项目经验”上下文窗口也没有记忆很多人对 Agent 有个误解以为它能像老员工一样“心里有数”。实际上每次新对话模型面对的都是一个什么都不懂的实习生。它确实读过整个代码库——准确地说是你喂给它的那部分——但它不会自动提炼出“这个项目的接口变更流程是什么”“约定的目录结构为什么这样设计”“哪些代码是不能碰的历史包袱”。就算你把整个项目都放进上下文也没用。上下文窗口是有极限的塞满之后模型反而会丢失对局部细节的注意力。而且项目约定这种东西往往散落在不同地方README 里一段、某个模块顶部注释里一段、某个历史 commit message 里一段。模型不会主动把这些信息拼成一个完整的规则系统。所以问题的真正解法不是给模型换更大的上下文而是给它一个“经验查询机制”让它知道在什么时候、去哪里、读取哪一条经验规则然后按规则执行。这就是技能层存在的意义。1.3 为什么叫 Auto-Driven 而不是手动 Prompt 模板市面上已经有很多人分享“神仙 Prompt”把一大段精心设计的指令放在系统提示词里。这种做法也能用但本质上是被动的Prompt 只能覆盖你预先想到的场景一旦任务超出预设它就失效了。而且提示词写多了会占掉大量上下文空间Agent 反而变得迟钝。Auto-Driven 的思路不一样。技能文件不是一条写死的指令而是一本“操作手册”。Agent 在接到任务时先根据任务描述里的信号比如“重构”“迁移”“替换”“跨文件”自己去匹配应该调用哪本手册然后按手册里写的步骤一步步执行。两者的区别类比一下就是手动 Prompt 像你每次都牵着实习生的手告诉他怎么做Auto-Driven 技能层像是你给实习生一个书架告诉他“遇到哪类问题就去翻哪本书”他自己读、自己判断、自己照着做。后者才能真正让 Agent 在复杂项目里跑起来。我在 v0.1.5 里做的事情本质上就是把这个“书架”搭得更合理让 Agent 更快找到正确的书、更少拿错书。2. 技能层的核心设计把隐性经验变成显式协议2.1 一份技能清单该写什么、不写什么很多人第一次搭技能库容易犯一个毛病什么都往里塞。我自己 v0.1.0 的时候就写了一大堆技能从“Go 语言最佳实践”到“数据库索引设计原则”结果 Agent 每次任务都要扫描一遍上下文直接爆掉。后来我总结出一条经验技能文件只写“在这个项目里该怎么做”不写“通用知识”。比如“Go 语言里 channel 怎么用”这种内容模型本来就会不需要你教但“本项目的错误处理必须走 errorx.Wrap 统一包装”“迁移数据库时必须在 migration 目录下提交双向 SQL”这类项目特有的约定才是值得写成技能的东西。技能清单应该包含四类信息触发场景什么类型的任务进入这个技能的处理范围。执行步骤处理此类任务时先做什么、再做什么、最后验证什么。判定标准做到什么程度算完成哪些信号代表当前操作有问题。回退方案执行失败时应该从哪里重新开始或者什么时候该停下来问人。不写的内容也重要。技能文件里不应该出现具体的业务逻辑实现——那是代码的事不是技能的职责。也不应该写一次性任务比如“帮我把这个 bug 修了”这种用完即弃的东西放技能库里只会增加噪声。2.2 触发条件与执行入口让 Agent 自己决定何时调用技能层最核心的机制是“自主触发”。Agent 需要根据当前任务判断该调用哪个技能而不是靠用户手动 /skill-name 去敲。为了让自主触发可靠每个技能文件的头部都有一段 frontmatter里面最关键的是 when_to_use 和 when_not_to_use 这两个字段。我在 v0.1.5 里把它们称为“触发评估表”——不光告诉 Agent 什么时候用还明确告诉它什么时候不要用。拿跨文件重构这个技能举例它的触发评估表长这样--- name: cross-file-refactor description: 跨文件重构成熟度检查。当需要修改多个文件的结构、迁移接口或替换调用链时使用。 when_to_use: - 任务描述出现“重构”“迁移”“替换”“大范围改动” - 涉及接口签名调整、文件结构调整、调用方批量更新 - 修改一个模块后预计会影响超过3个其他文件 when_not_to_use: - 仅修改单个文件内的局部逻辑 - 纯新增功能不涉及现有接口变动 - 只改文档和注释 priority: high ---这个设计的关键在于“不适用信号”。一开始我只有 when_to_use结果 Agent 会把所有沾点边的任务都套到这个技能上反而增加了不必要的步骤。加了 when_not_to_use 之后误触发率明显下降。另外description 字段要写成“搜索引擎摘要”的风格。Agent 在匹配技能时本质上是拿任务描述跟技能描述做语义匹配所以描述里要包含任务场景关键词而不是一段空泛的话。2.3 上下文激活区控制 Token 消耗的设计技能文件不能一股脑全读进上下文必须分级加载。否则技能库一壮大Agent 的开场思考里就全是技能内容正事还没干上下文先废了一半。我的方案是做一个三层的上下文激活区第一层是索引区通常放在项目根目录的 SKILLS.md 里。这个文件非常短只列每个技能的名称、一句话描述和文件路径。Agent 每次对话开始时读一遍索引知道“有这么些技能可用”。第二层是常驻区也就是全局规则文件Claude Code 里是 CLAUDE.mdCodex 里是 AGENTS.md。这里只写高层原则比如“进行任何跨文件修改前必须查找并更新所有调用方”“提交前必须跑完整测试”。这些原则不隶属于某个具体技能是贯穿所有任务的底线。第三层是按需加载区真正的技能文件。只有当 Agent 根据索引判断“当前任务属于这个技能的触发范围”时才会主动去读取完整的技能文件。这个读取是实时的、任务相关的不会长期占用上下文。这套三层设计很关键。你如果直接把二十个技能文件都塞给 Agent它就会被大量无关步骤干扰但如果没有索引层Agent 又不知道去哪里找技能。索引区让“发现”和“加载”分离成本可控。2.4 每个技能的标准结构让步骤可执行、可验证技能正文部分我统一用“执行协议 验证清单 回退信号”三段式结构。以跨文件重构技能为例它的简化版本是这样的# 执行协议 1. 先构建当前调用关系图列出所有受影响的文件。基于代码检索逐文件确认不要凭记忆猜。 2. 从受影响最小的文件开始改每改完一个文件立即跑编译/测试不允许一次性改完再验证。 3. 接口变更时所有调用方必须同步更新禁止留下兼容层或过期注释。 4. 全部改动完成后输出变更摘要涉及文件清单、每个文件的改动原因、最终验证结果。 # 验证清单 - [ ] 编译是否通过 - [ ] 相关测试是否全部通过 - [ ] 是否还有调用方引用旧接口 - [ ] 是否还有过期注释或无用的中间代码 # 回退信号 - 如果调用关系图无法在有限步骤内构建清楚停止并询问用户。 - 如果编译错误超过5个回退最近一次改动重新开始不要继续硬修。 - 如果新代码与项目既有风格明显不一致主动对比相邻模块写法再继续。这套结构的关键在于“可验证”。技能不只是一堆建议而是每一步都有明确的输出和检查点。Agent 执行到某一步如果卡住回退信号会告诉它该止损还是换策略。我当时设计这个三段式的时候参考了一个很朴素的直觉如果我自己手动做这个任务我会怎么控制节奏答案是“分步走、每步验证、错了及时回头”。技能文件就是把这种节奏显式化让模型照着做。3. 在 Codex 和 Claude Code 里落地时的具体差异3.1 Claude CodeCLAUDE.md 的全局规则与技能分包Claude Code 对技能库的接入方式相对自然。项目根目录的 CLAUDE.md 是它的常驻记忆文件每次会话都会读取。我在这里放的是前面说的“常驻区”几条全局原则 技能索引的引用说明。具体写法上我利用的是 Claude Code 对文件路径的自动感知能力。在 CLAUDE.md 里我会写上# 全局规则 - 任何跨文件修改前必须先在 SKILLS.md 中检索对应技能并完整读取技能文件后执行。 - 执行技能时按技能内“执行协议”的步骤逐一进行每步完成后检查“验证清单”。 - 当任务超出所有技能覆盖范围时按通用工程原则处理并在输出中标注“此处无技能覆盖按通用逻辑执行”。关键一点是让 Agent“主动去读技能文件”而不是把技能内容抄进 CLAUDE.md。CLAUDE.md 的优点是可以无限写但一旦写长上下文的常驻开销就上来了。我的经验是CLAUDE.md 控制在 300 行以内只写原则和路径具体操作全部放 skills/ 目录下的独立文件里。Claude Code 还支持 slash command比如 /cross-file-refactor 手动触发某个技能。这个我保留作为“人工兜底”因为有时任务描述比较模糊Agent 自主匹配可能选错技能。手动触发能强制它读正确的文件但这个功能我不常用——它本质上又回到了手动 Prompt 模式多了反而麻烦。3.2 CodexAGENTS.md 与显式调用方式Codex 的语境略有不同。它的常驻文件叫 AGENTS.md机制跟 CLAUDE.md 类似但在技能调用的行为习惯上不太一样。我在实际测试中的感受是Codex 更喜欢“显式指令式”的处理方式也就是在 AGENTS.md 里写得越直白它执行得越稳。例如跨文件重构这个场景我在 AGENTS.md 里会写- 当任务包含“重构”或“迁移”或“替换”关键词时必须读取 skills/cross-file-refactor.md 并按其步骤执行。 - 读取技能文件后把技能中的“执行协议”作为任务计划的强制约束不允许自行简化步骤。 - 每个文件修改完成后运行一次构建命令并记录结果。Codex 对“必须”“不允许”这类强约束词的理解比 Claude Code 更敏感。这可能是两个模型在训练数据上对指令层级理解的差异。我推荐各自工具下尽量贴合工具的口味写规则不要为了统一格式强行用同一套措辞。另一个差异是文件路径的写法。Codex 对相对路径的解析有时候会飘尤其是多目录项目里。保险起见我在 AGENTS.md 里用的是“路径前缀 关键词”的组合描述比如“仓库根目录下 skills/ 子目录中”。Claude Code 则较少出现这个问题。3.3 跨工具适配时踩过的兼容性坑我最初做这套框架的时候核心目标是“一套技能双工具通用”。理想很丰满实际撞了不少墙。第一个坑是 Markdown 语法的严格程度。Claude Code 对 YAML frontmatter 的解析比较宽松稍微有点格式瑕疵也能识别Codex 则更严格frontmatter 一旦出现无法解析的字段它可能直接把整个技能文件当作普通文档不会触发对应机制。后来我统一采用最基础的 YAML 结构避免使用复杂嵌套、缩进式列表字段名全部用下划线而非连字符。第二个坑是两个工具对“优先级”字段的理解不一样。Claude Code 会参考 priority 字段做任务规划但 Codex 在文件里看到 priority 时基本忽略它更信 AGENTS.md 里那句“必须读取”的硬指令。所以我在技能文件里保留 priority但在常驻规则里用强制指令兜底。第三个坑是技能的“语气”。Claude Code 偏协作你用“建议”它也会认真执行Codex 偏任务驱动你写“建议”它可能真的当建议处理可做可不做。现在我的技能文件统一用祈使句写操作步骤把模糊空间尽量压缩。这三个坑其实没有完美解法我的处理原则是技能文件保持中立格式但每个工具的接入说明里单独调整措辞强度。4. v0.1.5 这轮迭代我改了什么为什么这么改4.1 v0.1.0 的教训技能文件膨胀导致上下文爆炸第一版技能库我写了二十多个技能从“接口设计原则”到“日志规范”到“数据库迁移”事无巨细。结果就是Agent 每次任务开始都要把索引读一遍然后经常一口气加载三四个技能上下文窗口被大量步骤描述占据真正用于代码分析的余量所剩无几。当时最典型的问题出现在一个模拟项目 X 的前后端联调任务中Agent 同时加载了“API 设计”“错误处理”“测试规范”三个技能任务还没开始思考过程已经写了四五千字然后开始遗忘前置指令。这让我意识到技能库不是越全越好而是越“精准”越好。4.2 v0.1.3 引入分级技能L0/L1/L2从 v0.1.3 开始我把技能分成三个等级等级适用场景加载方式数量上限L0全局底线规则所有任务都适用常驻5条以内L1高频任务如跨文件重构、测试补全、代码审查按需加载8个左右L2低频深度任务如性能剖析、依赖升级手动触发或按需加载不限但保持收敛L0 技能其实不算“技能”更像是常驻规则。它们只用几句话描述不占用大量 token。L1 是主力写完整执行协议。L2 则是那些你一个月可能用两次但一旦用就需要深度指导的任务。分级之后Agent 不会在普通任务里加载 L2 技能上下文压力大幅缓解。这个改动在纯 token 消耗上感受非常明显v0.1.0 时代一次中等规模重构的对话平均要烧掉 8 万到 10 万 tokenv0.1.3 之后降到 5 万到 6 万。4.3 v0.1.5 的关键变化自动触发评估表与回退链路v0.1.5 这一版最主要的变化有两个一个是触发评估表另一个是回退链路。触发评估表在前面已经展示过了核心是 when_not_to_use 字段。这个字段的价值不在“锦上添花”而在于减少 Agent 的无效动作。以前一个技能被误触发后Agent 会走一遍完整流程浪费大量步骤和时间现在它可以在读技能前就完成判断直接跳过不适用场景把节省的上下文留给真正的分析。回退链路则是给技能执行兜底。以前的技能文件只写“怎么做”没写“做砸了怎么办”。Agent 一旦在某一步卡住往往会原地打转不断尝试同一套失败策略。我在 v0.1.5 里给每个技能加了“回退信号”段落明确定义哪些情况代表当前方向错了、应该回到哪一步重新开始、或者直接停下来询问用户。举个例子跨文件重构技能里的回退信号是“如果编译错误超过5个回退最近一次改动重新开始不要继续硬修。”这条规则看着普通但实测中非常管用。Agent 以前会一个错误一个错误地修修完这个冒出来那个越陷越深现在它在错误数量达到阈值后主动回退反而快速回到正轨。4.4 版本管理怎么配合 Git 仓库技能库本身也是一个工程需要版本管理。我用 git tag 做版本标记每个 tag 对应一个发布节点。changelog 文件记录了每个版本改了什么、为什么改。比如 v0.1.5 的 changelog 就写了三条为所有 L1 技能增加 when_not_to_use 触发排除条件新增“回退信号”字段明确执行失败时的止损策略修复 Codex 下 frontmatter 解析兼容性问题移除嵌套缩进列表。跨项目复用的时候我不直接把技能库整体复制到每个项目而是把技能库作为一个子模块链接进来然后在每个项目的 AGENTS.md / CLAUDE.md 里做引用。这样技能库的更新可以一次性推送到所有项目不需要每个项目手动改。但注意一点全局技能库只能放“通用工程经验”放不了“项目特有约定”。项目特有的错误处理规范、目录结构说明、历史包袱注意事项必须写在项目自己的常驻文件里。这两者的边界一开始很容易模糊我的划分标准是换一个项目这条经验还成立吗成立进技能库不成立留在项目文件里。5. 实测这套工作流在哪些场景真正改变了结果5.1 多文件重构从“改一处崩三处”到按协议执行跨文件重构是我最早写技能、也是收益最明显的场景。v0.1.0 时代几乎每次重构都要我人工盯着改v0.1.5 版本之后Agent 的执行路径变得可预测它会先构建调用关系图、从最小影响文件开始改、每步验证、最后输出变更摘要。我印象最深的是一次接口迁移任务涉及 28 个文件。v0.1.5 里的 Agent 先花了几分钟把调用关系梳理清楚然后按影响范围从小到大逐个文件处理中间两次因为编译错误触发了回退信号但回退后都快速修正了方向。最终一次通过率虽然没说 100%但需要我人工返工的部分明显减少至少不会出现“改完还漏了三处调用方”这种低级失误。这套机制的本质是让 Agent 从“凭感觉写代码”变成了“按规程施工”。重构这种事最怕的不是能力不够而是节奏失控技能协议很好地控制了节奏。5.2 测试补全和回归检查明显稳了测试补全这个场景比较有意思。裸用 Agent 时它的常见问题是为了覆盖率而编测试测了很多没用的边缘情况反而漏了真正的核心路径或者测完不跑直接交差。我在技能库里加了一个“测试补全”的 L1 技能要求 Agent 做三件事先定位被测模块的核心业务路径再按“正常路径—边界条件—异常分支”的顺序补测试最后必须实际运行测试套件并报告结果。同时规定了一个强制动作新增测试后必须执行一次全量回归防止新测试本身破坏了现有测试的假设。实测下来这个技能把测试补全任务从“数量量产”变成了“质量产出”漏测率明显下降。但我也得说句公道话Agent 写测试用例的“直觉”还不够好尤其是边界值的选择经常不是最有代表性的那个。技能可以约束流程但没法完全替代人的测试设计能力。5.3 Debug 类任务的现状仍然需要人工判断并不是所有任务都在技能化之后变好了。Debug 类任务是我目前觉得收益最小的领域。技能文件确实可以规定“先复现、再定位、再修复、再验证”这个流程但问题在于Bug 的根因往往藏在项目语义里需要人对业务逻辑的理解。技能可以告诉 Agent 怎么做但没法告诉它“这个模块的历史包袱是什么”“为什么这里会跟另一个模块产生隐蔽耦合”。所以在我的技能库里Debug 类技能是 L2 级别只在问题特征明确时触发。大部分时间我宁愿自己先定位到可疑区间再让 Agent 深入分析也不让它从头开始盲找。这不是技能框架的失败而是这个任务类型本身对“项目语境”的依赖太高单纯靠流程约束解决不了。5.4 一组客观的对比数据我在自己的模拟项目 X 上做了一组粗略统计对比 v0.1.0 和 v0.1.5 的实测表现。说明一下这不是严格的控制变量实验样本量也不大但趋势有参考价值指标v0.1.0v0.1.5跨文件重构一次通过率约35%约70%每次任务平均返工轮次3-4轮1-2轮测试补全漏测率中等偏高明显下降上下文token消耗中等任务8万-10万5万-6万误触发技能概率高明显降低一次通过率从 35% 到 70%主要归功于两件事触发评估表让 Agent 少做无关动作回退信号让它错了能及时回头。token 消耗的下降则是分级加载的直接结果。当然70% 这个数字离“放心放手”还远得很。碰到复杂跨模块改动我仍然会全程盯。但对比 v0.1.0 时代“三天两头气得想砸电脑”现在的工作流已经进入可预测、可干预、可复盘的状态。6. 如果你也想搭一套我的建议和避坑清单6.1 从哪个规模开始尝试最合适先泼一盆冷水不要一上来就追求“大而全”。你只需要从当前最痛的一个任务类型开始比如“跨文件修改老出错”那就先写这一个技能加进常驻规则跑一个星期再说。我推荐的起步配比是1 条常驻规则 2 到 3 个 L1 技能 0 个 L2 技能。先把这套最小闭环跑通感受技能命中率、上下文开销、返工率的变化再逐步丰富技能库。一上来就写二十个技能你根本不知道哪个有用哪个在捣乱。判断技能是否有效的标准也简单观察“误用率”。如果技能经常被触发但没带来明显改善该技能大概率是废话如果技能很少被触发但触发后总能解决任务那就是好技能。6.2 最容易被忽略的三个坑第一个坑是技能文件的存放位置。Agent 不是会自动扫描整个仓库的它只会根据常驻文件的指引去读取指定路径。如果你把技能文件放在一个深层级目录、或者名字不够直观Agent 就会经常找不到。我的经验是skills/ 目录放仓库根目录下文件名用描述性短语比如 cross-file-refactor.md而不是 01.md、02.md。第二个坑是触发条件写得太窄或太宽。写窄了Agent 该用时不用写宽了Agent 不该用时乱用。我在 v0.1.5 里用的平衡方法是双向定义when_to_use 用“任务描述中出现什么词”来锚定when_not_to_use 用“什么情况下即使出现这些词也不该用”来排除。这个写法值得试。第三个坑是忽略了技能之间的冲突。比如“跨文件重构”和“代码审查”两个技能如果同时加载它们给出的步骤可能有重叠甚至矛盾。我的处理方式是技能之间通过 priority 字段排序并在常驻规则里写明“当一个技能的执行步骤与另一个技能重合时以高优先级技能为准”。6.3 排查 Agent“不按技能走”的通用方法论最后聊聊最常见的挫败场景规则写了Agent 就是不听。遇到这种情况我的排查顺序是固定的。第一步检查技能文件是否被实际读取。让 Agent 在开头思考里输出“当前读取的技能索引内容”如果它根本没提到技能文件问题一定出在路径或触发描述上。第二步检查触发条件是否匹配。把实际任务描述和 when_to_use 里的关键词逐一对比很多时候你以为匹配上了但语义上并不强相关。第三步检查常驻规则和技能文件的约束是否冲突。比如常驻规则里可能有一条“优先使用项目既有工具函数”而技能文件里写着“按新技术栈封装 API”这俩放在一起Agent 自然不知道该听谁的。第四步也是最后一步才是怀疑模型理解能力的问题。以上三步都排除了还不行那就换一种措辞风格、或者拆成更细的技能再试。我在 v0.1.5 开发过程中至少有一半的“Agent 不听话”属于第二步问题——不是 Agent 的问题是我触发条件写得不清不楚。把这一点想明白之后心态会好很多。我自己在这几轮迭代里最大的体会是主模型的能力给了我们很大的想象空间但把想象变成稳定产出靠的是一点点把“经验”磨成显式、可加载、可验证的协议。技能库不是什么玄学手段它就是给 Agent 用的工程文档帮它把项目那本厚厚的“隐形的书”翻开一页页读出来。现在这套框架在我的日常开发里稳定跑着后面我打算把 L2 技能库再补一轮重点解决依赖升级和性能剖析这类深度任务。如果你也在折腾自己的技能工作流欢迎多交流踩坑经验永远不嫌多。