Skip to content

ManagedAgentRecord: add disable_local_spawn flag to prevent Desktop from reactively spawning an agent whose runtime is externally managed #6468

Description

@ScottyOfAus

Problem

When an agent identity is served by an externally-provisioned runtime (e.g. a VPS running buzz-acp as a systemd unit), Buzz Desktop still spawns a local process for that agent on every reactive trigger, channel open, member-sidebar load, @mention click. The local spawn competes with the remote instance: both connect to the relay under the same identity key, both receive channel events, and both may respond.

start_on_app_launch: false does not help. It only gates reconcile_managed_agent_runtimes at startup. The reactive path...
start_managed_agent_runtime_pair_lazy → start_pair in runtime_commands.rs, checks only backend == BackendKind::Local and fires regardless.

Repro

  1. Configure an agent in Buzz Desktop (Local backend, start_on_app_launch: false).
  2. Run the same identity on an external host (e.g. VPS via systemd, same nsec).
  3. Mention the agent in any channel the Desktop user has open.
  4. Desktop spawns a local buzz-acp process alongside the external one. Both connect. Both may reply.

Expected behaviour

Desktop should provide a way to say: "this identity is owned by a remote runtime, do not spawn locally." The persona must stay in managed-agents.json (on Windows the nsec lives in Credential Manager, keyed by pubkey; deleting the persona loses the key). Only the local process spawn is suppressed, and it is trivially reversible.

Relevant design context

VISION_REMOTE_AGENTS.md (PR #3924) describes exactly this use case as the intended long-term feature. The planned mechanism (Provider backend + deploy handshake) would address it eventually, but:

Provider mode is not usable for self-hosted/VPS deployments yet (it requires a buzz-backend-* binary on PATH)
Switching to Provider backend today triggers deploy_to_provider on channel mention clicks, breaking mentions with "provider not found on PATH"
The vision doc targets a Kubernetes-based managed deploy; self-provisioned VPS is out of scope for that path
A minimal flag is the correct stepping stone.

Proposed fix

Add disable_local_spawn: bool (default false, serde default) to ManagedAgentRecord in types.rs. Add one guard in start_pair() before the spawn:

if record.disable_local_spawn {
    return Err("local spawn disabled, runtime is externally managed".into());
}

Expose as a toggle in Settings → Agents alongside start_on_app_launch. This is intentionally narrower than the Provider-deploy path, it is a flag for operators who are already running agents on external infrastructure and simply need Desktop to step aside.

Notes

The fix must be in start_pair(), not only in reconcile_managed_agent_runtimes. Two paths reach start_pair: the boot reconciliation (gated today by start_on_app_launch) and the lazy reactive spawn (start_managed_agent_runtime_pair_lazy), which is the unfixed one.
The flag should default false so existing behaviour is unchanged for everyone not explicitly opting in.
Toggling back to false restores normal local-spawn behaviour immediately, no persona or key changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions