-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Model/provider not updated when switching agents #2846
Description
Bug
When switching agents via /forge, /muse, /sage, /agent, or /agent-{id}, the model and provider are not updated to reflect the new agent's configured model/provider. This affects analytics tracking and user feedback, even though the prompt display and actual LLM calls work correctly.
Root Cause
on_agent_change() at crates/forge_main/src/ui.rs:186-209 only calls set_active_agent() (which stores the agent ID). It does not:
- Resolve the new agent's model via
get_agent_model() - Call
update_model()to update the analytics tracker - Display the model/provider change to the user
Current code
async fn on_agent_change(&mut self, agent_id: AgentId) -> Result<()> {
let agent = self.api.get_agents().await?
.iter().find(|agent| agent.id == agent_id)
.cloned()
.ok_or(anyhow::anyhow!("Undefined agent: {agent_id}"))?;
// Only sets the active agent ID — does NOT update model/provider
self.api.set_active_agent(agent.id.clone()).await?;
let name = agent.id.as_str().to_case(Case::UpperSnake).bold();
let title = format!("∙ {}", agent.title.as_deref().unwrap_or(MISSING_AGENT_TITLE)).dimmed();
self.writeln_title(TitleFormat::action(format!("{name} {title}")))?;
Ok(())
}Comparison: How model IS updated elsewhere
When the user runs /model (crates/forge_main/src/ui.rs:2749-2753):
self.api.set_default_model(model.clone()).await?;
self.update_model(Some(model.clone()));
self.writeln_title(TitleFormat::action(format!("Switched to model: {model}")))?;When init_state() runs (crates/forge_main/src/ui.rs:2957-3008):
let mut operating_model = self.get_agent_model(active_agent.clone()).await;
self.update_model(operating_model);Proposed Solution
Update on_agent_change() to resolve and propagate the agent's model after switching:
async fn on_agent_change(&mut self, agent_id: AgentId) -> Result<()> {
let agent = self
.api
.get_agents()
.await?
.iter()
.find(|agent| agent.id == agent_id)
.cloned()
.ok_or(anyhow::anyhow!("Undefined agent: {agent_id}"))?;
self.api.set_active_agent(agent.id.clone()).await?;
// Update model tracking to reflect the new agent's model
let model = self.get_agent_model(Some(agent.id.clone())).await;
self.update_model(model.clone());
let name = agent.id.as_str().to_case(Case::UpperSnake).bold();
let title = format!(
"∙ {}",
agent.title.as_deref().unwrap_or(MISSING_AGENT_TITLE)
)
.dimmed();
// Show model info if agent uses a specific model
let model_info = model
.map(|m| format!(" ∙ model: {m}").dimmed().to_string())
.unwrap_or_default();
self.writeln_title(TitleFormat::action(format!("{name} {title}{model_info}")))?;
Ok(())
}Affected Call Sites
All callers of on_agent_change() are affected:
| Command | File | Line |
|---|---|---|
/forge |
crates/forge_main/src/ui.rs |
1874 |
/muse |
crates/forge_main/src/ui.rs |
1877 |
/sage |
crates/forge_main/src/ui.rs |
1880 |
/agent (interactive selection) |
crates/forge_main/src/ui.rs |
1994 |
/agent-{id} (direct switch) |
crates/forge_main/src/ui.rs |
2017 |
Impact
- Analytics/tracking: The model sent to the tracker is stale after agent switch
- User feedback: No model/provider info shown when switching to an agent with a different model
- Chat flow: NOT affected —
ForgeApp::chat()independently resolves the agent's model/provider viaAgentProviderResolver, so LLM calls use the correct model
Why This Was Missed
The built-in agents (forge, muse, sage) don't specify their own model or provider — they inherit session defaults. The bug only manifests with custom agents (in ~/.forge/agents/*.md or .forge/agents/*.md) that define their own model/provider. The AgentDefinition schema supports optional model and provider fields (crates/forge_repo/src/agent_definition.rs:34-38), but no built-in agents use them.
Additional Notes
- The prompt display is correct — it independently resolves the model per-agent on every call via
get_agent_model(). This makes the bug harder to notice visually. - Consider also checking if
/configreflects the agent's model correctly —on_show_config()atcrates/forge_main/src/ui.rs:1317-1384usesget_agent_model(None)which returns the default model, not the agent-specific one.