Skip to content

feat(subagent): replace downgrade heuristic with 4-step model resolution chain#724

Merged
ahmedhesham6 merged 1 commit into
mainfrom
feat/subagent-model-resolution
May 4, 2026
Merged

feat(subagent): replace downgrade heuristic with 4-step model resolution chain#724
ahmedhesham6 merged 1 commit into
mainfrom
feat/subagent-model-resolution

Conversation

@ahmedhesham6

Copy link
Copy Markdown
Collaborator

Description

Replaces the hard-coded downgrade_model_choice() heuristic with a configurable 4-step subagent model resolution chain.

Changes Made

  • SubagentConfig: New model field on SubagentConfig (both in CLI profile config and MCP server config), allowing per-profile subagent model overrides via [profiles.default.subagent] model = "...".
  • resolve_subagent_model(): New resolution function with a clear priority chain:
    1. Caller override — per-call model parameter on DynamicSubagentRequest, used verbatim when set
    2. Profile config[subagent].model from the active profile
    3. Built-in defaults — provider-specific cost-effective models via default_subagent_model() lookup table (anthropic→haiku-4-5, openai→gpt-5-mini, gemini→2.0-flash, etc.)
    4. Parent inherit — falls back to parent model verbatim when no other source applies
  • SubagentConfig.model threaded through all call sites: ACP server, async mode, interactive mode, MCP server, autopilot, warden tests
  • Observability: Logs resolved model with resolution step (caller_override, profile_config, builtin_default, parent_inherit) and task ID
  • Tests: Replaced old downgrade tests with resolution priority tests; added config parsing and merge tests for the new subagent field

Related Issues

Replaces the brittle string-replacement downgrade logic (opus→haiku, sonnet→haiku) with a maintainable lookup table and explicit configuration surface.

Testing

  • All tests pass locally (cargo test -p stakpak-mcp-server, config tests)
  • No clippy warnings (cargo clippy --all-targets -- -D warnings)
  • Code formatted (cargo fmt --check)

Breaking Changes

None — the new model parameter on DynamicSubagentRequest is optional and defaults to the existing behavior (provider-specific default → parent inheritance).

…ion chain

- Add SubagentConfig to ProfileConfig with optional model field
- Thread subagent_model() through all call sites (ACP, async, interactive, MCP, autopilot, warden)
- Replace downgrade_model_choice() with resolve_subagent_model() resolution chain:
  1. Caller-supplied model override
  2. Profile [subagent].model config
  3. Built-in provider-specific defaults (new default_subagent_model() table)
  4. Parent model inheritance
- Add model parameter to DynamicSubagentRequest for per-call overrides
- Add logging of resolved model with resolution step for observability
- Update tests: config parsing/merge for subagent field, resolution priority tests
@ahmedhesham6 ahmedhesham6 merged commit cdae8f7 into main May 4, 2026
1 check passed
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