Skip to content

feat(models): SWE_MODEL_LOW/MED/HIGH per-tier model env vars#100

Merged
AbirAbbas merged 3 commits into
mainfrom
feat/model-tiers-opencode
Jul 20, 2026
Merged

feat(models): SWE_MODEL_LOW/MED/HIGH per-tier model env vars#100
AbirAbbas merged 3 commits into
mainfrom
feat/model-tiers-opencode

Conversation

@AbirAbbas

@AbirAbbas AbirAbbas commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Brings the claude_code-style tier approach to every runtime (open_code, codex, claude_code) and both implementations (Python + Go): three env vars map the 17 agent roles to models by capability tier, instead of enumerating 17 models.<role> keys.

SWE_MODEL_HIGH=openrouter/z-ai/glm-5.2#high        # planning-heavy: pm, architect, tech_lead, replan
SWE_MODEL_MED=openrouter/deepseek/deepseek-v4-pro  # coding/review/QA (coder, qa, code_reviewer, ...)
SWE_MODEL_LOW=openrouter/deepseek/deepseek-v4-flash # mechanical: qa_synthesizer, git

Precedence (lowest → highest): runtime base defaults → SWE_DEFAULT_MODEL/AI_MODEL/HARNESS_MODELtier env varsmodels.defaultmodels.<role>. With no tier vars set, resolution is byte-identical to today. SWE_MODEL_HIGH also becomes the default for the standalone plan pipeline (its reasoners are high-tier).

The optional #variant reasoning-effort suffix rides on the model string and is consumed by the harness providers (opencode --variant, codex model_reasoning_effort) — Agent-Field/agentfield#801, which implements it in all three SDKs (Python/Go/TS). Plain tier models work with current SDK releases; once #801 ships, the agentfield floor here should be bumped so Docker builds pick it up.

Changes

Python: swe_af/execution/schemas.pyMODEL_TIERS, ROLE_TO_TIER, TIER_MODEL_ENV_VARS, _tier_models_from_env(); tier layer in resolve_runtime_models(); _default_planning_model() consults SWE_MODEL_HIGH first. .env.example documented. 15 new tests (tests/test_model_tiers.py).
Go: go/internal/config/resolve.goRoleToTier + tierModelsFromEnv() at the identical precedence point; DefaultPlanningModel() consults SWE_MODEL_HIGH first. 15 subtests mirroring the Python contract 1:1 (modeltiers_test.go); env-isolation lists extended in config_test.go / orch/plan_test.go.

Validation

  • Python: make check (literal CI steps, fresh 3.12 venv, committed tree): 1052 passed, 1 skipped
  • Go: CI go job reproduced literally (GOWORK=off, Go 1.23 toolchain, pinned sparse SDK clone): gofmt/build/vet/test -race — all 26 packages ok
  • Live end-to-end (runtime=open_code, tier vars above): all 17 roles resolved to their tier's model, models.coder override still wins, and opencode session records confirmed architect served by z-ai/glm-5.2 (variant high), coder by deepseek-v4-pro, qa_synthesizer by deepseek-v4-flash

Notes

  • Fast mode (swe_af/fast/) has no env cascade at all today, so tiers were deliberately not mirrored there — separate decision.

🤖 Generated with Claude Code

AbirAbbas and others added 3 commits July 20, 2026 13:08
Classify the 17 agent roles into three capability tiers (high = planning
reasoning, med = coding/review/QA, low = mechanical) and let each tier be
pointed at a model with one env var, instead of enumerating 17 role keys.
Tier vars slot between the SWE_DEFAULT_MODEL cascade and caller config in
resolve_runtime_models; SWE_MODEL_HIGH also becomes the default for the
plan pipeline, whose reasoners are high-tier.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ier layer

RoleToTier + tierModelsFromEnv in internal/config, applied at the same
precedence point as swe_af/execution/schemas.py (after the default-model
env cascade, before models config); DefaultPlanningModel consults
SWE_MODEL_HIGH first. Tests mirror tests/test_model_tiers.py 1:1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AbirAbbas
AbirAbbas merged commit 039726a into main Jul 20, 2026
3 checks passed
@AbirAbbas
AbirAbbas deleted the feat/model-tiers-opencode branch July 20, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant