Skip to content

Allow defining the LLM model per orchestrator instance #296

Description

@Weegy

Summary

Let each orchestrator instance define its own LLM model. Today the model is a single global default applied to every Agent's orchestrator. With the pluggable LLM provider work merged (#289, #292), the next step is making the model a per-instance choice so one Agent can run on a different model (or provider) than another.

Current behaviour

The orchestrator is the @omadia/n plugin (middleware/packages/harness-orchestrator), and it is instantiated per Agent (per-Agent plugin-scoped registration). The model is resolved in plugin.ts:

const model =
  (ctx.config.get<string>('orchestrator_model') ?? '').trim() ||
  DEFAULT_ORCHESTRATOR_MODEL;

ctx.config is plugin-scoped, so the storage layer can already hold a distinct value per Agent. In practice every instance resolves to the same value: ORCHESTRATOR_MODEL (default claude-opus-4-8, middleware/src/config.ts) is seeded into the orchestrator plugin config once at first boot, and there is no per-Agent control to override it afterwards. Per-turn routing (orchestrator_model_routing + model_routing_{classifier,simple,complex}_model) exists, but it is also a global toggle and assumes the Claude family.

So the limitation is not the config plumbing. It is that the model is set globally and not surfaced as a per-instance setting.

Motivation

  • Cost and latency differ per Agent. A high-volume support Agent can run on a cheaper model while a reasoning-heavy Agent stays on the top model, instead of forcing one global choice.
  • The provider abstraction only pays off when instances can actually pick different models. Right now every Agent is locked to one model regardless of how many providers are registered.
  • It removes a deploy-time decision (ORCHESTRATOR_MODEL env) from something that should be an operator runtime choice per Agent.

Proposed change

  1. Surface orchestrator_model as a per-Agent setting in the Admin UI (Agent configuration), reading from and writing to the per-Agent orchestrator plugin config that already backs it.
  2. Resolution order per instance: per-Agent setting, then the global seeded default (ORCHESTRATOR_MODEL), then DEFAULT_ORCHESTRATOR_MODEL. Keep ORCHESTRATOR_MODEL as the fallback so existing deployments are unchanged.
  3. Populate the model picker from the @omadia/llm-provider registry (the same source the builder model registry already uses), so only registered models are selectable and the list stays correct as providers are added.
  4. Make per-turn routing config (model_routing_*) resolvable per instance as well, so an Agent that opts into routing can pin its own simple/complex models. Cross-provider per-turn routing stays out of scope (the model router still assumes one family per modelRouting block).
  5. Hot-apply on config change the same way the orchestrator already re-registers per Agent, so changing an Agent's model does not need a restart.

Out of scope

  • Cross-provider per-turn routing inside a single modelRouting block (the classifier and fallbacks assume one model family). Tracked separately if needed.
  • Sub-agent model selection (SUB_AGENT_MODEL) and the Agent Builder model choice (separate issue).

Acceptance criteria

  • An operator can set a different orchestrator model per Agent in the Admin UI and the change takes effect without a restart.
  • Agents with no per-Agent model set keep running on ORCHESTRATOR_MODEL; behaviour for existing deployments is unchanged.
  • The model picker lists only models registered in @omadia/llm-provider.
  • The resolved model per instance is visible in logs or Admin so an operator can confirm which model an Agent is on.

References

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions