Skip to content

Feature Request: Support external agent systems (non-ACP) for real-time communication in Buzz communities #2663

Open

Description

@daveryai-bot

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:

  1. buzz-cli — a one-shot REST CLI tool. No persistent connection, no real-time message receiving.
  2. buzz-acp with 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-cli for 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-cli v0.1.0 installed and working
  • buzz-acp compiled 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

  1. scottybo commented on Jul 24, 2026

    @scottybo

    Would love to see support for this - looking to run Buzz on the same server as my OpenClaw and use that as the harness

  2. webdevtodayjason commented on Jul 24, 2026

    @webdevtodayjason

    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 buzz CLI, detects mentions of the agent, gathers the
    mention'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:

    • NIP-42 auth with the agent's own key via the CLI — no special-casing.
    • Membership + posting — once the agent was a channel member, posting was
      unremarkable, as it should be.
    • Threaded replies — messages send --reply-to <mention-id> resolves the
      NIP-10 thread root server-side, so replies nest correctly without the agent
      computing the root itself. A really nice affordance for bots.
    • Round-trip latency ~5–6 s, essentially all inference.

    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 but
    has 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 the
    private 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 compact drops the fields agents need

    For messages get, --format compact returns only {id, content, created_at}
    — it drops pubkey and tags. Those are exactly what an agent's read path
    needs: pubkey to skip its own messages (no self-reply loop) and identify
    senders, tags for p-tag mention detection and h/e thread 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+tags in 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). But buzz agents only opens
    Desktop draft forms (draft-create / draft-update); there is no
    headless/CLI publish. To register from a server we hand-built and signed the
    30177 and POST /events with NIP-98 auth — and wrote a small custom Rust keytool
    just 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 directory
    registration doesn't require the desktop app.

    4. The kind:30177 content schema is strict, and the relay won't catch a bad one

    The 30177 content is the desktop's ManagedAgentEventContent: required fields are
    name (not display_name), parallelism, and respond_to (the
    RespondTo enum 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:0 profile so clients can resolve and display it. Our live E2E
    worked with just those two — the kind:30177 directory entry was not required
    for delivery (it's a separate concern: it governs the desktop directory listing
    and respond_to policy).

    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 live
    round-trips, neither mention carried a p tag — both were plain-text
    @hermes, answered only via the bridge's display-name matching:

    mention 1e5837b1  "@hermes welcome aboard …"  tags=[["h","<channel>"]]   (no p-tag)
    mention 5021a4fb  "@hermes u there?"           tags=[["h","<channel>"]]   (no p-tag)
    

    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 carry
    mentions 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.

  3. Bartok9 commented on Jul 26, 2026

    @Bartok9
    Contributor

    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.

  4. Bartok9 commented on Jul 26, 2026

    @Bartok9
    Contributor

    Taking on the full #2663 external-agent / OpenClaw realtime path (not only the gap#1 users me slice).

    Plan:

    • Keep feat(cli): add buzz users me for external-agent identity #2933 open as the small self-identity PR
    • Land a feature PR for listen/stream + field-report gaps (compact message fields, headless agents publish/30177 validation, OpenClaw-oriented CLI surface)
    • Coordinating so we don't fight BYOH/Hermes ACP PRs for the same seam

    Will link the full PR here when opened.

  5. Bartok9 commented on Jul 26, 2026

    @Bartok9
    Contributor

    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), compact pubkey/tags, headless agents publish (30177 + validation), docs, and users me so 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.

  6. 0xtigerclaw commented on Jul 29, 2026

    @0xtigerclaw

    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, same BUZZ_AUTH_TAG owner 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:

    Client Origin Result
    buzz-acp built from main (485d03a) GCE VM rejected: not a relay member
    buzz-acp built from v0.5.0 tag GCE VM rejected: not a relay member
    buzz-acp binary from the desktop bundle, run manually residential IP connects, subscribes
    Buzz desktop app (v0.5.0) residential IP connects, subscribes

    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:

    1. Is origin-based restriction of NIP-OA agent auth on hosted relays intentional policy, and if so, is it documented anywhere?
    2. Is there a supported way to run a desktop-registered agent from a server against a hosted community today (community API token, allowlisted egress, or similar)?
    3. If not, is server-side agent support for hosted communities on the roadmap, per this issue?

    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.

  7. 139 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions