diff --git a/desktop/src-tauri/src/commands/agents.rs b/desktop/src-tauri/src/commands/agents.rs index c666af6632..4d667e83e3 100644 --- a/desktop/src-tauri/src/commands/agents.rs +++ b/desktop/src-tauri/src/commands/agents.rs @@ -44,6 +44,17 @@ fn build_deploy_payload( crate::managed_agents::resolve_persona_env(app, record.persona_id.as_deref())?; let merged_env = crate::managed_agents::merged_user_env(&persona_env, &record.env_vars); + // Resolve system prompt and model via the persona (same as local spawn). + // Re-reads the persona store so edits take effect without recreating the agent. + let personas = load_personas(app).unwrap_or_default(); + let (effective_prompt, effective_model) = + crate::managed_agents::resolve_effective_prompt_and_model( + record.persona_id.as_deref(), + &personas, + record.system_prompt.as_deref(), + record.model.as_deref(), + ); + Ok(serde_json::json!({ "name": &record.name, "relay_url": &record.relay_url, @@ -51,8 +62,8 @@ fn build_deploy_payload( "auth_tag": &record.auth_tag, "agent_command": &record.agent_command, "agent_args": &record.agent_args, - "system_prompt": &record.system_prompt, - "model": &record.model, + "system_prompt": &effective_prompt, + "model": &effective_model, "turn_timeout_seconds": record.turn_timeout_seconds, "idle_timeout_seconds": record.idle_timeout_seconds, "max_turn_duration_seconds": record.max_turn_duration_seconds, diff --git a/desktop/src-tauri/src/managed_agents/runtime/tests.rs b/desktop/src-tauri/src/managed_agents/runtime/tests.rs index 446a6ba28d..d018380490 100644 --- a/desktop/src-tauri/src/managed_agents/runtime/tests.rs +++ b/desktop/src-tauri/src/managed_agents/runtime/tests.rs @@ -216,8 +216,18 @@ fn resolve_prompt_falls_back_when_no_persona_id() { assert_eq!(model.as_deref(), Some("record-model")); } +/// Tests prompt/model resolution **in isolation** when the persona is missing. +/// +/// In a real spawn, `resolve_persona_env()` (called later in `spawn_agent_child`) +/// would **fail closed** if the persona cannot be found — because persona env_vars +/// may contain required API credentials. This test only validates the +/// `resolve_effective_prompt_and_model` helper's fallback behavior, NOT that a +/// full agent spawn would succeed with a missing persona. #[test] fn resolve_prompt_falls_back_when_persona_not_found() { + // NOTE: This tests the prompt/model resolution layer only. A full spawn + // with a missing persona_id would fail at resolve_persona_env() before + // the process is ever created. let personas = vec![persona_fixture("custom:other", "Other prompt", None)]; let (prompt, model) = resolve_effective_prompt_and_model(