# Channel System The Channel System in OpenClaw is a highly decoupled messaging platform integration layer. It allows OpenClaw to interface with diverse services like WhatsApp, Telegram, Slack, and Discord through a unified set of interfaces while preserving platform-specific capabilities. *** ## Plugin-Per-Platform Pattern OpenClaw employs a strict plugin architecture where every supported messaging platform is a self-contained module located under `src/channels/plugins/`. This directory contains over 100 files, with each platform adapter implementing a standard set of interfaces defined in `types.plugin.ts` and `types.adapters.ts`. Key aspects of this pattern include: * **Isolation**: Each plugin maintains its own dependencies and platform-specific logic (e.g., the Telegram plugin handles its own bot API calls). * **Standardized Lifecycle**: Plugins implement `ChannelLifecycleAdapter` to manage startup, shutdown, and health checks. * **Feature-Based Opt-in**: Plugins advertise their capabilities (e.g., `threads`, `reactions`, `media`) via a `ChannelCapabilities` object, allowing the core to gracefully degrade or enhance features per-channel. *** ## Shared Registry & Helpers A centralized `registry.ts` manages all active channel plugins. Instead of hardcoding platform logic into the core, the registry provides a discovery mechanism for the system to interact with whatever plugins are currently loaded. ### Message Normalization Incoming raw messages from various platforms are normalized into a standard `MsgContext` before reaching the agent or session logic. This normalization ensures consistent handling of: * **Sender Identification**: Mapping platform-specific IDs to a common structure containing `SenderId`, `SenderName`, and `SenderUsername`. * **Thread Tracking**: Normalizing `ThreadId` and `ReplyToId` so the core can track conversations across platforms that represent threads differently (e.g., Slack's thread timestamps vs. Telegram's reply-to message IDs). * **Channel Metadata**: Attaching `Channel` (platform name) and `ChatType` (direct, group, or channel) to every inbound payload. ### Shared Utilities OpenClaw provides several helper modules that plugins use to reduce boilerplate: * `sender-identity.ts`: Validates and sanitizes sender metadata. * `chat-meta.ts`: Manages channel-level metadata like labels, blurbs, and documentation links. * `session-envelope.ts`: Handles the wrapping of messages for persistent storage. *** ## Access Control & Routing OpenClaw enforces security and session boundaries at the channel level. ### Allowlist-based Access The system uses an allowlist-based policy for each channel. The `allowlist-match.ts` and `allow-from.ts` utilities provide logic to verify if a specific sender or group is permitted to interact with the agent. This ties directly into [[Security]] policies, preventing unauthorized access before a session is even initialized. ### Session Routing Incoming messages are routed to specific sessions based on their origin: * **Direct Messages (DMs)**: Usually routed to a per-sender session. * **Group Chats**: Messages are routed to a session keyed by the group ID. * **Thread Binding**: `thread-bindings-policy.ts` determines if a message should stay within an existing session or trigger the creation of a child session. *** ## Channel-Specific Auth Authentication is delegated to the individual plugins through the `ChannelAuthAdapter`. Each platform handles its own credential requirements: * **Bot Tokens**: Simple token-based auth (Telegram, Discord). * **OAuth**: Flow-based authentication for user-level access (Slack, Matrix). * **QR Code Pairing**: Used by platforms like WhatsApp or Signal to link an existing account. The `ChannelSetupAdapter` provides a standardized `ChannelSetupInput` bag containing fields for `botToken`, `appToken`, `privateKey`, and more, which are then stored in the system's secure configuration. *** ## Relevance to Luna The OpenClaw channel system provides a blueprint for expanding Luna beyond its current CLI-only interface. Key lessons for [[Channels]]: * **Establish a Rich Normalized Type**: Before adding a second channel, Luna should define a robust internal message format. This prevents the core logic from becoming littered with "if platform is Discord" checks. * **Abstract Outbound Routing**: By defining a common `ChannelOutboundAdapter`, Luna can send messages to any platform using a unified API, even if the underlying delivery mechanism (WebSocket, HTTP POST, CLI print) varies wildly. Cross-references: [[Core]], [[Security]]