AI-SDLC 实践 01|用好 Claude Code/Codex 提供的六种能力

Claude Code 和 Codex 都提供六种可以直接拿来搭流程的能力:AGENTS.md/CLAUDE.md、Skill、Subagent、Hook、MCP、权限与沙箱。

本篇讲三件事:

  • 六种能力各自的作用和适用场景;
  • 我们在 AI-SDLC 的五个阶段里分别用它们做了什么;
  • 同一套工程怎样同时支持 Claude Code 和 Codex。

文中的平台行为以两边截至 2026 年 11 月的官方文档为准。

Agent = Model + Harness:Harness 管的是上下文窗口

一个 Coding Agent 可以拆成两部分:Model 负责推理,Harness 负责模型之外的一切,包括对话循环、工具调用、上下文的组装与压缩、subagent 的派生与回收、权限确认和外部连接。

Claude Code 和 Codex 的 Harness 已经相当完整,这些部分不需要再自己造一遍。

我们要做的是先把宿主的能力摸清楚、尽量复用,只补宿主没有的部分:

  • CLI:推进工作流,给 Agent 提供辅助工具(第 00 篇讲过它和宿主、Agent 的分工);
  • 知识库:沉淀架构规范和编码规则,提升 Agent 生成代码的质量。

Harness 最核心的工作,是决定每一轮送进模型的上下文窗口里装什么。系统提示、AGENTS.md/CLAUDE.md、工具定义、skill 列表、历史消息、工具结果,都在争同一块空间。

两边的官方文档里有不少预算数字:

  • Codex 拼接 AGENTS.md 时,合计默认只读前 32 KiB;skill 的初始列表默认最多占上下文窗口的 2%;
  • Claude Code 建议单个 CLAUDE.md 控制在 200 行以内;skill 的描述在列表里超过 1,536 字符会被截断。

这些数字说明,宿主自己也在严格控制窗口里的每一块内容。AI-SDLC 要做的,是用 Harness 提供的能力,让窗口在每个环节只装这个环节需要的东西。

需求理解阶段不该带着上一个任务的编译日志,评审角色不该看到开发角色的试错过程。窗口里无关的内容越少,Agent 越专注,判断也越稳定。

六种能力:各自作用在窗口的哪个位置

AGENTS.md/CLAUDE.md 常驻窗口,skill 用到时才进入,subagent 另开一个窗口,hook 在固定时机补充内容,MCP 从外部拉取内容,权限与沙箱在窗口之外由宿主强制执行。

AGENTS.md/CLAUDE.md:每轮都在窗口里

项目根目录的 AGENTS.md/CLAUDE.md 在会话开始时进入窗口,之后每一轮请求都带着它。

上下文压缩时,它不和历史对话一起被总结,而是原样放回窗口:Claude Code 的官方文档写明会从磁盘重新注入,Codex 的开源实现也会在压缩后把 AGENTS.md 重新插入上下文。

例外是按需加载的部分。Claude Code 里,子目录下的 CLAUDE.md 和带 paths: 的规则,要等 Agent 读写对应目录的文件时才加载;压缩时它们会和普通对话一起被总结掉,下次碰到相关文件再加载。Codex 则读取从仓库根目录到当前目录这一路上的 AGENTS.md,逐级拼接。

  • 适合:每次会话都必须知道的少量硬规则,以及流程入口在哪里;
  • 不适合:只在某个阶段才用的方法。它每一轮都占着窗口,用不上的轮次就是浪费。

Skill:用到时才读全文

两边的 skill 都遵循 Agent Skills 开放标准。平时窗口里只有 skill 的名字和描述,模型判断要用时才读入 SKILL.md 全文。

调用方式有两种:模型按描述自动选用,或者显式调用(Claude Code 输入 /名字,Codex 输入 $名字)。

  • 适合:某个阶段的做法、模板、检查清单;
  • 不适合:必须每次生效的约束,模型没有调用就不生效。

