Skip to content

[Bug] Remote managed agents are hidden and unmentionable on secondary devices #2349

Open

Description

@geff08565-sketch

Summary

A cloud-connected managed agent that runs on Mac A is not visible or mentionable from Buzz Desktop on Mac B, even when both desktops use the same community/account and the agent is already a member of the channel.

The agent is visible and mentionable on Mac A. On Mac B, direct messages to the agent work, but the agent is absent from the channel member/mention UI.

This appears to couple two separate concepts:

  1. discovering/mentioning a remote cloud agent; and
  2. owning and launching that agent's local runtime.

Environment

  • Buzz Desktop 0.4.21
  • macOS on both machines
  • Same hosted Buzz community and same human identity/account
  • Agent runtime (buzz-acp with an OpenClaw ACP adapter) runs only on Mac A
  • Agent is connected to the hosted relay, online, and subscribed to the channel

Steps to reproduce

  1. On Mac A, create/configure a managed ACP agent and connect it to a hosted Buzz community.
  2. Add the agent to a channel as a bot member.
  3. Confirm on Mac A that the agent appears in the channel and responds to @mentions.
  4. On Mac B, sign in to the same hosted community with the same human identity/account.
  5. Open the same channel and type @.

Actual behavior

  • Mac B does not show the remote agent in the mention/member UI.
  • Other agents present in Mac B's local managed-agents.json are shown (including agents marked "not in channel").
  • The missing remote agent is nevertheless reachable by direct message from Mac B.
  • Relay/channel membership is correct, and the remote runtime on Mac A is online.
  • Restarting Buzz Desktop on Mac B does not fix the problem.

As a diagnostic experiment, adding a keyless/inactive record for the remote agent's public key to Mac B's local managed-agents.json makes the agent appear in @ autocomplete. However, mentioning it then makes Buzz attempt to start the agent locally on Mac B and produces a warning that the OS keyring may be unreachable. Mac B does not possess the agent's private key by design.

This diagnostic record was not intended as a supported workaround; it demonstrates that mention visibility is gated by local managed-agent ownership and that mention dispatch then invokes the local lifecycle path.

Expected behavior

  • Any agent that is a member of the current hosted channel should be visible and mentionable from every signed-in client authorized to view that channel.
  • Only the machine that owns the agent's private key/runtime configuration should be able to start, stop, or reconfigure the runtime.
  • Mentioning an online remote agent should send the mention to its existing remote runtime; it should not require a local managed-agents.json record or local keyring entry.

In short: remote visibility/invocation should be separate from local runtime ownership.

Impact

This breaks the primary multi-device workflow: a user cannot reliably communicate with agents running on an always-on Mac mini from another Mac, despite using the same hosted community and despite the agents being online and channel members.

It also creates a dangerous UX ambiguity: attempting to restore visibility with a local definition causes the second client to try to launch a duplicate runtime and ask for keyring access.

Suggested direction

  • Build mention candidates from hosted channel membership/profile data, not only local managed-agent definitions.
  • Represent remote agents as non-owned/non-launchable entities on secondary clients.
  • Route mentions to the hosted agent identity without calling the local managed-agent start path.
  • Keep lifecycle controls gated on possession of the local private key/runtime definition.

Related issues

