← Back to PRs

#21088: fix: sessions_sspawn model override ignored for sub-agents

by Slats24 open 2026-02-19 16:51 View on GitHub →
commands size: XS
Fix bug where sessions_spawn model parameter was ignored, causing sub-agents to always use the parent's default model. The allowAny flag from buildAllowedModelSet() was not being captured or used. 🤖 AI-assisted (Claude) - fully tested locally Fixes #17479, #6295, #10963 ## Summary Summary Problem: sessions_spawn model override was ignored - sub-agents always ran on parent's default model despite modelApplied: true being returned Why it matters: Users cannot run sub-agents on different models, breaking multi-model workflows What changed: Capture and use the allowAny flag from buildAllowedModelSet() instead of checking allowedModelKeys.size === 0 What did NOT change (scope boundary): No changes to model validation, auth, or catalog loading logic ## Change Type (select all) - [x] Bug fix - [ ] Feature - [ ] Refactor - [ ] Docs - [ ] Security hardening - [ ] Chore/infra ## Scope (select all touched areas) - [x] Gateway / orchestration - [ ] Skills / tool execution - [ ] Auth / tokens - [ ] Memory / storage - [ ] Integrations - [ ] API / contracts - [ ] UI / DX - [ ] CI/CD / infra ## Linked Issue/PR Closes #17479 Related #6295, #10963 ## User-visible / Behavior Changes - sessions_spawn with a model parameter now correctly applies the model override to the spawned sub-agent - Previously: sub-agent would use parent's default model regardless of model parameter - Now: sub-agent uses the specified model when it's properly configured/authenticated ## Security Impact (required) - New permissions/capabilities? (`No`) - Secrets/tokens handling changed? (`No`) - New/changed network calls? (`No`) - Command/tool execution surface changed? (`No`) - Data access scope changed? (`No`) ## Repro + Verification ### Environment - OS: macOS (Apple Silicon) - Runtime/container: Node.js via Homebrew - Model/provider: DeepSeek, Moonshot/Kimi, xAI/Grok - Integration/channel: Discord - Relevant config: Multi-provider setup with moonshot, deepseek, xai, claude configured ### Steps 1. Configure agent with default model deepseek/deepseek-chat 2. Use sessions_spawn tool with model: "moonshot/kimi-k2.5" 3. Check which model the sub-agent actually uses ### Expected - Sub-agent runs on moonshot/kimi-k2.5 ### Actual Actual before fix: - Sub-agent runs on deepseek/deepseek-chat despite modelApplied: true Actual after fix: - Sub-agent correctly runs on moonshot/kimi-k2.5 ## Evidence Attach at least one: - [ ] Failing test/log before + passing after - [ ] Trace/log snippets - [ ] Screenshot/recording - [ ] Perf numbers (if relevant) ## Human Verification (required) Human Verification (required) - Verified scenarios: Telling agent to spawn specific sub-agents with moonshot/kimi-k2.5, instead of deepseek/deepseek-chat (default). - Edge cases checked: Model not in catalog (correctly fails), default model (works), non-default model (now works) - What you did NOT verify: Other files with similar pattern (model-selection.ts, directive-handling.*.ts) ## Compatibility / Migration - Backward compatible? (`Yes`) - Config/env changes? (`No`) - Migration needed? (`No`) ## Failure Recovery (if this breaks) How to disable/revert this change quickly: Revert this commit Files/config to restore: src/commands/agent.ts Known bad symptoms: Sub-agents fail to spawn or use wrong model ## Risks and Mitigations List only real risks for this PR. Add/remove entries as needed. If none, write `None`. - Risk and Mitigations: - Risk: Similar bug pattern may exist in other files (model-selection.ts, directive-handling.*.ts) - Mitigation: This PR fixes the main sessions_spawn path; other files can be addressed in follow-up PRs if needed. <img width="544" height="242" alt="Screenshot 2026-02-19 at 16 49 27" src="https://github.com/user-attachments/assets/1e66ab7c-1c8a-4e7d-b122-e4f60064f08f" /> <!-- greptile_comment --> <h3>Greptile Summary</h3> Fixed bug where `sessions_spawn` model parameter was ignored, causing sub-agents to always use the parent's default model despite `modelApplied: true` being returned. **Root cause**: The `allowAny` flag returned by `buildAllowedModelSet()` was not being captured or used. The code was incorrectly checking `allowedModelKeys.size === 0` as a proxy for "allow any model", but this check is semantically wrong - an empty set means no models are allowed when there's an allowlist configured. **Key changes**: - Added `allowAnyModel` variable to capture the `allowAny` flag from `buildAllowedModelSet()` (line 402, 414) - Replaced `allowedModelKeys.size > 0` check with `!allowAnyModel` in validation logic (line 426) - Replaced `allowedModelKeys.size === 0` check with `allowAnyModel` when applying stored overrides (line 453) **How `allowAny` works**: According to `buildAllowedModelSet()` in `model-selection.ts:365`, `allowAny` is `true` when no model allowlist is configured (`rawAllowlist.length === 0`), meaning all models are permitted. The function can also return `allowAny: true` in fallback scenarios when the allowlist resolves to an empty set. **Impact**: Multi-model workflows now work correctly - users can spawn sub-agents on different models as intended. <h3>Confidence Score: 4/5</h3> - This PR is safe to merge with low risk - it's a targeted bug fix that correctly implements the intended model override behavior - The fix correctly addresses the root cause by capturing and using the `allowAny` flag instead of relying on the incorrect proxy check `allowedModelKeys.size === 0`. The logic is sound: when no allowlist is configured, `allowAny` is true and all models should be accepted. The changes are minimal, well-scoped, and align with the existing `buildAllowedModelSet()` API. However, there's a risk that similar patterns exist in other files (as noted in PR risks: `model-selection.ts`, `directive-handling.*.ts`), which could still have the same bug. Score is 4 instead of 5 due to: (1) lack of automated test coverage for this specific fix, and (2) similar bug patterns may exist elsewhere in the codebase. - Pay attention to the files mentioned in the PR risks: `src/auto-reply/reply/model-selection.ts`, `src/auto-reply/reply/directive-handling.model.ts`, and `src/auto-reply/reply/directive-handling.persist.ts` - these files use similar `allowedModelKeys.size` checks that may need the same fix in follow-up PRs <sub>Last reviewed commit: e313788</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs