Files
galaxy/specs/QUALITY-643/PRODUCT.md
T

6.7 KiB

Harness-Specific Model Selection in Orchestration Config

Linear: QUALITY-643

Summary

When a user selects a non-Oz harness (Claude Code, Codex) in the orchestration config UI, the model picker should show models that the selected harness actually supports, and the chosen model should reach the harness process. Today the model picker always shows Warp's internal model catalog regardless of harness, and those IDs are not recognized by third-party harness CLIs.

Figma: none provided — changes are behavioral within existing orchestration config UI chrome (plan card and run_agents confirmation card).

Behavior

Harness picker content

  1. The harness picker populates from the server-provided availableHarnesses list (via HarnessAvailabilityModel), not from a hardcoded client-side list. This ensures the desktop matches the web UI and respects admin-configured harness availability.

  2. Each harness entry displays its display_name from the server with the corresponding brand icon (Warp logo for Oz, Claude logo for Claude Code, OpenAI logo for Codex, Gemini logo for Gemini CLI).

  3. Enabled harnesses are selectable. Disabled harnesses (admin-disabled via org settings) appear in the list with a visual indicator (e.g. greyed text or a "disabled" badge) but cannot be selected.

  4. Enabled harnesses appear before disabled harnesses in the list.

  5. If the currently-selected harness becomes disabled (e.g. after a server refresh), the picker retains the selection but the UI should indicate the issue.

Model picker content by harness

  1. When the harness picker is set to Oz (or is empty/unset), the model picker shows the Warp LLM catalog — the same models shown in single-agent mode. This is the current behavior and must not regress.

  2. When the harness picker is set to Claude Code, the model picker shows:

    • A "Default model" entry at the top (value: empty string) meaning "don't override — let the harness use its own default."
    • The server-provided Claude Code model catalog (e.g. best, opus, sonnet, haiku, opus (1M context), sonnet (1M context), pinned versions like opus 4.7, sonnet 4.6). This matches the Oz web UI's harness model selector.
  3. When the harness picker is set to Codex and the execution mode is Cloud, the model picker shows:

    • A "Default model" entry at the top (value: empty string), same as Claude Code.
    • The server-provided Codex model catalog (e.g. default, GPT-5.5, GPT-5.4, GPT-5.4 mini). The default entry from the server explicitly skips writing the model key to config, which has the same practical effect as the "Default model" entry but is Codex-specific. This matches the Oz web UI's Codex model selector.

    When the execution mode is Local, the model picker shows only the "Default model" entry. The Codex CLI reads its model from ~/.codex/config.toml, which is shared global state — writing to it from a child agent would clobber the user's existing config and race with parallel agents. Local Codex children inherit whatever model the user has configured.

  4. When the harness picker is set to Gemini (currently disabled for orchestration), the model picker follows the same pattern: "Default model" at top, then server-provided Gemini models if any exist.

  5. Each model entry displays its display_name from the server catalog. The raw id (e.g. "opus", "gpt-5.4") is the value stored as the selected model_id and passed to the harness process. No provider icons or model spec sidecars are shown for harness models (they lack that metadata).

Defaults when no model is specified

  1. When the orchestration config is created (via create_orchestration_config) or the harness changes and no model_id is specified (empty string), the model picker defaults to:
  • Oz: the orchestrator's current model (the model the parent agent is using).
  • Non-Oz harnesses (Claude Code, Codex, Gemini): the "Default model" entry (empty string), meaning the harness uses its own default.

Model reset on harness change

  1. When the user changes the harness, the model_id resets because each harness has its own disjoint model catalog. The reset target is "Default model" (empty string) for non-Oz harnesses, or the first available Warp LLM for Oz. The only exception is the empty string itself ("Default model"), which can persist across non-Oz harness changes.

Loading and empty states

  1. If the harness model catalog has not yet been fetched from the server when the user switches to a non-Oz harness, the model picker shows only the "Default model" entry. Once the catalog arrives, the picker repopulates with the full list, keeping "Default model" selected.

  2. If the server returns an empty model list for a harness, the model picker shows only the "Default model" entry. The model_id remains empty.

Consistency across UI surfaces

  1. The orchestration config block (plan card) and the run_agents confirmation card must show the same harness-specific models, using the same server catalog, and behave identically when the harness changes.

  2. The sync_picker_selections logic (which syncs picker UI state to the edit state) must correctly match harness-specific model IDs against the harness model list, not against Warp's internal LLM catalog, when a non-Oz harness is active.

Model ID delivery to harness processes

  1. When the user selects a model for Claude Code and agents are launched, the selected model_id (e.g. "opus") must reach the Claude Code CLI process as the ANTHROPIC_MODEL environment variable. This applies to both local child agents and remote agents.

  2. When the user selects a model for Codex and agents are launched in Cloud mode, the selected model_id (e.g. "gpt-5.4") must be written to ~/.codex/config.toml as the top-level model key before the Codex CLI starts. If the selected model is "default", the model key must NOT be written (or must be removed if previously present), allowing Codex to use its own default. In Local mode, no model override is written — the user's existing ~/.codex/config.toml is used as-is.

  3. When the user selects a model for Oz, the existing model_id propagation behavior (Warp internal LLM preference) must not change.

  4. When the "Default model" entry is selected (empty model_id) for any non-Oz harness, no model override is injected — the harness process uses its own default.

Auto-launch behavior

  1. The matches_active_config check (which determines whether a run_agents call auto-launches without user confirmation) must treat harness-specific model_ids the same as Warp model_ids: an exact string match between the request's model_id and the config's model_id.