Skip to content

Codex 编排的开源规范:Symphony

作者:Alex Kotliarskyi、Victor Zhu 和 Zach Brock

六个月前,在开发一个内部生产力工具时,我们团队做出了一个当时颇具争议的决定:构建一个完全没有人工编写代码的代码仓库。仓库中的每一行代码都必须由 Codex 生成。

为了实现这一目标,我们从底层重新设计了工程工作流。我们构建了一个对智能体友好的代码仓库,大量投入自动化测试和防护机制,并将 Codex 视为一个完整的团队成员。我们在此前关于 运行框架 (harness) 工程的博客文章中记录了这一过程。

这一方法确实奏效了,但随后我们遇到了下一个瓶颈:上下文切换。

为了解决这个问题,我们构建了一个名为 Symphony 的系统。 Symphony 是一个智能体编排器,它将类似 Linear 的项目管理看板转化为编程智能体的控制平面 (control plane)。每一个未关闭的任务都会对应一个智能体,智能体持续运行,而人类负责审查结果。

本文将介绍我们如何构建 Symphony — 在部分团队中将已合并到主分支的 Pull Request 数量提升了 500% — 以及如何将你自己的 issue 跟踪系统转化为一个始终在线的智能体编排系统。

即使编程智能体变得越来越易用 — 无论是通过 Web 应用还是 CLI 访问 — 它们本质上仍然是交互式工具。

随着 OpenAI 内部智能体工作规模的扩大,我们开始感受到一种新的负担。每位工程师都会打开多个 Codex 会话,分配任务、审查输出、引导智能体,然后不断重复这一过程。在实践中,大多数人通常只能同时管理 3 到 5 个会话,再多就会因为上下文切换而变得困难。一旦超过这个范围,生产力就会下降:我们会忘记每个会话正在做什么,在不同终端之间来回切换以将智能体拉回正轨,还需要调试那些中途停滞的长时间运行任务。

智能体本身运行很快,但系统的瓶颈在于人类注意力。我们实际上构建了一支能力极强的“初级工程师团队”,却让人类工程师对其进行细粒度管理。这种模式无法扩展。

我们意识到,我们优化的对象是错误的。我们一直围绕编程会话和已合并的 PR 来组织系统,而实际上,这两者只是达成目标的手段。软件工作流通常是围绕交付物组织的,例如 issue、任务、工单和里程碑。

于是我们开始思考:如果不再直接监督智能体,而是让它们从任务跟踪系统中主动获取工作,会发生什么?

这个想法最终演变为 Symphony — 一份书面规范 (spec),作为“监督者”来编排智能体工作。

将 issue 跟踪器转化为智能体编排器

Section titled “将 issue 跟踪器转化为智能体编排器”

Symphony 源于一个简单的理念:任何未关闭的任务都应由智能体接手并完成。我们不再在多个标签页中管理 Codex 会话,而是将 issue 跟踪系统作为控制平面 (control plane)。

在这一模式下,每一个未关闭的 Linear issue 都会映射到一个专属的智能体工作空间。Symphony 持续监控任务看板,确保每一个活跃任务在完成之前始终有智能体在循环执行。如果某个智能体崩溃或卡住,Symphony 会自动重启它;如果出现新的工作,Symphony 会立即接手并开始组织执行。

我们的工作流是基于工单状态构建的,将任务管理工具 Linear 作为一个状态机来使用。

Coding agents use Linear as a state machine to work alongside us.

在实践中,Symphony 将工作从会话和 Pull Request 中解耦。有些 issue 会在多个代码仓库中产生多个 PR;而另一些则只是纯粹的调研或分析,完全不会涉及代码库。

一旦以这种方式对工作进行抽象,工单就可以代表更大粒度的工作单元。

我们经常使用 Symphony 来编排复杂功能开发和基础设施迁移。例如,我们可以创建一个任务,让智能体分析代码库、Slack 或 Notion,并产出一份实现方案。当我们确认方案可行后,智能体会生成一棵任务树,将工作拆分为多个阶段,并定义任务之间的依赖关系。

智能体只会处理未被阻塞的任务,因此在这个 DAG(一个执行步骤序列)结构中,执行会自然且高效地并行展开。在下面的示例中,我们将 React 升级标记为依赖 Vite 迁移。正如预期,智能体会在 Vite 迁移完成之后才开始升级 React。

智能体还可以自行创建任务。在实现或审查过程中,它们经常会发现一些超出当前任务范围的改进点,例如性能问题、重构机会或更优架构。这时,它们会直接创建新的 issue,供我们后续评估和排期 — 其中许多后续任务同样会被智能体接手执行。在我们进行整体监督的同时,智能体能够保持有序并持续推进工作。

这种工作方式显著降低了启动不确定性任务的认知成本。即使智能体做错了,这些结果仍然具有信息价值,而我们的成本几乎为零。我们可以以极低成本创建工单,让智能体进行原型验证和探索,并随时丢弃不满意的结果。

