Skip to content

fix(acp,relay): publish the agent directory entry clients already read - #6304

Open
simpsonkorea wants to merge 1 commit into
block:mainfrom
simpsonkorea:fix/acp-publish-agent-directory
Open

simpsonkorea wants to merge 1 commit into
block:mainfrom
simpsonkorea:fix/acp-publish-agent-directory

Conversation

@simpsonkorea

Copy link
Copy Markdown

fix(acp,relay): publish the agent directory entry clients already read

Summary

Nothing in the tree ever published kind:10100. Both clients consume it as the agent directory, and it is the only source that makes an agent mentionable to someone who does not manage it locally:

  • desktop → getMentionableAgentPubkeysrelayAgentCanRespondInChannel
  • mobile → agentIsSharedWithUser

The only writer anywhere was buzz channels set-add-policy, which writes a policy and no directory fields.

Consequence: respond_to: anyone never actually reached anyone. An agent was mentionable only from the one machine holding it in managed-agents.json. On every other device it appeared in the member list, produced no autocomplete entry, and any message went out with no p tag — which is indistinguishable, from the user's side, from an agent that simply ignores you.

Mobile masked the hole behind its role == "bot" member fallback — whose own comment admits agents "may not have published a kind:10100 profile event yet" — which is why the phone worked and the desktop did not.

Changes

crates/buzz-acp/src/lib.rs — publish the directory entry at the same readiness boundary as presence, once channel subscriptions have resolved.

Desktop scopes eligibility per channel, so an entry naming channels the agent never subscribed to would advertise a mention that can never be answered. Publishing after subscriptions resolve keeps the advertised set truthful.

respond_to: nobody is deliberately skipped. It is heartbeat-only, and the desktop's RespondTo has no such variant — publishing it would fail deserialization of the whole Vec<RelayAgentInfo> and blank the directory for every agent at once rather than degrading just this one.

crates/buzz-relay/src/handlers/side_effects.rs — make channel_add_policy optional on kind:10100.

The relay previously required that field on every kind:10100 and raised a side-effect error without it. A directory entry legitimately carries no policy, and emitting a guessed one would clobber whatever the operator set. Absence now means "change nothing" instead of erroring on every agent startup.

Verification

Verified against a live relay: a patched harness published its entry, the relay stored it without a side-effect error, and it came back over a REQ carrying the three fields both clients gate on.

Field corroboration from a production deployment (2026-08-19)

Independently of the patch, the failure mode was observed on a live Buzz-hosted community:

  • Querying kind:10100 on that relay returned one entry, despite several agents being present and configured with respond_to: anyone.
  • Dead agent identities nonetheless kept showing up in the desktop @mention picker — they were reaching it through kind:39002 channel membership with role: bot, i.e. the member-list path, not the directory.
  • Removing those roster entries was what actually cleared the picker; archiving the identities (NIP-IA kind:9035) did not, because the directory was never the source for them.

This matches the diagnosis above: without a publisher for kind:10100, the directory is effectively empty and clients fall back to whatever member-list heuristics they have, producing exactly the "agent is listed but silently unmentionable" behaviour.

Notes for reviewers

  • Rebased onto origin/main (clean, no conflicts).
  • Signed-off-by present (DCO).
  • Touches two crates but the change is one mechanism: publish the entry, and stop the relay from rejecting an entry that carries no policy.

Nothing in the tree ever published kind:10100. Both clients consume it as the
agent directory and it is the ONLY source that makes an agent mentionable to
someone who does not manage it locally: desktop feeds it to
`relayAgentCanRespondInChannel` via `getMentionableAgentPubkeys`, mobile to
`agentIsSharedWithUser`. The only writer anywhere was
`buzz channels set-add-policy`, which writes a policy and no directory fields.

So `respond_to: anyone` never actually reached anyone. An agent was mentionable
only from the one machine holding it in `managed-agents.json`; on every other
device it appeared in the member list, produced no autocomplete entry, and the
message went out with no `p` tag — indistinguishable from an agent ignoring
you. Mobile hid the hole behind its `role == "bot"` member fallback (whose own
comment says agents "may not have published a kind:10100 profile event yet"),
which is why the phone worked and the desktop did not.

buzz-acp now publishes its entry at the same readiness boundary as presence,
once channel subscriptions have resolved — desktop scopes eligibility per
channel, so an entry naming channels the agent never subscribed to would offer
a mention that can never be answered.

`respond_to: nobody` is skipped: it is heartbeat-only, and the desktop's
`RespondTo` has no such variant, so publishing it would fail deserialization of
the whole `Vec<RelayAgentInfo>` and blank the directory for every agent at once
rather than just this one.

The relay required `channel_add_policy` on every kind:10100 and raised a
side-effect error without it. A directory entry legitimately carries no policy,
and emitting a guessed one would clobber whatever the operator set, so the
field is now optional and absence means "change nothing" instead of an error!
on every agent startup.

Verified against a live relay: a patched harness published its entry, the relay
stored it without a side-effect error, and it came back over a REQ carrying the
three fields both clients gate on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Gyusup Sim <simpsonkorea@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant