diff --git a/desktop/src-tauri/src/managed_agents/restore.rs b/desktop/src-tauri/src/managed_agents/restore.rs index 25dadbeec6..27c3187fa1 100644 --- a/desktop/src-tauri/src/managed_agents/restore.rs +++ b/desktop/src-tauri/src/managed_agents/restore.rs @@ -332,10 +332,15 @@ pub async fn restore_managed_agents_on_launch( // mid-turn session is not resumed by an // eager child — and silently reintroduces // N idle brains on every launch. + // Connect via the configured relay + // (`relay_url`), not the normalized + // key — see spawn_agent_child: the + // loopback fold to 127.0.0.1 is + // identity-only. spawn_agent_child( app, record, - &key.relay_url, + &relay_url, true, owner_hex_ref, ) diff --git a/desktop/src-tauri/src/managed_agents/runtime.rs b/desktop/src-tauri/src/managed_agents/runtime.rs index 9fa9e0cce6..5956dadfda 100644 --- a/desktop/src-tauri/src/managed_agents/runtime.rs +++ b/desktop/src-tauri/src/managed_agents/runtime.rs @@ -535,9 +535,7 @@ pub fn spawn_agent_child( .map(|p| p.display().to_string()) .unwrap_or_else(|| effective_command.clone()); - // The caller supplies the explicit canonical pair relay. This is the only - // relay this child may connect to, regardless of the record/workspace default. - let effective_relay_url = runtime_key.relay_url.clone(); + let effective_relay_url = relay_url.to_string(); // CONFIGURED relay, not normalized key (multi-tenant by Host); see commit msg // Augment PATH for DMG launches so child processes can find: // - bundled CLI via ~/.local/bin symlink @@ -880,7 +878,7 @@ pub fn spawn_agent_child( super::spawn_snapshot::SpawnConfigInputs { record, descriptor: &descriptor, - relay_url: &effective_relay_url, + relay_url: &runtime_key.relay_url, // NORMALIZED: matches needs_restart recompute (see commit msg) team_instructions: team_instructions.as_deref(), system_prompt: effective_prompt.as_deref(), model: effective_model.as_deref(), @@ -992,7 +990,9 @@ pub fn start_managed_agent_process( // Scalar PIDs are migration-only and never establish pair liveness. record.runtime_pid = None; - let mut process = spawn_agent_child(app, record, &key.relay_url, false, owner_hex)?; + // Connect via the configured relay (`relay_url`), not the normalized key — + // see spawn_agent_child: the loopback fold to 127.0.0.1 is identity-only. + let mut process = spawn_agent_child(app, record, &relay_url, false, owner_hex)?; let now = now_iso(); let receipt = super::ManagedAgentRuntimeReceipt { key: key.clone(), diff --git a/desktop/src-tauri/src/managed_agents/runtime_commands.rs b/desktop/src-tauri/src/managed_agents/runtime_commands.rs index c0e55184b1..06bb209663 100644 --- a/desktop/src-tauri/src/managed_agents/runtime_commands.rs +++ b/desktop/src-tauri/src/managed_agents/runtime_commands.rs @@ -283,7 +283,9 @@ fn start_pair( .lock() .ok() .map(|keys| keys.public_key().to_hex()); - let mut process = spawn_agent_child(&app, record, &key.relay_url, lazy, owner.as_deref())?; + // Connect via the configured relay (`relay_url`), not the normalized key — + // see spawn_agent_child: the loopback fold to 127.0.0.1 is identity-only. + let mut process = spawn_agent_child(&app, record, &relay_url, lazy, owner.as_deref())?; let now = crate::util::now_iso(); let receipt = ManagedAgentRuntimeReceipt { key: key.clone(), @@ -504,7 +506,11 @@ pub async fn reconcile_managed_agent_runtimes( Ok((record, key, requested)) => { match start_pair( record.pubkey.clone(), - key.relay_url.clone(), + // Connect via the raw requested community URL, not the + // normalized pair key — see spawn_agent_child: the + // loopback fold to 127.0.0.1 is identity-only and would + // land the agent in a different, empty tenant. + requested.clone(), true, Some(&record.updated_at), app.clone(),