由于编排器运行在开发环境 (devbox) 上且始终在线,我们可以在任何地方添加任务,并确信会有智能体接手处理。例如,我们团队中曾有工程师在一个网络条件较差的小木屋里,仅通过手机上的 Linear 应用就完成了三项重要变更。

这种工作方式带来的探索能力提升

Section titled “这种工作方式带来的探索能力提升”

在观察 Symphony 带来的影响时,最直观的变化是产出。在 OpenAI 的一些团队中,已合并到主分支的 PR 数量在前三周内增长了 6 倍。在 OpenAI 之外,Linear 创始人 Karri Saarinen 也提到,在 Symphony 发布后,工作空间创建量出现了明显增长。不过,更深层的变化在于团队对“工作”的理解方式。

当工程师不再需要花时间管理 Codex 会话时,代码变更的成本结构发生了根本变化。由于不再需要投入人力推动具体实现,每一次变更的感知成本显著下降。

这也改变了我们的工作方式。在 Symphony 中启动探索性任务变得非常轻量:尝试一个想法、探索一次重构、验证一个假设,然后只保留那些有价值的结果。

此外,它还扩大了可以发起工作的角色范围。产品经理和设计师现在可以直接在 Symphony 中提交功能请求,无需检出代码仓库,也无需管理 Codex 会话。他们只需描述需求,就能获得一个评审包,其中包含该功能在真实产品中的视频演示。

Symphony 在大型单体仓库(就像我们在 OpenAI 用的那种) 中同样表现出色。在这种环境下,将一个 PR 成功落地到主分支的“收尾阶段”往往缓慢且脆弱。系统会持续监控 CI,在需要时自动执行变基、解决冲突、重试不稳定的检查,并整体上推动变更通过整个流水线。当一个任务进入合并 阶段时,我们已经可以高度确信该变更能够在无需人工干预的情况下顺利进入主分支。

Before and after grid of Symphony

在这一层级上运作不可避免地存在权衡。当我们从交互式引导智能体转向按工单分配工作时,我们失去了在执行过程中持续干预并随时纠偏的能力。有时智能体产出的结果会完全偏离预期。但这些失败同样具有价值 — 它们暴露了系统中的缺口,并帮助我们提升系统的稳健性。

我们没有手动修补这些结果,而是增加防护措施和技能,使智能体在下一次能够正确完成任务。随着时间推移,这促使我们为运行框架 (harness) 增加了新的能力,例如运行端到端测试、通过 Chrome DevTools 驱动应用,以及管理 QA 冒烟测试。同时,我们也显著改进了文档,并明确了什么才是“好的结果”。

并非所有任务都适合 Symphony 这种工作方式。有些问题仍然需要工程师直接使用交互式 Codex 会话来处理,尤其是那些高度不确定或需要强判断力与专业经验的任务。在实践中,这类任务通常也是工程师最有兴趣投入精力的部分。

不同之处在于,Symphony 可以处理大部分常规实现工作。这使工程师能够一次专注于一个复杂问题,而不必在大量小任务之间频繁切换上下文。

我们还发现,将智能体当作状态机中的刚性节点并不是一个理想的模型。随着模型能力的提升,它们能够解决的问题远超我们试图限定的范围。例如,在早期版本中,所有 GitHub 集成都被放在外层运行框架 (harness) 中 — 当时我们假设 Codex 只负责代码修改,而将提交变更、运行测试等流程写死在系统中。早期版本的智能体工作方式只是让 Codex 完成具体任务本身,这种方式被证明具有不少局限性。事实上,Codex 完全可以创建多个 PR,也可以读取评审反馈并进行修改。因此我们为它提供了更多工具 — 例如 gh CLI、读取 CI 日志的技能等 — 现在我们可以让 Codex 执行更多类型的工作,例如关闭旧 PR,或生成已完成与已放弃任务的报告。这类工作已经远远超出了最初“功能实现”的范围。

因此,我们最终转向为智能体设定 “目标 (objective)” ,而不是严格的状态转换。这类似于优秀的管理者为团队成员设定目标的方式。模型的核心能力在于推理,因此应为其提供工具和上下文,然后让它们自主完成任务。

当你打开 Symphony 代码仓库时,首先会注意到的是:从技术上讲,Symphony 其实只是一个 SPEC.md 文件 — 它定义了问题以及预期的解决方案。我们没有构建一个复杂的监督系统,而是通过定义问题和目标解法,为智能体提供高层次的引导。

参考实现使用 Elixir 编写 — 因为当代码的生成成本接近于零时,我们终于可以根据语言本身的优势来做选择,例如 Elixir 在并发方面的能力 — 但其核心思想其实可以通过一份简单的 Markdown 文档来表达。我们建议你让常用的编程智能体参考该规范 (spec),并实现一套自己的版本。

Symphony 的第一个版本只是一个运行在 tmux 中的 Codex 会话,它会轮询 Linear,并为新任务生成子智能体。它能够工作,但稳定性并不理想。第二个版本被集成进我们的主项目代码仓库中,而该仓库本身就是围绕智能体设计的。我们已经构建了智能体运行框架 (harness),为智能体提供在该仓库中完成高质量工作的技能和上下文,因此 Symphony 的作用只是将这些组件连接起来。

当基础功能具备之后,我们开始用 Symphony 来构建 Symphony 本身。

当我们在内部演示该系统 — 展示其如何管理任务并附带工作证明视频 — 时,反馈非常积极:Symphony 项目频道迅速增长,组织内的多个团队也开始自发使用它。在 OpenAI,对外发布之前的前提是先达到内部的产品市场契合。基于我们在内部看到的使用情况,我们很快意识到应该将 Symphony 推广到公司之外。

因此,我们将这一想法提炼为一个独立的 SPEC.md,并让 Codex 来实现它。在参考实现中,我们选择了 Elixir,这是一门相对小众但在编排和监督并发进程方面具有优秀原语的语言。Codex 一次性完成了 Elixir 实现,随后我们持续迭代规范和实现。为了进一步打磨规范,我们还让 Codex 使用多种语言进行实现 — 包括 TypeScript、Go、Rust、Java 和 Python — 并通过这些实现结果识别歧义并简化系统。它在每种语言中都成功完成了实现。

在构建 Codex 的过程中,我们去除了大量非本质复杂度,例如对特定代码仓库或 Linear MCP 的依赖。Symphony 不再依赖内部仓库或工作流,其核心方法被简化为:

对于每一个未关闭的任务,都确保有一个智能体在其独立工作空间中运行。

除了帮助处理正在进行的工作之外,如今开发工作流本身也成为智能体能够理解并遵循的内容。开发工作流 — 处理 issue、检出代码仓库、将任务标记为进行中以便 PM 知道工作已启动、创建 PR、将其移动到审核状态、附加视频等 — 现在都被记录在一个简单的 WORKFLOW.md 文件中。这一整套流程原本由人类执行,但从未被显式记录。与其依赖这些隐性的步骤,我们现在将其文档化,并由 Symphony 确保智能体严格遵循。这使我们能够构建真正与人协同工作的智能体。如果我们决定让智能体在完成工作后附加自我反思,只需将该步骤写入 WORKFLOW.md,Symphony 就会引导智能体执行这一流程。

我们还使用了 Codex 的 app server 模式,这是 Codex 内置的一种无头 (headless) 运行模式。在这种模式下,我们可以运行 Codex,并通过文档完善的 JSON-RPC API 以编程方式与其交互,例如启动线程或响应对话轮次。这相比通过 CLI 或实时 tmux 会话与 Codex 交互,更加便捷且更具可扩展性。

Codex App Server 非常契合我们的使用场景:我们既利用了 Codex 提供的运行框架 (harness),又能够通过各种接口进行扩展。例如,为了避免将 Linear 的访问令牌暴露给子智能体,我们使用动态工具调用 (dynamic tool call) 来暴露底层的 linear_graphql 函数,从而在不依赖 MCP、也不向容器暴露访问令牌的情况下,对 Linear 执行任意请求。

Symphony 是一个刻意保持简洁的编排层。我们将其开源,是为了展示 Codex App Server 在与不同工作流工具(例如 Linear)结合使用时的能力。因此,我们并不打算将 Symphony 作为一个独立产品来持续维护。你可以将它视为一个参考实现。类似于许多开发者曾让编程智能体基于运行框架 (harness) 工程文章来快速搭建代码仓库,我们也希望你让自己的智能体参考 Symphony 的 specrepository,构建适配自身环境的实现版本。

其核心能力来自 Codex 及其 app server。Symphony 的作用,是将我们已经在使用的两个系统 — Codex 和 Linear — 连接起来,从而解决工作管理问题。随着编程智能体在推理和遵循指令方面不断增强,我们预计其他公司的瓶颈也会从“写代码”转向“管理智能体工作”。值得注意的是,尝试这类系统的门槛已经变得非常低 — 你完全可以直接用 Codex 构建自己的系统。

我们很高兴看到工程社区在发布后的几周内开始使用 Symphony。截至 4 月 23 日,该项目已在 GitHub 上获得超过 1.5 万颗星


我们很高兴看到工程社区在发布后的几周内开始使用 Symphony。截至 4 月 23 日,该项目已在 GitHub 上获得超过 1.5 万颗星

社区开发者也积极响应,推出了多种语言的实现版本,包括 Elixir、Go、TypeScript、Rust、Java、Python 等。还有开发者将其适配为 Claude Code + GitHub Issues 的版本。