πŸ€– AI Tools
Β· 9 min read

OpenAI Symphony: Open-Source Agent Orchestration That Turns Linear Tickets Into Pull Requests


Symphony is OpenAI’s open-source orchestration spec that turns Linear tickets into pull requests without human intervention. It watches your Linear board, picks up issues, spins up isolated workspaces, runs Codex agents inside them, and delivers PRs with passing CI. The repo has crossed 15K GitHub stars since its release, and for good reason: it solves the β€œlast mile” problem of coding agents by handling everything around the actual code generation.

Built entirely in Elixir/OTP, Symphony leans on the BEAM virtual machine’s strengths (fault tolerance, lightweight concurrency, distributed computing) to run dozens of coding agents in parallel on a single node. If an agent crashes, the supervision tree restarts it. If the whole node goes down, Symphony recovers state from the Linear board itself. No database. No external queue. Just a daemon, a tracker, and a set of conventions.

If you have been following our work on multi-agent systems, Symphony is the most production-ready implementation of the patterns we have been writing about. Let’s break it down.

How Symphony Works

The core loop is straightforward:

  1. A long-running daemon polls your Linear board on a configurable interval.
  2. When it finds an issue in a designated β€œReady for Agent” state, it claims the ticket by moving it to β€œIn Progress.”
  3. Symphony creates an isolated workspace for the task: a fresh git clone, pinned to the correct branch, with dependencies installed.
  4. A Codex agent is spawned inside that workspace with the issue description, relevant context files, and repo conventions as its prompt.
  5. The agent writes code, runs tests locally, and commits changes.
  6. Symphony opens a pull request against the target branch, links it to the Linear issue, and triggers CI.
  7. If CI passes, the ticket moves to β€œIn Review.” If CI fails, the agent gets the failure logs and retries (up to a configurable limit).

The entire state machine lives in memory. There is no database backing the orchestration layer. This sounds risky, but it is actually the key design insight: Linear itself is the source of truth. If Symphony restarts, it scans the board, finds tickets in β€œIn Progress” that it owns, and picks up where it left off. This is what the team calls β€œtracker-driven recovery,” and it eliminates an entire class of state synchronization bugs.

Linear Board (source of truth)
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Symphony Daemon    β”‚  ← Polls for ready tickets
β”‚   (Elixir/OTP)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Workspace Manager   β”‚  ← Creates isolated git clones
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Codex Agent Pool   β”‚  ← One lightweight process per task
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   PR + CI Pipeline   β”‚  ← Opens PR, verifies CI, updates Linear
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Architecture: Why Elixir/OTP

The choice of Elixir/OTP is not incidental. It is the architectural foundation that makes Symphony viable as a production orchestrator.

Supervision trees provide automatic recovery. Each coding agent runs as a child process under a supervisor. If an agent process crashes (out of memory, API timeout, unexpected error), the supervisor restarts it with a clean slate. This happens without affecting any other running agents.

Lightweight processes make concurrency practical. BEAM processes are not OS threads. They cost roughly 2KB of memory each and are preemptively scheduled by the VM. Symphony can run 50+ concurrent agents on a single node without resource contention becoming a bottleneck.

Distribution is built into the runtime. If one node is not enough, you can connect multiple BEAM nodes into a cluster. Symphony’s process registry supports this natively, so scaling from one machine to five is a configuration change, not an architecture change.

Pattern matching and immutable data make the state machine logic readable. Each ticket state transition is a function clause that matches on the current state and the event, returning the next state. No mutable flags. No hidden side effects.

ComponentTechnologyPurpose
Daemon / SchedulerElixir GenServerPolls Linear, manages tick cycle
Agent SupervisorOTP SupervisorRestarts crashed agents automatically
Workspace ManagerElixir + Git CLICreates and tears down isolated clones
Codex IntegrationOpenAI API (HTTP)Sends prompts, receives code patches
PR DeliveryGitHub API (Octokit)Opens PRs, links to Linear issues
CI VerificationGitHub Actions webhooksWatches for pass/fail, triggers retries

For a deeper look at how supervision trees and process-based concurrency apply to agent systems, see our guide on AI agent state management.

Key Features

Concurrency With Backpressure

Symphony does not just run agents in parallel. It applies backpressure to avoid overwhelming your CI pipeline or hitting API rate limits. You configure a max concurrency setting, and the daemon queues excess tickets until a slot opens. This prevents the common failure mode where an orchestrator spawns 30 agents and then every PR times out waiting for CI runners.

Configurable Retries

When an agent’s PR fails CI, Symphony does not just give up. It feeds the CI failure logs back to the agent and asks it to fix the issue. You configure the max retry count (default is 3). Each retry gets the full context: the original issue, the code written so far, and the specific failure output. In practice, this handles flaky tests and minor lint issues without human intervention.

Sandboxed Workspaces

Each agent gets a completely isolated workspace: a fresh git clone in a temporary directory with its own dependency installation. Agents cannot interfere with each other’s work. When the task completes (success or final failure), the workspace is cleaned up automatically. This also means agents can work on the same repo simultaneously without merge conflicts during development, though conflicts at PR merge time are still possible.

SSH Workers for Remote Execution

For teams that need stronger isolation or more compute per agent, Symphony supports SSH workers. Instead of running the Codex agent locally, it SSHs into a remote machine, sets up the workspace there, and runs the agent remotely. This is useful for repos with heavy build steps (large Rust projects, monorepos with long compilation times) where you want dedicated hardware per agent.

Video Walkthroughs

