The Orchestrator
The orchestrator is the heart of Symphony—a single authoritative process that owns all scheduling decisions.Responsibilities
Polling
Runs a tick every configured interval (default 30 seconds) to fetch candidate issues from Linear
Dispatch
Decides which issues to assign to agents based on eligibility rules and concurrency limits
State Tracking
Maintains in-memory runtime state for all running sessions, retry queues, and metrics
Reconciliation
Continuously checks issue states in Linear and stops agents when issues become ineligible
Orchestration States
Each issue in Symphony moves through distinct orchestration states (separate from Linear issue states):- Unclaimed – Issue is not running and has no retry scheduled
- Claimed – Orchestrator has reserved the issue to prevent duplicate dispatch
- Running – Worker task exists and agent session is active
- RetryQueued – Worker stopped but scheduled to retry after backoff delay
- Released – Claim removed because issue is terminal, non-active, or completed
A successful agent exit doesn’t mean the issue is done forever. If the issue remains in an active Linear state, Symphony schedules a continuation retry to give the agent another chance to complete the work.
Concurrency Control
Symphony provides two levels of concurrency control: Global LimitWorkspaces
Workspaces are isolated directory environments where agents execute their work.Workspace Layout
Each issue gets its own workspace directory:- Only
[A-Za-z0-9._-]characters are allowed - All other characters are replaced with
_
Workspace Lifecycle
Creation
When Symphony first encounters an issue, it creates the workspace directory. This happens only once per issue.
after_create Hook
If configured, runs setup commands (like
git clone) in the new workspace. This hook runs only when the directory is first created.Reuse Across Runs
The same workspace is reused for all subsequent runs of the same issue—retries, continuations, and rework cycles.
before_run Hook
Runs before each agent attempt, after workspace preparation. Useful for syncing latest changes or rebuilding dependencies.
after_run Hook
Runs after each agent attempt completes (success or failure). Failures are logged but ignored.
Safety Invariants
These invariants prevent agents from accidentally modifying files outside their designated workspace.Workspace Hooks
Hooks are shell scripts that run at specific points in the workspace lifecycle:Hook execution details
Hook execution details
- Hooks execute in a shell context with the workspace directory as
cwd - On POSIX systems, hooks run via
bash -lc <script> - Hook timeout is configurable (default: 60 seconds)
after_createandbefore_runfailures abort the current attemptafter_runandbefore_removefailures are logged but ignored
Workflow Files
TheWORKFLOW.md file is the contract between Symphony and your repository.
File Format
AWORKFLOW.md file contains YAML front matter for configuration and a Markdown body for the agent prompt:
Front Matter Configuration
The YAML front matter accepts these top-level sections:tracker - Issue tracker configuration
tracker - Issue tracker configuration
polling - Poll interval
polling - Poll interval
workspace - Workspace paths and hooks
workspace - Workspace paths and hooks
agent - Concurrency and retry settings
agent - Concurrency and retry settings
codex - Agent runtime configuration
codex - Agent runtime configuration
hooks - Workspace lifecycle scripts
hooks - Workspace lifecycle scripts
Prompt Template
The Markdown body is rendered as a template with these variables:issue – The normalized issue object:
attempt – Retry/continuation metadata:
Templates use Liquid-compatible syntax. Unknown variables or filters cause rendering to fail, preventing silent errors.
Dynamic Reload
Symphony watches
WORKFLOW.md for changes and reloads configuration dynamically without restart. Changes apply to:- Future dispatch decisions
- Polling interval (affects next tick scheduling)
- Concurrency limits
- Agent launch parameters
- Prompt content for new sessions
Linear Integration
Symphony integrates deeply with Linear to fetch work and track progress.Issue Selection
On each poll tick, Symphony fetches candidate issues that meet these criteria:Blocker Rule for Todo
If issue state is “Todo”, all blockers must be in terminal states. Issues with active blockers are skipped.
Dispatch Priority
Eligible issues are sorted before dispatch:- Priority ascending (1 is highest, 4 is lowest; null sorts last)
- Created at oldest first
- Identifier lexicographic (tie-breaker)
Issue Normalization
Symphony normalizes Linear’s GraphQL responses into a stable issue model:State Reconciliation
Every poll tick, Symphony reconciles running agent sessions: Part A: Stall Detection- If no Codex events received within
stall_timeout_ms, terminate the worker and queue retry - Disabled if
stall_timeout_ms <= 0
- Fetch current states for all running issue IDs
- If issue moved to terminal state → stop agent and clean workspace
- If issue moved to non-active state → stop agent, keep workspace
- If issue still active → update in-memory snapshot and continue
Tracker Write Boundary
Important design principle:Symphony does not write to Linear directly. All ticket mutations (state transitions, comments, PR links) are performed by the coding agent using tools defined in the workflow prompt.Symphony remains a scheduler and runner—it reads from Linear to discover work but delegates all tracker writes to the agents.
Agent Sessions
An agent session is a single execution of a coding agent for one issue.Session Lifecycle
Stream Turn
Read line-delimited JSON from stdout until turn completes, fails, times out, or is cancelled
Continuation Turns
If turn succeeds and issue still active, start additional turns (up to
max_turns) on the same threadSession Metadata
While an agent session runs, Symphony tracks:Retry and Continuation
Symphony distinguishes between two retry scenarios: Continuation Retry (after normal exit):- Agent completed a turn successfully
- Issue is still in an active Linear state
- Symphony schedules a short retry (~1 second) to re-check and possibly start another session
- Uses same workspace, increments attempt counter
- Agent failed, timed out, or was cancelled
- Symphony schedules exponential backoff retry:
min(10000 * 2^(attempt-1), max_retry_backoff_ms) - Default max backoff: 5 minutes
Next Steps
Quick Start
Get Symphony running in your environment
Workflow Configuration
Learn how to customize your WORKFLOW.md file