流程里的关键阶段应关闭自动触发,由流程显式调用:

  • Claude Code:在 frontmatter 里设 disable-model-invocation: true;
  • Codex:在 agents/openai.yaml 里设 allow_implicit_invocation: false。

Subagent:给子任务一个干净的窗口

subagent 在独立的窗口里工作,只把结果带回主会话,主窗口不会被它读过的大量文件填满。

两边都支持自定义角色:Claude Code 写在 .claude/agents/ 下的 markdown 文件里,Codex 写在 .codex/agents/ 下的 TOML 文件里,都可以单独指定 model 和 effort。

  • 适合:并行开发、独立评审、需要读大量文件的检索;
  • 不适合:需要和主会话频繁来回的任务。

subagent 的最后一条回复只是摘要,不能当作产物。角色文件只写职责、输入、产出和禁止项,方法留在 skill 里,不复制 skill 正文,否则两份内容会逐渐漂移。

Hook:在固定时机补上下文或拦截操作

hook 是宿主在会话生命周期的固定时机自动运行的脚本。宿主把这次事件的信息(会话、工具名、参数等)以 JSON 传给脚本,再按脚本的输出决定下一步。

两边共有的时机,按一次会话的顺序是:

  • 会话开始(SessionStart):往窗口里补一段上下文;
  • 用户提交(UserPromptSubmit):补上下文,或者拦下这次提交,不让它进入模型;
  • 工具调用前(PreToolUse):拦下这次调用、改写参数,或者补一段上下文。需要权限确认时还有 PermissionRequest,可以代替人批准或拒绝;
  • 工具调用后(PostToolUse):工具已经执行完,hook 撤销不了,只能补上下文或给模型反馈;
  • subagent 启动和结束(SubagentStart / SubagentStop):启动时给 subagent 补上下文,结束时可以要求它再做一轮;
  • 回合结束(Stop):可以不让 Agent 结束,要求它继续;
  • 压缩前后 (PreCompact / PostCompact):压缩前可以先做记录,也可以阻止这次压缩,压缩后的事件基本只用来记录。要在压缩之后补回内容,用的是来源为 compact 的会话开始事件。

归纳起来,hook 能做的就三件事:补上下文、拦下操作、要求继续。补进窗口的内容也有预算,Codex 默认每个 hook 约 2,500 token。

  • 适合:会话启动和压缩之后补回最小的恢复索引,每轮提交时提示当前阶段,拦截明确的危险命令;
  • 不适合:自动修代码、推进流程状态。

hook 的可靠性有边界。两边的 hook 出错或超时,默认都不会拦住工具调用。Codex 文档明确写着:把工具 hook 当作有用的护栏,而不是完整的强制边界。

Claude Code 可以给单个 hook 设 onFailure: "block",改为失败即拦截,Codex 文档里没有对应选项。此外,没有获得宿主信任的 hook 根本不会运行。

MCP:把外部事实拉进窗口

MCP 连接需求文档、设计稿、缺陷系统这类外部来源,Agent 按需调用工具,把内容读进窗口。

  • 适合:读取外部的事实来源;
  • 不适合:充当真相源。

MCP 返回的是此刻读到的内容,可能不完整,也可能读取失败。工具定义本身也占窗口,用不到的工具应当关掉,Codex 可以用 enabled_tools 和 disabled_tools 收窄。

权限与沙箱:窗口之外的硬边界

权限与沙箱不进入窗口,由宿主在模型之外强制执行。

Claude Code 用 allow、ask、deny 三类规则,按 deny、ask、allow 的顺序判定,allow 不能在 deny 里开例外。Codex 用沙箱模式和审批策略划定范围,再用命令前缀规则控制沙箱外的命令。

  • 适合:必须守住的约束,例如不准写某些目录、不准推送、不准联网;
  • 不适合:描述「怎么做」的方法。

六种能力放在一起看,一条约束该放在哪里,取决于它要有多可靠。可以提示的放进窗口,交给 AGENTS.md/CLAUDE.md 或 skill;必须拦住的交给权限与沙箱,hook 只作补充;必须证明没有违反的,交给下一节的 Checker。