One of the more unexpected features: Symphony can generate short video walkthroughs of the changes an agent made. It records a scripted walkthrough of the diff, file by file, with annotations explaining what changed and why. This makes code review faster because reviewers can watch a 2-minute video instead of reading a raw diff. The feature is optional and requires a screen recording dependency.

How It Compares to What We Built

During The $100 AI Startup Race, we built our own orchestrator to coordinate 7 AI agents working on a single codebase. Our system used cron-based scheduling, git-based state (branch names and commit messages encoded task status), and a simple bash script as the control plane.

It worked. But comparing it to Symphony highlights the gap between a scrappy prototype and a production system.

AspectOur Race OrchestratorSymphony
SchedulingCron jobs (fixed intervals)Event-driven (Linear webhook + polling)
State managementGit branches + commit messagesIn-memory + Linear as source of truth
Agent isolationSeparate branches (shared workspace)Fully isolated workspace per agent
Failure recoveryManual re-runAutomatic retry with CI log feedback
PR deliveryManual (agent commits, human opens PR)Automated PR with CI verification
Concurrency modelSequential (one agent at a time)Parallel with backpressure
Language/RuntimeBash + Python scriptsElixir/OTP

The biggest difference is reliability. Our orchestrator required babysitting. If an agent failed halfway through a task, we had to manually figure out what happened, reset the branch, and re-run. Symphony handles all of that automatically through its supervision tree and tracker-driven recovery.

That said, our approach had one advantage: simplicity. You can set up a cron + git orchestrator in an afternoon. Symphony requires an Elixir runtime, Linear integration, and meaningful configuration. For a hackathon or prototype, the simpler approach wins. For ongoing production use, Symphony is in a different league.

For more context on the frameworks landscape, check our roundup of the best AI agent frameworks in 2026.

Who Should Use Symphony

Symphony is not for everyone. It is purpose-built for a specific workflow, and it excels when your team matches that workflow.

You should use Symphony if:

  • Your team already uses Linear for project management.
  • You are using (or planning to use) Codex as your coding agent.
  • You have a backlog of well-defined, routine engineering tasks (bug fixes, small features, dependency updates, test coverage improvements).
  • You want to free up senior engineers from repetitive work so they can focus on architecture and design.
  • You are comfortable running an Elixir service in your infrastructure.

You probably should not use Symphony if:

  • You use Jira, Asana, or another tracker (there is no adapter system yet).
  • You want to use a different coding agent (Claude Code, Cursor, Aider). Symphony’s agent interface is tightly coupled to Codex.
  • Your tasks require complex multi-step reasoning across multiple services. Symphony works best on single-repo, well-scoped tickets.
  • You do not have CI set up. Symphony relies on CI as its verification layer.

Limitations

Linear-specific. Symphony reads from and writes to Linear. There is no plugin system or adapter layer for other project trackers. The team has mentioned that community adapters are welcome, but as of now, you need Linear.

Codex-focused. The agent interface assumes Codex’s input/output format. Swapping in a different coding agent is not a configuration change; it requires modifying the agent integration layer. This is a meaningful lock-in if you are evaluating multiple coding agents.

Requires Elixir runtime. If your team runs everything on Node.js or Python, adding an Elixir service to your stack is a real operational cost. You need to install Erlang/OTP and Elixir, manage BEAM releases, and learn enough about the ecosystem to debug issues. The Symphony team provides Docker images that reduce this friction, but it does not eliminate it.

No database means limited observability. Since state lives in memory and Linear, there is no built-in dashboard for historical runs, success rates, or agent performance metrics. You can build this by tailing logs, but it is not included out of the box.

Single-repo focus. Each Symphony instance targets one repository. If you have a monorepo, that works fine. If you have 20 microservices in separate repos, you need 20 Symphony instances (or a meta-orchestrator on top, which the docs do not cover).

FAQ

Can Symphony work with GitHub Issues instead of Linear?

Not out of the box. Symphony’s state machine is built around Linear’s workflow states (status transitions, assignee fields, label conventions). GitHub Issues has a different data model. A community adapter would need to map GitHub’s label-based workflow to Symphony’s expected state transitions. The core team has said they are open to PRs that add this, but it is not on their roadmap.

How does Symphony handle merge conflicts?

Symphony does not resolve merge conflicts automatically. Each agent works on an isolated branch, so conflicts only surface at merge time. If a PR has conflicts, Symphony marks the ticket as β€œNeeds Attention” in Linear and stops retrying. A human needs to resolve the conflict or rebase the branch. In practice, this is rare if your tickets are well-scoped and target different parts of the codebase.

What is the minimum infrastructure needed to run Symphony?

A single machine with Elixir 1.17+, Erlang/OTP 27+, and Git installed. You need API tokens for Linear, GitHub, and OpenAI. The daemon itself is lightweight (under 200MB RAM for 10 concurrent agents). For SSH workers, you need additional machines accessible via SSH with the same dependencies installed. The Docker image bundles everything except the API tokens, so docker run with environment variables is the fastest path to a working setup.

Getting Started

Clone the repo, copy the example config, fill in your API tokens, and start the daemon:

git clone https://github.com/openai/symphony.git
cd symphony
cp config/example.exs config/dev.exs
# Edit config/dev.exs with your Linear, GitHub, and OpenAI tokens
mix deps.get
mix symphony.start

Symphony will connect to your Linear board, log the tickets it finds, and wait for issues in the β€œReady for Agent” state. Move a ticket into that column, and watch it work.

For teams exploring agent orchestration more broadly, our guide on how to build multi-agent systems covers the foundational patterns that Symphony implements.