Skip to content

fix(desktop): connect managed agents to the configured relay, not the normalized loopback identity - #4664

Open
spkaplan wants to merge 1 commit into
block:mainfrom
spkaplan:pr-loopback-fix
Open

fix(desktop): connect managed agents to the configured relay, not the normalized loopback identity#4664
spkaplan wants to merge 1 commit into
block:mainfrom
spkaplan:pr-loopback-fix

Conversation

@spkaplan

@spkaplan spkaplan commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Desktop-managed agents came up online but discovered 0 channels and sat idle whenever the workspace relay was addressed as localhost (the desktop default and the seeded local-dev community). They only worked when the community was addressed as 127.0.0.1.

Root cause. The relay is multi-tenant, keyed by the literal request Host, so localhost:3000 and 127.0.0.1:3000 are distinct communities with isolated channels/members. buzz_core::relay::normalize_relay_url intentionally folds all loopback spellings to 127.0.0.1 for the runtime identity key — its own doc says:

Connection code may retain the configured URL; this canonical form is for identity, receipts, status and deduplication.

But the spawn path reused that normalized ManagedAgentRuntimeKey::relay_url as the child's actual BUZZ_RELAY_URL. So an agent for a community joined on localhost:3000 connected to the empty 127.0.0.1:3000 tenant: subscribe resolved 0 channels and the agent never woke.

Fix

Connect via the configured relay URL at every spawn site, keeping the normalized ManagedAgentRuntimeKey solely as the dedup identity (receipts, pid files, logs). Four sites in desktop/src-tauri/src/managed_agents/:

  • runtime.rs spawn_agent_child: use the raw relay_url param for BUZZ_RELAY_URL (not runtime_key.relay_url).
  • runtime.rs start_managed_agent_process: pass the configured relay_url, not key.relay_url.
  • runtime_commands.rs start_pair: same.
  • runtime_commands.rs reconcile start loop: pass the raw requested community URL, not key.relay_url.

This honors normalize_relay_url's documented contract and restores channel discovery for loopback-addressed local communities. No change to identity/dedup/receipts, which still use the normalized form.

Validation

Reproduced and verified end-to-end on a local self-hosted stack (relay on localhost:3000):

  • Before: agent log relay=ws://127.0.0.1:3000 -> "discovered 0 channel(s)" -> "no channel subscriptions resolved -- agent will sit idle".
  • After: same agent relay=ws://localhost:3000 -> "discovered 1 channel(s)" -> "subscribed to channel <spike>", and two managed agents (a Codex harness and a cursor-agent harness) each replied to an owner @mention in-channel.
  • branch-skew and desktop-tauri-checks (clippy + Tauri crate tests) pass locally against current main.

Test plan

  • Create a Desktop-managed agent in a community addressed as localhost:<port>, attach it to a channel, @mention it as owner — it should discover the channel and reply.
  • Confirm receipts / pid files / logs still key on the normalized (127.0.0.1) identity (no dedup regression across loopback spellings).

… normalized loopback identity

Managed agents came up "online" but discovered 0 channels and sat idle
whenever the workspace relay was addressed as `localhost` (the desktop
default and the seeded dev community).

Root cause: the relay is multi-tenant, keyed by the literal request Host,
so `localhost:3000` and `127.0.0.1:3000` are distinct communities.
`buzz_core::relay::normalize_relay_url` intentionally folds all loopback
spellings to `127.0.0.1` for the runtime *identity* key -- its own doc
says "connection code may retain the configured URL; this canonical form
is for identity, receipts, status and deduplication." But the spawn path
reused that normalized URL as the child's actual BUZZ_RELAY_URL, so agents
connected to the empty `127.0.0.1:3000` tenant while the human and their
channels lived on `localhost:3000`; subscribe resolved 0 channels and the
agent never woke.

Fix: connect via the configured relay URL at every spawn site, keeping the
normalized ManagedAgentRuntimeKey solely as the dedup identity (receipts,
pid files, logs):
  - spawn_agent_child: use the raw `relay_url` param for BUZZ_RELAY_URL
  - start_managed_agent_process / start_pair: pass the configured
    `relay_url`, not `key.relay_url`
  - reconcile start loop: pass the raw requested community URL

Honors normalize_relay_url's documented contract and restores channel
discovery for loopback-addressed local communities.

Signed-off-by: Sam Kaplan <samuel.kaplan@salesforce.com>
@spkaplan
spkaplan requested a review from a team as a code owner August 4, 2026 04:16

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c071752d1c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// joined on `localhost`, leaving it "online" but discovering 0 channels.
// `normalize_relay_url`'s own contract says connection code must retain the
// configured URL; this honors that.
let effective_relay_url = relay_url.to_string();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep restart hashes on a consistent relay URL

For relay URLs whose configured form differs from the normalized runtime key (the fixed localhost case, [::1], default ports, etc.), this raw assignment also changes the value stamped into process.spawn_config_hash; later build_managed_agent_summary recomputes the hash with key.relay_url (the normalized value), so a freshly started agent is reported as needs_restart immediately even though no config changed. Split the connection URL from the hash input, or make the summary recompute with the same configured URL.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant