#20968: fix(ui): enable save button when editing default agent models
app: web-ui
size: S
Cluster:
Model Management Enhancements
## Summary
- Problem: When an agent is not explicitly listed in agents.list (relying on agents.defaults), the UI handlers for model and fallback changes returned early, failing to mark the configuration as "dirty."
- Why it matters: Users with minimal or single-agent configurations were forced to use the "Config" tab to persist model changes, as the Agents overview UI was effectively read-only for the default agent.
- What changed: Updated onModelChange and onModelFallbacksChange in app-render.ts to correctly target agents.defaults.model when the default agent is edited. The fix also ensures that updates to defaults are always wrapped in a { primary: ... } object to comply with the stricter Zod schema for AgentDefaults.
- What did NOT change (scope boundary): Handlers for Tools and Skills were not changed because agents.defaults does not support these field overrides; they still require an explicit entry in agents.list.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [ ] Integrations
- [ ] API / contracts
- [x] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #20924
## User-visible / Behavior Changes
Users can now edit the Primary model and Fallbacks for the default agent in the /agents sidebar and successfully save those changes to their configuration.
## 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: Linux (WSL2) / Windows
- Runtime/container: Native Node.js
- Model/provider: Any
- Integration/channel (if any): N/A
- Relevant config: agents.defaults populated, agents.list empty.
### Steps
1. Navigate to /agents in the Control UI.
2. Select the default/main agent from the sidebar.
3. In the Overview panel, change the value of "Primary model (default)" or edit "Fallbacks".
4. Observe the "Save" button.
### Expected
- The "Save" button should become enabled immediately.
- Clicking "Save" should persist the change to agents.defaults.model in the configuration file.
### Actual
- Before this fix, the "Save" button remained disabled and changes were lost on page refresh.
## Evidence
Verified via code audit that the update correctly targets agents.defaults.model as an object { primary: modelId } to satisfy AgentDefaultsSchema (found in src/config/zod-schema.agent-defaults.ts).
## Human Verification (required)
- Verified scenarios: Editing both Primary Model and Fallbacks individually and together for the default agent.
- Edge cases checked: Verified that if the agent is in agents.list, the handler still correctly targets the specific list entry index instead of defaults.
- What you did not verify: I did not verify automatic persistence on mobile/TUI environments, as this is a dashboard-specific fix.
## 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 the changes to ui/src/ui/app-render.ts
- Files/config to restore: None.
- Known bad symptoms reviewers should watch for: If the object wrapping logic were missing, the backend would reject the save with a Zod validation error.
## Risks and Mitigations
- Risk: Potential invalid configuration if the target path for agents.defaults didn't exist in the form state.
- Mitigation: The code includes checks for configValue and agentsList.defaultId existence before attempting the update.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixed Save button in `/agents` UI for default agent model changes. Previously, editing the primary model or fallbacks for the default agent (when not explicitly listed in `agents.list`) would return early without marking the configuration as dirty, leaving the Save button disabled. The handlers now check if the agent matches `state.agentsList?.defaultId` and correctly target `agents.defaults.model` with proper object wrapping (`{ primary: modelId }`) to comply with the AgentDefaults Zod schema.
- Both `onModelChange` and `onModelFallbacksChange` handlers now support default agent editing
- Wraps model values in `{ primary, fallbacks? }` object when updating defaults
- Preserves existing behavior for agents explicitly listed in `agents.list`
<h3>Confidence Score: 4/5</h3>
- Safe to merge with minor consideration for edge case verification
- The fix correctly addresses the described problem by adding fallback logic to target `agents.defaults.model` when the agent isn't in the list. The object wrapping logic properly aligns with the strict Zod schema requirements. However, there's a minor edge case: the code assumes `state.agentsList?.defaultId` exists when falling through to the default path - if `defaultId` is undefined, the code would still return early, which is correct. The fix is well-structured and maintains backward compatibility.
- No files require special attention
<sub>Last reviewed commit: 1488ddf</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#20712: fix(subagents): prioritize agent runtime default model over global ...
by sourcesavant · 2026-02-19
80.1%
#11806: fix(ui): agent model dropdown not reflecting actual primary model
by arturhoo · 2026-02-08
79.5%
#23286: fix: use configured model in llm-slug-generator instead of hardcoded …
by wsman · 2026-02-22
79.0%
#11562: Fix #10883: Enforce subagent model configuration
by divol89 · 2026-02-08
78.7%
#21088: fix: sessions_sspawn model override ignored for sub-agents
by Slats24 · 2026-02-19
78.5%
#20275: fix(cli): include primary model in allowlist when adding fallbacks
by MFS-code · 2026-02-18
78.3%
#23816: fix(agents): model fallback skipped during session overrides and pr...
by ramezgaberiel · 2026-02-22
78.2%
#13376: fix: pass model directly to agent for sub-agent runs
by jrbobbyhansen-pixel · 2026-02-10
77.9%
#17021: fix(agents): read models from gateway config first
by Limitless2023 · 2026-02-15
77.6%
#21791: feat(TUI): show main agent model in status footer
by chansuke · 2026-02-20
77.5%