Symphony-Compatible Orchestration
OpenAI Symphony is an open specification for turning issue-tracker work into coding-agent runs. A WORKFLOW.md file in your repository says which issues to pick up, how to prepare a workspace and what prompt to give the agent.
ClawIDE Pro reads that file and runs the loop for you, with a panel where you can watch and steer it. It can also monitor a Symphony daemon you already run.
WORKFLOW.md format and the spec’s workspace, hook, template, polling, retry and reconciliation behaviour, but runs headless agent CLIs instead of Symphony’s Codex app-server client.
How it works
On every polling tick, ClawIDE:
- Checks the runs in progress. A run that has stalled is stopped. If its issue reached a terminal state, the run is stopped and its workspace removed; if the issue left the active states or disappeared, the run is stopped and the workspace kept.
- Fetches issues in the
active_statesfrom your tracker, keeping only those that have allrequired_labelsand aren’t blocked. - Sorts them by priority (most urgent first, unset last), then oldest first, then by identifier.
- Starts runs while there are free slots, both overall and per state.
For each run, ClawIDE creates or reuses a workspace for the issue, runs your hooks, renders the prompt and starts a headless agent in that workspace.
Set up
- Connect your tracker under Settings → Integrations.
- Add a
WORKFLOW.mdto the root of your project. - Open the project’s workspace, find Symphony in the sidebar and click Start.
If the file has problems, the panel lists every validation error and Start does nothing until they’re fixed.
WORKFLOW.md
The file is YAML front matter followed by the prompt template:
---
tracker:
kind: linear
active_states: [Todo, In Progress]
terminal_states: [Done, Canceled]
required_labels: [agent]
polling:
interval_ms: 30000
workspace:
root: ~/symphony_workspaces
hooks:
after_create: git clone git@github.com:acme/app.git .
before_run: git fetch origin && git checkout -B {{ issue.identifier }} origin/main
agent:
max_concurrent_agents: 2
max_turns: 20
clawide:
runner: claude
gateway: openrouter
---
You are working on {{ issue.identifier }}: {{ issue.title }}.
{{ issue.description }}
{% if attempt %}This is attempt {{ attempt }}. Check the workspace for earlier progress.{% endif %}
ClawIDE reads <project>/WORKFLOW.md unless a different path is configured. The front matter must be a map.
| Key | Default | Meaning |
|---|---|---|
tracker.kind | linear, jira or github | |
tracker.provider | Tracker-specific settings | |
tracker.active_states | States that make an issue eligible to run | |
tracker.terminal_states | States that end a run and remove its workspace | |
tracker.required_labels | Labels an issue must have to run | |
polling.interval_ms | 30000 | Time between ticks |
workspace.root | Temp folder | Where workspaces are created, by default symphony_workspaces in the system temp folder. Supports ~ and $VAR; relative paths are resolved from the WORKFLOW.md folder |
hooks.after_create | Runs once when a workspace is created | |
hooks.before_run | Runs before each attempt | |
hooks.after_run | Runs after each attempt | |
hooks.before_remove | Runs before a workspace is removed | |
hooks.timeout_ms | 60000 | Time limit for each hook |
agent.max_concurrent_agents | 10 | Runs at once, across all states |
agent.max_concurrent_agents_by_state | Per-state limits | |
agent.max_turns | 20 | Continuation runs per issue |
agent.max_retry_backoff_ms | 300000 | Longest wait between failed attempts |
codex.* | Kept for compatibility with other Symphony runners | |
clawide.runner | claude | Agent to run: claude, codex, opencode, gemini, qwen or goose |
clawide.args | Extra arguments for the runner | |
clawide.gateway | A model gateway for the runner |
Keys ClawIDE doesn’t know are kept and ignored, so the same file works with other Symphony implementations.
Prompt template
The prompt is rendered with strict Liquid. Two variables are available:
issue: the tracker issue, withid,identifier,title,description,state,priority,labels,url,assignee_id,blocked_by,created_atandupdated_at.attempt: empty on the first run, then the attempt number.
An unknown variable or filter is an error, so typos fail loudly instead of producing a broken prompt.
Workspaces and hooks
Each issue gets its own folder under workspace.root. The folder name is the issue identifier with any character other than letters, digits, ., _ and - replaced by _; if anything was replaced, a short hash is added so names stay unique. ClawIDE refuses any path that would land outside the root.
Hooks run with sh -lc, in the workspace folder, with hooks.timeout_ms as the limit:
| Hook | If it fails |
|---|---|
after_create | The workspace isn’t created |
before_run | The attempt is cancelled |
after_run | Logged and ignored |
before_remove | Logged and ignored |
Workspaces persist between runs. They’re removed when their issue reaches a terminal state, including issues found in a terminal state when the orchestrator starts.
Retries
- After a clean exit, if the issue is still active, ClawIDE starts a continuation run one second later, up to
agent.max_turns. - After a failure, it retries after
min(10000 × 2^(attempt − 1), max_retry_backoff_ms)milliseconds: 10 seconds, then 20, 40 and so on, up to 5 minutes by default.
Runners
Runs are headless, so agents can’t stop to ask for approval. The default commands use each CLI’s workspace-scoped mode, and the panel shows the sandbox and approval posture of the current runner.
| Runner | Command |
|---|---|
claude | claude -p --output-format stream-json --verbose --permission-mode acceptEdits |
codex | codex exec --sandbox workspace-write - |
opencode | opencode run |
gemini | gemini -p |
qwen | qwen -p |
goose | goose run -t |
The prompt is sent on standard input wherever the CLI supports it, rather than as a command-line argument.
The agent inherits ClawIDE’s environment minus tracker secrets such as LINEAR_API_KEY, JIRA_* and GITHUB_TOKEN, plus the gateway variables if clawide.gateway is set.
Each attempt’s output is written to ~/.clawide/symphony/<project-id>/<identifier>/attempt-<n>.log. The panel shows the last 64 KB.
The Symphony panel
In a project workspace, the Symphony sidebar section shows:
- whether
WORKFLOW.mdwas found, with a summary of its settings or its errors - Start, Stop and Refresh (poll now)
- running issues, with state, attempt, workspace and timing, and a link to each log
- issues waiting to retry, with the time of the next attempt and the last error
- counts of dispatched, succeeded and failed runs
On the free plan the section shows what Symphony does, with an upgrade option.
Monitor an existing Symphony daemon
If you already run a Symphony daemon, enter its URL under Monitor external daemon. ClawIDE reads its state from <url>/api/v1/state and can trigger a refresh with <url>/api/v1/refresh. Only http and https URLs are accepted, with a 5-second timeout.
API
All endpoints need Pro or a trial and take project_id as a query parameter.
| Endpoint | Method | Description |
|---|---|---|
/api/symphony | GET | Workflow status (found, path, errors, summary) and orchestrator state (running and retrying issues, counts) |
/api/symphony/start | POST | Start the orchestrator. Returns 400 invalid_workflow with the list of errors if the file is invalid |
/api/symphony/stop | POST | Stop the orchestrator |
/api/symphony/refresh | POST | Poll now. Returns 202 |
/api/symphony/log?identifier=…&attempt=… | GET | The last 64 KB of an attempt’s log, as plain text |
/api/symphony/monitor?url=… | GET | State from an external Symphony daemon |