fix(agents): restore global subagent model default priority over agent own model#58823
fix(agents): restore global subagent model default priority over agent own model#58823joeykrug wants to merge 29 commits into
Conversation
Greptile SummaryThis PR fixes a model-selection precedence regression introduced in PR #58003. It restores the correct priority order in both
Confidence Score: 5/5Safe to merge — minimal, targeted fix with good regression-test coverage and no collateral changes. All findings are P2 or lower. The logic change is a correct two-line swap applied consistently across both code paths, the updated and new tests directly cover the regression and the full priority matrix, and no unrelated code is touched. No files require special attention. Reviews (1): Last reviewed commit: "fix(agents): restore global subagent mod..." | Re-trigger Greptile |
155066c to
d588fb4
Compare
|
Codex review: keeping this open for maintainer follow-up; there is still a little grit to resolve. Keep this PR open. Current main still implements and tests the opposite subagent model precedence, while the docs support the reporter's expectation that Best possible solution: Keep this PR open for maintainer review. If the documented contract is intended, land this PR or a narrow equivalent, ideally with explicit allowlist validation for resolved subagent defaults and What I checked:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 7120f5b25487. |
9a24cf6 to
0cc6234
Compare
…t own model PR openclaw#58003 reordered resolveSubagentConfiguredModelSelection to prefer agentConfig.model over agents.defaults.subagents.model. This caused the main agent's own model to shadow the global subagent default — e.g. when the main agent runs Opus and defaults.subagents.model is GPT-5.4, subagents incorrectly inherited Opus instead of GPT-5.4. Restore the correct precedence: 1. agentConfig.subagents.model (explicit per-agent subagent config) 2. agents.defaults.subagents.model (global subagent default) 3. agentConfig.model (agent own model, last-resort fallback) Apply the same fix to the cron isolated-agent model selection path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add regression tests for resolveSubagentSpawnModelSelection covering the no-subagents-config 3-tier precedence: 1. session-level modelOverride wins over everything 2. agents.list[].model wins over agents.defaults.model 3. agents.defaults.model is used when neither override is set These complement the resolveSubagentConfiguredModelSelection tests added in the prior fix commit by pinning the spawn-time resolution path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4645342 to
5f5e960
Compare
|
Codex review: found issues before merge. Reviewed June 7, 2026, 11:09 PM ET / 03:09 UTC. Summary PR surface: Source +7, Tests +251, Other +127. Total +385 across 7 files. Reproducibility: yes. Source inspection shows current main still has helper and cron/fallback paths where Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Land one canonical subagent-model fix that aligns the shared resolver, cron/fallback behavior, docs, regression tests, and upgrade note for the provider/auth precedence change. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main still has helper and cron/fallback paths where Is this the best way to solve the issue? Unclear as a merge path. The shared-helper reorder is a plausible narrow fix, but the best solution requires maintainer agreement on the compatibility contract and whether this PR or the broader runtime PR should be canonical. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 181238fb5304. Label changesLabel justifications:
Evidence reviewedPR surface: Source +7, Tests +251, Other +127. Total +385 across 7 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
…; resolve conflicts (transport-stream, runs.test, preaction.test)
…precedence-global-default
…ack tests PR openclaw#58823's subagent-precedence fallback tests (agent-scope + cron isolated-agent) asserted legacy 'openai-codex/gpt-5.x', but their configs use 'openai/gpt-5.x' and the resolver returns the configured fallbacks verbatim (no aliasing) — so the expected value cannot be openai-codex. Per AGENTS.md, openai-codex is folded into openai (legacy input only), so the canonical runtime value is openai/*. The flip behavior (global defaults.subagents.model fallbacks win over the agent's own model) is correctly implemented in agent-scope.ts; only the test expectations were wrong. Fixes the 2 failing CI shards (agentic-agents-core-runtime, core-runtime-cron-isolated-agent).
…ecedence-global-default
Summary
Fixes #58822.
resolveSubagentConfiguredModelSelection: globalagents.defaults.subagents.modelnow takes priority over the parent agent's ownmodel.primary, with the agent's own model only used as a last-resort fallbacksrc/cron/isolated-agent/model-selection.ts) and the sharedresolveSubagentModelConfigSelectionResulthelper insrc/agents/agent-scope.tsBackground
PR #58003 reordered
resolveSubagentConfiguredModelSelectionto preferagentConfig.modeloveragents.defaults.subagents.model. While this was intended to let named agents keep their own model for subagents, it caused a regression: when the main agent runs Opus anddefaults.subagents.modelis GPT-5.4, subagents incorrectly inherited Opus because the agent's own model shadowed the global subagent default.The correct precedence is:
agentConfig.subagents.model— explicit per-agent subagent config (highest)agents.defaults.subagents.model— global subagent defaultagentConfig.model— agent's own model (last-resort fallback)Test plan
pnpm test src/agents/model-selection.test.ts— 105 tests passpnpm test src/cron/isolated-agent.model-formatting.test.ts— 32 tests passpnpm test src/agents/openclaw-tools.subagents.sessions-spawn.model.test.ts— 11 tests passpnpm test src/agents/subagent-spawn.model-session.test.ts— 1 test passespnpm test src/gateway/session-utils.test.ts— 84 tests passpnpm test src/gateway/sessions-patch.test.ts— 34 tests passReal behavior proof
Behavior addressed: Subagent model resolution for a main agent whose own
modeldiffers fromagents.defaults.subagents.model. Before this PR, an Opus-running agent withdefaults.subagents.model = openai/gpt-5still produced Opus subagents because the agent's ownmodelshadowed the global subagent default inresolveSubagentConfiguredModelSelection, in the sharedresolveSubagentModelConfigSelectionResulthelper, and in the cron isolated-agent path. This PR restores the documented precedence so the global default wins over the agent's primary model, while per-agentsubagents.modelstill takes the very top slot.Real environment tested: Linux x86_64 (Node v24.15.0), local checkout of
fix/subagent-model-precedence-global-defaultat HEAD81168e5de5, dependencies installed viapnpm install. Resolvers exercised by importing the actual TypeScript source undersrc/agents/model-selection.tsandsrc/agents/agent-scope.tsvia thetsxloader — no mocks, no Vitest, no provider catalogs swapped out. The cron isolated-agent path uses the sameresolveSubagentModelConfigSelectionResulthelper, so the asserted source values cover that resolver too.Exact steps or command run after this patch:
The script (
scripts/proof/pr-58823-subagent-precedence.mjs, committed in this PR for reviewer reproducibility) constructs three realOpenClawConfigshapes, callsresolveSubagentModelConfigSelectionResult,resolveSubagentConfiguredModelSelection, andresolveSubagentSpawnModelSelectionon each, and asserts both the resolved model ref and the selectionsourcelabel (subagent/default-subagent/agent).Evidence after fix: Verbatim terminal stdout (runtime log) from the live
node --import tsxrun above against the patched sources:For completeness, the Vitest suites listed in Test plan also pass on this branch (
pnpm test src/agents/model-selection.test.ts→ 105 passed;pnpm test src/cron/isolated-agent.model-formatting.test.ts→ 32 passed; etc.), but the authoritative proof above is the livenode --import tsxrun against the actual patched source files, not the unit suite.Observed result after fix:
defaults.subagents.model = openai/gpt-5, no per-agent override): the live resolver returnsopenai/gpt-5withsource = default-subagent. Before this PR it returnedanthropic/claude-opuswithsource = agent— the exact bug from fix(agents): subagent model precedence — global default shadowed by parent agent's own model #58822.subagents.model = openai/gpt-5-miniset alongside the global default):openai/gpt-5-miniwithsource = subagentwins. Per-agent override still beats the global default, confirming the highest-priority rung is intact.subagents.modelnordefaults.subagents.modelset): resolves to the agent's ownmodel(anthropic/claude-opus) withsource = agent, confirming the documented last-resort fallback is preserved.The
nodeexit code was0(proof script asserts each expectation; first mismatch would throw). Theagent-scopesource labels are produced by the sharedresolveSubagentModelConfigSelectionResulthelper used by bothsrc/agents/model-selection.tsandsrc/cron/isolated-agent/model-selection.ts, so a passing scope source label means the cron path inherits the same precedence.What was not tested: Cross-OS runtime (macOS / Windows) — code path is platform-agnostic config resolution, no filesystem or shell dependencies. Live spawn of an actual subagent process against a remote model provider — the resolver returns the same model ref regardless of whether the downstream spawn succeeds, and the spawn path is exercised by
src/agents/openclaw-tools.subagents.sessions-spawn.model.test.ts(11 passing). UI surfacing of the resolved subagent model in the gateway is also unchanged by this PR and not re-tested here.🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com