Model Policy
The model policy is the backbone of MoAI-ADK Tokenomics. Rather than “the best model for everything,” it declaratively assigns the right model to each agent — reasoning-heavy work like planning and auditing, and lightweight work like documentation and Git. It maximizes quality within your Claude Code subscription plan while preventing rate-limit errors.
The MoAI-ADK v3.0 agent catalog contains 11 agents (10 MoAI-custom + the
Anthropic built-in Explore). Under the No-Haiku policy, Haiku appears
nowhere. Opus carries every multi-turn agentic row and Sonnet is confined to
single-shot, input-dominated rows; the policy tier controls where each agent
sits on the Opus effort ladder, not which model class it gets.
| Policy (profile) | CLI flag | Opus cells | Sonnet cells | Best for |
|---|---|---|---|---|
| high | --model-policy high | 9 of 11 | 2 of 11 | Highest quality; max effort on the two rarest-invocation rows |
| medium (default) | --model-policy medium | 9 of 11 | 2 of 11 | Balance of quality and cost; the knee of the cost/score curve |
| low | --model-policy low | 7 of 11 | 4 of 11 | Lowest cost per task; agentic rows drop to Opus low |
Name mapping: The
profilefield inllm.yaml, the legacyperformance_tieralias, and the CLI flag--model-policyall use the same three valueshigh/medium/lowand map 1:1 (no separate translation). The default ismedium. The former top-tier namemaxis still read as an alias forhighso existing configs keep resolving, but saves always writehigh— no migration step is required.performance_tieris read only whenprofileis absent. User name and the like are kept separately inuser.yaml.
Why does this matter? Lowering the policy no longer means switching to a weaker model class. On a long-horizon agentic task, Opus at
loweffort scores higher and costs less per task than Sonnet at any effort, because the bill is set by how many steps a model spends finishing — not by the per-token rate. So thelowpolicy economizes within Opus by lowering reasoning depth, and reaches for Sonnet only on the single-shot rows where multi-step completion failure does not apply.
The 33 cells below are the profile matrix (11 agents × 3 profiles). Each cell is
the {model, effort} pair the resolver injects at spawn time. (The orchestrator
main session is not a spawned agent, so it is not in the table.)
| Agent | high | medium | low |
|---|---|---|---|
| manager-spec | opus / high | opus / medium | opus / low |
| manager-develop | opus / max | opus / medium | opus / low |
| manager-docs | opus / medium | opus / low | sonnet / low |
| manager-git | sonnet / low | sonnet / low | sonnet / low |
| manager-design | opus / high | opus / medium | opus / low |
| Agent | high | medium | low |
|---|---|---|---|
| plan-auditor | opus / high | opus / medium | opus / low |
| sync-auditor | opus / high | opus / medium | opus / low |
| super-advisor | opus / max | opus / high | opus / medium |
| builder-harness | opus / high | opus / medium | opus / low |
| e2e-tester | opus / medium | opus / low | sonnet / low |
| Agent | high | medium | low |
|---|---|---|---|
| Explore | sonnet / low | sonnet / low | sonnet / low |
Explorehas no agent file on disk, so its effort cannot be pinned in frontmatter — the matrix recordssonnet / lowas the call-time default, stated in the spawn prompt. The Agent Teams static layer (static role profiles) was retired in v3.0; parallel work is now covered by sub-agent parallel execution and dynamic workflows. Themoai cgteammate runtime (tmux panes) is preserved.
Haiku removal (v3.0): The former Haiku slots (documentation, MX tagging, Git procedures) were replaced with lower reasoning depth rather than a lower model class — cost is cut by effort tiering, not by model substitution.
- Opus on every agentic row:
manager-spec,manager-develop,plan-auditor,sync-auditor,manager-design,builder-harness,manager-docs,e2e-tester— all multi-turn work stays on Opus, because Opus atlowoutscores Sonnet at any effort while costing less per task - Sonnet only on single-shot rows:
manager-gitmechanics andExploresearch complete in one input-dominated pass, so multi-step completion failure does not apply and Sonnet’s lower input price is the operative factor. These two rows are fixed across all three profiles maxis confined to two cells:manager-developandsuper-advisor, in thehighprofile only — the rarest-invocation rows, where one decision carries disproportionate downstream costxhighis used nowhere: on Opus it matcheshighon score at 49% higher costlowsteps down effort, not model class: agentic rows move to Opuslow; onlymanager-docsande2e-testeradditionally fall back to Sonnet
To ensure the agent that authored a plan never audits it, plan-auditor and
sync-auditor keep assignments independent of manager-spec — bias prevention
is a structural property of the catalog, not of the cell values.
v3.0 adds a work phase and SPEC size (Tier) axis on top of per-agent
assignment. internal/config/model_routing.go declaratively manages the
Tier×Phase → {model, effort} matrix:
- model: inherit / sonnet / opus / glm / fable
- effort (reasoning depth): low / medium / high / xhigh / max
- tier (SPEC size): S / M / L
- phase (work phase): plan / run / sync / mx
Per-agent model+effort assignment is handled by a single profile matrix. The
active profile (profile — high/medium/low) selects one column of the
matrix; when profile is absent the legacy performance_tier is read as an
alias, and failing that it is interpreted as medium. For the detailed
per-agent mapping, see the Profile Matrix page.
moai init my-project
# The interactive wizard includes model policy selectionmoai update
# Interactive prompts:
# - Reset model policy? (y/n) — reset the model policy
# - Update GLM settings? (y/n) — configure GLM environment variablesmoai init my-project --model-policy high # Highest quality (max effort on 2 rows)
moai init my-project --model-policy medium # Balanced (default)
moai init my-project --model-policy low # Lowest cost per task--model-policy takes the three values high/medium/low and persists to the
performance_tier field of llm.yaml. The former top-tier name max is still
accepted as input and treated as an alias of high.
The default policy is
medium(llm.yamlperformance_tier: "medium", corresponding to CLI--model-policy medium— when absent, interpreted asmedium). GLM settings are isolated insettings.local.jsonand never committed to Git.
- CG Mode — cut costs with the Claude + GLM hybrid
- Agent Guide — customizing agents
- CLI Reference — moai init, moai update details