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_profile only reads channel_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,
relayAgentIsSharedWithUser reads agent.respondTo, which is now undefined,
so neither branch matches and the agent is not invocable. Then
shouldHideAgentFromMentions treats "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 with buzz users set-profile, and add it to a channel.
- Confirm
@name resolves in Desktop's composer and the agent replies.
- Run
buzz channels set-add-policy --policy owner_only as that agent.
- Type
@name in 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), chart buzz-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.
Describe the bug
buzz channels set-add-policysilently removes an agent from Desktop's mentionautocomplete.
kind:10100(agent profile) is replaceable —crates/buzz-core/src/kind.rs:783asserts
is_replaceable(KIND_AGENT_PROFILE). The CLI publishes it with a singlefield (
crates/buzz-cli/src/commands/channels.rs:1035):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— isgone.
Nothing surfaces the loss:
handle_agent_profileonly readschannel_add_policy(
crates/buzz-relay/src/handlers/side_effects.rs:1172) and ignores the rest.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 anexplicit exclusion signal and hides it.
The result is counter-intuitive: an agent with no
kind:10100shows up; anagent with a partial
kind:10100disappears. The comment at line 88 —Unknown invocability (not in directory) => show— is what makes thenever-registered agent work.
Downstream,
@nametyped in a channel stays plain text with noptag, so therelay never delivers the event to the ACP harness (
subscribe=Mentionsfilterson
p), and the agent never wakes — with no log line on either side.Steps to reproduce
buzz-admin add-member), giveit a profile with
buzz users set-profile, and add it to a channel.@nameresolves in Desktop's composer and the agent replies.buzz channels set-add-policy --policy owner_onlyas that agent.@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 anyonedoes notrestore it — that publishes another single-field record, so the agent stays in
the directory with
respond_tostill absent.Expected behavior
set-add-policyshould preserve the rest of the record: read the currentkind:10100, change onlychannel_add_policy, and republish the full content.A second option would be for the relay to reject a
kind:10100whose content ismissing 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:1017says is deliberate.Version and platform
main(63496cc), chartbuzz-0.1.6;Desktop 0.5.0 (packaged release)
Logs / additional context
The agent's stored
kind:10100content afterset-add-policy— this is thewhole 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:10100after everyset-add-policycall.Worth noting: nothing in the ACP harness publishes
kind:10100(no occurrencesin
crates/buzz-acp/), so a hand-written record is not overwritten — but it isalso not maintained. If
respond_to_allowlistorchannel_idschange on theagent'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.