@nhtio/rocket-chat-openclaw-integration
v1.20260404.11
Published
An OpenClaw Plugin which allows RocketChat to be used as a communications channel
Readme
Rocket.Chat OpenClaw Integration (Spec)
This repository specifies and implements an integration between:
- Rocket.Chat (self-hosted, via Realtime API WebSocket/DDP)
- OpenClaw (via a first-class "channel" plugin integration, comparable to Slack/Telegram/Discord)
Primary docs referenced by this spec:
- Rocket.Chat Realtime API (deprecated notice applies; we accept risk for v1): https://developer.rocket.chat/apidocs/realtimeapi
- OpenClaw channels:
- OpenClaw plugin development: https://docs.openclaw.ai/plugins/building-plugins
- OpenClaw channel plugins (how they work): https://docs.openclaw.ai/plugins/sdk-channel-plugins#how-channel-plugins-work
Goals
- Provide a Rocket.Chat "channel" integration for OpenClaw that matches existing channel behavior (send/receive, threading/replies where applicable, identity mapping, attachments, reactions, etc.).
- Implement as an OpenClaw channel plugin that connects directly to Rocket.Chat.
- Keep OpenClaw-side changes minimal; introduce additional OpenClaw plugin capabilities only if required to achieve parity with existing channel integrations.
Non-goals (initial)
- Re-implement Rocket.Chat's full permission/admin surface; only what is required for install, auth, and message/event delivery.
- Multi-workspace support (assume one Rocket.Chat workspace per OpenClaw gateway for v1).
- Backfilling historical messages (focus on real-time sync first).
High-level Architecture
We expect a single OpenClaw channel plugin that connects directly to Rocket.Chat.
- Transport: Rocket.Chat Realtime API (WebSocket/DDP) (deprecated per Rocket.Chat docs; accept risk for v1)
- Target Rocket.Chat version (v1): 8.2.0 (self-hosted; upgrades are controlled)
- Bot identity: one Rocket.Chat user per OpenClaw agent, each with the
botrole (admin-provisioned) - Auth: Personal Access Token (PAT) per bot user (manual provisioning)
A Rocket.Chat Apps-Engine app is explicitly out of scope for v1 (keeps deployment and ops simpler). If Rocket.Chat later removes or breaks Realtime API subscription streams we rely on, we will revisit an Apps-Engine-based design.
OpenClaw Channel Plugin Expectations (Draft)
Per the OpenClaw channel plugin documentation, OpenClaw core owns the shared
message tool and core prompt wiring. The channel plugin typically owns:
- Config (account resolution + setup)
- Security (DM policy + allowlists)
- Pairing (DM approval flow)
- Session grammar (mapping provider conversation ids to base chats + threads)
- Outbound delivery (send text/media/polls)
- Threading semantics (reply behavior)
Canonical session-id parsing hook:
messaging.resolveSessionConversation(...)(and optionally a bootstrap-safesession-key-api.tsexport for bundled plugins)
Reference: https://docs.openclaw.ai/plugins/sdk-channel-plugins#how-channel-plugins-work
Interfaces & Data Flow (Draft)
- Inbound (Rocket.Chat -> OpenClaw)
- OpenClaw channel plugin maintains a Realtime API WebSocket connection per configured bot account.
- The plugin subscribes to message streams for allowlisted rooms and forwards eligible events into OpenClaw sessions.
- Outbound (OpenClaw -> Rocket.Chat)
- OpenClaw issues channel actions (send text/media/reactions/etc) which the channel plugin executes via Rocket.Chat APIs.
Authentication & Trust (v1)
Trust boundary is Rocket.Chat <-> OpenClaw. There is no intermediate Apps-Engine app.
- Bot auth mechanism: Rocket.Chat Personal Access Tokens (PATs) +
userId(manual admin provisioning). - Transport security:
- The plugin MUST use
wss://for Realtime API connections andhttps://for any REST calls. - TLS certificate validation MUST be enabled (no insecure / skip-verify) unless an explicit
dangerouslyAllowInsecure: true-style config flag is set for local dev.
- The plugin MUST use
- Secret storage: PATs are stored only in OpenClaw config (not in repo) and treated as credentials equivalent to a password.
- Rotation / revocation: rotating or deleting a PAT in Rocket.Chat must revoke OpenClaw access for that bot.
Enforcement requirements for long-lived connections:
- On any auth error/unauthorized response on the WebSocket (or any REST call), the plugin MUST immediately close the WebSocket and stop processing events for that account.
- The plugin MUST periodically re-validate credentials (REST check) on a fixed cadence to bound worst-case revocation delay. Default target: <= 5 minutes.
- Blast radius: one bot account per OpenClaw agent id; compromising one PAT should not compromise other agents.
- Session-level authorization: inbound events must still pass OpenClaw allowlist + policy checks (DM policy, group policy, mention gating, per-room/per-user allowlists) before reaching the model.
Message Semantics (Draft)
For v1, feature scope should match the Slack channel integration behavior and capabilities as documented here:
- Slack channel docs: https://docs.openclaw.ai/channels/slack
At minimum, Slack documents inbound event subscriptions for:
- message events across channel types (
message.channels,message.groups,message.im,message.mpim) - reactions (
reaction_added,reaction_removed)
We should target comparable Rocket.Chat capabilities over the Realtime API.
Chat type semantics (Slack-aligned):
- DMs: 1:1 conversations (no mention requirement by default; gated by
dmPolicy) - Group chats: any multi-user room (public channels + private groups)
- mention-gated by default
- gated by group policy + allowlists (Slack-style defaults)
Draft mapping:
- Identity mapping: Rocket.Chat users <-> OpenClaw authors
- Rooms/channels: Rocket.Chat rooms <-> OpenClaw channel targets
- Threads/replies: follow Slack-style reply controls (reply-to mode + thread session keys)
- Attachments: deferred until explicitly specified (v1 supports plain text only)
- Edits/deletes: parity with Slack channel behavior
- Reactions: v1 supports reaction add/remove (Slack parity)
Deliverables
- An OpenClaw channel plugin for Rocket.Chat.
- Minimal installation/configuration steps.
Provisioning assumptions (v1):
- One Rocket.Chat bot user per OpenClaw agent id.
- Admin provides per-bot credentials/config into OpenClaw:
serverUrluserIdusername(for mention gating)pat(personal access token)
- Room allowlists accept room ids and/or room names; names are resolved to ids at startup when possible (Slack-style).
Compatibility Targets (Slack-parity)
Slack parity is the reference for how features should behave when implemented. For v1, this spec is explicit about what is in-scope vs deferred.
- Reference behavior: https://docs.openclaw.ai/channels/slack
V1 required support (MUST):
- Inbound: new messages (DMs + group chats), mention-gating in group chats
- Outbound: send text, reply in thread when inbound is threaded
- Reactions: reaction add/remove
- Commands: minimal prefix commands in-message (see below)
Deferred until explicitly specified (NOT v1):
- Edits
- Deletes
- Attachments (beyond plain text)
When we add any deferred item, it must match Slack semantics unless Rocket.Chat cannot represent it.
Commands (v1)
We intentionally do not use Rocket.Chat slash commands.
- Syntax: prefix
!at the start of the message (after trim)- Examples:
!status,!model g5.2,!stop
- Examples:
- Parsing precedence:
- If the trimmed message starts with
!, treat it as a command; do not send the command text to the model. - Otherwise treat as normal chat content.
- If the trimmed message starts with
Authorization model:
- Baseline gating (all commands): the sender must already be authorized for this room/DM by the normal channel policy (room allowlist + group policy + user allowlists / dmPolicy).
- Risky commands are more restricted:
!status: allowed for any authorized sender.!modeland!stop: allowed only for command operators.
Command operators (v1):
- Explicit allowlist per Rocket.Chat account (Slack-style).
- If
commandAllowFromis unset/empty, default is deny for!model+!stopin group chats.
Reply target:
- Reply publicly in the same room/thread (no DM fallback).
Semantics:
!status-> OpenClaw/status!model <name>-> OpenClaw/model <name>(accept aliases +provider/model)!stop-> OpenClaw/stop- Reference: https://docs.openclaw.ai/tools/slash-commands
Milestones (Draft)
- Event ingestion: new message events from allowlisted Rocket.Chat rooms arrive in OpenClaw
- Routing: inbound messages route to the OpenClaw agent represented by the bot account that was mentioned/DM'd
- Outbound send: OpenClaw can post messages into Rocket.Chat (thread replies supported)
- Parity pass (post-v1): edits, deletes, attachments
- Operational hardening: retries, idempotency, observability
Open Questions
These block finalizing the interface and auth model:
- Rocket.Chat Realtime API scope: which subscription streams cover all Slack-parity features (new messages, reactions, edits, deletes, pins/renames/membership if applicable)?
- Rocket.Chat thread model: what is the exact mapping between Rocket.Chat thread/reply metadata and OpenClaw's
reply_to+ optional:thread:session keys (Slack-style semantics)? Default: reply in thread when inbound is threaded. - Rocket.Chat mention semantics: confirm how mention metadata is exposed on Realtime API payloads (preferred) vs requiring text scanning for
@<username>. - Slack-default access control mapping: mirror Slack's
dmPolicy,groupPolicy, allowlists, and mention gating defaults in Rocket.Chat.- Slack docs: https://docs.openclaw.ai/channels/slack
- Realtime API deprecation: Rocket.Chat docs mark DDP methods as deprecated/unreliable and recommend REST for new development; v1 accepts this risk because Rocket.Chat upgrades are controlled (target version 8.2.0).
- Realtime API doc: https://developer.rocket.chat/apidocs/realtimeapi
Development Notes
- Keep top-level spec in this
README.md. - If/when the spec becomes too large, create a
specs/directory with focused documents (auth, message model, retry/idempotency, etc.).
