Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

broomva/symphony

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

64 Commits
tags
symphony
type reference
status active
area project
aliases
README
created 2026年03月06日

Symphony

A Rust implementation of the Symphony orchestration spec by OpenAI. For vault navigation see [[docs/Symphony Index|Symphony Index]]. For the canonical spec see [[SPEC]].

A Rust-based orchestration service that polls an issue tracker (Linear, GitHub, or local Markdown files), creates isolated per-issue workspaces, and runs coding agent sessions automatically.

Symphony turns your issue backlog into autonomous coding work — it watches for "Todo" issues, clones your repo into a sandboxed workspace, runs a coding agent (like Claude Code), and manages retries, concurrency, and lifecycle hooks.

How It Works

Tracker (Linear / GitHub / Markdown files)
 │
 ▼
 ┌────────────────────────┐
 │ Symphony Scheduler │ ← polls every N seconds
 │ ┌──────────────────┐ │
 │ │ Fetch candidates │ │
 │ │ Select & sort │ │
 │ │ Dispatch workers │ │
 │ └──────────────────┘ │
 └────────────┬───────────┘
 │
 ┌────────┴────────┐
 ▼ ▼
 ┌──────────┐ ┌──────────┐
 │ Worker 1 │ │ Worker N │ ← one per issue
 │ workspace│ │ workspace│
 │ + agent │ │ + agent │
 └──────────┘ └──────────┘
 │
 ▼
 ┌─────────────────────┐
 │ HTTP Dashboard │ ← live state at :8080
 │ /api/v1/state │
 │ /api/v1/refresh │
 └─────────────────────┘

Poll loop: Fetches active issues from the configured tracker → filters by project & state → dispatches up to max_concurrent_agents workers.

Per-issue worker: Creates workspace directory → runs lifecycle hooks (clone repo, rebase, etc.) → renders prompt template with issue data → launches coding agent → runs post-hooks (commit, etc.).

Reconciliation: On each tick, refreshes running issue states from the tracker. If an issue moves to a terminal state (Done/Canceled), the worker is cleaned up.

Quick Start

Prerequisites

  • Rust 1.85+ (edition 2024)
  • A coding agent CLI (e.g., claude)
  • One of: Linear API key, GitHub token, or a local tasks/ directory with .md files
  • gh CLI (if using GitHub hooks)

Build

make build # release build → target/release/symphony

Configure

Create a WORKFLOW.md in your project root. This file has YAML frontmatter (config) and a Liquid template body (the prompt sent to the agent):

---
tracker:
 kind: linear
 api_key: $LINEAR_API_KEY # env var expansion
 project_slug: 71c211385593 # Linear project slug ID
 active_states:
 - Todo
 terminal_states:
 - Done
 - Canceled
 - Duplicate
polling:
 interval_ms: 30000 # poll every 30s
workspace:
 root: ~/my-workspaces/project # per-issue dirs created here
hooks:
 after_create: | # runs once when workspace is first created
 gh repo clone MyOrg/my-repo . -- --depth 50
 git checkout -b "$SYMPHONY_ISSUE_ID"
 before_run: | # runs before each agent session
 git fetch origin main
 git rebase origin/main || git rebase --abort
 after_run: | # runs after each agent session (failure ignored)
 git add -A
 git diff --cached --quiet || git commit -m "$SYMPHONY_ISSUE_ID: automated changes"
 timeout_ms: 120000
agent:
 max_concurrent_agents: 1
 max_turns: 10
codex:
 command: "claude --dangerously-skip-permissions"
server:
 port: 8080
---
You are a senior software engineer.
## Task
{{ issue.identifier }}: {{ issue.title }}
{% if issue.description %}
## Description
{{ issue.description }}
{% endif %}
{% if issue.labels %}
## Labels
{{ issue.labels | join: ", " }}
{% endif %}
## Instructions
- Read the codebase thoroughly before making changes
- Write clean, well-tested code following existing patterns
- Run existing tests to make sure nothing is broken
{% if attempt %}
## Retry
This is retry attempt {{ attempt }}. The previous attempt failed.
Review what went wrong and try a different approach.
{% endif %}

Set your API key

export LINEAR_API_KEY="lin_api_..."

Run

# Use default WORKFLOW.md in current directory
symphony
# Or specify a path
symphony /path/to/WORKFLOW.md
# Override the dashboard port
symphony --port 9090

Symphony will start polling Linear, and you'll see structured logs:

symphony starting workflow="WORKFLOW.md"
startup terminal cleanup complete cleaned=2
fetched candidate issues count=7
dispatching issue identifier="STI-746" title="Add auth flow"
workspace created path="~/my-workspaces/project/STI-746"
agent session completed identifier="STI-746" exit_code=0

Dashboard

Open http://localhost:8080 for a live HTML dashboard showing running/retrying issues, token usage, and concurrency.

API endpoints:

Endpoint Description
GET / HTML dashboard
GET /api/v1/state Full orchestrator state JSON
GET /api/v1/issues/:id Single issue status
POST /api/v1/refresh Trigger immediate poll
GET /health Health check

Architecture

Rust workspace with 8 crates:

Crate Responsibility
symphony-core Domain types: Issue, Session, Workspace, OrchestratorState
symphony-config WORKFLOW.md loader, typed config, live file watcher
symphony-tracker Tracker adapters (Linear, GitHub, Markdown), issue fetching, state normalization
symphony-workspace Per-issue directory lifecycle, hook execution, path safety
symphony-agent Coding agent subprocess management (CLI pipe + JSON-RPC modes)
symphony-orchestrator Poll loop, dispatch, reconciliation, retry queue
symphony-observability Structured logging, HTTP dashboard + REST API
symphony-arcan Arcan runtime adapter — bridges Symphony to the Agent OS stack

Dashboard

A separate TypeScript/React dashboard lives in dashboard/ (Turborepo, Bun). It provides a web UI for monitoring Symphony orchestrator state, issues, and agent sessions.

Key Features

  • Live config reload: Edit WORKFLOW.md while running — changes apply on next tick
  • Lifecycle hooks: after_create, before_run, after_run, before_remove with timeout enforcement
  • Retry with backoff: Failed sessions retry with exponential backoff; continuations retry immediately
  • Concurrency control: Configurable max_concurrent_agents with slot-based dispatch
  • Workspace isolation: Each issue gets its own directory; path traversal attacks are blocked
  • Template rendering: Liquid templates with full issue context (title, description, labels, attempt count)
  • Environment injection: $SYMPHONY_ISSUE_ID available in all hook scripts
  • Terminal cleanup: On startup, cleans workspaces for issues already in Done/Canceled state

WORKFLOW.md Reference

Frontmatter Fields

Field Required Default Description
tracker.kind yes Tracker type (linear, github, or markdown)
tracker.api_key yes (linear/github) API key (supports $ENV_VAR syntax); not needed for markdown
tracker.project_slug yes Linear slug, owner/repo, or directory path for markdown
tracker.active_states no ["Todo"] States that make an issue eligible
tracker.terminal_states no ["Done","Canceled"] States that trigger cleanup
polling.interval_ms no 30000 Poll interval in milliseconds
workspace.root no ./workspaces Root directory for per-issue workspaces
hooks.after_create no Shell script run once on new workspace
hooks.before_run no Shell script run before each agent session
hooks.after_run no Shell script run after each agent session
hooks.before_remove no Shell script run before workspace cleanup
hooks.timeout_ms no 30000 Hook execution timeout
agent.max_concurrent_agents no 1 Max parallel agent sessions
agent.max_turns no 10 Max agent turns per session
codex.command yes Agent CLI command to run
server.port no HTTP dashboard port (omit to disable)

Template Variables

The body after the --- frontmatter is a Liquid template with these variables:

Variable Type Description
issue.identifier string Issue ID (e.g., STI-746)
issue.title string Issue title
issue.description string Issue body/description
issue.labels array Issue labels
attempt number Retry attempt number (nil on first run)

Development

make smoke # compile + clippy + test (the gate)
make check # cargo check + clippy
make test # cargo test --workspace
make build # cargo build --release
make fmt # cargo fmt --all

136 tests across all crates (131 unit + 5 integration tests requiring LINEAR_API_KEY).

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

Key extension points:

  • Tracker plugins: Implement the TrackerClient trait to add support for Jira, etc. (Linear, GitHub, and Markdown are built-in)
  • Agent runners: The agent runner supports any CLI that speaks line-delimited JSON on stdout
  • Workflow templates: Create new WORKFLOW.md examples for different use cases

Community

  • Issues — bug reports, feature requests
  • Discussions — questions, ideas, show & tell

License

Apache License 2.0 — see LICENSE for details.

This project implements the Symphony specification originally published by OpenAI under the Apache 2.0 license.

About

Rust orchestration daemon for coding agents — polls Linear/GitHub/Markdown, creates isolated workspaces, dispatches agent sessions with EGRI self-improvement.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

Contributors

AltStyle によって変換されたページ (->オリジナル) /