我们在五个阶段里怎么用这六种能力

AI-SDLC 的五个阶段,窗口里装的东西各不相同。下面按阶段说明每个窗口由哪些能力组装,具体做法在后续各篇展开。

需求理解(第 03 篇)。 阶段 skill 由流程显式加载。需求文档和设计稿通过 MCP 读取,结论落盘时带上来源;读不到时记为「源不可用」并继续,不凭记忆补全。

仓库里能查到的事实由 Agent 自己查,只有会改变目标、范围、授权或验收标准的问题才拿去问人。

方案设计与评审(第 04 篇)。 方案评审交给评审 subagent。它的窗口里只有方案本身,以及方案引用的接口合同、组件和设计材料,不带方案作者的推理过程,这样评审结论才独立于作者。

开发(第 05 篇)。 按任务图派发开发 subagent,每个只拿一份上下文清单,列出要读哪些文件、为什么读,其中包括知识库里和这块代码相关的架构规范与编码规则(知识库见第 08 篇)。

派生几个 subagent、何时结束,由 CLI 按任务图计算,不交给 skill 决定。产物先写到磁盘,再报告完成。

验证与联调测试(第 06 篇)。 评审和测试在同一个冻结的候选版本上并行。评审 subagent 和流程门禁调用同一个 Checker,不存在两套标准。

交付(第 07 篇)。 宿主的权限规则和流程里的逐动作授权构成两道闸。推送、合并、提测逐项确认,前一项的授权不延续到下一项。

跨阶段(第 02 篇)。 hook 在会话启动、上下文压缩前后和每轮提交时运行,补回三件事:当前在哪个阶段、下一步做什么、必须读哪些文件。hook 只输出路径和摘要,不写流程状态。

宿主之外的一块:Checker

六种能力都只是让 Agent 更可能做对,没有一种负责判断结果对不对。这一块由我们在 CLI 里补上:每个阶段的出口都有确定性检查,输出 pass 或 blocked,blocked 时附上 path:line。

Checker 只读磁盘上的产物,不看模型怎么描述自己的工作。编译和测试通过,也抵消不了越界修改。

一套工程如何同时支持 Claude Code 和 Codex

同一套流程要在两个宿主上都能用。如果两边各写一套配置,几个月后必然对不上。

我们的做法是:角色、skill、hook 这些配置按一种通用格式只写一份(下文称中立源),再由脚本生成两边各自需要的文件(下文称投影)。

工程目录大致是这样:

text 复制代码
<仓库根目录>/
├── AGENTS.md          # 两边共用的入口文件
├── CLAUDE.md          # 只有一行 @AGENTS.md
├── agents/            # 中立源:角色定义
├── skills/            # 中立源:各阶段的 skill
├── docs/              # 知识库:架构规范、编码规则
├── .claude/           # Claude Code 投影
│   ├── agents/        # sync 生成
│   ├── skills/        # sync 生成
│   └── settings.json  # hook 与权限规则,随仓库提交
├── .agents/
│   └── skills/        # Codex 读取的 skill,sync 生成
└── .codex/            # Codex 投影
    ├── agents/        # sync 生成
    ├── hooks.json     # 随仓库提交
    └── config.toml    # MCP 等配置

人只改 AGENTS.md、中立源和知识库。角色和 skill 的投影由 CLI 生成,两边的 hook 配置随仓库提交。

投影怎么生成:会话开始时由 hook 调用 sync

投影由 CLI 的 sync 命令生成。两边的会话开始 hook 都配置成同一条命令,调用 sync:

  1. 读取中立源里的角色和 skill;
  2. 按两边各自的格式写出投影:角色写成 Claude Code 的 markdown 和 Codex 的 TOML,skill 分别放进 .claude/skills/ 和 .agents/skills/;
  3. 生成时检查同名冲突,并记录只有一边支持的能力怎么降级。

