moa - mixture of agents
moa asks one question to several local AI coding CLIs in parallel and collects their
answers with attribution. Reach for it when one model's answer isn't enough and you want to
see where independent models agree, diverge, or contradict.
The CLI is self-documenting. Run moa --help (and moa <command> --help) for the full
flag list - this file only covers what's non-obvious about driving it well.
Prerequisites
uv tool install moa-cli (or run ad-hoc with uvx moa-cli ...). Then moa doctor lists
which agent CLIs are installed and their default models. You need at least two of claude,
codex, agy, opencode on PATH and logged in - moa drives the CLIs you already pay for
and needs no API keys of its own.
Three modes
moa ask(the default) - council / peer review. N agents answer in parallel; each answer streams back with attribution as it lands. The right choice the vast majority of the time.moa distill- council, then one strong aggregator merges the answers into a single synthesized response. Use when you want one answer, not N to read.moa debate- sequential adversarial rounds plus a moderator verdict. The costliest and least reliably-beneficial mode; reach for it only when surfacing disagreement is the actual goal.
How to prompt
The CLIs are stateless - no memory of your conversation. Write a fully self-contained prompt every call: state the question, paste the relevant code/plan/diff, and say what a good answer looks like.
Pass the prompt inline as the string argument - that's the normal case, and it's all the
context the panel ever receives. Don't write a temporary briefing file just to feed it in.
Reserve -f PATH (or -f - for stdin) for piping existing content straight through, e.g.
git diff | moa ask -f - "Review this diff for bugs." - not for a throwaway file you create
for the occasion.
Agents run read-only by default; pass --yolo only when you actually want the panel to
change your working tree.
Parse with --json
--json emits one JSON object per line (JSONL) with a status field per agent - the right
output when an agent consumes the result. Without it, answers print under a labelled heading
on stdout and progress notes go to stderr (so piping stdout stays clean). Prefer --json
whenever you parse programmatically.
Selecting the panel and config
-n N asks the top N installed agents in priority order (claude -> codex -> agy ->
opencode). -p NAME pins an exact set, -x NAME drops agents, -m PROVIDER=MODEL
overrides a model. Persist defaults with moa config set ... (e.g. moa config set num 2,
moa config set exclude codex) and inspect them with moa config show. Per-verb flags:
moa ask --help / moa distill --help / moa debate --help.
Example
moa ask --json "I'm choosing between SQLite and flat Markdown files for ~10k offline-first \
local notes with full-text search and Dropbox sync. Recommend one with tradeoffs."
Report results the way a good peer review would: say which providers answered and which
failed or timed out (check status in the JSON), then summarize where they agree, disagree,
and any unique insight each contributed. Don't silently drop a model that errored.
Supersedes hand-rolling parallel claude -p / codex exec calls, or the older
peer-review skill: call moa and parse its output.