2026年4月27日 · Engineering
An open-source spec for Codex orchestration: Symphony
著者: Alex Kotliarskyi、Victor Zhu、Zach Brock
はじめに
6か月前、チームは内部生産性ツールの開発中に議論を呼ぶ決断を下しました。リポジトリ内のすべての行は人間が直接書かない――すべてをCodexで生成する、という方針です。それを実現するために、私たちはエンジニアリングのワークフローを根本から再設計しました。エージェントに適したリポジトリを構築し、自動テストとガードレールに大きく投資し、Codexをフルメンバーのチームメイトとして扱いました。この取り組みは以前のブログ記事でまとめています(ハーネスエンジニアリング) 。そしてうまくいきましたが、次のボトルネックに直面しました: コンテキストスイッチです。
この問題を解決するために私たちが作ったシステムが Symphony です。Symphony (opens in a new window) は、Linear のようなプロジェクト管理ボードをコーディングエージェントのコントロールプレーンに変えるエージェントオーケストレータです。すべてのオープンタスクにエージェントが割り当てられ、エージェントは継続的に動作し、人間は結果をレビューします。本記事では、Symphony をどのように作ったか(いくつかのチームで PR のランディング数が500%増加した)と、あなたの課題トラッカーを常時稼働するエージェントオーケストレータに変える方法を説明します。
対話型コーディングエージェントの限界
Webアプリや CLI 経由で使いやすくなっても、コーディングエージェントは依然として対話型のツールです。OpenAI 内でエージェント作業の規模が拡大するにつれて、新たな負担が見えてきました。各エンジニアは複数の Codex セッションを開き、タスクを割り当て、出力をレビューし、エージェントを誘導し、そして繰り返す。実際には、多くの人が同時に快適に扱えるのは 3〜5 セッションまでで、それを超えるとコンテキストスイッチがつらくなり、生産性が落ちました。
どのセッションが何をしているかを忘れ、ターミナルを行き来してエージェントを戻し、途中で停滞した長時間タスクをデバッグする。エージェント自体は高速でしたが、システムのボトルネックは人間の注意力でした。非常に有能なジュニアエンジニアのチームを事実上作っておきながら、人間のエンジニアが彼らをマイクロマネジメントしている状態でした。それではスケールしません。
視点の転換
私たちは最適化対象を間違えていることに気づきました。システムをコーディングセッションやマージ済み PR を中心に設計していたが、PR やセッションはあくまで手段です。ソフトウェアワークフローは大抵、デリバラブル(イシュー、タスク、チケット、マイルストーン)を中心に組織されています。そこで、エージェントを直接監督するのをやめ、代わりにタスクトラッカーから仕事を引っ張らせたらどうなるかを考えました。このアイデアが Symphony となり、エージェント的作業をオーケストレートする監督者として機能する一つの仕様書になりました。
タスクトラッカーをエージェントオーケストレータに変える
Symphony の出発点は単純です: オープンなタスクはすべてエージェントに拾われ完了されるべき、という考え方。複数タブで Codex セッションを管理する代わりに、私たちはイシュー トラッカーをコントロールプレーンにしました。この構成では、各オープンな Linear イシューが専用のエージェントワークスペースにマッピングされます。Symphony はタスクボードを継続的に監視し、アクティブなタスクごとにエージェントが実行ループに入っていることを保証します。エージェントがクラッシュまたはスタックしたら再起動し、新しい作業が現れればそれを拾い、作業を整理します。
私たちはチケットのステータスを基にワークフローを構築し、タスクマネージャ Linear を状態機械として使いました。実務では、Symphony は作業をセッションや PR から切り離します。あるイシューは複数のリポジトリにまたがる複数の PR を生むこともあれば、コードベースに全く触れない純粋な調査・分析の仕事もあります。このように抽象化されると、チケットはより大きな作業単位を表現できます。我々はしばしば複雑な機能やインフラ移行のオーケストレーションに Symphony を使います。
たとえば、エージェントにコードベース、Slack、Notion を分析して実装計画を作るタスクを出すことがあります。計画に満足したら、エージェントはタスクのツリーを生成し、作業を段階に分け、タスク間の依存関係を定義します。エージェントはブロックされていないタスクのみを開始するため、DAG(実行ステップの順序)に対して自然かつ最適に並列実行が展開されます。たとえば、React のアップグレードを Vite への移行にブロックとして設定した場合、期待どおり Vite への移行が完了してからエージェントは React のアップグレードを開始しました。
エージェントは自ら作業を作成することもできます。実装やレビューの最中に、現在のタスクの範囲外の改善点(パフォーマンス問題、リファクタリング、より良いアーキテクチャなど)に気づくことがよくあります。その場合、単に新しいイシューを作成し、私たちは後で評価してスケジュールできます。これらのフォローアップタスクの多くもエージェントに拾われます。私たちがこのプロセスを監督する一方で、エージェントは整理され作業を前に進め続けます。
この働き方は、曖昧な作業を始める認知的コストを劇的に下げます。エージェントが間違った結果を出しても、それ自体が有益な情報であり、私たちのコストはほぼゼロです。安価にプロトタイプや探索をエージェントに任せ、望ましくない探索は破棄できます。オーケストレータは devbox 上で常時稼働するため、どこからでもタスクを追加すればエージェントが拾ってくれます。例えば、チームのあるエンジニアは電波の悪い山小屋から Linear アプリ経由で 3 つの大きな変更を行いました。
探索の増加
Symphony を使った効果で最も明白だったのはアウトプットの量です。OpenAI 内のいくつかのチームでは、導入後最初の3週間でランディングした PR の数が 500% 増加しました。OpenAI 以外でも、Linear の創業者 Karri Saarinen は Symphony 公開時に作成されたワークスペース数の急増を指摘しました (opens in a new window)。しかし、より深い変化はチームが仕事を考える方法の変化です。
エンジニアが Codex セッションの監督に時間を割かなくなると、コードの経済性が完全に変わります。実装そのものを人間が推進するための労力を投資しなくなるため、各変更の認識コストが下がります。これにより、Symphony 上で投機的なタスクを立ち上げるのが簡単になりました。アイデアを試す、リファクタを探索する、仮説をテストする — うまくいったものだけを残せばいいのです。また、作業の起点を広げる効果もあります。プロダクトマネージャやデザイナーが直接 Symphony に機能要求を投げられるようになり、リポジトリをチェックアウトしたり Codex セッションを管理したりする必要がなくなりました。彼らは機能を記述すると、実際のプロダクト内で動く機能の動画ウォークスルーを含むレビューパケットを受け取ります。
Symphony は大きなモノレポ(OpenAI が持つもののような)でも威力を発揮します。PR をランディングする最後の一歩が遅くて脆い場合、システムは CI を監視し、必要ならリベースし、競合を解決し、フレークするチェックを再試行し、変更をパイプラインに通す役割を果たします。チケットが「Merging」に達する頃には、人間のベビーシッティングなしに main ブランチへ入る高い確信を持てます。
Symphony を実装したことで、より多くの作業をエージェントに委譲し、私たちはより難しく探索的な課題に集中できるようになりました。
新たに生じた問題
このレベルで運用することにはトレードオフが伴います。エージェントを対話的に誘導するのではなくチケット単位で仕事を割り当てるようにしたことで、途中でこまめに軌道修正する能力を失いました。時にエージェントは全く的外れな成果を出すことがありますが、それは有益な失敗であり、システムのギャップを明らかにして堅牢にする手助けになりました。結果を手でパッチする代わりに、ガードレールやスキルを追加して次回はエージェントが成功するようにしました。時間とともに、エンドツーエンドテストの実行、Chrome DevTools を用いたアプリ駆動、QA スモークテストの管理など、ハーネスに新しい能力を追加しました。ドキュメントを大幅に改善し、「良い見た目」を明確にしました。
すべてのタスクが Symphony スタイルに合うわけではありません。曖昧な問題や強い判断・専門性が必要な作業は、インタラクティブな Codex セッションでエンジニアが直接扱うべきです。実務上、これらは通常エンジニアが時間を費やすべき最も興味深く楽しい仕事です。違いは、Symphony がルーチンな実装作業の大部分を処理できることで、エンジニアは小さなタスク間を行き来する代わりに一つの難しい問題に集中できるようになる点です。
また、エージェントを状態機械の硬直したノードとして扱うのはうまくいかないことも学びました。モデルは賢くなり、私たちが押し込もうとする箱より大きな問題を解けるようになります。初期のエージェント作業は Codex にタスクを実装させるだけでしたが、それは制約がきつすぎました。Codex は複数の PR を作成し、レビューのフィードバックを読み対応することが可能です。そこで私たちはツール(gh CLI、CI ログを読むスキルなど)を与え、Codex に古い PR をクローズさせたり、完了した作業と放棄された作業のレポートを引かせたりできるようにしました。これらのタスクは初期の機能実装ボックスの範囲外でした。最終的に私たちはエージェントに厳格な遷移ではなく目的(objective)を与える方向に移りました。優れたマネージャがメンバーに目標を割り当てるのと同じです。モデルの力は推論能力にあるので、ツールとコンテキストを与えて自由に調理させましょう。
Symphony を使って Symphony を構築する
Symphony リポジトリを開くと (opens in a new window)、最初に気づくのは、技術的には Symphony が単なる SPEC.md ファイルであることです—問題の定義と意図された解法の記述です。複雑な監督システムを構築する代わりに、私たちは問題と意図された解決策を定義し、エージェントに高レベルの舵取りを与えました。
Symphony Service Specification
Status: Draft v1 (language-agnostic)
Purpose: Define a service that orchestrates coding agents to get project work done.
1. Problem Statement
Symphony is a long-running automation service that continuously reads work from an issue tracker
(Linear in this specification version), creates an isolated workspace for each issue, and runs a
coding agent session for that issue inside the workspace.
The service solves four operational problems:
- It turns issue execution into a repeatable daemon workflow instead of manual scripts.
- It isolates agent execution in per-issue workspaces so agent commands run only inside per-issue
workspace directories.
- It keeps the workflow policy in-repo (
WORKFLOW.md) so teams version the agent prompt and runtime
settings with their code.
- It provides enough observability to operate and debug multiple concurrent agent runs.
Implementations are expected to document their trust and safety posture explicitly. This
specification does not require a single approval, sandbox, or operator-confirmation policy; some
implementations may target trusted environments with a high-trust configuration, while others may
require stricter approvals or sandboxing.
Important boundary:
- Symphony is a scheduler/runner and tracker reader.
- Ticket writes (state transitions, comments, PR links) are typically performed by the coding agent
using tools available in the workflow/runtime environment.
- A successful run may end at a workflow-defined handoff state (for example
Human Review), not
necessarily Done.
2. Goals and Non-Goals
2.1 Goals
- Poll the issue tracker on a fixed cadence and dispatch work with bounded concurrency.
- Maintain a single authoritative orchestrator state for dispatch, retries, and reconciliation.
- Create deterministic per-issue workspaces and preserve them across runs.
- Stop active runs when issue state changes make them ineligible.
- Recover from transient failures with exponential backoff.
- Load runtime behavior from a repository-owned
WORKFLOW.md contract.
- Expose operator-visible observability (at minimum structured logs).
- Support restart recovery without requiring a persist
(原文はここで終端に到達しています。仕様書全文や実装例はリポジトリの SPEC.md を参照してください。)