这样每次开会话,投影都会自动对齐到中立源的最新版本,不需要谁记得手动同步。中立源里改了一个 skill,下一次会话就生效。

实现时有三个细节要处理:

  • 本次会话能不能立刻用上。 Claude Code 扫描 skill 通常早于会话开始的 hook 结束,hook 新写入的 skill 可能赶不上第一条提示;hook 返回 reloadSkills: true,Claude Code 会在 hook 结束后重新扫描。角色文件的改动,Claude Code 几秒内就能检测到。Codex 会自动检测 skill 的变化。
  • 触发 sync 的 hook 配置不能由 sync 生成。 它是整套同步的起点,要随仓库提交,内容固定为一条调用 CLI 的命令。配置不变,Codex 也就不会因为某次同步要求重新审核这条 hook。
  • sync 要快,失败不挡路。 它跑在会话启动的路上,Claude Code 的第一条回复要等会话开始的 hook 跑完。同步失败时,会话照常开始,用的是上一次的投影,由预检报告投影已过期。

sync 生成投影时守三条规则:

  • 不手改投影:投影文件带生成标记,每次同步都按中立源重新生成,手改的内容会被覆盖;
  • 同名冲突直接失败:Codex 遇到同名 skill 不合并,两个都会出现;Claude Code 同一目录下的同名角色只加载其中一个,加载哪个没有确定顺序。sync 发现同名就失败,不交给宿主去选;
  • 能力差异显式降级:只有一边具备的能力(比如下文的只读 subagent),投影时记录降级方式和补位手段,不悄悄丢掉。

生成投影时,要照顾到两边的这些差异:

