Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/openai/symphony/llms.txt

Use this file to discover all available pages before exploring further.

The agent configuration section controls how Symphony schedules and retries agent runs, including concurrency limits and turn budgets.

Configuration

WORKFLOW.md
agent:
  max_concurrent_agents: 10
  max_turns: 20
  max_retry_backoff_ms: 300000

Fields

max_concurrent_agents
integer
default:10
Global limit for concurrent agent sessions.The orchestrator enforces this limit during dispatch:
available_slots = max(max_concurrent_agents - running_count, 0)
When all slots are occupied, eligible issues wait for the next poll tick.Dynamic: Changes apply immediately to future dispatch decisions without restart.
max_turns
integer
default:20
Maximum Codex turns per agent run (per worker session).After each successful turn, the agent runner:
  1. Checks if the issue is still in an active state
  2. If active and under max_turns, starts another turn on the same thread
  3. If max_turns is reached, returns control to the orchestrator
The first turn receives the full rendered task prompt. Continuation turns receive minimal guidance:
Continuation guidance:
- The previous Codex turn completed normally, but the Linear issue is still in an active state.
- This is continuation turn #X of Y for the current agent run.
- Resume from the current workspace and workpad state instead of restarting from scratch.
- The original task instructions and prior turn context are already present in this thread.
- Focus on the remaining ticket work and do not end the turn while the issue stays active unless you are truly blocked.
Important: Reaching max_turns does not fail the run. The orchestrator schedules a continuation retry to re-check the issue state.
max_retry_backoff_ms
integer
default:300000
Maximum retry delay in milliseconds (5 minutes by default).Caps exponential backoff for failure-driven retries:
delay = min(10000 * 2^(attempt - 1), max_retry_backoff_ms)
Retry schedule examples:
  • Attempt 1: 10 seconds
  • Attempt 2: 20 seconds
  • Attempt 3: 40 seconds
  • Attempt 4: 80 seconds
  • Attempt 5: 160 seconds
  • Attempt 6+: 300 seconds (capped)
Note: Normal continuation retries after clean exits use a fixed 1-second delay, not exponential backoff.
max_concurrent_agents_by_state
object
Per-state concurrency limits (optional).Allows finer control over how many agents can run for issues in specific states:
agent:
  max_concurrent_agents: 10
  max_concurrent_agents_by_state:
    "in progress": 5
    "merging": 2
State keys are normalized (trim + lowercase) for lookup. If a state isn’t listed, the global max_concurrent_agents applies.Invalid entries (non-positive or non-numeric values) are ignored.

Concurrency Control

The orchestrator evaluates concurrency in this order:
  1. Global limit check:
    running_count < max_concurrent_agents
    
  2. Per-state limit check (if configured):
    state_running_count < max_concurrent_agents_by_state[normalized_state]
    
  3. Blocker rule (for Todo state only):
    • Issues in Todo state with non-terminal blockers are not dispatched
Example from source:
@spec max_concurrent_agents_for_state(term()) :: pos_integer()
def max_concurrent_agents_for_state(state_name) when is_binary(state_name) do
  state_limits = get_in(validated_workflow_options(), [:agent, :max_concurrent_agents_by_state])
  global_limit = max_concurrent_agents()
  Map.get(state_limits, normalize_issue_state(state_name), global_limit)
end

Retry Behavior

Continuation Retries

After a normal worker exit (no error), the orchestrator:
  1. Removes the running entry
  2. Marks the issue as completed (bookkeeping only)
  3. Schedules a continuation retry with 1-second delay
  4. On retry, re-fetches the issue state:
    • If still active → re-dispatch
    • If terminal or missing → release claim and clean workspace

Failure Retries

After abnormal worker exit (error, timeout, stall), the orchestrator:
  1. Removes the running entry
  2. Schedules a failure retry with exponential backoff
  3. Increments the attempt counter
  4. On retry, re-fetches the issue state and re-dispatches if still eligible

Retry Queue Management

Retry entries track:
  • issue_id: Tracker issue ID
  • identifier: Human-readable ID (for logs)
  • attempt: 1-based retry attempt number
  • due_at_ms: Monotonic timestamp for retry execution
  • timer_handle: Runtime timer reference
  • error: Optional error message from previous attempt
From source:
defp schedule_issue_retry(state, issue_id, attempt, opts) do
  identifier = Keyword.get(opts, :identifier, issue_id)
  error = Keyword.get(opts, :error)
  delay_type = Keyword.get(opts, :delay_type, :exponential)

  delay_ms =
    case delay_type do
      :continuation -> @continuation_retry_delay_ms
      :exponential -> exponential_backoff_ms(attempt, state.max_retry_backoff_ms)
    end

  due_at_ms = System.monotonic_time(:millisecond) + delay_ms
  timer_ref = Process.send_after(self(), {:retry_issue, issue_id}, delay_ms)

  retry_entry = %{
    issue_id: issue_id,
    identifier: identifier,
    attempt: attempt,
    due_at_ms: due_at_ms,
    timer_handle: timer_ref,
    error: error
  }

  put_in(state.retry_attempts[issue_id], retry_entry)
end

Turn Budget Example

Given max_turns: 20:
  1. Turn 1: Agent receives full task prompt, completes
  2. State check: Issue still active → continue
  3. Turn 2-19: Agent receives continuation guidance, continues work
  4. Turn 20: Agent completes final turn
  5. State check: Issue still active but max_turns reached
  6. Orchestrator action: Schedule continuation retry (1s delay)
  7. Retry fires: Re-check issue state and dispatch new worker session if still active
This allows long-running work to span multiple worker sessions without failing.

Configuration Reloading

Agent configuration changes are applied dynamically:
  • max_concurrent_agents: Affects next dispatch cycle
  • max_turns: Affects newly started agent runs
  • max_retry_backoff_ms: Affects future retry scheduling
  • max_concurrent_agents_by_state: Affects next dispatch cycle
Running agents continue with their original turn budget.

Examples

High Throughput

agent:
  max_concurrent_agents: 50
  max_turns: 10
  max_retry_backoff_ms: 60000

Conservative with Per-State Limits

agent:
  max_concurrent_agents: 10
  max_turns: 30
  max_retry_backoff_ms: 600000
  max_concurrent_agents_by_state:
    "in progress": 5
    "merging": 2
    "rework": 3

Single Agent (Sequential)

agent:
  max_concurrent_agents: 1
  max_turns: 50
  • polling - Control polling frequency
  • codex - Configure turn timeouts and stall detection
  • tracker - Define active and terminal states