← Back to Projects

Teaching Buzz to Mention Remote Agents

A self-hosted Buzz pilot exposed the work behind first-class remote agents: identity discovery, native Nostr mentions, isolated routing, and a clearer interoperability contract.

An abstract laptop sends a glowing message through a self-hosted relay, which routes it to two distinct blue and coral agent identities.

Buzz starts from a compelling premise: humans and AI agents should be able to share the same rooms, identities, and collaboration patterns. We wanted to find out how well that premise held when the agents were not launched by the Buzz desktop app or an Agent Client Protocol harness, but instead lived in an existing OpenClaw gateway.

We already knew OpenClaw could join Buzz. The real question was whether we could make that connection feel dependable and first-class: stronger onboarding, distinct agent identities, deterministic mentions, isolated conversations, safer multi-agent routing, and a cleaner experience for people using the desktop client. Pursuing that stronger integration exposed a useful compatibility gap: the transport protocol was ready for remote agents before every client-side assumption was.

Our earlier Buzz spotlight looked at the product as a fast-moving open-source workspace for human and agent teams. This project goes one layer deeper: instead of evaluating the experience from the outside, we connected an existing multi-agent system and followed the identity, membership, and mention data all the way through the client and relay.

What we were trying to build

Our pilot runs a self-hosted Buzz relay on the 7090 server. Buzz Desktop on a Mac Studio acts as the human client. OpenClaw connects from the server as a native messaging gateway with two Buzz accounts:

  • Emma, routed to OpenClaw's main agent
  • Rose, routed to a separate Rose agent

Each agent has its own Nostr keypair, Buzz profile, verified owner tag, room membership, presence, and OpenClaw account binding. Both identities share the same room without sharing a private key or agent session.

That last point matters. This is not one bot changing its display name. It is a multiplexed gateway carrying multiple independently addressable agents.

We began with the public Buzz macOS app, version 0.5.3. The installed app remained untouched throughout the investigation. Client experiments ran in a separate development build with its own macOS bundle identifier, application-data directory, and Keychain entry. That isolation let us patch, reset, and inspect the development client without risking the working public installation or its identity.

The goal was not to ship a private Buzz fork. It was to determine whether the failure came from our unusual architecture, the relay, the OpenClaw adapter, or the desktop client—and to leave behind a precise compatibility case that could be fixed upstream.

The first routing problem

At first, both agents could see the same room traffic and appeared to feed off one another. We added a conservative text fallback for names such as @Emma and @Rose, but the fallback alone did not solve the underlying route mismatch.

The important bug was the room identifier. OpenClaw's bindings were matching the bare Buzz UUID while inbound sessions used Buzz's canonical peer form, buzz:<UUID>. Once both account bindings used the canonical identifier, Emma and Rose received separate session keys and deterministic account routing.

We kept the text-name matcher as a compatibility fallback, with narrow boundaries so words such as “rosemary” do not accidentally wake Rose. Native public-key mentions take precedence.

The adapter also needed to behave like a real multi-account messaging platform rather than two loosely connected relay clients. Each inbound event is deduplicated before it reaches an agent pipeline, messages authored by the connected bot identities are ignored as inbound prompts, and mention gating is evaluated against the account's own public key. Those boundaries are what prevent a response from one agent from becoming a new prompt for the other.

The directory record that was already there

Buzz uses Nostr kind 10100 events as agent-directory profiles. OpenClaw was already publishing one for each identity with three intentionally minimal fields:

{
  "name": "Emma",
  "display_name": "Emma",
  "channel_add_policy": "anyone"
}

Rose received the corresponding record under her own public key. OpenClaw also published normal profile metadata, preserved owner authentication tags, and refreshed presence.

The profile synchronization is deliberately conservative. It preserves an existing display name and any valid existing channel_add_policy; for a new record it supplies anyone because adding an identity to a Buzz room does not, by itself, expand OpenClaw's accepted ingress. The gateway still accepts messages only from explicitly configured Bot-role rooms.

The first client diagnosis suggested that Emma and Rose had no directory records. Direct inspection showed that the relay had received both records correctly. The actual problem was subtler: Buzz's mention autocomplete treated optional directory fields such as respond_to and channel_ids as part of its eligibility test. Because OpenClaw's valid profiles were sparse, the client excluded the agents even though both were already Bot members of the current channel.

That made channel membership and directory metadata disagree about the same identity.

Following the data through Buzz

The investigation checked every layer that could plausibly have removed or hidden the mention:

  • kind 0 profile events contained usable names for Emma and Rose
  • kind 10100 directory events existed and were returned by the relay
  • the channel's kind 39002 membership record listed both identities as Bot members
  • older structured messages proved the relay could store and return p tags
  • new plain-text tests reached the relay without p tags, showing the metadata was missing before publication rather than stripped afterward

This changed the diagnosis. The server had not lost OpenClaw's records, and OpenClaw had not failed to publish them. The desktop client could see the data but interpreted it incorrectly while assembling autocomplete candidates.

What changed in the local client

Working against the local Buzz client, Codex first incorporated local equivalents of two already proposed changes. One expanded autocomplete eligibility for remotely hosted or shared agents. The other resolved typed mention names into public-key tags in the Rust/Tauri message-sending path. Both addressed genuine weaknesses, but neither completely fixed this case.

Buzz applied two eligibility filters. The first excluded agents that were neither locally managed nor appropriately shared; it was adjusted to admit agents that belong to the current channel. A second filter still removed Emma and Rose because their directory records existed without optional sharing metadata. In effect, the client conflated three separate questions:

  1. Is this agent a member of the current room?
  2. Should this agent appear in broader discovery?
  3. Which people or event types is the agent configured to answer?

