Repository navigation
Description
Problem
Buzz's agent model currently requires agents to run as ACP subprocesses spawned by buzz-acp (Claude Code, Goose, Codex, etc.). External agent systems — like OpenClaw, custom backends, or any non-ACP agent platform — cannot participate in real-time Buzz conversations.
Today, the only ways for an external agent to interact with a Buzz community are:
buzz-cli— a one-shot REST CLI tool. No persistent connection, no real-time message receiving.buzz-acpwith a supported harness — spawns its own agent subprocess, which means the agent identity is tied to the harness (e.g., Claude Code), not to an external agent system.
This means if you run an AI assistant on your own infrastructure (OpenClaw, a custom backend, etc.) and want it to participate in a Buzz community alongside humans, there is no real-time path.
Use Case
We run an AI assistant (DeanAI) on OpenClaw with Discord, Telegram, and Google Chat integrations. We set up a Buzz community for human-agent collaboration between:
- Dean (human, Buzz desktop app)
- DeanAI (AI on OpenClaw, currently can only use
buzz-clifor one-shot REST calls) - DeanWynn (another AI instance on a separate machine)
DeanAI can post messages via buzz-cli, but cannot receive messages in real-time. When Dean sends a message in Buzz, there's no listener to pick it up and route it to OpenClaw. The conversation is one-directional without manual polling.
Proposed Solutions (any one would solve this)
Option A: Webhook-based agent integration
Allow registering a webhook URL per agent identity. When the agent is @mentioned or a message arrives in a subscribed channel, Buzz POSTs the event to the webhook. The external agent processes it and responds via buzz-cli or a REST API call.
Option B: WebSocket listener mode in buzz-cli
Add a buzz listen command that maintains a persistent WebSocket connection to the relay, streaming incoming events as JSON to stdout. External systems can pipe this into their own processing pipeline and respond via buzz-cli commands.
Option C: Custom agent command in buzz-acp
Allow --agent-command to point to an arbitrary executable (not just Claude Code/Goose/Codex) that speaks a simple JSON-in/JSON-out protocol over stdio — essentially a generic bridge mode. This would let external systems write a thin shim script that forwards messages to their own API.
Environment
- Buzz relay: local (port 18800) and hosted community (
daveryai.communities.buzz.xyz) buzz-cliv0.1.0 installed and workingbuzz-acpcompiled but not running (no compatible agent harness configured)- External agent: OpenClaw on Linux (WSL2)
Current Workaround
Manual polling via buzz messages get --channel <uuid> --limit N on a cron — but this is not real-time and adds unnecessary latency.
Happy to contribute or help test any of these approaches. Thanks for considering!
Activity
scottybo commentedon Jul 24, 2026
Would love to see support for this - looking to run Buzz on the same server as my OpenClaw and use that as the harness
webdevtodayjason commentedon Jul 24, 2026
We built and ran an external agent on Buzz end-to-end, and since #2663 is about
supporting external agent systems, here's a field report: what worked out of the
box, five concrete gaps we hit, and what we'd propose.
What we built
A small daemon that bridges a Buzz relay to an external AI brain: it polls
channels over the
buzzCLI, detects mentions of the agent, gathers themention's thread as context, calls the agent (a separate inference process), and
posts the reply threaded under the mention. The agent has its own Nostr identity
and channel membership — a first-class relay participant, not a relay-side plugin.
What worked first-try
Genuinely smooth. A live mention→reply round-trip worked on the first attempt,
and again from a second, distinct client identity:
unremarkable, as it should be.
messages send --reply-to <mention-id>resolves theNIP-10 thread root server-side, so replies nest correctly without the agent
computing the root itself. A really nice affordance for bots.
The five gaps an external-agent operator hits
None were hard blockers, but each cost real time or a workaround.
1. No self-identity endpoint ("who am I?")
There is no
buzz users me/whoami. An agent process holds a private key buthas no first-class way to ask for its own pubkey — deriving it needs a
secp256k1 x-only computation (a crypto dependency) or another tool. We worked
around it by requiring the pubkey out-of-band (
BUZZ_PUBLIC_KEY) alongside theprivate key, which means configuring identity twice for the exact case (agents)
where you least want to.
Propose:
buzz users me(or a flag) that prints the identity's own pubkey/npub.2.
--format compactdrops the fields agents needFor
messages get,--format compactreturns only{id, content, created_at}— it drops
pubkeyandtags. Those are exactly what an agent's read pathneeds:
pubkeyto skip its own messages (no self-reply loop) and identifysenders,
tagsforp-tag mention detection andh/ethread scoping. So the"lightweight" format is unusable for the poll loop, and it looks like the right
choice — the omission is silent.
Propose: keep
pubkey+tagsin compact, or document it as display-only.3. No headless publish path for the agent directory (kind:30177)
Registering an agent in the directory means publishing an owner-authored
kind:30177(NIP-AP managed-agent definition) — param-replaceable, keyed by(owner_pubkey, 30177, d_tag=agent_pubkey). Butbuzz agentsonly opensDesktop draft forms (
draft-create/draft-update); there is noheadless/CLI publish. To register from a server we hand-built and signed the
30177 and
POST /eventswith NIP-98 auth — and wrote a small custom Rust keytooljust to do it. An external-agent operator has no CLI on-ramp for the one step
that lists the agent in the directory.
Propose: a headless
buzz agents publish(sign + POST the 30177) so directoryregistration doesn't require the desktop app.
4. The
kind:30177content schema is strict, and the relay won't catch a bad oneThe 30177 content is the desktop's
ManagedAgentEventContent: required fields arename(notdisplay_name),parallelism, andrespond_to(theRespondToenum serializes kebab-case:owner-only/allowlist/anyone).The trap: the relay does not validate 30177 content — it's relay-opaque, the
persona-envelope validator doesn't run on it — so a wrong-shaped body is
accepted by the relay but silently fails to parse in the desktop directory.
The entry looks published and simply never renders, with nothing surfacing the
mismatch.
Propose: publish the 30177 content schema (required keys + allowed values),
and validate (or at least warn on) 30177 content at ingest instead of accepting a
body the directory can't parse.
5. External agents aren't offered in the @-mention selector (#2603)
What an external agent needs to receive and answer is modest: relay
membership (buzz-admin add-member — required even to publish its own events)
plus a
kind:0profile so clients can resolve and display it. Our live E2Eworked with just those two — the
kind:30177directory entry was not requiredfor delivery (it's a separate concern: it governs the desktop directory listing
and
respond_topolicy).But that delivery path only works because the agent polls the channel and
matches its own display name in message text. The desktop mention selector
does not offer the external/managed agent (this is #2603 — the managed-list gate
is evaluated before the directory), so a human can't pick it from @-autocomplete
and no structured
p-tag mention is emitted. First-hand: in our two liveround-trips, neither mention carried a
ptag — both were plain-text@hermes, answered only via the bridge's display-name matching:Propose: make membership +
kind:0(or a directory presence) satisfy mention-eligibility so external agents appear in the @-selector and humans emit a proper
p-tag — rather than external agents depending on plain-text name matching.Net
Buzz's Nostr-first model is a good fit for external agents — an agent is just
another signer with a key and a membership, and
p-tag / NIP-10 primitives carrymentions and threading cleanly. The friction is almost entirely at the
onboarding/identity edge (self-identity, headless directory publish, a strict
30177 schema the relay accepts but the directory silently can't parse, and a
mention-eligibility gate that shuts external agents out of the @-selector) plus
one read-path footgun (compact format).
Smoothing those five would make "bring your own agent" close to turnkey. Happy to
share the bridge implementation if useful.
Bartok9 commentedon Jul 26, 2026
Taking a first slice of gap #1 from the external-agent field report:
buzz users me/whoami(local identity, no relay). PR incoming so OpenClaw-style bridges don't need a bespoke secp256k1 step just to learn their own pubkey.Bartok9 commentedon Jul 26, 2026
Taking on the full #2663 external-agent / OpenClaw realtime path (not only the gap#1
users meslice).Plan:
agents publish/30177 validation, OpenClaw-oriented CLI surface)Will link the full PR here when opened.
Bartok9 commentedon Jul 26, 2026
Taking the full external-agent product path for #2663 (not only gap #1):
PR: https://github.com/block/buzz/pull/$(gh pr list --repo block/buzz --head Bartok9:bartok9/feat-external-agent-2663 --json number -q '.[0].number')
Ships:
buzz listen(Option B + optional webhook), compactpubkey/tags, headlessagents publish(30177 + validation), docs, andusers meso the branch is self-contained for E2E. Leave #2933 open as the thin identity slice.Residual: Desktop @-mention selector (gap #5); Option C stays with BYOH/ACP harness work.
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): external-agent realtime path for block#2663
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): external-agent realtime path for block#2663
0xtigerclaw commentedon Jul 29, 2026
Adding a data point that suggests hosted-relay policy moved in the opposite direction of this request today, and a question about the supported path.
Setup: hosted community on
*.communities.buzz.xyz, one desktop-managed Claude Code agent (buzz-acp), pilot for a small investment team. We are migrating the agent from a laptop to a server (GCE, europe-west3) for availability, reusing the same identity: same nsec, sameBUZZ_AUTH_TAGowner attestation.Observed behavior change, 2026-07-29: at 09:18 UTC the agent connected from the GCE VM successfully (NIP-42 + attestation accepted, channels discovered, presence online, turns served). From roughly midday UTC, the identical connection is rejected at auth with
restricted: not a relay member. No credential or client changes on our side between those points.Isolation matrix, all with the same key + attestation:
Plain member NIP-42 auth (a non-agent member key used by our approval bot) is unaffected from the same VM: it authenticates and holds live subscriptions. Only the agent-attestation path appears origin-sensitive. Relay NIP-11 reports software 0.2.0.
Questions:
Happy to provide timestamps, request traces, or test against a canary relay. For a team pilot, an agent that only exists while one laptop is awake is the main adoption blocker, so we would rather run it your supported way than work around it.
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): external-agent realtime path for block#2663
feat(cli): add `buzz users me` for external-agent identity (block#2663)
139 remaining items
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): external-agent realtime path for block#2663
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): external-agent realtime path for block#2663
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): external-agent realtime path for block#2663
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): external-agent realtime path for block#2663
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): add `buzz users me` for external-agent identity (block#2663)
feat(cli): external-agent realtime path for block#2663
feat(cli): add `buzz users me` for external-agent identity (block#2663)