.opencode/models/models.yaml is now the ONE file humans edit to assign a model to an agent. tools/sync_models.py regenerates every derived surface — the .opencode/models/*.txt files, opencode.json's `agent` block, and each non-tier agent's .md `model:` frontmatter — so an assignment cannot drift across surfaces. `--check` verifies with no writes and is enforced in CI by test_model_registry_in_sync_with_manifest. Hardened after adversarial review: - Deletes orphan <agent>.txt files left behind when an override is dropped from the manifest. The dispatcher's resolver reads <agent>.txt before default.txt, so a stale file would silently pin the old model. Tier .txt files are left to sync_tier_models.py. - Rejects a manifest key that does not name a real agent (no matching .opencode/agents/<name>.md) instead of silently appending a bogus opencode.json entry and leaving the real agent on the default model. - Validates the regenerated opencode.json BEFORE writing it, so a bad render aborts cleanly instead of corrupting the file on disk. Tier-ladder agents (task-implementor-tier-*) remain governed separately by tiers.yaml + sync_tier_models.py and are passed through untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.2 KiB
.opencode/models/ — Model registry
Single source of truth: models.yaml
models.yaml is the ONE file you edit to assign an LLM model to an
agent. Every other model-bearing surface is generated from it by
tools/sync_models.py — do not hand-edit the generated artifacts; the
next sync overwrites them.
# models.yaml
default: local-claude/claude-haiku-4-5
agents:
conflict-resolver-worker: local-claude/claude-opus-4-6
estimator-implementation: local-claude/claude-sonnet-4-6
# ... only agents needing a NON-default model appear here
tools/sync_models.py regenerates, from models.yaml:
| Generated artifact | Consumed by |
|---|---|
.opencode/models/<agent>.txt, default.txt |
the dispatcher's _opencode_worker._resolve_role_model |
opencode.json → agent.<name>.model |
OpenCode's static agent registry |
model: frontmatter in .opencode/agents/<agent>.md |
OpenCode's per-agent config |
Both OpenCode-facing surfaces (the opencode.json block and the
.md frontmatter) are written, because which one OpenCode honours has
varied across versions — writing both makes the assignment correct
regardless. Since all of them derive from the one manifest, they cannot
disagree.
Swapping a model
- Edit
models.yaml. - Apply it — either:
- relaunch the controller pipeline —
tools/run-controller-state-machine-pipeline.shrunssync_models.pyautomatically at startup (before OpenCode boots); or - run
python3 tools/sync_models.pyby hand.
- relaunch the controller pipeline —
- Restart OpenCode — it caches its config at process start, so a running server keeps the old model until restarted. (The pipeline launcher restarts OpenCode for you.)
Verify with no writes — python3 tools/sync_models.py --check exits 1
on any drift between models.yaml and the generated artifacts (suitable
for CI or a pre-launch gate).
Tier-ladder agents — tiers.yaml
The task-implementor-tier-* agents are governed separately by
tiers.yaml + tools/sync_tier_models.py (the escalation ladder has
its own manifest, generator, and drift test). sync_models.py passes
their opencode.json entries through untouched and never edits their
.md files. To change a tier model, edit tiers.yaml and run
tools/sync_tier_models.py.
Inheriting agents
task-implementor and agent-evolution-pool-supervisor have no
opencode.json agent entry and no model: line — they deliberately
inherit their caller's model. sync_models.py does not touch them.
File reference
| File | Role |
|---|---|
models.yaml |
Source of truth — per-agent model assignment (hand-edited) |
tiers.yaml |
Source of truth for the tier ladder (hand-edited) |
<agent>.txt, default.txt |
Generated by sync_models.py |
README.md |
This file |
Every model id is providerID/modelID; the provider must be declared
in opencode.json's provider block — sync_models.py validates this
and aborts on an unknown provider.
See also
../../tools/sync_models.py— the generator.../../tools/sync_tier_models.py— the tier generator.../../docs/development/models.md— design history and the planned Stage 2 fallback layer.