The corrected behavior makes current channel membership authoritative: if an identity is a Bot member of the room, it is mentionable there. Directory policy still governs discovery of agents that are not already members.

This is a stronger rule because membership is the actual access boundary. Optional capability hints can enrich discovery, but they should not erase an identity the room already recognizes.

Autocomplete was only half the path. Buzz represents a native Nostr mention with a p tag containing the mentioned identity's public key. The first typed-mention change added p tags when messages passed through the Rust/Tauri send path, including some replies and attachment-bearing messages. Ordinary messages commonly bypassed that path and were published directly by the renderer over WebSocket. The local client therefore needed the normal renderer path to carry the selected identity as a p tag too.

We verified the result directly in the relay data:

  • an Emma message included the room's h tag plus a p tag matching Emma's public key
  • a Rose message included the same room h tag plus a p tag matching Rose's public key
  • an earlier test message from before the fix contained only the h tag

That difference is the line between a name that merely looks like a mention and a protocol-level mention that any compatible remote system can route.

The validation went beyond a successful manual reply. The focused frontend suite passed 21 tests along with TypeScript and formatting checks, and the shared Rust mention resolver passed its focused tests. The important regression case is now explicit: a remote Bot member with a sparse but valid kind 10100 profile must remain mentionable, and an ordinary renderer-published message must contain the resolved p tag.

What Hermes clarified

Hermes documents three ways to participate in Buzz: a desktop-managed ACP runtime, a buzz-acp relay bridge that connects Buzz to an ACP agent over standard input and output, and a native Hermes gateway platform.

The ACP bridge reinforces several good boundaries:

  • one dedicated Nostr identity per agent
  • channel membership as the access boundary
  • automatic discovery of rooms where the identity is a member
  • explicit owner-only response gates for privileged headless automation

Our OpenClaw integration is closest to Hermes's native gateway path, but with a notable difference: it uses native Nostr transport in both directions and carries multiple agent identities through one gateway. ACP remains a useful interoperability layer for launching or connecting agent runtimes, but it is not required for remote invocation. At the Buzz protocol level, a kind 9 room message with the appropriate h and p tags is enough to address a remote agent.

The gap we found

The missing piece is not basic transport. It is a clear discovery and capability contract for agents hosted outside Buzz's own desktop and ACP workflows.

A richer OpenClaw directory profile could safely add descriptive metadata, an avatar, and the channel IDs already configured for that identity. It may also be useful to advertise explicit response capabilities or a protocol version. Those fields should be based on a documented contract, however, not added merely to satisfy a client filter.

The robust model is:

  • current Bot membership determines whether an agent can be mentioned in that room
  • directory policy and capabilities help discover agents outside the room
  • every outbound client path serializes a selected mention as a p tag
  • each remote agent owns a distinct identity and session route

What should improve next

Separate membership, discovery, and authorization

Channel membership should answer whether an identity belongs in a room. Directory metadata should describe the agent and advertise genuine capabilities or policies. A field such as respond_to should not accidentally decide whether an existing room member is visible.

Document the kind 10100 contract

Adapter authors need to know which fields are required, optional, descriptive, behavioral, advisory, or authoritative. OpenClaw should not publish respond_to, channel_ids, or capability claims merely to satisfy a current client filter. Those fields should reflect behavior the adapter actually implements.

Treat membership as the current source of truth

A kind 39002 membership record is stronger evidence of current room membership than a denormalized channel list in a profile. Profile lists can become stale when an agent is invited later, especially when the identity is externally hosted or one gateway carries several identities.

Unify outbound mention behavior

Renderer/WebSocket and Rust/Tauri publishing should share one mention-resolution contract. Name extraction, public-key resolution, and p-tag generation should behave identically regardless of whether a message is plain text, a reply, or carries an attachment.

Test externally hosted agents deliberately

The compatibility matrix should include agents not managed by Buzz Desktop, sparse kind 10100 profiles, membership-event onboarding, multiple identities behind one gateway, missing optional discovery fields, and both outbound send paths.

Make exclusions observable

During development, it was hard to distinguish missing profiles, missing directory events, absent membership, insufficient permissions, client filtering, and relay mutation. A diagnostic explanation for why an autocomplete candidate was excluded—and a preview of the p tags about to be published—would shorten this class of investigation considerably.

Improve invitation and onboarding

Mentioning now works, but inviting an external agent into another room still crosses identity discovery, owner authorization, channel_add_policy, membership updates, and adapter behavior. Buzz could make this path clearer by showing which identity records exist, why an invitation is allowed or denied, and what an external gateway must publish.

Publish an implementation-neutral adapter guide

Hermes is a valuable reference implementation, but remote-agent compatibility should not depend on copying Hermes-specific behavior. A small protocol guide and capability-version marker would give OpenClaw and other gateways a stable target while leaving room for richer avatars, descriptions, configured channels, and response capabilities.

Where the pilot stands

The working baseline now includes:

  • a self-hosted Buzz relay and Mac Studio client
  • separate Emma and Rose Nostr identities
  • synchronized names, profiles, verified ownership, and presence
  • Bot membership in the shared room
  • canonical per-account OpenClaw routing
  • native p-tag mentions from the modified development client
  • conservative name fallback for older clients
  • separate agent sessions without cross-agent feedback loops

That baseline is already useful. The next phase is to make the surrounding discovery, onboarding, diagnostics, security policies, and adapter contracts as deliberate as the transport—so externally hosted agents feel like distinct, safely routed participants rather than an accidental compatibility case.

References