Channels are communication backends that connect Clawlet to various messaging platforms. Each channel handles receiving messages from users and sending responses back.
- Overview
- Available Channels
- Telegram Setup
- Discord Setup
- WhatsApp Setup
- Slack Setup
- Creating Custom Channels
- Configuration Reference
Channels form the interface between users and the AI agent. They:
- Receive Messages - Listen for incoming messages from the platform
- Convert Format - Transform platform-specific messages to internal format
- Publish to Bus - Send messages to the message bus for processing
- Send Responses - Deliver agent responses back to the platform
User Message -> Channel -> MessageBus -> AgentLoop -> Response
^ |
|____________________________________|
All channels extend BaseChannel:
class BaseChannel(ABC):
@property
@abstractmethod
def name(self) -> str:
"""Channel identifier (e.g., 'telegram', 'discord')"""
pass
@abstractmethod
async def start(self) -> None:
"""Start the channel (connect to platform)"""
pass
@abstractmethod
async def stop(self) -> None:
"""Stop the channel (disconnect from platform)"""
pass
@abstractmethod
async def send(self, msg: OutboundMessage) -> None:
"""Send a message to the platform"""
pass| Channel | Status | Features |
|---|---|---|
| Telegram | Stable | Bot API, commands, text, images |
| Discord | Stable | Guild messages, DMs, reactions |
| Beta | Business API, text, media | |
| Slack | Stable | Socket Mode, HTTP, threads, blocks |
- Create a bot via @BotFather
- Get your bot token
Add to ~/.clawlet/config.yaml:
channels:
telegram:
enabled: true
token: "${TELEGRAM_BOT_TOKEN}"Set the environment variable:
export TELEGRAM_BOT_TOKEN="your-bot-token-here"- Text Messages - Full support for text conversations
- Commands -
/startand other commands - Images - Receive and send images
- Groups - Works in group chats
clawlet agent --channel telegram| Issue | Solution |
|---|---|
| Bot not responding | Check token is correct |
| Rate limits | Telegram has limits; implement delays |
| Webhook vs Polling | Clawlet uses polling by default |
- Create a Discord application at Discord Developer Portal
- Create a bot user
- Get your bot token
- Enable Message Content Intent in Bot settings
Add to ~/.clawlet/config.yaml:
channels:
discord:
enabled: true
token: "${DISCORD_BOT_TOKEN}"
command_prefix: "!" # Optional, default: "!"Set the environment variable:
export DISCORD_BOT_TOKEN="your-bot-token-here"Discord requires an additional package:
pip install discord.py- Guild Messages - Messages in server channels
- Direct Messages - Private conversations
- Reactions - React to messages
- Slash Commands - Optional slash command support
- Threads - Reply in threads
Required intents:
- Message Content Intent
- Server Messages Intent
- Direct Messages Intent
clawlet agent --channel discord| Issue | Solution |
|---|---|
| "discord.py not installed" | Run pip install discord.py |
| Bot not seeing messages | Enable Message Content Intent |
| Permission errors | Check bot role permissions in server |
- WhatsApp Business Account - Required for API access
- Phone Number ID - From Meta Business Suite
- Access Token - System User token from Meta
- Verify Token - Custom string for webhook verification
Add to ~/.clawlet/config.yaml:
channels:
whatsapp:
enabled: true
phone_number_id: "${WHATSAPP_PHONE_NUMBER_ID}"
access_token: "${WHATSAPP_ACCESS_TOKEN}"
verify_token: "${WHATSAPP_VERIFY_TOKEN}"
allowed_users: [] # Optional: restrict to specific numbers- Go to Meta Business Suite
- Create a WhatsApp Business Account
- Add a phone number
- Create a System User with WhatsApp permissions
- Generate an access token
WhatsApp requires a publicly accessible webhook endpoint:
- Deploy Clawlet with a public URL (or use ngrok for testing)
- Configure webhook URL in Meta dashboard:
https://your-domain.com/webhook/whatsapp - Verify token must match your configuration
- Text Messages - Send and receive text
- Media Messages - Images, documents, audio
- Mark as Read - Mark incoming messages as read
- Reply - Reply to specific messages
clawlet agent --channel whatsapp| Issue | Solution |
|---|---|
| Webhook verification failed | Check verify_token matches |
| Messages not received | Check webhook URL is accessible |
| Rate limits | WhatsApp has rate limits; implement backoff |
- Create a Slack App at api.slack.com
- Get your Bot Token (
xoxb-...) - Get your App-Level Token (
xapp-...) for Socket Mode - Subscribe to events in your app
Add to ~/.clawlet/config.yaml:
channels:
slack:
enabled: true
bot_token: "${SLACK_BOT_TOKEN}" # xoxb-...
app_token: "${SLACK_APP_TOKEN}" # xapp-... (for Socket Mode)
signing_secret: "${SLACK_SIGNING_SECRET}" # For HTTP mode
mode: "socket" # "socket" or "http"Slack requires additional packages:
pip install slack-bolt aiohttpSocket Mode connects via WebSocket - no public endpoint needed:
- Enable Socket Mode in your Slack app
- Generate an App-Level Token (
xapp-...) - Configure:
channels:
slack:
mode: "socket"
bot_token: "xoxb-..."
app_token: "xapp-..."HTTP mode requires a public endpoint:
channels:
slack:
mode: "http"
bot_token: "xoxb-..."
signing_secret: "..."
http_path: "/slack/events"
http_port: 3000Required OAuth scopes:
app_mentions:read- Read @mentionschannels:history- Read channel messageschat:write- Send messagesim:history- Read DMsim:write- Send DMsfiles:write- Upload files
- App Mentions - Respond when bot is mentioned
- Direct Messages - Private conversations
- Channel Messages - Messages in channels bot is in
- Thread Replies - Organized conversations
- Rich Formatting - Blocks and attachments
- File Sharing - Upload and share files
- Reactions - React to messages
clawlet agent --channel slack| Issue | Solution |
|---|---|
| "slack-bolt not installed" | Run pip install slack-bolt |
| Bot not responding | Check bot is invited to channel |
| Socket connection failed | Verify app_token is correct |
| Signature verification failed | Check signing_secret |
Create a custom channel by extending BaseChannel:
from clawlet.channels.base import BaseChannel
from clawlet.bus.queue import MessageBus, InboundMessage, OutboundMessage
class MyChannel(BaseChannel):
"""Custom channel implementation."""
def __init__(self, bus: MessageBus, config: dict):
super().__init__(bus, config)
# Initialize your channel
self.api_key = config.get("api_key")
@property
def name(self) -> str:
return "my_channel"
async def start(self) -> None:
"""Start the channel."""
# Connect to your platform
# Start listening for messages
# Start outbound loop
asyncio.create_task(self._run_outbound_loop())
async def stop(self) -> None:
"""Stop the channel."""
self._running = False
# Disconnect from platform
async def send(self, msg: OutboundMessage) -> None:
"""Send a message to the platform."""
# Implement sending logic
pass
async def _handle_incoming(self, data: dict):
"""Handle incoming message from platform."""
# Convert to InboundMessage
msg = InboundMessage(
channel=self.name,
user_id=data["user_id"],
content=data["text"],
metadata=data,
)
# Publish to message bus
await self._publish_inbound(msg)@dataclass
class InboundMessage:
channel: str # Channel name
user_id: str # Platform-specific user ID
content: str # Message text
metadata: dict # Additional data (attachments, etc.)@dataclass
class OutboundMessage:
channel: str # Target channel
user_id: str # Target user
content: str # Response text
metadata: dict # Additional dataRegister your channel in the channels module:
# clawlet/channels/__init__.py
def get_my_channel():
from .my_channel import MyChannel
return MyChannelAdd configuration support:
# config.yaml
channels:
my_channel:
enabled: true
api_key: "${MY_CHANNEL_API_KEY}"All channels support:
| Field | Type | Description |
|---|---|---|
enabled |
bool | Enable/disable the channel |
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | Yes | Bot token from BotFather |
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | Yes | Bot token |
command_prefix |
string | No | Command prefix (default: "!") |
| Field | Type | Required | Description |
|---|---|---|---|
phone_number_id |
string | Yes | Phone Number ID |
access_token |
string | Yes | System User access token |
verify_token |
string | Yes | Webhook verification token |
allowed_users |
list | No | Allowed phone numbers |
| Field | Type | Required | Description |
|---|---|---|---|
bot_token |
string | Yes | Bot token (xoxb-...) |
app_token |
string | Socket Mode | App token (xapp-...) |
signing_secret |
string | HTTP Mode | Signing secret |
mode |
string | No | "socket" or "http" (default: socket) |
http_path |
string | HTTP Mode | Webhook path |
http_port |
int | HTTP Mode | HTTP server port |
Run multiple channels simultaneously:
channels:
telegram:
enabled: true
token: "${TELEGRAM_BOT_TOKEN}"
discord:
enabled: true
token: "${DISCORD_BOT_TOKEN}"All enabled channels will be started when the agent runs.
- Multi-Agent Documentation - Route messages to different agents
- Webhooks Documentation - Receive external events
- Quick Start Guide - Get started quickly