[FEATURE] Mixture of Agents (MoA) as a first-class model/preset
Summary
Support Mixture of Agents (MoA): a selectable "model" in the picker that fans every user turn out to N advisor models in parallel, then aggregates their analyses with a final aggregator model — the pattern popularized by the MoA papers and already shipped in other agent products (e.g. Hermes' MOA presets). Today opencode can only run one model per session; MoA would let users pick an ensemble exactly like they pick a single model.
Motivation
- MoA reliably improves answer quality on reasoning-heavy tasks (parallel independent analyses + aggregation beats a single pass, especially with small models).
- Users already mix models via providers (OpenRouter-style routing); MoA is the natural next step and the pattern is proven in production elsewhere.
- A local reference implementation exists and is battle-tested (see below), so the design is validated, not speculative.
Proposed design
1. Presets (config-level)
A preset defines the ensemble:
moa:
presets:
captain-test:
advisors:
- model: ollama-cloud/glm-5.2
max_tokens: 600
- model: ollama-cloud/minimax-m3
max_tokens: 600
aggregator:
model: ollama-cloud/deepseek-v4-flash:0731
reasoning_effort: max
max_tokens: 4096
fanout: user_turn # every user turn, or explicit
- Advisors receive the FULL task + context (unbounded input; only output capped).
- Aggregator receives advisor analyses + original task, produces the final answer.
- Per-preset token caps, timeouts, and model roles.
- Presets appear in the model picker as
moa/<preset> entries, selectable exactly like any other model.
2. Runtime behavior
- Per user turn: fan out to advisors in parallel -> collect analyses -> aggregator synthesizes -> stream the final answer back (SSE).
- Failure isolation: one dead advisor must not kill the turn; aggregate over whatever succeeded.
- Abort/cancel must cancel in-flight advisor calls cleanly.
- Token/usage accounting per advisor + aggregator, surfaced in the session UI.
3. Config & UX
- Presets defined in config (opencode.json or a dedicated moa block), same surface as provider models.
- Picker shows
moa/<preset> entries; switching presets mid-session works like switching models.
- Traces optional (per-preset, for audit).
Reference implementation
A working local implementation already exists:
tools/moa/ — standalone MoA runner (CLI + lib) in a fork of this repo: https://github.com/patrickpassosb/opencode/pull/40927
- Same wrapper also shipped in the security-lab repo (merged): thread-pool parallel advisors, aggregator synthesis, per-advisor failure isolation, JSON traces, config precedence (defaults -> yaml -> env -> CLI flags), OpenAI-compatible transport (works with any provider, not just OpenAI).
- 26 tests, live-verified against real models via an OpenAI-compatible proxy.
The core MoA engine (lib/moa.py) is ~450 lines and self-contained; the design above is directly informed by its real-world usage.
Open questions
- Should MoA be a provider-level feature (a
moa provider wrapping other providers) or a session-level feature (session runs a preset regardless of provider)?
- Should presets be per-user (global config) or per-project?
- Does the team want fanout modes beyond
user_turn (e.g. only on explicit trigger)?
Impact
- Adds a new selectable model class to the picker without breaking existing single-model behavior.
- Backwards compatible: no change unless a user configures presets.
[FEATURE] Mixture of Agents (MoA) as a first-class model/preset
Summary
Support Mixture of Agents (MoA): a selectable "model" in the picker that fans every user turn out to N advisor models in parallel, then aggregates their analyses with a final aggregator model — the pattern popularized by the MoA papers and already shipped in other agent products (e.g. Hermes' MOA presets). Today opencode can only run one model per session; MoA would let users pick an ensemble exactly like they pick a single model.
Motivation
Proposed design
1. Presets (config-level)
A preset defines the ensemble:
moa/<preset>entries, selectable exactly like any other model.2. Runtime behavior
3. Config & UX
moa/<preset>entries; switching presets mid-session works like switching models.Reference implementation
A working local implementation already exists:
tools/moa/— standalone MoA runner (CLI + lib) in a fork of this repo: https://github.com/patrickpassosb/opencode/pull/40927The core MoA engine (lib/moa.py) is ~450 lines and self-contained; the design above is directly informed by its real-world usage.
Open questions
moaprovider wrapping other providers) or a session-level feature (session runs a preset regardless of provider)?user_turn(e.g. only on explicit trigger)?Impact