Activity

  1. ScaleLeanChris commented on Jul 22, 2026

    @ScaleLeanChris

    I reproduced the same lifecycle/discovery coupling with an external Hermes gateway on Buzz Desktop 0.4.22.

    The identity is an owner-attested Buzz agent key, but Hermes owns the runtime and connects directly to the relay. I initially used a Claude Code managed-agent record only to provision the identity. While that local record existed, mentioning the identity could launch Buzz's local ACP harness and race the external Hermes gateway, producing a duplicate reply. Removing the local managed-agent record fixed the duplicate: the external gateway now authenticates with NIP-42 + NIP-OA over WebSocket, receives the mention, and posts exactly one threaded reply.

    Two UI artifacts remain after the local record is removed:

    • The Agents page still shows the built-in Hermes / Start Hermes persona card. That button starts a local Buzz ACP persona; it does not report or control the external Hermes runtime.
    • The external Hermes profile remains discoverable from relay identity/profile data, but its historical ACP observer activity can look like current managed-runtime state.

    This supports the issue's proposed separation: relay identity and mentionability should come from hosted membership/profile state, while Start/Stop controls should appear only when the client owns that runtime. An explicit external or remote-managed runtime type would also give gateways a truthful status surface without registering a local harness.

    Related Hermes integration issue: NousResearch/hermes-agent#68871

  2. hbendev commented on Jul 22, 2026

    @hbendev

    #2314 fixes this (and #2149 introduced it)

    I support this, I think it makes sense to allow mentioning a bot when the member access is configured to Anyone or Allowlist. Would open up using Buzz from environments without an ACP running (web, mobile). Use case: sharing the relay with non-technical people, and you, as a relay owner, want to pay for the LLM usage (but really, anybody, in the end, it was you who reconfigured the respond-to field and opened up your own agent).

  3. hbendev commented on Jul 22, 2026

    @hbendev

    In fact, this creates a clear Desktop/Mobile inconsistency.

    Desktop identifies shared agents through relayAgentIsSharedWithUser: allowlisted users qualify, whereas agents configured to respond to anyone require a shared channel. However, addCandidate rejects non-locally-managed agents before applying those sharing rules.

    Mobile has no equivalent restriction. It applies the sharing rules and includes eligible non-member agents. Its comment stating that this mirrors Desktop’s useMentions is therefore no longer accurate.

    Is this inconsistency intentional? If not, #2314 appears to restore the shared-agent behavior.

    Oh, and also. You can just DM these agents from the remote client just fine, and they'll respond.

  4. tonic20 commented on Jul 23, 2026

    @tonic20

    Still live at main HEAD (acfbb1b, v0.4.23) — confirming with a real external-Hermes repro.

    Setup: an external Hermes-bridge agent (owner-attested Buzz key) published a valid kind:10100 profile (respond_to: anyone, scoped to a shared channel) and joined that channel as a bot member. It's reachable by DM and by p-tagged mentions, but never appears in Desktop @ autocomplete — exactly as described here.

    Root cause (matches @hbendev's read): in desktop/src/features/messages/lib/useMentions.ts, addCandidate runs isAgentIdentityInManagedList(candidate, managedAgentPubkeys) and drops every non-locally-managed agent before shouldHideAgentFromMentions can apply the relay/invocability rules. So the member-eligibility branch of shouldHideAgentFromMentions (and its shows member agents with unknown invocability unit test) is unreachable for any agent you don't personally manage.

    On the two open PRs — #2314 vs #2333. I traced both through the actual eligibility functions at HEAD. Both surface the in-channel member bot correctly, but they differ on an existing tested behavior:

    QUINN  (relay-only, allowlist incl. viewer, NON-member) — e2e test expects HIDDEN
      current (pre-filter) : HIDDEN
      #2314   (no pre-filter): SHOWN   <-- regresses "relay-only agents stay hidden ... even when allowlisted"
      #2333   (mentionable)  : HIDDEN
    OMAR   (member bot, respond_to anyone, shared channel) — want SHOWN
      current : HIDDEN  (the bug)
      #2314   : SHOWN
      #2333   : SHOWN
    

    Why #2314 regresses: deleting the pre-filter outright lets an allowlisted non-member relay agent through, because relayAgentIsSharedWithUser treats an allowlist match as "shared" regardless of channel → it lands in mentionableAgentPubkeys → shown. #2314's pnpm test (3268 pass) is unit-only and doesn't exercise the relay-only agents stay hidden from channel mentions even when allowlisted Playwright spec, so it passed locally.

    #2333 avoids this with a narrower gate — isAgentIdentityMentionable = managed || (isMember && role === "bot") — which keeps the allowlisted-non-member agent hidden while admitting in-channel bots, and it ships both a unit test and an e2e test for the shared-in-channel-bot case.

    Recommendation: land #2333 (complete fix + regression coverage; currently draft). #2314 would need to adopt the narrower gate before it's safe to merge.

  5. jb-one-1001 commented on Jul 25, 2026

    @jb-one-1001

    Reproduced on Desktop v0.4.23 with a genuinely separate human member, not only a secondary device using the same identity.

    • Owner creates and deploys a native provider-backed managed agent.
    • Agent is a bot member of a private shared channel.
    • The second human is a channel member and is explicitly present in the agent runtime's respond_to: allowlist.
    • The agent is online and responds when a correct p tag reaches it.
    • Owner sees the agent in @ autocomplete; the second human does not.
    • The second human can see/tag an old service identity only when it is represented as an ordinary channel member rather than an agent.

    The v0.4.23 source confirms the same ordering problem already described here: useMentions.ts rejects non-locally-managed agent identities via isAgentIdentityInManagedList(...) before shouldHideAgentFromMentions(...) can honor relay-directory/channel/allowlist eligibility.

    This blocks the core shared-compute workflow: one owner funds and hosts an always-on agent while other allowlisted team members invoke it. We are temporarily using a clearly disclosed service identity and will move back to native shared agents once the Desktop fix ships.

    The narrower channel-member-agent approach in #2693/#2333 matches this production reproduction and avoids exposing unrelated non-member relay agents.

  6. ke6yjc commented on Aug 13, 2026

    @ke6yjc

    I reproduced this with the same owner identity signed into two Macs:

    • Mac mini hosts and runs the managed agent.
    • MacBook is the daily client.
    • Both the owner and agent are confirmed members of the same channel on the relay.
    • The agent is visible in the MacBook channel member panel but absent from @ autocomplete.
    • Fully restarting Desktop does not restore autocomplete.
    • Manually sending @Agent ping posts visible text, but the agent does not wake.

    I compared the signed relay events:

    • Failed MacBook event 7336da29…2ca0c3 contains the channel h tag only; it has no agent p tag.
    • An earlier working event 3a898c42…d95084 contains the same channel h tag plus the agent’s p tag.

    We also removed a duplicate same-named agent identity from the MacBook by renaming it. The owner-level name ambiguity disappeared, but the remote agent still did not appear in autocomplete. Relay membership and profile lookup remained correct throughout.

    The current Desktop source suggests a narrower owner-only cross-device cause in desktop/src/features/agents/lib/agentAutocompleteEligibility.ts:

    • getMentionableAgentPubkeys() always admits locally managed agents.
    • A relay-only agent is admitted by relayAgentIsSharedWithUser() only when respondTo === "anyone", or when respondTo === "allowlist" and the current pubkey is listed.
    • There is no branch that recognizes the current human as the owner of a remote owner-only agent.
    • RelayAgent in desktop/src/shared/api/types.ts does not expose an owner pubkey that this eligibility check could use.
    • The existing unit test explicitly expects an owner-only relay agent in a shared channel to be rejected.

    That explains the device asymmetry:

    • Host Mac: agent is locally managed, so it is admitted to autocomplete.
    • Second Mac: the same agent is relay-only and owner-only, so it is filtered out despite the same owner and valid channel membership.

    Suggested regression test / acceptance case:

    1. One owner signs into devices A and B.
    2. An owner-only agent is managed and running only on device A.
    3. The owner and agent share a channel.
    4. On device B, the agent appears in autocomplete as a remote/non-launchable identity.
    5. Selecting it sends the existing agent pubkey as a p tag.
    6. Device B does not mint, configure, or start a duplicate local agent.

    This also appears related to #3739 and #5319, but #2349 remains the closest match for the observed same-owner, two-device failure.

  7. hondoaus commented on Aug 15, 2026

    @hondoaus

    Confirming the architectural point here from another implementation: an existing Hermes Agent runs continuously on a VPS while Buzz Desktop is only a client.

    We intentionally kept the remote identity out of the local managed-agent store. Instead, the Hermes agent publishes/maintains its relay identity and a complete kind:10100 directory record.

    With current 0.5.x Desktop we were able to get the remote agent recognized in channel members and into @ autocomplete using respond_to=allowlist + the viewer pubkey, without giving Desktop the agent private key or local spawn configuration.

    That validates the separation proposed in this issue: remote visibility/invocation does not need local runtime ownership.

    The remaining product gap is the management surface: the remote Hermes agent still does not appear in the main Agents tab (#3054/#4834). Adding a fake local record would violate the security model and risks a duplicate/local launch attempt, exactly as described here.

    For our use case, the ideal state is one stable remote identity that every authorized client can discover/mention, while lifecycle controls are only shown on the host/control-plane that actually owns the runtime.

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

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