Codex Sub-agent 机制详解
此前我们已深入解析主流 Harness 的 Memory、Compaction 及 Goal 机制:
- Claude Code 与 Codex Memory 机制详解
- Claude Code 与 Codex 压缩机制详解
- Coding Agent Goal 机制详解
本文将继续梳理 Codex 源码,聚焦 sub-agent 机制,重点探讨以下核心问题:
本文基于发表时最新的 Codex 源码(multi-agent v2)。该版本设计成熟巧妙,契合教科书级的 Sub-agent 架构,故不再参考旧版。
鉴于 Harness 迭代迅速,Claude Code 泄露的旧源码已无研读价值。Codex 设计精良,值得详述,后续将补充其他产品的 Sub-agent 机制分析。
致敬所有开源 Harness 产品,特别表扬 kimi-code 及新开源的 minimax code。
下文将先解析提示词,再展开介绍六个核心协作工具。
一、主 Agent 与 Sub-agent 的提示词
#主 Agent
仓库内置的主 Agent 基础提示词如下(模型元数据和配置可覆盖,运行时可能追加共享环境、并发额度等说明):
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
You can spawn sub-agents to handle subtasks, and those sub-agents can spawn their own sub-agents.
All agents in the team, including the agents that you can assign tasks to, are equally intelligent and capable, and have access to the same set of tools.
You can use `spawn_agent` to create a new agent, `followup_task` to give an existing agent a new task and trigger a turn, and `send_message` to pass a message to a running agent without triggering a turn.
Child agents can also spawn their own sub-agents.
You can decide how much context you want to propagate to your sub-agents with the `fork_turns` parameter.
You will receive messages in the analysis channel in the form:
```
Message Type: MESSAGE | FINAL_ANSWER
Task name: <recipient>
Sender: <author>
Payload:
<payload text>
```
They may be addressed as to=/root
核心含义:作为 /root,负责统筹用户目标。可创建子 Agent、追加任务或发送消息;子 Agent 亦可继续派生。团队成员能力对等,共享工具集。
关键要素包括:任务路径、协作工具、继承上下文及消息接收格式。
#Sub-agent
子 Agent 的基础提示词如下:
You are an agent in a team of agents collaborating to complete a task.
You can spawn sub-agents to handle subtasks, and those sub-agents can spawn their own sub-agents. All agents in the team, including the agents that you can assign tasks to, are equally intelligent and capable, and have access to the same set of tools.
You can use `spawn_agent` to create a new agent, `followup_task` to give an existing agent a new task and trigger a turn, and `send_message` to pass a message to a running agent.
Child agents can also spawn their own sub-agents.
When you provide a response in the final channel, that content is immediately delivered back to your parent agent.
You will receive messages in the analysis channel in the form:
```
Message Type: NEW_TASK | MESSAGE | FINAL_ANSWER
Task name: <recipient>
Sender: <author>
Payload:
<payload text>
```
You may also see them addressed as to=/root/..., which indicates your identity is /root/...
核心含义:作为团队成员执行分配任务,可使用协作工具或创建下一级子 Agent。在 final channel 的回复将直接回传至父 Agent。
两者提示词高度相似,主要差异对比如下:
| 对比项 | 主 Agent | 子 Agent |
|---|---|---|
| 身份 | 明确为 /root |
路径动态生成,如 /root/research |
| 工作定位 | 完成用户总体目标 | 完成分配的具体任务 |
| 最终结果 | 面向主会话输出 | 强制回传直接父 Agent |
| 创建其他 Agent | 支持 | 支持 |
结论:子 Agent 并非简化版执行器,它继承了父 Turn 的主要配置、权限及工作目录,拥有独立的对话上下文和执行循环。
#默认不主动派生子 Agent
具备创建能力并不意味着随时创建。V2 默认模式指导如下:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. Do not spawn sub-agents unless the user or applicable AGENTS.md/skill instructions explicitly ask for sub-agents, delegation, or parallel agent work.</multi_agent_mode>
意指:撤销主动委派指令。仅在用户、AGENTS.md 或 Skill 明确要求时,才创建子 Agent 或进行并行工作。
切换至 Ultra 模式时,采用 Proactive 指导:
<multi_agent_mode>Proactive multi-agent delegation is active. Any earlier developer instruction requiring an explicit user request before spawning sub-agents no longer applies. This mode remains active until a later multi-agent mode developer message changes it. User requests override this hint.
If at any point you can parallelize work by delegating tasks to another agent (no matter if you are root or subagent), you should do so using collaboration tools if it could save time or improve quality.</multi_agent_mode>
意指:允许主动委派。若分包能提升效率或质量,无论主副 Agent 均应使用协作工具(用户指令优先)。
推测:随着 Bash 等工具能力提升及执行层并发控制的完善,日常任务中 Sub-agent 的必要性降低。
Codex 还提供 functions.exec 等万能工具,允许模型通过 JavaScript 编排多次工具调用、并行处理及结果整合,设计精妙且日益流行。
二、六个 Sub-agent 工具
协作工具位于 collaboration 命名空间,共六个:
| 工具 | 主要用途 |
|---|---|
spawn_agent |
创建子 Agent 并分配初始任务 |
send_message |
传递信息但不唤醒目标 |
followup_task |
追加任务,必要时唤醒目标 |
wait_agent |
等待消息、完成通知或其他唤醒事件 |
interrupt_agent |
中断目标当前 Turn |
list_agents |
查询团队成员和状态 |
注:"Turn"指 Agent 接收任务后,从推理、调用工具到结束的完整执行过程,包含多次 LLM 请求。
#1. spawn_agent:创建子 Agent
核心参数:
| 参数 | 含义 |
|---|---|
task_name |
任务名(小写字母、数字、下划线) |
message |
分配给子 Agent 的初始任务说明 |
fork_turns |
继承父 Agent 的历史轮数,默认 "all" |
可选参数 model、reasoning_effort 用于覆盖模型及推理强度。
调用示例:
{
"task_name": "check_tests",
"message": "检查登录模块的测试覆盖,列出缺失用例,暂时不要修改代码。",
"fork_turns": "3"
}
路径呈逻辑树结构(如 /root/check_tests/edge_cases),内存通过 Map 维护而非逐层嵌套。
fork_turns:继承范围解析
| 取值 | 继承范围 |
|---|---|
"all" |
继承经过滤清理的可用父模型历史 |
"none" |
不继承父对话历史 |
"3" 等正整数 |
继承最近 N 个可识别的 Turn |
none 并非完全空白,仍包含基础指导、工具定义、环境信息及新任务。
all 非原始日志复制:保留用户消息、Assistant 最终回复及系统指导;过滤普通 Tool Call/Result、推理中间态。配置类记录另作处理,并清理父角色信息以适配子身份。
若父历史已压缩,Fork 会处理现有 Checkpoint,不会重新展开原文。目前设计暂不支持子 Agent 利用 KV Cache 复用父上下文。
子 Agent 完成后的通知机制
子 Agent 正常结束时,最终回复自动封装为完成消息发送至父 Agent 信箱,无需额外提交工具。
通信类型为 ResponseItem::AgentMessage(序列化后为 agent_message),简化结构如下:
{
"type": "agent_message",
"author": "/root/check_tests",
"recipient": "/root",
"content": [
{
"type": "input_text",
"text": "Message Type: FINAL_ANSWER\nTask name: /root\nSender: /root/check_tests\nPayload:\n发现两项缺失用例……"
}
]
}
仅最后一句消息自动回传,中间分析及工具结果不进入父上下文。需提前汇报时使用 send_message。
#2. send_message:投递消息
参数:target(Agent 标识或路径)和 message。
示例:
{
"target": "/root/client",
"message": "登录接口将新增 request_id 参数,请先不要修改调用处,等接口约定确认后再继续。"
}
底层流程:
AgentControl 提交 InterAgentCommunication。
消息读取时机
若子 Agent 正在运行工具,新消息入队但不中断当前操作。工具返回后,下次 LLM 请求即可同时看到结果与新消息。
注意:发送成功仅代表投递完成,不等于模型已读取。
此外,send_message 不会唤醒空闲 Agent。若需启动新 Turn,应使用 followup_task。
持久化机制
SQLite 记录父子关系表 thread_spawn_edges:
CREATE TABLE thread_spawn_edges (
parent_thread_id TEXT NOT NULL,
child_thread_id TEXT NOT NULL PRIMARY KEY,
status TEXT NOT NULL
);
status 表示派生关系状态。需注意:入队消息未落盘前,崩溃后无法恢复。
#3. followup_task:追加任务并唤醒
参数同 send_message,但内部标记 trigger_turn=true。
| 目标状态 | send_message | followup_task |
|---|---|---|
| 正在执行 | 加入 Mailbox,边界读取 | 加入 Mailbox,当前 Turn 可处理 |
| 普通空闲 | 不启动新 Turn | 启动新 Turn |
示例:子 Agent 完成分析后,主 Agent 可调用此工具让其继续补全测试。
#4. wait_agent:等待事件
可选参数 timeout_ms(默认 30 秒,范围 10 秒 -1 小时)。父 Agent 可借此等待子 Agent 消息、完成通知或超时,期间可并行处理其他工作。超时不会停止子 Agent。
#5. interrupt_agent:中断 Turn
参数仅 target。发送中断指令取消当前 Turn,保留身份与历史,后续可接新任务。适用于方向错误需立即修正的场景。
#6. list_agents:查询状态
可选 path_prefix 过滤分支。状态包括初始化、运行、完成、中断等。Completed 表示任务结束但仍可通过 Followup 激活。
资源不足时可卸载空闲 Agent(保留身份与历史)。并发额度由团队共享,防止无限派生。
三、多 Sub-agent 编辑同一文件的冲突处理
公共提示词明确指出:
All agents share the same directory. In detail:
- All agents have access to the same container and filesystem as you.
- All agents use the same current working directory.
- As a result, edits made by one agent are immediately visible to all other agents.
默认共用工作目录,spawn_agent 不自动创建独立 Worktree。A 修改文件后 B 立即可见,但 B 上下文中已读取的旧内容不会自动更新。文件共享与上下文同步是两回事。
若无显式分工,同时修改同一文件存在冲突风险。默认路径无跨 Agent 文件锁及自动合并机制。
建议:显式划分文件/模块范围,约定共享接口;如需同处修改,由单一 Agent 负责落盘,其余通过消息提出建议。
写在最后
Codex 的 Sub-agent 设计成熟,主副 Agent 通信高效且地位对等。
默认不派发子 Agent 源于工具并发能力已足够强大。
Harness 层未做多 Agent 冲突控制,需依赖主 Agent 合理规划子 Agent 行为。

