之前我写了篇 Codex CLI 与 OpenCode 的对比,那篇文章侧重于 general 场景的横向评测。最近在开发一个 Obsidian 同步插件时,我有了更深的感受——当任务复杂度提升到某个临界点,两者的差距不是线性增长,而是质的分化

场景:开发一个复杂的插件 链接到标题

这个插件需要:

  • 理解 Obsidian 的插件 API 和事件系统
  • 实现增量同步的状态机(chunker + diff + merge)
  • 与 CouchDB 后端交互,处理冲突解决
  • 多文件协同,跨多个模块的状态一致性

用 Codex 跑这个任务,从头到尾大约 20 分钟,人工介入 1 次(最后 review 时改了一个变量名)。

用 OpenCode 跑同一个任务,大约 40 分钟,人工介入 4 次

  1. 某个子任务完成后需要确认,才肯继续
  2. doom loop 检测触发了一次
  3. 压缩后上下文丢失,一度开始改无关内容
  4. 最后合并时又需要一次确认

这不是模型的问题——两者用的都是 deepseek v4 flash medium。问题出在架构设计上。

架构分析:单 Agent 循环 vs 多 Subagent 树 链接到标题

OpenCode 的单 Agent 循环 链接到标题

OpenCode 的核心执行逻辑在 SessionProcessor.process(),是一个 while(true) 的单线程循环:

// OpenCode - 单 Agent 循环示意
while (true) {
  const stream = await LLM.stream(input)
  for await (const value of stream.fullStream) {
    switch (value.type) {
      case 'tool-call':
        const result = await executeTool(value.toolName, value.input)
        // 将结果注入下一个 turn
        break
      case 'finish-step':
        if (result === 'tool-calls') continue
        return // 任务完成
    }
  }
  // 上下文超限?触发 compaction
  if (needsCompaction) await compact()
}

这个模型有几个固有的限制:

  1. Doom Loop 检测是双刃剑 当同一个工具被连续调用 3 次且参数相同,OpenCode 会暂停并等待用户确认。这是好的安全设计,但对于某些"正当的重复操作"(比如批量创建 10 个文件),它也会触发中断。

  2. 上下文压缩是全局的 当对话历史太长,OpenCode 会调用一个专门的 compaction agent 来压缩上下文。压缩后,原先分散在多处的地方变量可能丢失,LLM 的指令跟随会退化。

  3. 没有任务分解机制 复杂任务只能在一个 Agent 里顺序执行。每个子任务都依赖同一个上下文窗口,任何一个环节出问题都会影响后续。

Codex 的多 Subagent 树 链接到标题

Codex 的核心区别是支持 Subagent Fork——一个任务可以分解为多个独立或半独立的子代理并行执行:

// Codex - Subagent Fork 示意
pub enum SpawnAgentForkMode {
    FullHistory,           // 复制完整历史
    LastNTurns(usize),    // 只复制最近 N 轮
}

pub struct SpawnAgentOptions {
    pub fork_parent_spawn_call_id: Option<String>,
    pub fork_mode: Option<SpawnAgentForkMode>,
    pub parent_thread_id: Option<ThreadId>,
    pub environments: Option<Vec<TurnEnvironmentSelection>>,
}

这带来了几个关键优势:

  1. 任务天然分解 复杂插件开发可以分解为:

    • Subagent A:实现 chunker 模块
    • Subagent B:实现 sync 状态机
    • Subagent C:实现 CouchDB 交互层
    • 主 Agent:协调各模块,最终合并 每个子代理独立运行在自己的上下文中,互不干扰。
  2. RolloutBudget 精细控制 Codex 有 RolloutBudget 机制,可以精确控制每个子任务的 token 预算,避免单任务耗尽整个会话的资源。

  3. TurnEnvironmentSelection 多环境并行 Codex 支持在不同的"环境"中并行执行任务,每个环境有独立的文件视图和工具权限。这对于插件开发尤其有用——可以在隔离环境中测试,不污染主分支。

  4. 压缩是局部的 每个 Subagent 独立压缩自己的历史,不会因为一次全局压缩而丢失其他无关模块的上下文。

两种设计哲学 链接到标题

维度 OpenCode
设计优先级 可控性 > 吞吐量
哲学 “AI 应当随时可以被干预”
适用场景 短任务、需要频繁确认
安全模型 per-tool/per-command 细粒度
上下文管理 全局压缩

这没有对错之分。OpenCode 的设计更保守,更适合团队场景——每个操作都能被审计和干预。Codex 的设计更激进,适合个人开发者跑长任务,不需要中途停下来"教它怎么做"。

实际感受 链接到标题

Codex 的 20 分钟长跑 链接到标题

我给 Codex 的 prompt 大约是:

“实现一个 Obsidian 同步插件,参考 Obsidian Sync 的 chunk-based 增量同步方案,支持 CouchDB 后端,实现冲突解决…”

Codex 自动分解了子任务,Subagent 并行工作,中途只有一次我手动让它停了一下(因为它想用一个过时的 API)。最后 review 时发现代码质量很高,状态机设计合理,注释也很清晰。

OpenCode 的 4 次介入 链接到标题

同样的 prompt,OpenCode 会在每个"阶段"完成后等待确认:

  • chunker 实现完了,等我确认
  • sync 模块开始,等我确认
  • 突然触发 doom loop 检测(它在尝试用同样的方式读文件),我点了继续
  • compaction 后上下文丢失,它开始改无关内容,我赶紧拉回来
  • 最后合并,又等确认

单次任务时间反而更长,介入次数更多。

什么时候选哪个 链接到标题

任务类型 推荐
复杂插件/SDK 开发 Codex
快速单文件修改 OpenCode
需要多模型切换、本地模型 OpenCode
多日 goal 持久化 Codex
团队安全审计 OpenCode

结论 链接到标题

Codex 之所以在复杂任务上表现更好,不是因为模型更强,而是因为架构设计上允许任务分解和并行执行。OpenCode 的单 Agent 循环 + 全局压缩模型,在短任务上可控性强,但在长任务上会成为瓶颈。

这不是一个工具比另一个工具"更好"的问题,而是不同架构适合不同任务的问题。如果你经常跑 10 分钟以上的复杂开发任务,Codex 的 Subagent 机制会显著提升体验。如果你主要是快速修改、团队协作、需要细粒度权限控制,OpenCode 仍然是更好的选择。

两者的设计哲学恰好代表了这个领域两种路线的分歧:一种是把 AI 当作需要被监督的助手,另一种是把 AI 当作可以独立作业的同事。哪种更合适,取决于你的工作场景。