# Channel Messages The ZeroClaw messaging protocol is built around the `Channel` trait and a unified message format. This allows the system to treat disparate platforms—from Discord to Slack to SMS—as a consistent stream of `ChannelMessage` objects. *** ## Channel Trait The `Channel` trait is the core abstraction for all platform implementations. It defines how the system interacts with a specific messaging service. ```rust #[async_trait] pub trait Channel: Send + Sync { /// Human-readable channel name fn name(&self) -> &str; /// Send a message through this channel async fn send(&self, message: &SendMessage) -> anyhow::Result<()>; /// Start listening for incoming messages (long-running) async fn listen(&self, tx: tokio::sync::mpsc::Sender) -> anyhow::Result<()>; /// Check if channel is healthy async fn health_check(&self) -> bool { true } /// Signal that the bot is processing a response (e.g. "typing" indicator). async fn start_typing(&self, _recipient: &str) -> anyhow::Result<()> { Ok(()) } /// Stop any active typing indicator. async fn stop_typing(&self, _recipient: &str) -> anyhow::Result<()> { Ok(()) } // ... draft and reaction methods } ``` *** ## Draft Update Protocol ZeroClaw implements a progressive "Draft" protocol designed for streaming LLM responses. Instead of sending multiple message fragments, platforms that support editing (Telegram, Discord, Slack) can update a single message in place as the response is generated. ### Protocol Methods * `supports_draft_updates()`: Returns true if the platform allows message editing. * `send_draft(&SendMessage)`: Sends the initial message and returns a platform-specific `message_id`. * `update_draft(recipient, message_id, text)`: Appends or replaces the content of the existing message. * `finalize_draft(recipient, message_id, text)`: Performs a final update, often used to apply markdown formatting or remove "typing" statuses. * `cancel_draft(recipient, message_id)`: Deletes the draft if the generation is aborted. This protocol significantly reduces notification noise on user devices and provides a much smoother "typing" experience during long generations. *** ## Reactions and Pinning ZeroClaw supports standard interactive elements across most platforms. ### Reactions * `add_reaction(channel_id, message_id, emoji)`: Adds a Unicode emoji reaction. * `remove_reaction(channel_id, message_id, emoji)`: Removes a previously added reaction. ### Pinning * `pin_message(channel_id, message_id)`: Pins a message to the channel. * `unpin_message(channel_id, message_id)`: Unpins a message. *** ## ChannelMessage Struct The `ChannelMessage` is the Data Transfer Object (DTO) for all incoming and outgoing communication. ```rust pub struct ChannelMessage { pub id: String, pub sender: String, pub reply_target: String, pub content: String, pub channel: String, pub timestamp: u64, /// Platform thread identifier (e.g. Slack `ts`, Discord thread ID). /// When set, replies should be posted as threaded responses. pub thread_ts: Option, } ``` *** ## SendMessage Builder Sending messages uses a builder pattern to handle optional fields like subjects and threading context. ```rust pub struct SendMessage { pub content: String, pub recipient: String, pub subject: Option, pub thread_ts: Option, } impl SendMessage { pub fn new(content: impl Into, recipient: impl Into) -> Self; pub fn with_subject(content: impl Into, recipient: impl Into, subject: impl Into) -> Self; pub fn in_thread(mut self, thread_ts: Option) -> Self; } ``` *** ## Platform Implementations ZeroClaw includes implementations for 26 platforms, including: * Slack, Discord, Telegram, Microsoft Teams * WhatsApp (Twilio/Meta), Signal, Matrix * Twilio SMS, SendGrid Email, Postmark * IRC, XMPP, Mattermost, Rocket.Chat * Custom Webhooks and WebSocket adapters *** ## Relevance to Luna Luna should adopt the `ChannelMessage` structure as its baseline message DTO in [[Core]]. The **Draft Update Protocol** is particularly critical for Luna's SignalR implementation. Rather than streaming raw text chunks to the frontend and letting the client manage the state, the SignalR hub can follow the `send_draft` / `update_draft` / `finalize_draft` flow. This ensures consistency between web clients and external messaging channels documented in [[Channels]]. The `SendMessage` builder pattern provides a clean API for Luna services to dispatch notifications without manually constructing complex JSON payloads.