Skip to content

Managed agents are only mentionable from the machine that runs them #3277

Description

@4dlt

Describe the bug

A managed agent can only be @mentioned from the machine that runs it. From any
other client on the same relay, the agent produces no autocomplete entry, so the
sent message carries no p tag and the agent's harness never dispatches. The
message lands in the channel as plain text and nothing happens.

There is no error and no UI signal that this is unsupported — the agent shows in
the member list, its kind:0 profile resolves, and it replies normally when
mentioned from its host machine. The failure is indistinguishable from a
misconfiguration, which makes it expensive to diagnose.

This blocks the "one shared agent on an always-on host" setup: today every person
has to run their own copy of every agent, producing duplicate identities with
duplicate display names.

Steps to reproduce

  1. Point two Buzz clients (A and B) at the same relay.
  2. On A, create a managed agent, add it to a channel, set respond_to to
    anyone, and start it. Confirm it is a bot member of that channel.
  3. On A, @mention the agent in that channel — it autocompletes and replies.
  4. On B, open the same channel and type @ followed by the agent's name.
  5. No autocomplete entry appears. Sending the text anyway produces an event with
    no p tag, and the agent never runs.

Expected behavior

The agent appears in B's autocomplete and is mentionable, producing the same
p-tagged event that A produces.

Version and platform

  • Buzz version: v0.4.26 desktop (also reproduces on current main)
  • OS: macOS

Logs / additional context

Two independent causes, either of which is sufficient on its own.

1. The desktop app never publishes the kind:10100 agent profile it reads back.
list_relay_agents queries {"kinds":[10100]} unfiltered, and
agents_from_events parses the result into RelayAgentInfo. But no code path in
desktop/src-tauri ever publishes a 10100 event — the only publisher in the
repo is buzz channels set-add-policy in the CLI, which writes only
channel_add_policy. The relay does not synthesize one either;
handle_agent_profile just reads channel_add_policy off it as a side effect.
So relayAgentsQuery.data is empty for any desktop-created agent, and the entire
relay-agent branch of getMentionableAgentPubkeys is unreachable in practice.

2. isAgentIdentityInManagedList drops every non-locally-managed agent.
Added in a4dfead ("fix(desktop): prefer live agent mentions", #2149), the gate at
useMentions.ts addCandidate runs before shouldHideAgentFromMentions and
discards any candidate with isAgent === true whose pubkey is not in the
locally managed set. A remote agent that is a bot channel member enters via
the members loop with isAgent set from member.role === "bot" and is dropped
there.

First released in v0.4.20; git diff v0.4.26 HEAD on useMentions.ts and
agentAutocompleteEligibility.ts is empty, so current main behaves the same.

On a fix

I prototyped against the real eligibility functions. No single-signal change
works — each one either fails to unblock the remote agent or un-hides an identity
that your existing tests require to stay hidden:

must be swap gate to mentionable bypass gate for members
mira — agent-flagged profile, channel member, no runtime HIDDEN HIDDEN SHOWN
quinn — relay-only, allowlists the viewer, not a member HIDDEN SHOWN HIDDEN
remote agent — directory-backed, respond_to: anyone, bot member SHOWN SHOWN SHOWN
locally managed agent SHOWN SHOWN SHOWN

(mira and quinn are the existing fixtures behind "own profile-only agents
are hidden from channel mentions"
and "relay-only agents stay hidden from
channel mentions even when allowlisted"
.)

Two rules satisfy all four rows:

  • Gate on managed OR (in the directory and invocable by me and a
    member of a channel I share)
    ; or
  • require channel overlap in both branches of relayAgentIsSharedWithUser
    its allowlist branch currently ignores channelIds entirely — and then gate on
    the resulting mentionable set.

Either way, cause 1 has to be fixed first: with no 10100 record published, every
rule that keeps mira hidden also keeps the remote agent hidden. The client
change alone is a no-op.

I read #2149 as deliberate rather than accidental — it is solving real clutter
from stale and duplicate agent identities using the only liveness signal
available at the time ("does this machine run it"). Publishing the directory
record supplies a better signal, so the filter can keep its intent without
excluding remote agents.

Happy to open a PR for either or both halves if you'd like — flagging first per
CONTRIBUTING.

Related but distinct: #1743 covers a resolved mention not being delivered to an
offline agent; this is a mention that cannot be resolved at all from another
device.

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