Repository navigation
Description
Describe the bug
buzz channels set-add-policy silently removes an agent from Desktop's mention
autocomplete.
kind:10100 (agent profile) is replaceable — crates/buzz-core/src/kind.rs:783
asserts is_replaceable(KIND_AGENT_PROFILE). The CLI publishes it with a single
field (crates/buzz-cli/src/commands/channels.rs:1035):
let content = serde_json::json!({ "channel_add_policy": policy }).to_string();Because the event is replaceable, this replaces the agent's full directory
record rather than merging into it. Every other field the record carried —
respond_to, respond_to_allowlist, channel_ids, name, agent_type — is
gone.
Nothing surfaces the loss:
- The relay accepts it.
handle_agent_profileonly readschannel_add_policy
(crates/buzz-relay/src/handlers/side_effects.rs:1172) and ignores the rest. - Desktop hides the agent without an error. In
desktop/src/features/agents/lib/agentAutocompleteEligibility.ts:21,
relayAgentIsSharedWithUserreadsagent.respondTo, which is nowundefined,
so neither branch matches and the agent is not invocable. Then
shouldHideAgentFromMentionstreats "in the directory but not invocable" as an
explicit exclusion signal and hides it.
The result is counter-intuitive: an agent with no kind:10100 shows up; an
agent with a partial kind:10100 disappears. The comment at line 88 —
Unknown invocability (not in directory) => show — is what makes the
never-registered agent work.
Downstream, @name typed in a channel stays plain text with no p tag, so the
relay never delivers the event to the ACP harness (subscribe=Mentions filters
on p), and the agent never wakes — with no log line on either side.
Steps to reproduce
- Register a CLI-driven ACP agent (own keypair,
buzz-admin add-member), give
it a profile withbuzz users set-profile, and add it to a channel. - Confirm
@nameresolves in Desktop's composer and the agent replies. - Run
buzz channels set-add-policy --policy owner_onlyas that agent. - Type
@namein the same channel.
The agent no longer appears in the autocomplete. The mention is sent as plain
text and the agent never responds. Reverting with --policy anyone does not
restore it — that publishes another single-field record, so the agent stays in
the directory with respond_to still absent.
Expected behavior
set-add-policy should preserve the rest of the record: read the current
kind:10100, change only channel_add_policy, and republish the full content.
A second option would be for the relay to reject a kind:10100 whose content is
missing fields a previously stored record had — though read-modify-write in the
CLI seems simpler and keeps the relay out of client-behavior enforcement, which
channels.rs:1017 says is deliberate.
Version and platform
- Buzz version: relay + CLI built from
main(63496cc), chartbuzz-0.1.6;
Desktop 0.5.0 (packaged release) - OS: relay on Kubernetes (Debian container), Desktop on Windows 11
Logs / additional context
The agent's stored kind:10100 content after set-add-policy — this is the
whole record:
{"channel_add_policy":"owner_only"}Republishing the full record restores invocability, which is the workaround:
{"pubkey":"<agent>","name":"<name>","agent_type":"claude-agent-acp",
"channels":["<channel-name>"],"channel_ids":["<channel-uuid>"],
"capabilities":[],"status":"online",
"respond_to":"allowlist","respond_to_allowlist":["<owner>"],
"channel_add_policy":"owner_only"}So the mitigation today is to republish the whole kind:10100 after every
set-add-policy call.
Worth noting: nothing in the ACP harness publishes kind:10100 (no occurrences
in crates/buzz-acp/), so a hand-written record is not overwritten — but it is
also not maintained. If respond_to_allowlist or channel_ids change on the
agent's side, the directory silently drifts out of sync. Having the harness
publish its own record at boot would fix both this bug's blast radius and the
drift.
Activity
hondoaus commentedon Aug 15, 2026
Confirming the practical impact of this from an external Hermes Agent integration.
We deliberately avoided
buzz channels set-add-policyafter tracing this replaceable-event behavior and instead published a complete agent-signed kind:10100 record. That was necessary because Desktop mention eligibility depends on fields beyondchannel_add_policy(respond_to,respond_to_allowlist,channel_ids, etc.).In our live self-hosted deployment:
respond_to=owner-onlywas stored and the identity was recognized as an agent, but it was not mentionable by Desktop;respond_to=allowlist, the owner's pubkey inrespond_to_allowlist, the existingchannel_ids, andchannel_add_policy=owner_onlymade@KITTappear immediately.So a partial
set-add-policywrite would definitely have destroyed the metadata that made this work.+1 for making
set-add-policyread/modify/write the existing full kind:10100 rather than replacing it with a one-field body. For externally managed agents, kind:10100 is effectively the public directory/invocability contract, so silent field loss is very hard to diagnose.fix(cli): merge set-add-policy into the head kind:10100 record (block…