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

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, 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) 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

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

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:

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.
  • 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. 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, 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →