Skip to content

Automattic/symphony

 
 

Repository files navigation

Symphony

Symphony runs coding agents (Codex or Claude) on your Linear issues and GitHub pull requests, so your team manages the work instead of babysitting the agents.

It watches Linear for issues to pick up, creates an isolated workspace for each one, runs the agent against a workflow prompt you define per repo, and keeps the run moving — retrying failures and recovering stalled sessions — until there is a pull request to review. You can also point it at an existing PR from the CLI to address review comments, fix failing CI, or resolve conflicts.

Demo video

Warning

Symphony is an engineering preview for operator-controlled, trusted environments. It includes operational guardrails, but it is not a hardened multi-tenant service and should run behind trusted network and authentication boundaries.

Symphony dashboard screenshot

How It Works

Linear issue or PR -> Symphony -> workspace -> agent -> pull request
  1. Pick up work. Symphony polls Linear and claims eligible issues (or you hand it a PR directly).
  2. Isolate it. Each run gets a fresh workspace — a clean checkout or worktree, never your source repo.
  3. Run the agent. It launches the configured agent against that repo's WORKFLOW.md prompt.
  4. Keep it moving. Failed runs retry with backoff, stalled agents are detected and recovered, and results are reported back to Linear — so a long queue does not need constant supervision.

Issue runs end with a pull request and validation evidence. PR runs push back to the existing PR head branch instead of opening a second one. If a claimed issue moves to a terminal state (Done, Closed, Cancelled, Duplicate), Symphony stops its agent and cleans up the workspace.

Glossary
  • Workflow: the repo-owned policy and prompt that tells Symphony what to run.
  • Run: one attempt to make progress on a Linear issue.
  • Workspace: the isolated checkout or worktree for a run.
  • Tracker: the system Symphony polls for work, currently Linear.
  • Repo route: an entry under repositories: in symphony.yml that pairs a local checkout with its WORKFLOW.md and optional Linear selectors. One Symphony process can supervise many repo routes.
  • Quality gate: the optional pre-dispatch check that decides whether an issue is clear enough for an agent.
  • Harness engineering: the practice of preparing a codebase with scripts, tests, docs, and guardrails so coding agents can work safely.

Features

  • Multi-repo orchestration — one process supervises several repositories from a single symphony.yml, with per-repo Linear selectors and conflict detection.
  • LiveView dashboard — active runs, watched issues, the retry queue, quality-gate state, per-issue transcripts, and an audit timeline.
  • Operator controls — pause, resume, and stop, persisted across restarts.
  • PR-driven runs — work an existing pull request from the CLI for review comments, failing CI, and conflict fixes.
  • Recovery — a watchdog and retry queue handle stalled or failed sessions.
  • Durable run store — run history, retry backoff, captured learnings, token totals, and notification dedupe.
  • Workspace guardrails — age-based cleanup, startup orphan removal, and disk free-space pauses.
  • Scoped agent tools — current-issue Linear updates, GitHub PR evidence, and attachment handling.
  • Quality gate — optionally scores issue clarity before dispatch so unclear work is held back.
  • Executor + reviewer runs — an optional read-only reviewer agent gates the executor's push.
  • Docker runner — host Symphony with mounted repos, state, logs, and agent credentials.

Symphony Web dashboard screenshot

Quickstart

Symphony works best in codebases that have adopted harness engineering: scripts, tests, docs, and workflow prompts that let coding agents work safely.

  1. Get a Linear token from Settings → Security & access → Personal API keys, and export it as LINEAR_API_KEY. Symphony reads all secrets from the environment — to avoid plaintext .env files on disk, load them through a secrets manager such as 1Password Environments, op run, or direnv (see docs/security.md).

  2. Install the toolchain and build:

    cd symphony
    mise trust && mise install
    mise exec -- mix setup
    mise exec -- mix build
  3. Scaffold operator config. Run mise exec -- ./bin/symphony init from your operator repo to create symphony.yml, then edit the issue scope, agent command, workspace root, and repositories:.

  4. Write a workflow per repo. Invoke the symphony-init-workflow skill from Codex or Claude in each target repo; the agent inspects the repo and writes a tailored WORKFLOW.md.

  5. Start Symphony:

    mise exec -- ./bin/symphony

