Rust implementation of the draft Symphony service specification. It runs a long-lived scheduler that reads Linear issues, creates per-issue workspaces, and drives Codex app-server sessions inside those workspaces.
This project is still in active development and is not ready for production or general use. Do not rely on it for unattended automation, critical workflows, or environments where unexpected agent behavior could cause harm.
cargo run -- path/to/WORKFLOW.mdIf the workflow path is omitted, the service uses ./WORKFLOW.md.
Local .env files are loaded automatically from the current directory before startup validation. Existing process environment variables win over values in .env.
Copy .env.example to .env and fill in local secrets:
cp .env.example .envEnable the optional HTTP status surface with --port or server.port in WORKFLOW.md:
cargo run -- WORKFLOW.md --port 8080Before running the daemon, use preflight mode to validate config and Linear read access without dispatching agents or touching workspaces:
cargo run -- --preflight WORKFLOW.mdPreflight exits after loading .env, validating WORKFLOW.md, fetching candidate issues, fetching terminal issues, and checking state refresh for a small candidate sample.
The HTTP extension binds 127.0.0.1 and serves:
GET /GET /api/v1/stateGET /api/v1/{issue_identifier}POST /api/v1/refresh
If you use mise, the repo includes convenience tasks:
mise run test
mise run lint
mise run verify
mise run symphonySet SYMPHONY_WORKFLOW and SYMPHONY_PORT to customize the symphony task.
This implementation targets trusted developer automation environments.
- Codex approval defaults are passed through unless configured in
WORKFLOW.md. - Command and file-change approval requests are auto-approved for the session.
- User-input and elicitation requests fail the run immediately so sessions do not stall indefinitely.
- Unsupported dynamic tool calls receive a JSON-RPC error or failed tool result and the session continues where the Codex protocol allows.
- The optional
linear_graphqltool uses the active Linear endpoint and token from the loaded workflow config. - Workspaces are created/reused under
workspace.root; successful runs preserve workspaces. - Existing non-directory workspace paths are treated as fatal workspace errors.
- No built-in VCS reset or workspace population is performed; use
hooks.after_createandhooks.before_runfor checkout/bootstrap policy. - Terminal-state cleanup deletes only the sanitized per-issue workspace under the configured workspace root after running
hooks.before_removebest-effort.
- Workspace keys replace characters outside
[A-Za-z0-9._-]with_. - Workspace paths are normalized and must remain under
workspace.root. - Codex app-server is launched with the per-issue workspace as its subprocess working directory.
The Codex app-server client uses the generated JSON-RPC v2 method names available in current Codex CLI builds: initialize, thread/start, and turn/start. Codex-owned policy values such as approval_policy, thread_sandbox, and turn_sandbox_policy are passed through as workflow-provided JSON values.
The upstream Symphony specification is vendored at docs/specs/SPEC.md for implementation reference.