Browse the docs

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.

ClawIDE is Symphony-compatible, not a conformant Symphony implementation. It follows the 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.
The Symphony section of the workspace sidebar: workflow status, Start, Stop and Refresh buttons, running and retrying issues with log links, and the external daemon monitor.

How it works

On every polling tick, ClawIDE:

  1. 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.
  2. Fetches issues in the active_states from your tracker, keeping only those that have all required_labels and aren’t blocked.
  3. Sorts them by priority (most urgent first, unset last), then oldest first, then by identifier.
  4. 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

  1. Connect your tracker under Settings → Integrations.
  2. Add a WORKFLOW.md to the root of your project.
  3. 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.

KeyDefaultMeaning
tracker.kindlinear, jira or github
tracker.providerTracker-specific settings
tracker.active_statesStates that make an issue eligible to run
tracker.terminal_statesStates that end a run and remove its workspace
tracker.required_labelsLabels an issue must have to run
polling.interval_ms30000Time between ticks
workspace.rootTemp folderWhere 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_createRuns once when a workspace is created
hooks.before_runRuns before each attempt
hooks.after_runRuns after each attempt
hooks.before_removeRuns before a workspace is removed
hooks.timeout_ms60000Time limit for each hook
agent.max_concurrent_agents10Runs at once, across all states
agent.max_concurrent_agents_by_statePer-state limits
agent.max_turns20Continuation runs per issue
agent.max_retry_backoff_ms300000Longest wait between failed attempts
codex.*Kept for compatibility with other Symphony runners
clawide.runnerclaudeAgent to run: claude, codex, opencode, gemini, qwen or goose
clawide.argsExtra arguments for the runner
clawide.gatewayA 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, with id, identifier, title, description, state, priority, labels, url, assignee_id, blocked_by, created_at and updated_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:

HookIf it fails
after_createThe workspace isn’t created
before_runThe attempt is cancelled
after_runLogged and ignored
before_removeLogged 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.

RunnerCommand
claudeclaude -p --output-format stream-json --verbose --permission-mode acceptEdits
codexcodex exec --sandbox workspace-write -
opencodeopencode run
geminigemini -p
qwenqwen -p
goosegoose 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.md was 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.

EndpointMethodDescription
/api/symphonyGETWorkflow status (found, path, errors, summary) and orchestrator state (running and retrying issues, counts)
/api/symphony/startPOSTStart the orchestrator. Returns 400 invalid_workflow with the list of errors if the file is invalid
/api/symphony/stopPOSTStop the orchestrator
/api/symphony/refreshPOSTPoll now. Returns 202
/api/symphony/log?identifier=…&attempt=…GETThe last 64 KB of an attempt’s log, as plain text
/api/symphony/monitor?url=…GETState from an external Symphony daemon