The LiveView dashboard runs at http://127.0.0.1:4000 by default. It has no built-in authentication and binds to loopback only — to expose it remotely, front it with a reverse proxy that handles auth (Tailscale, Cloudflare Access, nginx). See docs/security.md for details.

Configuration

Symphony reads two files:

  • symphony.yml — operator config: issue source, workspaces, agents, pollers, gates, notifications, and the repositories: list. Plain YAML.
  • WORKFLOW.md — repo-local prompt and per-repo hooks. YAML front matter, then the prompt template. Each repo under repositories: has its own.

Minimal symphony.yml:

issues:
  provider: linear
  linear:
    scope:
      project_slug: "..."
workspaces:
  root: ~/code/workspaces
agent:
  runtime: codex
  command: codex app-server
repositories:
  - key: my-repo
    workflow: ./WORKFLOW.md
# issue_gate is omitted here, so issues are dispatched without LLM scoring.

Minimal WORKFLOW.md:

---
hooks:
  after_create: |
    git clone git@github.com:your-org/your-repo.git .
prompts:
  pr: |
    You are working on PR {{ pr.url }}.
    Intent: {{ pr.intent }}
---

You are working on a Linear issue {{ issue.identifier }}.

Follow this repository's conventions and validation commands before handoff.

Title: {{ issue.title }}
Body: {{ issue.description }}

The Markdown body is the issue prompt; prompts.pr is the optional PR-mode template. Symphony prepends a managed runtime context (workspace isolation, untrusted-input handling, scoped tools, secret handling, response shape) before either, so keep WORKFLOW.md focused on repo-specific commands, conventions, and validation gates.

For the full reference — every supported key, defaults, prompt variables, CLI flags, and the issue gate — see docs/configuration.md.

Running

Start the service from a directory containing symphony.yml (or pass --config to point elsewhere):

./bin/symphony                       # start the service
./bin/symphony --config ./other.yml  # use a different operator config

Run a single issue synchronously, without the poll loop or dashboard:

./bin/symphony run ACME-123 --timeout 30m --no-retry

Work an existing PR:

./bin/symphony pr 123 --intent "address review comments"

Preview the assembled prompt

symphony workflow preview renders the exact base-issue prompt the agent would receive for the repo-local WORKFLOW.md, using deterministic sample issue data — no Linear access, network, or running orchestrator required. Use it to confirm your template and {% render %} partials resolve correctly before a real run:

./bin/symphony workflow preview                       # renders ./WORKFLOW.md
./bin/symphony workflow preview --file path/to/WORKFLOW.md
./bin/symphony workflow preview --agent claude        # default: codex

An unknown {% render %} partial or undefined variable is reported as an error, so the command doubles as a quick workflow lint.

Operator controls

The dashboard exposes Pause, Resume, and per-issue Stop at /. The same controls are available from the CLI over a loopback HTTP control plane on the dashboard port — no distributed Erlang setup required:

mise exec -- mix symphony.pause "deploy window"
mise exec -- mix symphony.resume
mise exec -- mix symphony.stop ACME-123
mise exec -- mix symphony.pr 123 --intent "fix failing CI"

Pause stops new dispatches while in-flight agents continue; Stop ends one issue's session and records it as stopped without changing the Linear issue state.

Docker

The Docker runtime mounts your operator config, repositories, credentials, and agent command into the service. See docker/README.md.

Documentation

About This Fork

This repository is a fork of OpenAI's openai/symphony, introduced in OpenAI's open-source Codex orchestration Symphony post. This fork keeps Symphony as the Elixir/OTP service at the repository root and includes local operational changes. SPEC.md is retained as a behavior reference for this service, not as instructions for building a separate implementation from scratch.

License

This project is licensed under the Apache License 2.0.

About

Symphony turns project work into isolated, autonomous implementation runs, allowing teams to manage work instead of supervising coding agents.

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Elixir 98.2%
  • CSS 0.6%
  • Python 0.5%
  • Liquid 0.4%
  • Shell 0.1%
  • Dockerfile 0.1%
  • Makefile 0.1%