buzz CLI binary (“JSON in, JSON out”); inbound uses a native Nostr WebSocket subscription (via the already-bundled websockets package) with CLI polling as fallback. No extra Python packages are required — just the buzz binary.
Buzz renders markdown, so agent replies keep their formatting. Images are delivered as uploads (local files) or links (URLs). Replies can thread onto an existing message via its event id. When progress or status messages are enabled, they inherit the triggering Buzz event as their reply anchor instead of appearing as unrelated top-level channel posts.
Files sent to the agent are fetched back off the relay with the agent’s authenticated identity and cached locally, so tools receive a real file path rather than a /media/… URL that anonymous requests cannot read. Images, audio, video, and documents (PDFs and the like) are all handled.
Inbound messages arrive over a persistent NIP-42-authenticated Nostr WebSocket subscription by default (near-instant delivery), with automatic fallback to CLI polling when the WebSocket can’t be established. Outbound messages always go through the buzz CLI. Control it with transport / BUZZ_TRANSPORT: auto (default), websocket (require WS, fail otherwise), or poll. If your relay membership uses NIP-OA owner attestation, set BUZZ_AUTH_TAG to the four-string auth tag JSON.
Run mibyan gateway setup and pick Buzz for a guided walk-through.
Prerequisites
- The
buzzCLI binary on yourPATH(or pointBUZZ_CLI_PATHat it) — build it from the Buzz repo withcargo build --release -p buzz-cli - A Buzz community relay URL (e.g.
https://mycommunity.communities.buzz.xyz) - A Nostr private key (nsec or hex) whose identity is already a member of that community
Configure Mibyan
You can configure Buzz two ways — thegateway block in config.yaml (canonical) or environment variables (which override it). The private key is a secret and always belongs in ~/.mibyan/.env.
Option A — config.yaml
~/.mibyan/.env:
Option B — environment variables
Recommended default settings
When wiring up Buzz, set these defaults inconfig.yaml to keep the channel clean and the agent focused on final results rather than its internal tool execution log. These match the behavior on Telegram and email, which already suppress intermediate tool output.
interim_assistant_messages: false— prevents intermediate tool results, reasoning comments, and progress updates from being posted as separate messages to the channel. Only the final response goes to the channel.tool_progress: off— suppresses tool progress bubbles (e.g., “Running terminal command…”, “Reading file…”). Keeps the channel focused on actual results, not process.poll_interval: 4— balances inbound latency (up to 4s delay) against relay load. Lower values increase polling frequency; higher values reduce it.allowed_users: []+allow_all_users: false— private mode by default. Only listed users can interact. Setallow_all_users: truefor community mode where everyone can chat (admin tier still restricted to the owner).require_mention: true— in channels, the agent only responds when addressed. DMs always dispatch regardless of this setting.
tool_progress: all — but interim_assistant_messages should still be false to avoid spamming with every tool result.
Mentions, channels, and DMs
- In shared channels the agent only responds when addressed — by
@name, its npub, or its hex pubkey. Everything else is ignored. - Direct messages always reach the agent, no mention needed.
- The agent’s own messages are never dispatched back to it (self-echo suppression by pubkey), and every event is de-duplicated by event id against a per-channel high-water mark.
Reply threading
Replies are threaded by default: the agent’s answer (and any enabled progress/status messages) is anchored to the message that triggered it. Anchoring is NIP-10 aware — when the triggering message was already inside a thread, the agent replies to that thread’s root, so the answer joins the existing thread instead of nesting a new one-message sub-thread under every turn. To post replies flat at the channel level instead, set either of these (they are equivalent;reply_in_thread matches the key Slack uses):
deliver=buzz).
Access control
By default the allow-list is empty, which means every community member who mentions the agent gets a response only ifBUZZ_ALLOW_ALL_USERS=true; otherwise restrict access by listing npubs or hex pubkeys in BUZZ_ALLOWED_USERS (or allowed_users in config.yaml). Community membership itself is enforced by the relay — only members can post.
The allow-list also gates inbound attachments: relay media is fetched with the agent’s own Buzz credentials, so a download only happens for a sender the gateway explicitly authorizes. A denied, missing, or failed authorization leaves the message text untouched and makes no credentialed request.
Cron jobs and notifications (deliver=buzz) are delivered to the home channel — BUZZ_HOME_CHANNEL if set, otherwise the first watched channel — and work even when cron runs outside the gateway process.
Inbound attachments
Buzz messages with native NIP-94imeta tags can deliver images, audio,
video, and documents to the agent. Mibyan downloads attachments only after
the message has passed self-echo, addressing, and sender authorization checks.
Each file must use HTTPS and declare an exact byte size and SHA-256 digest;
redirects, URL credentials, fragments, oversized payloads, and integrity
mismatches are rejected.
The relay’s own HTTPS origin is trusted automatically. If a community stores
media on another public origin, add its exact host or host:port to
attachment_hosts under gateway.platforms.buzz.extra. Non-default ports
must be listed explicitly. Protected media that requires authenticated
retrieval through the Buzz CLI is not handled by this native public-URL path.
Run the gateway
mibyan gateway status — Buzz connection state is reported there, including for env-only setups.
Notes and limitations
BUZZ_*env vars are available in terminal tool children for Buzz sessions — the agent can invoke thebuzzCLI directly (e.g.buzz messages send ...) becauseBUZZ_PRIVATE_KEY,BUZZ_AUTH_TAG,BUZZ_RELAY_URL, and the otherBUZZ_*variables are passed through to terminal subprocesses when the session’s platform isbuzzor the process is a Buzz Desktop managed agent (BUZZ_MANAGED_AGENT). Non-Buzz sessions on the same host,execute_code, and other non-terminal spawns remain sealed.- Inbound streaming has a watchdog. On the WebSocket transport a connection that goes quiet for five minutes, or whose socket the relay closed underneath us, is torn down and reconnected with backoff; while that happens the gateway health (
/health/detailed, dashboard status) reports Buzz asretrying, notconnected. On thepolltransport the adapter pollsbuzz messages getper watched channel everypoll_intervalseconds (default 4), so expect up to one interval of latency. - On (re)connect the adapter seeds its high-water mark from the newest events, so channel history is never replayed into the agent.
- New DM conversations are discovered automatically (every few poll sweeps).
- The private key is passed to the CLI via the subprocess environment — it never appears in argv or logs.

