OpenSymphony
OpenSymphony is a Rust implementation of the OpenAI Symphony specification for orchestrating AI coding agents. It connects to Linear for issue tracking and uses OpenHands as the agent runtime.

What is OpenSymphony?
OpenSymphony automates software development workflows by:
- Polling Linear for issues in active states (Todo, In Progress, etc.)
- Creating isolated workspaces for each issue with lifecycle hooks
- Dispatching AI agents via OpenHands to work on issues autonomously
- Managing retries, reconciliation, and cleanup based on issue state changes
- Providing a terminal UI (FrankenTUI) for monitoring and operator control
Key Features
- Hierarchy-aware scheduling: Parent issues wait for sub-issues to complete
- WebSocket-first runtime: Real-time agent updates with REST reconciliation
- Per-issue workspaces: Deterministic, isolated directories with lifecycle hooks
- GraphQL-only Linear integration: Agent-side Linear reads and writes through checked-in helper/query assets
- Conversation reuse policies: Default per-issue reuse with optional fresh-per-run resets
- Local-first MVP: Trusted-machine deployment with optional hosted mode
OpenSymphony 1.0.0 is the compatibility boundary for the GraphQL-only Linear
rewrite. See Migration Guide if you are upgrading an
older setup.
Packaging note: crates.io exposes a single public package, opensymphony.
Internally, the repo still keeps clear subsystem boundaries under
crates/opensymphony-*, but those directories are now internal module trees,
not separately published crates.
Quick Start
Prerequisites
- Rust toolchain (stable)
- Python 3.12+ with
uvfor OpenHands server - Linear API key (for tracker integration)
- LLM API key (any LiteLLM-compatible provider: OpenAI, Anthropic, Fireworks, etc.)
For platform-specific Rust and Python/uv setup steps, see Prerequisites.
Installation
OpenSymphony manages a local OpenHands agent-server; install the pinned runtime like this:
Required Environment
Before running opensymphony run, export your provider settings for the
OpenHands conversation agent:
These LLM_* variables are required unless your target repo's WORKFLOW.md
has been customized to resolve the LLM configuration some other way.
Bootstrap A Target Repo
Bootstrap the target repository in place:
opensymphony init guides the bootstrap flow, customizes WORKFLOW.md, and
can optionally scaffold automated code review via the OpenHands PR Review Plugin, including GitHub setup through gh when it is installed and authorized for the target repo.
Running the Orchestrator
Then start from the target repository:
For real-time monitoring while the orchestrator is running, run the TUI in a separate terminal window:
Further Details
For generated files, environment variables, config.yaml, and the template
repo details behind init, see Configuration.
For alternate config paths, debug, rehydrate, packaging, and local operator
workflows, see Operations.
Optional troubleshooting and validation:
To inspect the command surface, run:
opensymphony --help
Architecture
┌─────────────────────────────────────────────────────────────┐
│ OpenSymphony Daemon │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Orchestrator│ │ Linear │ │ OpenHands Client │ │
│ │ Scheduler │ │ Adapter │ │ (REST + WebSocket) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
│ │ │ │ │
│ ┌──────▼────────────────▼────────────────────▼──────────┐ │
│ │ Workspace Manager │ │
│ │ (per-issue directories, hooks, manifests) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼──────────────────────────────┐ │
│ │ Control Plane API (read-only) │ │
│ │ GET /healthz, /api/v1/snapshot, /api/v1/events │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ Linear │ │ OpenHands │
│ (Issues) │ │ Agent-Server │
└─────────────┘ └─────────────────┘
▲ ▲
│ │
┌────┴────────────┐ ┌────┴────┐
│ GraphQL Helper │ │ Agent │
│ + Query Assets │ │ Runtime │
└─────────────────┘ └─────────┘
Internal Boundaries
OpenSymphony keeps explicit internal subsystem boundaries while shipping as one installable crates.io package:
| Internal module tree | Responsibility |
|---|---|
opensymphony_orchestrator |
Poll loop, scheduling, retries, state machine |
opensymphony_linear |
GraphQL client for orchestrator-side Linear reads |
opensymphony_openhands |
REST/WebSocket client for agent runtime |
opensymphony_workspace |
Workspace lifecycle, hooks, containment |
opensymphony_control |
Control plane API and snapshot derivation |
opensymphony_tui |
FrankenTUI operator client |
opensymphony_cli |
CLI entrypoints: init, run, debug, daemon (demo), tui, doctor, rehydrate |
Deployment Modes
Local Supervised Mode (MVP)
The default mode for individual developers:
- One OpenHands server subprocess managed by the daemon
- Host filesystem access (process-level isolation)
- Loopback-only binding
- No auth by default
openhands:
transport:
base_url: http://127.0.0.1:8000
External Local Mode
For debugging or CI with a manually managed server:
openhands:
transport:
base_url: http://127.0.0.1:8000
session_api_key_env: OPENHANDS_API_KEY
Hosted Remote Mode (Future)
For organizational deployment with stronger isolation:
openhands:
transport:
base_url: https://agent-server.example.com
session_api_key_env: OPENHANDS_API_KEY
websocket:
auth_mode: header
See docs/deployment-modes.md for full details.
Workspace Lifecycle
Each issue gets a deterministic workspace:
<workspace_root>/<issue_identifier>/
├── .opensymphony/
│ ├── issue.json # Issue metadata
│ ├── conversation.json # Conversation registry and launch profile
│ └── openhands/
│ └── create-conversation-request.json
├── .opensymphony.after_create.json # Hook receipt
├── <repo_files> # Cloned repository
└── logs/ # Execution logs
Debugging Sessions
Use opensymphony debug <issue-id> to reopen the OpenHands conversation that OpenSymphony used for that issue:
The command resolves the issue reference to its managed workspace, reads
.opensymphony/conversation.json, and resumes the same conversation_id from the
original working directory. The conversation registry persists the issue reference,
stable OpenHands conversation ID, timestamps, transport details, and the launch
profile that created the session so a missing-but-recoverable thread can be
rehydrated without losing continuity.
When the workflow uses the local supervised OpenHands server, opensymphony debug
targets the same configured base URL as the orchestrator. If a ready server is
already listening there, the debug command reuses it; otherwise it starts a local
server for the session. For the most predictable behavior, prefer the
orchestrator-managed server and avoid leaving unrelated standalone openhands
CLI sessions bound to the same port.
Lifecycle Hooks
after_create: Clone repository, setup environmentbefore_run: Pre-execution checksafter_run: Post-execution cleanupbefore_remove: Final cleanup before workspace deletion
Testing
# Unit tests
# Static validation
# Live tests (requires OpenHands server)
OPENSYMPHONY_LIVE_OPENHANDS=1
# Smoke test
# Live E2E test
OPENSYMPHONY_LIVE_OPENHANDS=1
Documentation
- Architecture - High-level design and component interactions
- Configuration - Target repo bootstrap and runtime config
- Deployment Modes - Local vs hosted deployment
- Operations - Doctor, rehydration, diagnostics, and local ops
- Testing - Test strategy and validation layers
- Migration Guide - Breaking changes and upgrade steps for 1.0.0
- AGENTS.md - Repository guidelines for coding agents
- Development Guide - Contributing and development details
Safety and Security
Local Mode: The MVP runs with process-level isolation on trusted developer machines. Agent code executes on the host filesystem. This is suitable for:
- Solo development on trusted repositories
- Local experimentation
- CI on controlled runners
Hosted Mode (future): Will provide stronger isolation with container-backed workspaces and mandatory auth.
Version Pinning
OpenSymphony pins exact versions for reproducibility:
openhands-agent-server==1.14.0openhands-sdk==1.14.0- Rust stable toolchain
The managed local OpenHands bundle is sourced from tools/openhands-server/
and provisioned with opensymphony install openhands.
License
Acknowledgments
- OpenAI Symphony - The specification this implements
- OpenHands - The agent runtime
- FrankenTUI - Terminal UI framework