* fix(buzz): messages sent during Gateway downtime are dropped after restart Every new Gateway process subscribed to Buzz rooms starting at its own start time, because the lookback flag that enables backlog paging is process-local. That cutoff is applied as the NIP-01 since filter, so any room message a human sent while the process was down was never returned by the relay and never reached the agent or the transcript. The account gateway now persists a per-account recovery watermark in the plugin state store. First-ever setup still starts from the current time; later process starts resume from the saved watermark, clamped to the existing 24 hour retention floor. The watermark advances only after inbound handling completes and is stored at the admitted message created_at, so the inclusive since boundary re-offers the last admitted message to the existing persistent event-id dedupe guard. * fix(buzz): keep the cold-start recovery cursor behind unfinished work Codex review found two ways the recovery watermark could still drop room messages. Backlog replay dispatches up to eight handlers concurrently, so a newer message finishing before an older one committed the newer timestamp; a crash then left the older message with no dedupe record and a cursor already past it. The stored timestamp was also the sender controlled created_at, so a future dated room event pushed the cursor past locally observed time and excluded real downtime messages on the next start. The account gateway now tracks a recovery frontier per session. A checkpoint is the highest completed message time bounded by the oldest still running message, the oldest failed message, and the receipt time observed when the message was admitted. Checkpointing stays closed until the bus reports the room backlog fully drained, so a session that is still paging history cannot commit past events it has not seen yet. catchUpHistory now reports drained or incomplete for that signal. * fix(buzz): scope cold-start recovery per room and fence it at enqueue Admit replay work into the recovery frontier when it enters the dispatch queue instead of when a worker starts it, so a crash cannot persist a cutoff past an event that is still queued. Key recovery cursors by room instead of by account, so a room configured after the first start resolves to the current time and gets no backfill, while existing rooms resume from their own cursor. Record an account-level start marker so the first start under a watermark-aware build recovers the existing retention window instead of repeating the reported loss on the first restart after an upgrade. * fix(buzz): keep cold-start recovery to accounts that already ran An account with no persisted cursor is a fresh install as often as it is a pre-watermark upgrade, and stored state cannot tell them apart, so the first start no longer replays the retention window. It records the current time as each room cursor and recovers only from the second start onward. Dropping the account start marker also removes the interrupted-bootstrap window where a marker written before the room cursors made the next start treat cursor-less rooms as initialized. Recovery state capacity is now derived from the supported room limit instead of a smaller fixed number, and any non-complete history paging outcome, not just timestamp-over-limit, holds the recovery frontier undrained. * fix(buzz): bound the recovery cursor store to each account ClawSweeper found that the recovery watermark opened one fixed plugin-state namespace for every account while sizing it at the per-account supported room count. Plugin-state capacity is enforced per plugin and namespace, so once one account registered its full room allowance, a second account's register call threw and its rooms stayed at the current-time cutoff, which is the same dropped-message outcome this PR set out to fix. The store is now opened against a namespace derived from the account identity, so each account carries its own supported room capacity. The account moves out of the entry key into the namespace, which leaves one account-scoped store path rather than a fallback, and makes cross-account cursor mixing unrepresentable. * fix(buzz): simplify durable restart recovery Co-authored-by: yetval <yetvald@gmail.com> * test(buzz): use real relay response in recovery fixture Co-authored-by: yetval <yetvald@gmail.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
@openclaw/buzz
Official Buzz channel plugin for OpenClaw. It connects an OpenClaw agent to approved Buzz rooms for text conversations and threaded replies.
Requirements
You need:
- A Buzz relay URL
- A Buzz owner or admin
- A room where the bot can receive the Bot role
Use wss:// outside local development.
Set up
openclaw channels add --channel buzz
OpenClaw installs the plugin if needed, asks for the relay URL, and generates a dedicated bot identity.
Give the displayed public key only to a Buzz owner or admin:
buzz channels add-member \
--channel <ROOM_UUID> \
--pubkey <BOT_PUBLIC_KEY> \
--role bot
Closed relays may also require the bot to be added as a relay member. Setup waits for approval, discovers accessible rooms, and saves the selected rooms and default target.
Restart the Gateway if it was already running.
Verify
openclaw channels status --probe
Inspect the current bot, approved rooms, and room members:
openclaw directory self --channel buzz
openclaw directory peers list --channel buzz
openclaw directory groups list --channel buzz
openclaw directory groups members --channel buzz --group-id buzz:<ROOM_UUID>
Buzz profile and room names are used as display labels, while public keys and room UUIDs remain the stable identities. Archived rooms are omitted; an archive or restore event rebuilds only the Buzz connection's room subscriptions and does not stop the Gateway.
Send a test message:
openclaw message send \
--channel buzz \
--target <ROOM_UUID> \
--message "Hello from OpenClaw"
Security and scope
- Never give OpenClaw a human owner's private key.
- The generated bot private key is stored in OpenClaw configuration; only its public key is displayed.
- Treat Buzz messages as untrusted agent input.
- Currently supported: text conversations, threads, typing, and directory lookup in group rooms.
- Not yet supported: DMs, media, reactions, or creating rooms from OpenClaw.
Full documentation: https://docs.openclaw.ai/channels/buzz
Package: @openclaw/buzz · Plugin ID: buzz