### Minimal Workflow Configuration Example Source: https://github.com/openai/symphony/blob/main/elixir/README.md A basic example of a WORKFLOW.md file, demonstrating essential configuration fields like tracker, workspace, hooks, and agent settings. ```md --- tracker: kind: linear project_slug: "..." workspace: root: ~/code/workspaces hooks: after_create: | git clone git@github.com:your-org/your-repo.git . agent: max_concurrent_agents: 10 max_turns: 20 codex: command: codex app-server --- You are working on a Linear issue {{ issue.identifier }}. Title: {{ issue.title }} Body: {{ issue.description }} ``` -------------------------------- ### Install and Check Elixir Version with Mise Source: https://github.com/openai/symphony/blob/main/elixir/README.md Use mise to install Elixir and Erlang versions and verify the installation. ```bash mise install mise exec -- elixir --version ``` -------------------------------- ### Service Startup Algorithm Source: https://github.com/openai/symphony/blob/main/SPEC.md Initializes the service by configuring logging, starting observability, and setting up the workflow watch. It defines the initial state, validates the dispatch configuration, cleans up terminal workspaces, and schedules the first tick of the event loop. ```pseudocode function start_service(): configure_logging() start_observability_outputs() start_workflow_watch(on_change=reload_and_reapply_workflow) state = { poll_interval_ms: get_config_poll_interval_ms(), max_concurrent_agents: get_config_max_concurrent_agents(), running: {}, claimed: set(), retry_attempts: {}, completed: set(), codex_totals: {input_tokens: 0, output_tokens: 0, total_tokens: 0, seconds_running: 0}, codex_rate_limits: null } validation = validate_dispatch_config() if validation is not ok: log_validation_error(validation) fail_startup(validation) startup_terminal_workspace_cleanup() schedule_tick(delay_ms=0) event_loop(state) ``` -------------------------------- ### After Create Hook Script Source: https://github.com/openai/symphony/blob/main/elixir/WORKFLOW.md Executes after a workspace is created. Clones the repository and installs dependencies using 'mise' if available. ```shell git clone --depth 1 https://github.com/openai/symphony . if command -v mise >/dev/null 2>&1; then cd elixir && mise trust && mise exec -- mix deps.get fi ``` -------------------------------- ### Workflow Configuration with Environment Variables Source: https://github.com/openai/symphony/blob/main/elixir/README.md An example of a WORKFLOW.md file using environment variables for sensitive information and dynamic paths. ```yaml tracker: api_key: $LINEAR_API_KEY workspace: root: $SYMPHONY_WORKSPACE_ROOT hooks: after_create: | git clone --depth 1 "$SOURCE_REPO_URL" . codex: command: "$CODEX_BIN --config 'model=\"gpt-5.5\"' app-server" ``` -------------------------------- ### GET /api/v1/state Source: https://github.com/openai/symphony/blob/main/SPEC.md Returns a summary view of the current system state, including running sessions, retry queue, token/runtime totals, and rate limits. ```APIDOC ## GET /api/v1/state ### Description Returns a summary view of the current system state (running sessions, retry queue/delays, aggregate token/runtime totals, latest rate limits, and any additional tracked summary fields). ### Method GET ### Endpoint /api/v1/state ### Response #### Success Response (200) - **generated_at** (string) - Timestamp of when the state was generated. - **counts** (object) - Counts of running and retrying issues. - **running** (integer) - Number of currently running issues. - **retrying** (integer) - Number of issues in the retry queue. - **running** (array) - List of currently running issues. - **issue_id** (string) - Unique identifier for the issue. - **issue_identifier** (string) - User-friendly identifier for the issue. - **issue_url** (string) - URL to the issue tracker. - **state** (string) - Current state of the issue (e.g., "In Progress"). - **session_id** (string) - Identifier for the current session. - **turn_count** (integer) - Number of turns in the current session. - **last_event** (string) - The last event that occurred. - **last_message** (string) - The last message associated with the event. - **started_at** (string) - Timestamp when the issue started. - **last_event_at** (string) - Timestamp of the last event. - **tokens** (object) - Token usage for the issue. - **input_tokens** (integer) - Number of input tokens used. - **output_tokens** (integer) - Number of output tokens used. - **total_tokens** (integer) - Total tokens used. - **retrying** (array) - List of issues currently in the retry queue. - **issue_id** (string) - Unique identifier for the issue. - **issue_identifier** (string) - User-friendly identifier for the issue. - **issue_url** (string) - URL to the issue tracker. - **attempt** (integer) - Current retry attempt number. - **due_at** (string) - Timestamp when the retry is scheduled. - **error** (string) - The error that caused the retry. - **codex_totals** (object) - Aggregate token and runtime totals. - **input_tokens** (integer) - Total input tokens across all issues. - **output_tokens** (integer) - Total output tokens across all issues. - **total_tokens** (integer) - Total tokens used across all issues. - **seconds_running** (number) - Total seconds the system has been running. - **rate_limits** (any) - Information about current rate limits (null if not applicable). ### Response Example ```json { "generated_at": "2026-02-24T20:15:30Z", "counts": { "running": 2, "retrying": 1 }, "running": [ { "issue_id": "abc123", "issue_identifier": "MT-649", "issue_url": "https://tracker.example/issues/MT-649", "state": "In Progress", "session_id": "thread-1-turn-1", "turn_count": 7, "last_event": "turn_completed", "last_message": "", "started_at": "2026-02-24T20:10:12Z", "last_event_at": "2026-02-24T20:14:59Z", "tokens": { "input_tokens": 1200, "output_tokens": 800, "total_tokens": 2000 } } ], "retrying": [ { "issue_id": "def456", "issue_identifier": "MT-650", "issue_url": "https://tracker.example/issues/MT-650", "attempt": 3, "due_at": "2026-02-24T20:16:00Z", "error": "no available orchestrator slots" } ], "codex_totals": { "input_tokens": 5000, "output_tokens": 2400, "total_tokens": 7400, "seconds_running": 1834.2 }, "rate_limits": null } ``` ``` -------------------------------- ### GET /api/v1/ Source: https://github.com/openai/symphony/blob/main/SPEC.md Returns issue-specific runtime/debug details for the identified issue. ```APIDOC ## GET /api/v1/ ### Description Returns issue-specific runtime/debug details for the identified issue, including any information the implementation tracks that is useful for debugging. ### Method GET ### Endpoint /api/v1/ ### Parameters #### Path Parameters - **issue_identifier** (string) - Required - The identifier of the issue to retrieve details for. ### Response #### Success Response (200) - **issue_identifier** (string) - The identifier of the issue. - **issue_id** (string) - The unique ID of the issue. - **status** (string) - The current status of the issue (e.g., "running"). - **workspace** (object) - Information about the issue's workspace. - **path** (string) - The file path of the workspace. - **attempts** (object) - Information about retry attempts. - **restart_count** (integer) - Number of times the issue has been restarted. - **current_retry_attempt** (integer) - The current retry attempt number. - **running** (object) - Details if the issue is currently running. - **session_id** (string) - Identifier for the current session. - **turn_count** (integer) - Number of turns in the current session. - **state** (string) - Current state of the issue (e.g., "In Progress"). - **started_at** (string) - Timestamp when the issue started. - **last_event** (string) - The last event that occurred. - **last_message** (string) - The last message associated with the event. - **last_event_at** (string) - Timestamp of the last event. - **tokens** (object) - Token usage for the issue. - **input_tokens** (integer) - Number of input tokens used. - **output_tokens** (integer) - Number of output tokens used. - **total_tokens** (integer) - Total tokens used. - **retry** (object | null) - Details if the issue is in a retry state. - **logs** (object) - Information about issue logs. - **codex_session_logs** (array) - List of codex session log files. - **label** (string) - Label for the log file. - **path** (string) - File path of the log. - **url** (string | null) - URL to the log file. - **recent_events** (array) - List of recent events for the issue. - **at** (string) - Timestamp of the event. - **event** (string) - The type of event. - **message** (string) - Description of the event. - **last_error** (object | null) - Information about the last error encountered. - **tracked** (object) - Any additional tracked information. #### Error Response (404) - **error** (object) - **code** (string) - Error code (e.g., "issue_not_found"). - **message** (string) - Error message describing the issue. ### Response Example ```json { "issue_identifier": "MT-649", "issue_id": "abc123", "status": "running", "workspace": { "path": "/tmp/symphony_workspaces/MT-649" }, "attempts": { "restart_count": 1, "current_retry_attempt": 2 }, "running": { "session_id": "thread-1-turn-1", "turn_count": 7, "state": "In Progress", "started_at": "2026-02-24T20:10:12Z", "last_event": "notification", "last_message": "Working on tests", "last_event_at": "2026-02-24T20:14:59Z", "tokens": { "input_tokens": 1200, "output_tokens": 800, "total_tokens": 2000 } }, "retry": null, "logs": { "codex_session_logs": [ { "label": "latest", "path": "/var/log/symphony/codex/MT-649/latest.log", "url": null } ] }, "recent_events": [ { "at": "2026-02-24T20:14:59Z", "event": "notification", "message": "Working on tests" } ], "last_error": null, "tracked": {} } ``` ``` -------------------------------- ### Build All Project Components Source: https://github.com/openai/symphony/blob/main/elixir/README.md Run this command to build all components of the project. ```bash make all ``` -------------------------------- ### Clone and Run Symphony Elixir Project Source: https://github.com/openai/symphony/blob/main/elixir/README.md Steps to clone the Symphony repository, set up the Elixir project, and build and run the application. ```bash git clone https://github.com/openai/symphony cd symphony/elixir mise trust mise install mise exec -- mix setup mise exec -- mix build mise exec -- ./bin/symphony ./WORKFLOW.md ``` -------------------------------- ### Run All Project Gates Source: https://github.com/openai/symphony/blob/main/elixir/AGENTS.md Execute all quality gates, including formatting checks, linting, coverage, and Dialyzer analysis. This command ensures the project adheres to quality standards. ```bash make all ``` -------------------------------- ### Run Symphony with a Custom Workflow File Source: https://github.com/openai/symphony/blob/main/elixir/README.md Execute the Symphony service, specifying a custom path to the workflow configuration file. ```bash ./bin/symphony /path/to/custom/WORKFLOW.md ``` -------------------------------- ### System State Summary Source: https://github.com/openai/symphony/blob/main/SPEC.md Retrieves a summary of the current system state, including running and retrying issues, token usage, and rate limits. Use this endpoint for an overview of the system's operational status. ```json { "generated_at": "2026-02-24T20:15:30Z", "counts": { "running": 2, "retrying": 1 }, "running": [ { "issue_id": "abc123", "issue_identifier": "MT-649", "issue_url": "https://tracker.example/issues/MT-649", "state": "In Progress", "session_id": "thread-1-turn-1", "turn_count": 7, "last_event": "turn_completed", "last_message": "", "started_at": "2026-02-24T20:10:12Z", "last_event_at": "2026-02-24T20:14:59Z", "tokens": { "input_tokens": 1200, "output_tokens": 800, "total_tokens": 2000 } } ], "retrying": [ { "issue_id": "def456", "issue_identifier": "MT-650", "issue_url": "https://tracker.example/issues/MT-650", "attempt": 3, "due_at": "2026-02-24T20:16:00Z", "error": "no available orchestrator slots" } ], "codex_totals": { "input_tokens": 5000, "output_tokens": 2400, "total_tokens": 7400, "seconds_running": 1834.2 }, "rate_limits": null } ``` -------------------------------- ### Workspace Configuration Source: https://github.com/openai/symphony/blob/main/elixir/WORKFLOW.md Defines the root directory for the project's workspaces. ```yaml workspace: root: ~/code/symphony-workspaces ``` -------------------------------- ### Orchestration Instructions Template Source: https://github.com/openai/symphony/blob/main/elixir/WORKFLOW.md A Jinja2 template snippet providing instructions for an unattended orchestration session, emphasizing no human interaction and early stopping for blockers. ```jinja Instructions: 1. This is an unattended orchestration session. Never ask a human to perform follow-up actions. 2. Only stop early for a true blocker (missing required auth/permissions/secrets). If blocked, record it in the workpad and move the issue according to workflow. 3. Final message must report completed actions and blockers only. Do not include "next steps for user". Work only in the provided repository copy. Do not touch any other path. ``` -------------------------------- ### Conversion from CoreTokenUsageInfo to ThreadTokenUsage Source: https://github.com/openai/symphony/blob/main/elixir/docs/token_accounting.md Implements the conversion from CoreTokenUsageInfo to ThreadTokenUsage, mapping the respective fields. ```rust impl From for ThreadTokenUsage { fn from(value: CoreTokenUsageInfo) -> Self { Self { total: value.total_token_usage.into(), last: value.last_token_usage.into(), model_context_window: value.model_context_window, } } } ``` -------------------------------- ### Before Remove Hook Script Source: https://github.com/openai/symphony/blob/main/elixir/WORKFLOW.md Executes before a workspace is removed. Runs a mix task for cleanup. ```shell cd elixir && mise exec -- mix workspace.before_remove ``` -------------------------------- ### Run End-to-End Tests in Elixir Source: https://github.com/openai/symphony/blob/main/elixir/README.md Execute the external end-to-end test for Symphony. This requires setting a LINEAR_API_KEY and will create disposable Linear resources. ```bash cd elixir export LINEAR_API_KEY=... make e2e ``` -------------------------------- ### TokenUsageInfo Struct Definition Source: https://github.com/openai/symphony/blob/main/elixir/docs/token_accounting.md Defines the structure for token usage information, including total and last usage, and model context window. ```rust pub struct TokenUsageInfo { pub total_token_usage: TokenUsage, pub last_token_usage: TokenUsage, pub model_context_window: Option, } ``` -------------------------------- ### Check Module Specifications Source: https://github.com/openai/symphony/blob/main/elixir/AGENTS.md Validate that public functions in the 'lib/' directory have adjacent `@spec` annotations. This command helps maintain code quality and documentation. ```bash mix specs.check ``` -------------------------------- ### Worker Attempt Execution Algorithm Source: https://github.com/openai/symphony/blob/main/SPEC.md Defines the execution flow for a worker attempting to process an issue. It manages workspace creation, hook execution, agent session startup, and the turn-by-turn interaction with the agent, including prompt building and result processing. ```pseudocode function run_agent_attempt(issue, attempt, orchestrator_channel): workspace = workspace_manager.create_for_issue(issue.identifier) if workspace failed: fail_worker("workspace error") if run_hook("before_run", workspace.path) failed: fail_worker("before_run hook error") session = app_server.start_session(workspace=workspace.path) if session failed: run_hook_best_effort("after_run", workspace.path) fail_worker("agent session startup error") max_turns = config.agent.max_turns turn_number = 1 while true: prompt = build_turn_prompt(workflow_template, issue, attempt, turn_number, max_turns) if prompt failed: app_server.stop_session(session) run_hook_best_effort("after_run", workspace.path) fail_worker("prompt error") turn_result = app_server.run_turn( session=session, prompt=prompt, issue=issue, on_message=(msg) -> send(orchestrator_channel, {codex_update, issue.id, msg}) ) if turn_result failed: app_server.stop_session(session) run_hook_best_effort("after_run", workspace.path) fail_worker("agent turn error") refreshed_issue = tracker.fetch_issue_states_by_ids([issue.id]) if refreshed_issue failed: app_server.stop_session(session) run_hook_best_effort("after_run", workspace.path) fail_worker("issue state refresh error") issue = refreshed_issue[0] or issue if issue.state is not active: break if turn_number >= max_turns: break turn_number = turn_number + 1 app_server.stop_session(session) run_hook_best_effort("after_run", workspace.path) exit_normal() ``` -------------------------------- ### Issue-Specific Debug Details Source: https://github.com/openai/symphony/blob/main/SPEC.md Fetches detailed runtime and debugging information for a specific issue identifier. Useful for diagnosing problems with individual tasks or processes. Returns a 404 if the issue is not found. ```json { "issue_identifier": "MT-649", "issue_id": "abc123", "status": "running", "workspace": { "path": "/tmp/symphony_workspaces/MT-649" }, "attempts": { "restart_count": 1, "current_retry_attempt": 2 }, "running": { "session_id": "thread-1-turn-1", "turn_count": 7, "state": "In Progress", "started_at": "2026-02-24T20:10:12Z", "last_event": "notification", "last_message": "Working on tests", "last_event_at": "2026-02-24T20:14:59Z", "tokens": { "input_tokens": 1200, "output_tokens": 800, "total_tokens": 2000 } }, "retry": null, "logs": { "codex_session_logs": [ { "label": "latest", "path": "/var/log/symphony/codex/MT-649/latest.log", "url": null } ] }, "recent_events": [ { "at": "2026-02-24T20:14:59Z", "event": "notification", "message": "Working on tests" } ], "last_error": null, "tracked": {} } ``` -------------------------------- ### GraphQL Query/Mutation Input Shape for Linear Tool Source: https://github.com/openai/symphony/blob/main/SPEC.md Defines the preferred input structure for executing GraphQL queries or mutations against Linear using the `linear_graphql` tool. The `query` field is mandatory and must contain a single GraphQL operation, while `variables` is optional. ```json { "query": "single GraphQL query or mutation document", "variables": { "optional": "graphql variables object" } } ``` -------------------------------- ### Linear Tracker Configuration Source: https://github.com/openai/symphony/blob/main/elixir/WORKFLOW.md Configures the Linear issue tracker integration, specifying the project slug, required labels, active states, and terminal states. ```yaml tracker: kind: linear project_slug: "symphony-0c79b11b75ea" required_labels: [] active_states: - Todo - In Progress - Merging - Rework terminal_states: - Closed - Cancelled - Canceled - Duplicate - Done ``` -------------------------------- ### Issue Context Template Source: https://github.com/openai/symphony/blob/main/elixir/WORKFLOW.md A Jinja2 template snippet for displaying issue context, including identifier, title, status, labels, and description. ```jinja Issue context: Identifier: {{ issue.identifier }} Title: {{ issue.title }} Current status: {{ issue.state }} Labels: {{ issue.labels }} URL: {{ issue.url }} Description: {% if issue.description %} {{ issue.description }} {% else %} No description provided. {% endif %} ``` -------------------------------- ### Reconcile Active Runs Algorithm Source: https://github.com/openai/symphony/blob/main/SPEC.md Updates the state of currently running issues by fetching their latest states from the tracker. It terminates issues that have reached a terminal state and updates the state for active ones. ```pseudocode function reconcile_running_issues(state): state = reconcile_stalled_runs(state) running_ids = keys(state.running) if running_ids is empty: return state refreshed = tracker.fetch_issue_states_by_ids(running_ids) if refreshed failed: log_debug("keep workers running") return state for issue in refreshed: if issue.state in terminal_states: state = terminate_running_issue(state, issue.id, cleanup_workspace=true) else if issue.state in active_states: state.running[issue.id].issue = issue else: state = terminate_running_issue(state, issue.id, cleanup_workspace=false) return state ``` -------------------------------- ### Agent Configuration Source: https://github.com/openai/symphony/blob/main/elixir/WORKFLOW.md Configures the maximum number of concurrent agents and the maximum number of turns per agent. ```yaml agent: max_concurrent_agents: 10 max_turns: 20 ``` -------------------------------- ### Codex Command Configuration Source: https://github.com/openai/symphony/blob/main/elixir/WORKFLOW.md Specifies the command to run the Codex tool, including configuration for shell environment policy, model, and reasoning effort. ```yaml codex: command: codex --config shell_environment_policy.inherit=all --config 'model="gpt-5.5"' --config model_reasoning_effort=xhigh app-server approval_policy: never thread_sandbox: workspace-write turn_sandbox_policy: type: workspaceWrite networkAccess: true ```