能力 Claude Code Codex
AGENTS.md/CLAUDE.md CLAUDE.md 与 .claude/rules/;没有 CLAUDE.md 时读 AGENTS.md AGENTS.md 逐级拼接,默认上限 32 KiB
权限 allow / ask / deny 规则与权限模式 沙箱模式、审批策略、命令前缀规则
Skill .claude/skills/ .agents/skills/
自定义角色 .claude/agents/*.md .codex/agents/*.toml
subagent 权限 每个角色可单独限制工具和权限模式,可在独立 worktree 里工作 跟随主会话的权限,角色文件只能关掉少数能力
Hook 信任项目目录后运行;单条 hook 可设失败即拦截 每条 hook 单独审核,配置改动后要重新审核;同一时机的多条 hook 同时启动
MCP 项目级 .mcp.json,需批准 config.toml 的 [mcp_servers],项目级仅在受信任项目生效

两边行为不同的三个地方

一、能不能把某个角色单独设成只读。

在 Claude Code 里可以。评审角色的定义文件写上 tools: Read, Grep, Glob,这个角色就拿不到改文件的工具,由宿主保证。

在 Codex 里不行。subagent 的权限跟着启动它的主会话走:主会话能写文件,subagent 也能写。角色定义文件只能关掉 shell 等少数能力,在角色说明里写「不要改文件」只是一句提示。

所以在 Codex 上需要真正只读的评审时,我们单独开一个只读会话来跑,由 CLI 把它的输出写成文件;用 subagent 跑时,评审结束后由 Checker 检查它有没有改动评审目录以外的文件。

二、hook 的配置改了以后,还会不会运行。

Claude Code 按项目目录确认信任。确认之后,这个目录里配置的 hook 就会运行。

Codex 按每一条 hook 单独审核。它记录每条 hook 配置的指纹,配置一改,这条 hook 就会被跳过,直到有人重新审核。同一时机触发的多条 hook 还是同时启动的,没有先后顺序。

所以我们把 hook 配置固定成一条调用 CLI 的命令(会话开始时就是它在调用 sync),同一时机只挂这一条,具体逻辑放在 CLI 里迭代。配置很少需要改,团队成员不用反复重新审核,也不必担心多条 hook 的顺序。两边的 hook 事件名基本一致,这条命令按事件名分发即可,第 02 篇展开。

三、skill 放在哪个目录。

两边各读各的目录:Claude Code 读 .claude/skills/,Codex 读 .agents/skills/,互相不读对方的。

AGENTS.md 的情况不同:项目里没有 CLAUDE.md 时,Claude Code 会直接读 AGENTS.md;有 CLAUDE.md 时,也可以在里面写一行 @AGENTS.md 把它引进来。

所以 AGENTS.md 两边共用一份;skill 在中立源里只写一份,生成时分别放进两个目录。

同一个评审角色的两份投影

下面是同一个方案评审角色在两边的定义,都由中立源生成。评审结论要写成文件,所以两份配置都保留了写文件的能力。

Claude Code(.claude/agents/plan-reviewer.md):

markdown 复制代码
---
name: plan-reviewer
description: 对照接口合同和设计材料评审技术方案,只写评审结论
tools: Read, Grep, Glob, Write
model: inherit
effort: high
maxTurns: 30
---
只读取方案及其引用的合同文件。
评审结论写入评审目录下的一个文件,不修改其他文件。

Codex(.codex/agents/plan-reviewer.toml):

toml 复制代码
name = "plan-reviewer"
description = "对照接口合同和设计材料评审技术方案,只写评审结论"
model_reasoning_effort = "high"
developer_instructions = """
只读取方案及其引用的合同文件。
评审结论写入评审目录下的一个文件,不修改其他文件。
"""

[features]
shell_tool = false

Claude Code 一侧去掉了 Bash 和 Edit;Codex 一侧只能关掉 shell 工具,能写哪些文件由父会话的沙箱决定。两边都没法把写入范围限定到评审目录,「只改评审文件」最终由 Checker 核对。

已同步、已信任、已执行是三件事

sync 跑完,只代表投影写到位了,不代表宿主信任了它。Claude Code 有工作区信任和项目 MCP 的批准,Codex 有项目层信任和每条 hook 的单独审核。宿主信任了,也不代表它在这次会话里真的运行了。

所以预检阶段由 CLI 逐项检查:投影是否最新,必需的 hook 和 MCP 是否已被信任、是否可用。会话结束后,再从会话日志确认实际触发情况。

流程的正确性,不能建立在「hook 一定会运行」这个假设上。第 02 篇从这里接着讲阶段合同、状态机与恢复:hook 没有运行、会话中途压缩或中断时,流程靠什么接着走。

相关推荐
梯度下降者1 小时前
3天时间,我使用 Cursor 开发了一个提示词生成器
ai编程·next.js·cursor·产品开发·提示词生成器
70后写java的老码农2 小时前
换模型只改三行配置:LangChain4j + Spring Boot 3.5 实战,一次分别接入 9 家模型服务
后端·ai编程
Rain的Java大神实战圈3 小时前
面试官让你把 LLM、RAG、Agent、MCP 串起来讲清楚,90% 的 Java 工程师当场露馅
ai编程
西安小哥3 小时前
视口高度为 0:一次浏览器自动化调试的完整复盘
ai编程
孔令飞3 小时前
很多人想学AI Infra,今天推荐一个 AI Agent / AI Infra 学习路线
云原生·go·ai编程
前端双越老师3 小时前
程序员 1v1 访谈系列第十一期:应届生别做开发
java·agent·ai编程
VIP_CQCRE3 小时前
在 VS Code 等编辑器里用 OpenCode 接入 Ace Data Cloud:Provider 配置与 IDE 验证
大模型·ai编程·vs code·opencode·ace data cloud
熊猫钓鱼>_>4 小时前
三方库 NDK 原生模块跨平台适配与调试【鸿蒙心迹】
开发语言·华为·ai编程·harmonyos·鸿蒙·openharmony·鸿蒙心迹
一缕82年的清风4 小时前
智能体“自适应慢思考”的算力黑洞:当 Claude 5.5 与 GPT-6.1 Sol 陷入推理自旋,为什么高并发架构必须重构“认知预算熔断与快慢推测执行”?
gpt·claude·gemini