fix(cron): preserve model fallbacks when agent overrides primary#18210
Merged
steipete merged 1 commit intoopenclaw:mainfrom Feb 16, 2026
Merged
Conversation
When an agent config specifies `model: { primary: "..." }` without
an explicit `fallbacks` array, the existing code replaced the entire
model object from `agents.defaults`—discarding the default fallbacks.
This caused cron jobs (and agent sessions) to have only one model
candidate (the pinned model) plus the global primary as a final
fallback, skipping all intermediate fallback models.
The fix merges the agent model override into the existing defaults
model object using spread, so that keys like `fallbacks` survive
when the agent only overrides `primary`. Agents can still explicitly
override or clear fallbacks by providing their own `fallbacks` array.
Reproduction scenario:
- `agents.defaults.model = { primary: "codex", fallbacks: ["opus", "flash", "deepseek"] }`
- Agent config: `model: { primary: "codex" }`
- Cron job pins: `model: "flash"`
- Before fix: fallback candidates = [flash, codex] (3 models lost)
- After fix: fallback candidates = [flash, opus, deepseek, ..., codex]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When an agent config specifies
model: { primary: "..." }without an explicitfallbacksarray, the cron isolated-agent runner replaces the entire model object fromagents.defaults—discarding the default fallbacks chain.This causes cron jobs (and agent sessions) to have only two model candidates:
gemini-3-flash-preview)gpt-5.3-codex)All intermediate fallback models (Opus, DeepSeek, Qwen, Kimi, etc.) are silently lost.
Reproduction
Before fix: fallback candidates =
[flash, codex]— 3 models skippedAfter fix: fallback candidates =
[flash, opus, deepseek, kimi, codex]Impact
Any user with:
model.primarymodelpinsagents.defaults.model.fallbacks...will have their fallback chain silently broken. When the pinned model hits a rate limit (429), the system skips directly to the global primary instead of trying intermediate fallbacks.
Fix
3-line change in
src/cron/isolated-agent/run.ts: spread the existingagentCfg.modelbefore applying the override, sofallbacks(and any other model config keys) survive when the agent only overridesprimary.Agents can still explicitly override or clear fallbacks by providing their own
fallbacksarray (includingfallbacks: []to disable).Tests
Added
run.model-fallback-preservation.test.tswith 6 test cases covering:All existing tests pass.
Greptile Summary
Targeted bug fix that changes the model override logic in the cron isolated-agent runner from a full replace to a shallow merge. Previously, when an agent config specified
model: { primary: "..." }withoutfallbacks, the entire model object fromagents.defaultswas replaced — silently discarding the default fallback chain. The fix spreadsexistingModelbefore applying the override, sofallbackssurvive when onlyprimaryis overridden.src/cron/isolated-agent/run.ts: 4-line change (including comment) that spreads the existing model config before applying the agent's override, correctly preservingfallbacksand any other model keys from defaults.run.model-fallback-preservation.test.ts: 6 well-structured test cases covering string override, object override, explicit fallback override, empty fallback clearing, undefined override, and missing defaults. Tests re-implement the merge logic locally rather than testing the actual exported function, which is a reasonable approach given the function's complex dependencies.Confidence Score: 5/5
Object.assignmerge and the downstreamresolveFallbackCandidatesfunction that readscfg.agents.defaults.model.fallbacks. Six test cases cover the key scenarios. No regressions or side effects identified.Last reviewed commit: 7af50ca
(4/5) You can add custom instructions or style guidelines for the agent here!