Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/openagen/zeroclaw/llms.txt

Use this file to discover all available pages before exploring further.

Every inbound and outbound message in ZeroClaw flows through the Channel trait. The trait normalises platform differences — polling vs. webhooks, threading models, typing indicators, reactions — so the agent orchestration layer never needs to know which platform it is talking on.

Channel trait

The trait lives at src/channels/traits.rs. Three methods are required; the rest have default no-op implementations you can override.
// Required methods
fn name(&self) -> &str;
async fn send(&self, message: &SendMessage) -> Result<()>;
async fn listen(&self, tx: mpsc::Sender<ChannelMessage>) -> Result<()>;

// Default implementations provided (override as needed):
// health_check()     — returns true by default
// start_typing()     — no-op
// stop_typing()      — no-op
// send_draft()       — no-op
// update_draft()     — no-op
// finalize_draft()   — no-op
// cancel_draft()     — no-op
// add_reaction()     — no-op
// remove_reaction()  — no-op
ChannelMessage carries a normalised message with fields id, sender, reply_target, content, channel, timestamp, and an optional thread_ts for platforms that support threading.

Built-in channels

CLI

Interactive terminal session. Polling (stdin read loop).

Telegram

Telegram Bot API. Polling via getUpdates with long-poll timeout.

Discord

Discord Bot. Polling via gateway websocket.

Slack

Slack Bot. Webhook or Socket Mode.

Mattermost

Mattermost Bot. Webhook delivery.

iMessage

iMessage via BlueBubbles or similar bridge. Polling.

Matrix

Matrix protocol. Polling via sync API.

Signal

Signal Messenger via signal-cli bridge. Polling.

WhatsApp

WhatsApp via WA Web bridge. Polling.

Linq

Linq messaging. Polling.

Email

IMAP/SMTP email channel. Polling.

IRC

IRC client. Polling via TCP connection.

Lark

Lark / Feishu. Webhook delivery.

DingTalk

DingTalk. Webhook delivery.

QQ

Tencent QQ. Polling.

Nostr

Nostr decentralised protocol. Relay polling.

Webhook

Generic inbound webhook endpoint. Push delivery via ZeroClaw gateway.

MQTT

MQTT broker subscription. Polling via broker keep-alive.

Nextcloud Talk

Nextcloud Talk. Polling.

WATI

WATI WhatsApp Business API. Webhook delivery.

ClawdTalk

ZeroClaw-native inter-agent channel.

Delivery modes

ModeHow it worksExamples
PollingZeroClaw calls the platform API on a timer or long-poll loopTelegram, Discord, Matrix, Signal, QQ, IRC, Email
Webhook / PushPlatform pushes events to ZeroClaw’s gateway serverSlack Socket Mode, Lark, DingTalk, WATI, generic Webhook
For webhook channels, the gateway server (src/gateway/) must be reachable from the platform. Use a tunnel (cloudflare, tailscale, ngrok, or custom) to expose a local instance.

Channel allowlist

Each channel supports an allowed_users list that gates which senders the agent will process. Messages from users not on the list are silently dropped in the listen loop before they reach the orchestration layer.
[channels.telegram]
bot_token     = "..."
allowed_users = ["alice", "bob"]   # Telegram usernames; empty = allow all
An empty allowed_users list means all senders are accepted. Always set explicit allowlists on internet-facing channels in production deployments.

CLI commands

zeroclaw channel list           # list configured channels and their status
zeroclaw channel start          # start listening on all enabled channels
zeroclaw channel doctor         # run health_check() on each channel and report results

Registering a new channel

1

Implement the Channel trait

Create your implementation file in src/channels/. Implement the three required methods: name(), send(), and listen().
use anyhow::Result;
use async_trait::async_trait;
use tokio::sync::mpsc;

pub struct MyChannel { /* your fields */ }

#[async_trait]
impl Channel for MyChannel {
    fn name(&self) -> &str { "my-channel" }

    async fn send(&self, message: &SendMessage) -> Result<()> {
        // deliver message.content to message.recipient
        Ok(())
    }

    async fn listen(&self, tx: mpsc::Sender<ChannelMessage>) -> Result<()> {
        // poll or subscribe; send ChannelMessage values to tx
        Ok(())
    }
}
2

Register in the channel factory

Add your channel to src/channels/mod.rs so it can be instantiated from config.
3

Add config keys

Add any required configuration fields to ChannelsConfig in src/config/schema.rs.
4

Write tests

Cover auth/allowlist enforcement and health_check with focused unit tests.
See Adding providers, channels, tools, and peripherals for the complete Channel trait signature and a full working example.

Build docs developers (and LLMs) love