两个 Codex 会话第一次能直接对话:@提及与原生 worktree 如何补齐并行协作

两个终端,一个仓库#
并行跑 Agent 的第一天通常很爽,第二天开始难受。
爽的部分很直观:一个会话在查一个诡异的线上报错,另一个会话在写新功能,互不等待,吞吐翻倍。难受的部分往往在某个具体时刻才浮现:屏幕上两条命令的输出开始交错,两个 Agent 都在动同一批文件,git status 里混着两段来路不同的改动,你分不清哪一行属于谁。
于是你退回到单线程。理由也很充分:混乱的成本超过了并行的收益。
这里真正缺的东西有两样,而且它们看起来是互相矛盾的。第一样是隔离,让两个会话在文件层面彻底不共享。第二样是通信,让它们还能交换结论、对齐接口、传递契约。只做隔离,就得到两个互不知情的孤岛,最后还是要人来当信使;只做通信,就得到两双手抢同一个键盘。
2026 年 8 月到 9 月之间,Codex CLI 用两个分别发布的原语,把这两半凑齐了。有意思的是,它们单独看都不算革命性,合起来才产生了新东西。
原语一:把会话变成可寻址的对象(v0.150.0)#
2026 年 8 月 26 日发布的 v0.150.0 里,有一条很不显眼的特性说明:可以用 @ 提及其他 Codex 任务,也可以让 Agent 在终端里读取、创建或给任务发消息。
这条说明之所以不显眼,是因为它太像聊天软件的功能。但在 Agent 语境里,「可寻址」是一个结构性变化。
在此之前的跨会话协作,只有三条路,每条都有味道:
- 共享文件:会话 A 把结论写进一个临时文件,会话 B 去读。问题是两份工作流的文件边界开始重叠,孤儿文件堆积,而且谁写谁读的时序完全靠约定。
- 手工轮询:会话 B 反复检查某个状态文件是否更新。浪费 turn,而且延迟不可控。
- 底层消息总线:
codex queue提供的消息通道能工作,但需要额外脚本,属于工程师专属工具,团队里推广不开。
@task-name 把这件事降级成了一个名字。会话 B 想知道会话 A 查到了什么,直接 @investigate 提问,对方的状态、输出和历史都是可读的。没有文件被创建,没有时序竞争,没有共享的可写介质。
这里有个容易被忽略的设计细节:它把「对方的上下文」也变成了可查询资源。过去在终端之间传递结论,你复制的是对方的文字总结,而总结是人写的,或者是被压缩过的,信息在搬运过程中掉了一层。命名通道拿到的是会话自己的状态与历史,信息衰减更少。
同时发布的还有 Interrupt 钩子,能在顶层 turn 被打断时执行命令或 MCP 处理器。单独看是可靠性增强,放在并行场景里,它意味着「被中断」不再等于「状态不明」。
原语二:worktree 从手工脚本变成受管资源#
隔离这件事,社区早就用 git worktree 解决了。问题在于解决得很不好用。
在 worktree 支持被收进 CLI 之前,想让两个会话并行跑同一个仓库,你需要手动执行 git worktree add,然后处理一串容易漏掉的环境变量(GIT_DIR、GIT_WORK_TREE、GIT_INDEX_FILE),还得考虑内容过滤、钩子继承、失败回滚。这段脚本在社区里被反复分享,说明它确实有用,也说明它确实麻烦。
v0.153.0 引入了 WorktreeManager,把上面那整套隔离契约收进一次调用:每个并行会话拿到一个从 HEAD 或指定 base ref 切出的独立 worktree,钩子继承、文件监视器、环境变量都被自动抑制,创建失败时自动回滚。
然后是那个真正改变默认行为的节点:v0.156.0(2026 年 9 月 22 日)把 worktree 支持设为默认开启,并且可以直接在 agent 命令中心里,从任务列表创建一个 worktree 会话。官方发布说明里那句话很朴素:「按状态过滤任务,并从 agent 命令中心创建 worktree 会话;worktree 支持现在默认启用。」
对照一下前后两代做法:
| 事项 | 手工时代(v0.153.0 之前) | 受管时代(v0.153.0+,v0.156.0 起默认) |
|---|---|---|
| 创建并行会话 | 手工执行 git worktree add | agent 命令中心或 codex agents TUI |
| 抑制环境变量 | 手动 export 一串 git 变量 | 由 WorktreeManager 自动处理 |
| 钩子处理 | 手工 unset 或禁用 | 自动抑制 |
| 失败回滚 | 手动 git worktree remove | 自动回滚 |
| 跨会话查询 | 共享临时文件或 codex queue | @task-name 提及 |
| 合并责任 | 隐式,很容易忘 | 刻意设计为显式人工步骤 |
最实用的一行是最后那行。前四行是效率提升,最后一行是设计立场。
按官方文章的说法,一个过去需要十行 shell 脚本才能搭起来的双 worktree 会话,现在在 agents TUI 里是四次按键。数字不重要,重要的是它把一个「需要读文档才敢做的事」变成了「顺手就做了」。
三种可以直接抄的协作模式#
隔离和通信都到位之后,真正有意思的问题是:怎么用。原始文章总结了三种模式,我觉得它们覆盖了大部分真实需求,值得逐个说清楚,以及各自适合什么场景。
模式一:调查与改造分离#
这是最常见也最省心的一种。任务 A 以只读方式跑,负责定位失败面、梳理根因,产出一份结构化的诊断结论。任务 B 负责写代码,但在动第一个文件之前,先去问 A。
# 任务 B(实现侧)在调查完成后的动作:
# "在修改任何东西之前,先向 @investigate 查询根因摘要。"
关键在时序。B 并没有被系统层面阻塞,但「写文件之前必须先查询 A」这条软依赖,把过早改动挡在了门外。A 完成之后,B 引用它的结论继续,人不需要在两个终端之间搬运输出。
这个模式有个常被忽视的好处:它保护的是实现会话的上下文窗口。诊断阶段要读大量文件、跑大量只读命令,这些操作的中间产物对实现阶段毫无价值,却会挤占推理空间。把两者分到不同 worktree,等于给实现会话做了一次免费清理。
模式二:同一需求的两种架构,并行跑#
两个 worktree 用不同架构实现同一个功能,第三个会话在两个都完成后通过 @ 分别查询,汇总取舍,交给人做决定,然后只合并其中一个分支,另一个直接丢弃。
对架构选型这种「不确定哪个更好」的问题,并行实现比顺序评估更快,也比开一场两小时的会更快。第三个会话不需要从零读两套代码,它拉的是两个实现会话自己给出的结构化摘要。
要提醒一点:这个模式只适合实现成本可控的需求。如果每个方案都要三天,并行就是三天的双倍浪费,顺序做更划算。
模式三:前后端并行,中途对齐契约#
前端和后端两个会话同时开发,中途必须就一个 API 契约(接口定义或类型 schema)达成一致,否则两边都完不成。以前这个同步点靠人在终端之间粘贴,或者临时提交到共享分支。现在它是会话之间的一次问答:
# @frontend 在契约检查点查询:
# "@backend 确认一下 /api/events 的响应结构。"
# @backend 回复当前 schema 草稿。
# @frontend 拿到确认后的 schema 继续。
这个模式最容易失败的地方不是技术,是契约检查点没有事先写下来。什么时候对齐、对齐什么字段,必须提前落到 AGENTS.md 的一个协调小节里,写清楚任务名、检查点名称和期望交换的信息。没写,两个 Agent 就会各自埋头走到很深的地方,然后撞在一起。
为什么最后一步合并不自动化#
这三个模式有一个共同的不变量,原始文章说得很清楚:Agent 完成不等于代码集成。两个会话各自完成工作,得到的是两个孤立的分支,不是一个合并好的代码库。
你可以把「自动合并」做出来,但 Codex 的 worktree 模型刻意不做。它把 git merge 当成一次必须有意识做出的人类动作,而不是 Agent 完成的自动后果。
我对这个立场持赞成态度,理由有三层。
第一层是责任归属。如果并行会话能自动合并,那「谁批准了这次改动」这个问题就没有答案了。而在多 Agent 场景里,出错时的回溯能力比省下的三十秒重要得多。
第二层是冲突的性质。两个 Agent 各自按自己的理解实现同一个接口,冲突往往不是文本层面的(那种 git 能自动解决),而是语义层面的:两边对同一个字段的含义理解不同,代码都能编译,测试都不报错,合并后系统错了。这种冲突只有人看得到。
第三层是工作区卫生。原始文章提到一个很真实的观察:跳过合并纪律的团队,往往会积累一堆过期的 worktree,等到发现集成冲突的时候,两个实现已经分叉得很远。合并这一步被显式写出来,同时也在提醒你清理。
顺带说,v0.156.0 的发布说明里还有一条值得单独注意的安全变化:不受信任的项目不再提供项目级 AGENTS.md 指令,同时加强了托管的读取拒绝策略。放在并行场景里意义很大:任何一个 worktree 都可能是从一个不受信任的仓库派生出来的,如果项目级指令能随便注入,@ 提及通道就成了一个很顺手的横向移动路径。
落地清单:先写进 AGENTS.md 的三节#
多 worktree 工作流里,口头约定等于没有约定。下面是一个双会话并行冲刺的最小骨架,可以直接改:
## 并行会话配置(v0.156.0+)
### 活动任务
| 任务名 | Worktree | 角色 | 状态 |
|--------|----------|------|------|
| @investigate | worktree-invest | 只读 | 运行中 |
| @implement | worktree-impl | 写入 | 待启动 |
### 协调规则
- @implement 在写任何文件之前,必须先查询 @investigate。
- 契约检查点:@implement 与 @investigate 确认受影响的文件清单。
- 合并:人工审查两个会话后,合并 @implement 分支。
### 合并纪律
- 任何任务都不得自行合并到主分支。
- @implement 在最终提交前用 `git diff main` 确认改动范围。
- 合并完成后,通过命令中心清理未使用的 worktree。
三节的分工很清楚:活动任务回答「有哪些会话在跑」,协调规则回答「它们在什么时机交换什么」,合并纪律回答「谁有权把结果落到主干」。缺任何一节,并行就会退化成两个互不知情的进程。
适合谁,不适合谁#
写到这里,该给一个不那么客气的判断。
值得用的情况:一个任务天然可以拆成两个不共享文件的子任务,而且中间有一个明确的同步点。典型的是「先诊断再修」「前后端定契约」「两种方案选一个」。这些场景里,隔离减少污染,通信减少返工,两样都吃到。
不值得用的情况:任务本身很小,或者拆分边界说不清楚。把一个两小时的改动拆成两个会话,协调开销会吃掉全部收益。另外,如果两个会话要改的文件高度重叠,worktree 也救不了你,那本质上是同一份工作。
还有一类需要谨慎:依赖大量隐式约定的任务。@ 提及只能传递显式写下来的东西。如果你们团队的关键决策一直是靠代码风格和口头默契传递的,那把它拆给两个会话,只会让默契失效得更快。
结语#
把这两件事放在一起看,会发现它们解决的不是效率问题,而是信任边界问题。
@task-name 让会话之间的信息流动变得可寻址、可审计,取代了共享临时文件那种「谁写谁读全靠约定」的模糊地带。受管 worktree 让隔离成为默认,而不是需要精心维护的脚本。而把合并留给人,是在整条流水线上刻意保留了一个人类判断点。
这三者合起来回答的是一个很基础的问题:当你同时派出多个 Agent,你到底还把不掌握最后那道门。
从 v0.150.0 到 v0.156.0 只隔了不到一个月,但那个月里 Codex CLI 补上的东西,恰好是过去让很多人放弃并行的那一段。
参考来源#
- Cross-Task Coordination: Combining @Mentions and Native Worktrees for Parallel Coding, Daniel Vaughan, Codex Knowledge Base, 2026-09-29. https://codex.danielvaughan.com/2026/09/29/cross-task-coordination-mentions-worktrees-parallel-coding-codex-cli/
- Codex CLI v0.150.0 Release Notes, OpenAI, 2026-08-26. https://github.com/openai/codex/releases/tag/rust-v0.150.0
- Codex CLI v0.153.0 Release Notes, OpenAI, 2026-09. https://github.com/openai/codex/releases/tag/rust-v0.153.0
- Codex CLI v0.156.0 Release Notes, OpenAI, 2026-09-22. https://github.com/openai/codex/releases/tag/rust-v0.156.0