Repository navigation
Description
Describe the bug
An agent owned by one person can never appear in another person's @ mention autocomplete, in any channel, under any configuration. respond_to: anyone, respond_to: allowlist, channel membership, and shared-channel overlap all have no effect.
There appear to be two independent causes, and the second makes the first unreachable.
Cause 1 — the eligibility gate is unreachable for agents you don't own
useMentions.ts applies three gates in order (v0.5.1 desktop/src/features/agents/hooks/useMentions.ts:245-262):
if (isArchivedDiscovery(pubkey)) return;
if (!isAgentIdentityInManagedList(candidate, managedAgentPubkeys)) return; // :249
if (shouldHideAgentFromMentions({…})) return; // :252isAgentIdentityInManagedList (lib/agentAutocompleteEligibility.ts:57-65) keeps a candidate only if isAgent !== true or its pubkey is in managedAgentPubkeys. That set is built from useManagedAgentsQuery → the local list_managed_agents Tauri command, i.e. strictly the viewer's own agents — and apply_inbound_managed_agent deliberately refuses to mint one from a relay event (commands/personas/inbound.rs:376-404, "managed agents carry device-local secrets and are never minted from a relay event").
Relay-agent candidates are added with isAgent: true unconditionally (useMentions.ts:334-346), and member candidates get isAgent: true whenever profile?.isAgent === true (:318-323), which for a kind:0 profile is derived as owner_pubkey.is_some() (nostr_convert.rs:345) — always true for an agent, since sync_managed_agent_profile always attaches a NIP-OA owner attestation (relay.rs:401-455).
So for any viewer who does not own the agent, the candidate is dropped at :249 before shouldHideAgentFromMentions / relayAgentIsSharedWithUser ever run.
Typing the mention manually doesn't help either: extractMentionPubkeys (:794-831) resolves p tags from mentionMapRef plus the post-filter mentionCandidates, so no p tag is emitted for a filtered-out agent.
Cause 2 — relayAgentIsSharedWithUser reads an event kind nothing publishes
Even if Cause 1 is fixed, the eligibility logic is inert. relayAgentIsSharedWithUser (lib/agentAutocompleteEligibility.ts:12-31) reads channelIds / respondTo / respondToAllowlist from a RelayAgent, which comes from list_relay_agents (desktop/src-tauri/src/commands/agent_discovery.rs:1057-1074) — a query for exactly [{"kinds":[10100]}].
Nothing in the repo publishes a kind:10100 agent profile. The only 10100 writer is buzz channels set-add-policy (crates/buzz-cli/src/commands/channels.rs:1004-1038), whose content is {"channel_add_policy": …}. Agent identity is published as kind:0 plus kind:30177 (managed_agents/agent_events.rs), and the persona catalog as kind:30175. The eligibility path never consults 30177.
Consequently agents_from_events (nostr_convert.rs:445-496) defaults channel_ids: [] (:469-480) and leaves respond_to absent → respondTo: null (shared/api/tauri.ts:686-695), so relayAgentIsSharedWithUser returns false for every agent and every viewer.
Secondary effect: publishing a 10100 makes things worse. directoryAgentPubkeys is every pubkey in relayAgentsQuery.data, with no eligibility filter (useMentions.ts:182-190), and for a channel member shouldHideAgentFromMentions ends in return directoryAgentPubkeys.has(normalized) (agentAutocompleteEligibility.ts:85-97). So a 10100 that doesn't satisfy relayAgentIsSharedWithUser converts "unknown invocability ⇒ show" into "explicit exclusion ⇒ hide", removing an agent that channel members could previously see. Note also that 10100 is replaceable-by-pubkey, so publishing one destroys that agent's existing channel_add_policy event.
Steps to reproduce
- User A creates an agent, sets Responds to: Anyone, and adds it as a member of a channel shared with user B.
- Confirm on the relay that the agent's kind:30177 content has
"respond_to":"anyone"(visible inagents/retention/<64hex>.db, tablepersona_events). - As user B, in that shared channel, type
@followed by the agent's exact name. - The agent never appears in the autocomplete — no entry, and no "not in channel" label.
Same result with Responds to: Allowlist containing user B's 64-char hex pubkey.
Expected behavior
An agent whose owner has set respond_to: anyone (or an allowlist including the viewer) and which shares a channel with the viewer should be selectable in that viewer's mention autocomplete — which is what relayAgentIsSharedWithUser and the respond_to setting both clearly intend.
Version and platform
- Buzz version: 0.5.1 (verified unchanged in 0.5.2 —
agentAutocompleteEligibility.ts,agent_discovery.rs,agent_events.rsare all identical between the two tags) - OS: macOS 15 (Darwin 25.4.0), Apple Silicon
Logs / additional context
The agent-side gate is configured correctly and is not the problem: record.respond_to reaches the harness as --respond-to at spawn (managed_agents/runtime.rs:380-392), and author_allowed admits any author under RespondTo::Anyone for non-DM channels (crates/buzz-acp/src/lib.rs:250). The agent would answer; it simply cannot be addressed, because no p tag can be produced for it.
Possible fix directions (happy to open a PR if you can indicate a preference):
- Cause 1 — allow a candidate through
:249when its pubkey is inrelayAgentsQueryand it passesrelayAgentIsSharedWithUser, rather than requiring local ownership; and relax the corresponding early-return inextractMentionPubkeysso theptag is emitted. - Cause 2, option (a) — add a kind:10100 agent-profile publisher on the owner's desktop. Needs a new projection plus a source for
channel_ids, which doesn't exist today. - Cause 2, option (b) — repoint
list_relay_agentsat kind:30177 (which already carriesrespond_to/respond_to_allowlist) and resolve channel membership with a kind:39002#pquery, the same one the harness already uses atrelay.rs:651-668. This needs no relay change and seems the cleaner shape.
Workaround for anyone hitting this: skip mentions entirely by setting per-agent env BUZZ_ACP_SUBSCRIBE=all (plus BUZZ_ACP_KINDS=9 and BUZZ_ACP_CHANNELS=<uuid> to avoid wildcard kinds and unintended channels), which makes the agent answer messages in a scoped channel without requiring a p tag.
Activity
rjgalvez commentedon Jul 30, 2026
I found the way to make it work via env variables of agents BUZZ_ACP_SUBSCRIBE to subscribe to a channel and BUZZ_ACP_CONFIG with a .toml file:
so it only answers messages that starts with "?", plus instructions to answer in thread (agent was not sending messages)
KokyCode commentedon Jul 30, 2026
While @rjgalvez fix is great, it's just more feasible mentioning the agents instead. Please fix asap
rjgalvez commentedon Jul 30, 2026
@KokyCode yes, its a workaround that we found in our team and works, but of course it's more friendly to mention
AlanSobenes commentedon Aug 1, 2026
Confirming on Windows and on 0.5.3 — this reports macOS and 0.5.1/0.5.2, and nothing has changed.
Setup: self-hosted relay, three users, each running desktop-managed agents. Symptoms match exactly, and in both directions simultaneously — A cannot mention B's agents while B cannot mention A's, in channels where all parties and the agents are members. The agents' own messages render normally in those channels, so publishing works and only addressability fails. The symmetry is useful confirmation that this is structural rather than per-account misconfiguration: it reproduces without either side having touched the other's settings.
Verified against 0.5.3 (
desktop/src-tauri0.5.3):agentAutocompleteEligibility.ts, thekinds: [10100]query atagent_discovery.rs:1054, and the single 10100 writer atcrates/buzz-cli/src/commands/channels.rs:1038are all unchanged from your description.One detail relevant to fix option (b) that I don't see called out: the kind:30177 snapshot is built from the definition-tier fields, not the runtime ones —
desktop/src-tauri/src/managed_agents/agent_snapshot.rs:194-209:The harness, meanwhile, is spawned from the instance-level
record.respond_to/record.respond_to_allowlist. These diverge in practice — on this machine an agent helddefinition_respond_to: "anyone"with an empty definition allowlist while its running process reportedrespond_to=allowlist(2)with two keys. Repointinglist_relay_agentsat 30177 would therefore advertise a policy the agent doesn't enforce, in either direction: visible-but-silent, or answers-but-hidden. Worth reconciling the two tiers, or sourcing the projection from the instance fields.oleg-ai-dev commentedon Aug 4, 2026
Opened #4716 with a fix for both stacked causes described here (relaxing the
isAgentIdentityInManagedListgate for Cause 1, repointinglist_relay_agentsfrom the never-publishedkind:10100tokind:30177+ akind:39002 #pchannel-membership query for Cause 2).I know this issue already has a large number of open PRs attempting the same fix, so in case it's useful for whoever triages this regardless of which PR ends up merged: the detail that seems to be missing from the ones I was able to check is that
respond_to/respond_to_allowlistneed to be sourced from the instance-tier runtime fields on thekind:30177record, not the definition-tier fields. The two can diverge in practice (the running harness is spawned from instance-tier fields), so a fix that reads definition-tier would ship a policy the agent doesn't actually enforce — agent visible but silent, or answering but still hidden from the mention picker. Worth checking regardless of which PR this thread ends up going with.Tested manually against a local dev relay with two separate identities, and separately end-to-end against a real hosted community across two independent machines. Full details, root cause, and test plan are in the PR description.
fix(desktop): let channel-member agents reach the mention picker
fix(desktop): let channel-member agents reach the mention picker