子代理
一个 Codex 会话默认只有一个代理在干活:读文件、想方案、改代码、跑测试,按顺序一件件来。遇到「同时调查三个模块各自怎么处理超时」「前端和后端各改一部分」这类可以拆开并行的任务,一个代理就显得慢了。
子代理(subagent)让主代理可以派生出若干个辅助代理,把边界清楚的子任务交给它们并行处理,自己继续推进主线,最后汇总结果。这一页讲子代理怎么启用、怎么让 Codex 使用它、如何定义自己的角色,以及什么时候用、什么时候不该用。
功能还在快速演进
子代理相关的配置和界面在不同版本间变化较多,下面的内容依据写作时的官方源码(codex-rs/core/src/agent/、codex-rs/config/src/config_toml.rs)整理,细节以你本机版本和 官方文档 为准。
先弄清楚:它不会自己乱开
这是最容易误解的一点。子代理功能(功能开关 multi_agent)在当前版本中默认已开启,但 Codex 不会因为任务复杂就主动派生子代理。源码里给模型的规则写得很明确:只有当用户、或适用的 AGENTS.md / skill 明确要求使用子代理、委派或并行代理时,才可以派生;「请深入分析」「彻底调查」这类要求不算授权。
所以想用子代理,就要在提示词里直接说:
用子代理并行调查下面三个问题,每个问题一个 explorer,汇总后给我结论:
1. internal/gateway 里上游超时是在哪一层设置的,默认多少
2. internal/billing 在请求失败时是否会扣费
3. 前端 web/src/api 对 504 有没有重试也可以在 AGENTS.md 里写一条长期规则,比如「审查大型改动时,用子代理分别检查后端和前端」。
主代理怎样使用子代理
开启后,主代理多了一组管理子代理的工具:
| 工具 | 作用 |
|---|---|
spawn_agent | 派生一个子代理,给它任务说明,可指定角色、模型、推理强度,以及是否带上当前对话历史 |
send_input | 给运行中的子代理追加消息 |
wait_agent | 等待子代理完成并取回结果 |
resume_agent | 恢复一个已有的子代理继续工作 |
close_agent | 关闭不再需要的子代理 |
一个典型的流程是:主代理先拆分任务,派出几个子代理处理互不依赖的部分,自己继续做不依赖这些结果的工作,需要时再等待并整合结果。
几条默认行为:
- 模型:子代理默认继承主代理的模型,除非你明确要求换模型,或者配置了
default_subagent_model。 - 权限:子代理继承主代理的审批策略、沙箱设置和工作目录,不会因为是子代理就获得更多权限。
- 上下文:派生时可以选择只给子代理任务说明(干净的上下文),也可以把当前对话历史分叉给它。
- 界面:在 CLI 里用
/subagents在本会话的各个子代理之间切换,查看它们在做什么。
内置角色
角色决定子代理的定位和配置。当前内置三个:
| 角色 | 定位 |
|---|---|
default | 通用代理,和主代理一样 |
explorer | 回答关于代码库的具体问题,强调快速、结论可靠;适合并行派出多个,各查一个问题 |
worker | 执行实际工作:实现功能的一部分、修测试或 bug、拆分大型重构;要求明确每个 worker 负责的文件范围,避免互相覆盖 |
内置提示里对 worker 有一条很实用的规则:要告诉每个 worker「代码库里不只有你一个人」,不要回滚别人的改动,并明确各自负责哪些文件。你自己布置并行实现任务时,也应该这样写。
配置
全局参数
# ~/.codex/config.toml
[features]
multi_agent = true # 当前版本默认开启,写出来便于明确
[agents]
max_threads = 4 # 同一会话同时打开的子代理上限,默认 6
max_depth = 1 # 嵌套深度:1 表示子代理不能再派生子代理,默认 1
default_subagent_model = "gpt-5.5" # 子代理默认模型,不设则继承主代理
default_subagent_reasoning_effort = "medium"max_threads 是 max_concurrent_threads_per_session 的别名。模型名以 /model 里列出的为准。旧资料里的 job_max_runtime_seconds 在当前版本已不起作用。
关于 max_depth
深度 0 是你直接对话的主代理,深度 1 是它派生的子代理。默认值 1 意味着子代理不能再往下派生。调大它会让任务树变深,成本和失控风险都会迅速上升,一般没有必要。
自定义角色
内置角色不够用时,可以定义自己的角色。有两种写法。
写法一:在 config.toml 里声明,指向一个角色文件
[agents.reviewer]
description = "代码审查:只读检查改动中的正确性、并发安全和错误处理问题,按严重程度汇报,不修改文件。"
config_file = "./agents/reviewer.toml" # 相对路径相对于这个 config.toml
nickname_candidates = ["审查员甲", "审查员乙"]写法二:直接把角色文件放进 agents 目录
Codex 会扫描配置目录下的 agents/ 文件夹(用户级是 ~/.codex/agents/,项目级是项目的 .codex/agents/,后者需要信任项目),其中每个 .toml 文件就是一个角色:
# ~/.codex/agents/reviewer.toml
name = "reviewer"
description = "代码审查:只读检查改动中的正确性、并发安全和错误处理问题,按严重程度汇报,不修改文件。"
nickname_candidates = ["审查员甲", "审查员乙"]
developer_instructions = """
你是代码审查员。只阅读和运行只读命令,不修改任何文件。
审查范围:用户指定的改动(默认是当前分支相对 main 的 diff)。
重点:边界条件、错误是否被吞掉、并发访问共享状态、资源是否释放。
输出:按「严重 / 一般 / 建议」分组,每条给出文件和行号、问题、修改建议。
没有发现问题时明确说明,不要为了凑数编造问题。
"""
model_reasoning_effort = "high"
sandbox_mode = "read-only"角色文件的规则:
name、description、developer_instructions是角色的核心;放在agents/目录里被自动发现的文件,必须写developer_instructions。description会出现在主代理选择角色的说明里,要写清楚这个角色做什么、什么时候用。- 除这几项外,文件里可以写任何
config.toml支持的配置项(如model、model_reasoning_effort、sandbox_mode),作为这个角色的专属配置层。 - 子代理不会因为角色配置而突破主会话的权限边界。
定义好后,在提示词里点名使用:
实现完成后,派一个 reviewer 子代理审查本次改动,根据它的意见修复严重问题,再把审查结论给我。适合的场景
| 场景 | 做法 |
|---|---|
| 并行调研 | 几个互不相关的问题,各派一个 explorer,主代理汇总 |
| 分片实现 | 前端、后端、文档各派一个 worker,写明各自负责的目录,互不重叠 |
| 独立审查 | 实现完成后派一个只读的 reviewer,用干净的上下文看改动,更容易发现主代理的盲点 |
| 并行验证 | 主代理继续改代码的同时,派子代理跑耗时的测试或复现步骤 |
| 大规模机械修改 | 把几百个文件按目录分给几个 worker,各自完成同一种改造 |
不适合的场景:
- 强依赖、串行的任务:下一步必须等上一步结果,派出去只是多了等待和沟通成本。
- 小任务:改一个函数、修一个 typo,派生子代理的开销比任务本身还大。
- 多个代理改同一批文件:容易互相覆盖,合并困难。真要并行修改,按文件或目录划清边界;更彻底的隔离可以用 Worktree。
上下文隔离与成本
子代理的一大价值是上下文隔离。主代理的上下文窗口很宝贵:如果它亲自去翻三个模块的几十个文件,这些内容都会堆在它的上下文里。交给子代理去调查,主代理只收到一份简洁的结论,主线的上下文保持干净。
代价也很直接:
- token 消耗成倍增加。每个子代理都是独立的模型会话,有自己的系统提示、读取的文件和推理过程。同时开 4 个子代理,消耗大致可以按 4 个独立任务来估算。通过 HiveGPT 按量计费时,这一点要心里有数。
- 信息会丢失。不带对话历史派生的子代理只知道你(或主代理)写给它的任务说明,背景交代不清,它就会做无用功。
- 协调有成本。结果需要主代理整合、核对,并行改代码还可能产生冲突。
控制成本的几个办法:
- 把
max_threads设小一点,比如 2 到 4。 - 给调研类角色设置较低的推理强度,或用
default_subagent_model指定一个更便宜的模型(以/model里列出的为准)。 - 任务说明写得具体、有边界,要求子代理「只回答这个问题,结论不超过 200 字」。
一个完整示例
假设你要给一个 Go + Vue 项目的「导出报表」功能加上 Excel 格式:
任务:报表导出新增 Excel 格式。请按下面的方式分工,用子代理并行:
1. 派一个 explorer:找出现有 CSV 导出的完整调用链(前端按钮 → API → service),
只汇报文件路径和函数名,不改代码。
2. 拿到结果后,派两个 worker 并行实现:
- worker A 只负责 backend/internal/service/export*.go 和对应测试,
用已有的 excelize 依赖实现 Excel 生成,go test -tags=unit ./internal/service/... 必须通过;
- worker B 只负责 web/src/views/report/ 下的文件,在导出下拉中加入 Excel 选项,
pnpm run typecheck 必须通过。
告诉两个 worker:代码库里还有别人在改,不要动自己负责范围以外的文件。
3. 两边完成后,派一个 reviewer 子代理审查全部改动。
4. 你负责整合:处理 reviewer 提出的严重问题,最后列出全部改动文件和验证结果。这个提示词明确授权了子代理、划清了每个子代理的职责和文件范围、给出了各自的完成标准,主代理的职责也写清楚了。
小结
- 子代理让主代理把边界清楚的子任务交给辅助代理并行处理;当前版本默认开启(
multi_agent)。 - Codex 只在你或 AGENTS.md / skill 明确要求时才派生子代理,想用就在提示词里直接说。
- 内置
default、explorer、worker三个角色;自定义角色写在[agents.名字]或agents/*.toml,核心是 description 和 developer_instructions。 - 默认最多同时 6 个子代理、嵌套深度 1;子代理继承主会话的模型、沙箱和审批设置。
- 隔离上下文是主要好处,token 成倍增加是主要代价;只把能并行、边界清晰的任务交给子代理。
下一步:用规则和钩子约束 Codex 的行为,见 规则与钩子。