# How the Symphony Orchestrator Handles Issue Priority: Sorting and Dispatch Logic

> Learn how the Symphony orchestrator handles issue priority. Discover its sorting and dispatch logic that prioritizes critical tasks for efficient processing.

- Repository: [OpenAI/symphony](https://github.com/openai/symphony)
- Tags: internals
- Published: 2026-05-08

---

**The Symphony orchestrator handles issue priority by sorting candidate issues using a numeric rank (1–4, with 5 as default) before applying dispatch logic, ensuring higher-priority issues are processed first when agent capacity is limited.**

The openai/symphony orchestrator manages Codex-backed agent workloads by polling Linear for issues and scheduling them based on availability. Understanding how the Symphony orchestrator handles issue priority reveals a clean separation between ranking and dispatch logic, where priority influences the sort order but not the eligibility checks themselves.

## How Issue Priority Works in the Scheduling Loop

The orchestrator's scheduling logic, implemented in [`elixir/lib/symphony_elixir/orchestrator.ex`](https://github.com/openai/symphony/blob/main/elixir/lib/symphony_elixir/orchestrator.ex), treats priority exclusively as a sorting mechanism. This design ensures deterministic queue ordering while maintaining simple, state-based capacity checks.

### Fetching Candidate Issues from Linear

The process begins in `maybe_dispatch/1`, which retrieves the current issue set via `Tracker.fetch_candidate_issues/0` at lines 28–30. This function returns a list of `%Issue{}` structs (defined in [`elixir/lib/symphony_elixir/linear/issue.ex`](https://github.com/openai/symphony/blob/main/elixir/lib/symphony_elixir/linear/issue.ex)) containing metadata including the `priority` field.

### The Three-Part Sort Key

Before any dispatch checks occur, the orchestrator calls `sort_issues_for_dispatch/1` (lines 34–42) to construct a composite sort key for each issue:

1. **`priority_rank(issue.priority)`** – a numeric rank derived from the issue's priority field
2. **`issue_created_at_sort_key(issue)`** – a timestamp-based secondary key for temporal ordering
3. **`issue.identifier`** – a deterministic string tiebreaker

Because Elixir's `Enum.sort_by/2` orders values in ascending order, an issue with `priority = 1` (the highest priority) appears before `priority = 2`, and so on.

### Priority Ranking Logic

The `priority_rank/1` helper function at lines 44–46 implements a strict validation scheme:

- Integer priorities **1 through 4** are returned unchanged
- Any other value (including `nil`) falls back to **5**

This creates a five-tier system where lower numbers represent higher priority, and unprioritized issues default to the lowest rank (5).

## Code Implementation: Priority Sorting in [`orchestrator.ex`](https://github.com/openai/symphony/blob/main/orchestrator.ex)

The sorting implementation combines priority validation with temporal ordering to ensure fair but prioritized dispatch:

```elixir
defp sort_issues_for_dispatch(issues) when is_list(issues) do
  Enum.sort_by(issues, fn
    %Issue{} = issue ->
      {
        priority_rank(issue.priority),
        issue_created_at_sort_key(issue),
        issue.identifier || issue.id || ""
      }
    _ -> 
      {priority_rank(nil), issue_created_at_sort_key(nil), ""}
  end)
end

```

The `priority_rank/1` helper enforces the valid numeric range:

```elixir
defp priority_rank(priority) when is_integer(priority) and priority in 1..4, do: priority
defp priority_rank(_priority), do: 5

```

## Dispatch Decision Making

After sorting, the orchestrator iterates through the ordered list and applies `should_dispatch_issue?/5` (lines 55–67) to each entry. This function evaluates slot availability, active state sets, and terminal state constraints without reconsidering priority—the sorting phase has already ensured that if capacity exists, the highest-priority eligible issue receives the agent.

This architecture means priority acts as a queue ordering mechanism rather than a hard constraint. If the orchestrator has limited slots and five issues with priorities 1, 2, 2, 3, and 5, it will dispatch the priority 1 issue and both priority 2 issues before considering the lower-priority items.

## Summary

- The Symphony orchestrator handles issue priority exclusively during the sorting phase in `sort_issues_for_dispatch/1` within [`elixir/lib/symphony_elixir/orchestrator.ex`](https://github.com/openai/symphony/blob/main/elixir/lib/symphony_elixir/orchestrator.ex).
- Valid priority values are integers 1–4, with all other values (including `nil`) defaulting to 5 via the `priority_rank/1` helper.
- The sort order is ascending by priority rank, then by creation time (newer issues later), ensuring deterministic dispatch sequencing.
- Dispatch logic in `should_dispatch_issue?/5` respects the pre-sorted order but does not re-evaluate priority during capacity checks.
- Issues without valid priorities are placed after all explicitly prioritized issues in the dispatch queue.

## Frequently Asked Questions

### What priority values does Symphony recognize?

Symphony recognizes integer priorities 1 through 4 as valid rankings. These map directly to the numeric rank used in sorting, where 1 represents the highest priority and 4 represents the lowest valid priority. Any other integer or non-integer value is treated as unprioritized.

### How does Symphony handle issues without a priority?

Issues lacking a priority field or containing invalid values receive a default rank of 5 via the `priority_rank/1` fallback clause at line 46 of [`orchestrator.ex`](https://github.com/openai/symphony/blob/main/orchestrator.ex). This places them after all explicitly prioritized issues (1–4) in the dispatch queue, ensuring they are processed only when higher-priority work is complete.

### Does priority affect the dispatch eligibility checks?

No. Priority only influences the sort order applied before dispatch checks begin. The `should_dispatch_issue?/5` function evaluates capacity limits and state machine constraints without referencing priority, relying entirely on the pre-sorted list to ensure high-priority issues are evaluated first when slots become available.

### Where is the priority sorting logic located?

The priority sorting logic is implemented in [`elixir/lib/symphony_elixir/orchestrator.ex`](https://github.com/openai/symphony/blob/main/elixir/lib/symphony_elixir/orchestrator.ex), specifically within the `sort_issues_for_dispatch/1` function (lines 34–42) and the `priority_rank/1` helper (lines 44–46). The `%Issue{}` struct containing the priority field is defined in [`elixir/lib/symphony_elixir/linear/issue.ex`](https://github.com/openai/symphony/blob/main/elixir/lib/symphony_elixir/linear/issue.ex).