Channels

32 production-ready adapters, all normalising inbound messages into the same InboundMessage shape. Every adapter implements connect(), send(target, text), disconnect(), and ping().

InboundMessage contract

Every adapter, regardless of platform, produces an InboundMessage with these fields:

python
@dataclass
class InboundMessage:
    channel:    str   # adapter name, e.g. "telegram"
    sender_id:  str   # platform-specific user identifier
    sender_name:str   # display name (best-effort)
    content:    str   # plain-text body
    raw:        dict  # original platform payload
    timestamp:  float # Unix epoch seconds
    reply_to:   str | None  # thread/reply context
    attachments:list  # [{type, url, name}]

All 32 adapters

AdapterConfig keyTransportAuth
Telegramtelegrampython-telegram-bot v21Bot token
Discorddiscorddiscord.py gateway WebSocketBot token
Slackslackslack-bolt Socket ModeBot + App token
WhatsAppwhatsappMeta Cloud API v19.0Phone number ID + access token
EmailemailIMAP (aioimaplib) + SMTP (aiosmtplib)IMAP/SMTP credentials
SMS / TwiliosmsTwiML webhookTwilio account SID + auth token
Microsoft TeamsteamsAzure Bot Framework OAuth2Azure app ID + secret
Google Chatgoogle_chataiohttp webhook + service account JWTGCP service account key
Matrixmatrixmatrix-nio sync_foreverHomeserver URL + access token
IRCircPure asyncio RFC1459/2812 over TLS 6697SASL PLAIN / NickServ
Signalsignalsignal-cli subprocess JSON-RPCRegistered phone number
MattermostmattermostWebSocket events API + REST v4Access token
MastodonmastodonMastodon.py streamingInstance URL + access token
Nextcloud TalknextcloudOCS v2 REST long-pollHTTP Basic Auth
Generic Webhookwebhookaiohttp POSTOptional HMAC-SHA256
WebSocket / RESTbuilt-inFastAPI built-inOptional API key
LINElineaiohttp webhookHMAC-SHA256 X-Line-Signature
Feishu / Larkfeishuaiohttp webhookApp ID + App Secret (tenant access token)
iMessage (BlueBubbles)imessageREST pollingBlueBubbles server password
Synology Chatsynologyaiohttp webhookVerification token
Nostrnostraiohttp WebSocket relaysecp256k1 keypair (NIP-04)
Twilio Voicetwilio_voiceTwiML webhook + asyncio.FutureHMAC-SHA1 X-Twilio-Signature
Zalo OAzaloaiohttp webhookHMAC-SHA256 X-ZAlo-Signature + OAuth2
WeChat Workwechat_workaiohttp webhook (plain-text)SHA1 URL verification + access token
QQ Botqqaiohttp webhookHMAC-SHA256 + op=13 challenge
Tlon / UrbittlonEyre HTTP API + SSESession cookie (POST /~/login)
Facebook MessengermessengerMeta Graph API v19.0 webhookHMAC-SHA256 X-Hub-Signature-256
Rocket.ChatrocketchatDDP WebSocket + REST v1SHA-256 password login
TwitchtwitchIRC-over-WebSocket (IRCv3 tags)OAuth2 bearer token
BlueskyblueskyAT Protocol XRPC pollingApp password
ViberviberREST + webhookHMAC-SHA256 X-Viber-Content-Signature
XMPP / Jabberxmppslixmpp asyncio-nativeSASL PLAIN / SCRAM-SHA-1

Telegram

Uses python-telegram-bot v21. Supports text, voice, photo, and document messages.

toml
[channels.telegram]
bot_token  = "ENV:TELEGRAM_BOT_TOKEN"
allowed_chat_ids = []   # empty = allow all

Discord

Uses discord.py v2 with gateway WebSocket. Requires message_content intent enabled in the Discord Developer Portal.

toml
[channels.discord]
bot_token     = "ENV:DISCORD_BOT_TOKEN"
allowed_guilds = []   # empty = all guilds

Slack

Uses slack-bolt in Socket Mode — no public URL required. Requires a Slack App with Socket Mode enabled and the chat:write + app_mentions:read scopes.

toml
[channels.slack]
bot_token = "ENV:SLACK_BOT_TOKEN"    # xoxb-...
app_token = "ENV:SLACK_APP_TOKEN"    # xapp-... (Socket Mode)

WhatsApp

Uses the Meta Cloud API v19.0 webhook. Supports text, image, audio, video, and interactive messages.

toml
[channels.whatsapp]
phone_number_id = "ENV:WA_PHONE_NUMBER_ID"
access_token    = "ENV:WA_ACCESS_TOKEN"
verify_token    = "ENV:WA_VERIFY_TOKEN"  # for webhook registration

Email

Polls IMAP with aioimaplib; sends via aiosmtplib. STARTTLS supported. Threads replies to the same email thread.

toml
[channels.email]
imap_host = "imap.gmail.com"
imap_port = 993
smtp_host = "smtp.gmail.com"
smtp_port = 587
username  = "ENV:EMAIL_USERNAME"
password  = "ENV:EMAIL_PASSWORD"
poll_interval_seconds = 30

SMS / Twilio

Receives inbound SMS via TwiML webhook; replies with Twilio Messaging API.

toml
[channels.sms]
account_sid = "ENV:TWILIO_ACCOUNT_SID"
auth_token  = "ENV:TWILIO_AUTH_TOKEN"
from_number = "+15551234567"

Microsoft Teams

Uses Azure Bot Framework with 24-hour OAuth2 token cache.

toml
[channels.teams]
app_id     = "ENV:TEAMS_APP_ID"
app_secret = "ENV:TEAMS_APP_SECRET"

Google Chat

HTTP endpoint bot. Service account OAuth2 — pure Python via cryptography + httpx, no google-auth dependency. Token cached with 60s pre-expiry buffer. Supports space targets (spaces/<ID>) and threaded replies (spaces/<ID>/threads/<THREAD_ID>).

toml
[channels.google_chat]
service_account_json = "ENV:GOOGLE_SERVICE_ACCOUNT_JSON"  # base64-encoded JSON
verification_token   = "ENV:GOOGLE_CHAT_TOKEN"

Matrix

Uses matrix-nio with async sync_forever. Auto-joins rooms on invite.

toml
[channels.matrix]
homeserver   = "https://matrix.org"
access_token = "ENV:MATRIX_ACCESS_TOKEN"

IRC

Pure asyncio RFC1459/2812 implementation. TLS on port 6697. SASL PLAIN authentication. Auto-reconnect on disconnect.

toml
[channels.irc]
host     = "irc.libera.chat"
port     = 6697
nick     = "neuralcleave-bot"
password = "ENV:IRC_NICKSERV_PASSWORD"
channels = ["#general", "#dev"]

Signal

Delegates to a running signal-cli subprocess over JSON-RPC. Supports group messages.

toml
[channels.signal]
phone_number    = "+15551234567"  # registered Signal number
signal_cli_path = "/usr/bin/signal-cli"

LINE

HMAC-SHA256 X-Line-Signature verification. Push-message API for outbound — no replyToken window restriction. Supports direct user, group, and room targets. bot_user_id echo-loop guard.

toml
[channels.line]
channel_access_token = "ENV:LINE_CHANNEL_ACCESS_TOKEN"
channel_secret       = "ENV:LINE_CHANNEL_SECRET"
bot_user_id          = "ENV:LINE_BOT_USER_ID"

Feishu / Lark

Handles both v1 (legacy) and v2 (schema 2.0) event formats. URL verification challenge for webhook registration. Tenant access token cached with 60s pre-expiry buffer. Supports open_id, chat_id, user_id, and union_id targets.

toml
[channels.feishu]
app_id     = "ENV:FEISHU_APP_ID"
app_secret = "ENV:FEISHU_APP_SECRET"
bot_open_id = "ENV:FEISHU_BOT_OPEN_ID"   # for echo-loop prevention

iMessage (BlueBubbles)

REST polling against a self-hosted BlueBubbles server on macOS. Polls /api/v1/message?after=<ms>. Outbound via POST /api/v1/message/text. Supports direct (iMessage;-;phone), Apple ID email, SMS fallback, and group chat targets.

toml
[channels.imessage]
server_url = "http://your-mac-ip:1234"
password   = "ENV:BLUEBUBBLES_PASSWORD"
bot_handle = "+15551234567"   # your iMessage handle for echo-loop prevention

Synology Chat

Receives via aiohttp outgoing webhook. Sends via SYNO.Chat.External entry.cgi API. Supports user:{id}, channel:{id}, and bare integer string targets. SSL verify=False for self-signed NAS certificates.

toml
[channels.synology]
server_url        = "https://192.168.1.100:5001"
incoming_token    = "ENV:SYNOLOGY_INCOMING_TOKEN"
bot_username      = "neuralcleave"

Nostr

Connects to Nostr relays via aiohttp WebSocket. NIP-04 encrypted DMs (kind 4). Pure-Python secp256k1 + BIP-340 Schnorr — no extra pip dependencies. ECDH + AES-256-CBC encryption. Multi-relay broadcast with reconnect.

toml
[channels.nostr]
private_key = "ENV:NOSTR_PRIVATE_KEY"   # hex-encoded secp256k1 private key
relays      = ["wss://relay.damus.io", "wss://nos.lol"]

Twilio Voice

Multi-turn voice conversations via asyncio.Future bridging. Answers calls with a greeting + <Gather input="speech">. On each transcription, dispatches an InboundMessage and awaits an AI response. The response is wrapped in <Say> TwiML and followed by a new <Gather> for the next turn. All TwiML output is HTML-escaped.

toml
[channels.twilio_voice]
account_sid      = "ENV:TWILIO_ACCOUNT_SID"
auth_token       = "ENV:TWILIO_AUTH_TOKEN"
response_timeout = 10   # seconds to wait for AI response per turn

Zalo OA

HMAC-SHA256 X-ZAlo-Signature verification. Access token management via oauth.zaloapp.com/v4/oa/access_token with 60s pre-expiry buffer and in-memory refresh-token rotation. Outbound via Zalo OA v3 Customer Service Message API. Supports text, image, sticker, file, audio, video events.

toml
[channels.zalo]
app_id        = "ENV:ZALO_APP_ID"
app_secret    = "ENV:ZALO_APP_SECRET"
refresh_token = "ENV:ZALO_REFRESH_TOKEN"
oa_id         = "ENV:ZALO_OA_ID"

WeChat Work (WeCom)

Webhook in plain-text mode. GET URL challenge via SHA1(sort(token, timestamp, nonce)). POST XML inbound (text/image/voice/video/file/location/link). Access token cached for 7200s with 60s buffer. Targets: touser:, toparty:, totag:, @all, or bare string.

toml
[channels.wechat_work]
corp_id     = "ENV:WECHAT_CORP_ID"
agent_id    = "ENV:WECHAT_AGENT_ID"
secret      = "ENV:WECHAT_SECRET"
token       = "ENV:WECHAT_TOKEN"
bot_userid  = "neuralcleave_bot"

QQ Bot

HMAC-SHA256 X-Signature-Ed25519 + X-Signature-Timestamp verification. op=13 URL challenge. Dispatches AT_MESSAGE_CREATE, C2C_MESSAGE_CREATE, GROUP_AT_MESSAGE_CREATE, DIRECT_MESSAGE_CREATE events. Mention stripping. Access token cached 7200s with 60s buffer. Targets: channel:id, dm:guild_id, group:openid, c2c:openid.

toml
[channels.qq]
app_id      = "ENV:QQ_APP_ID"
client_secret = "ENV:QQ_CLIENT_SECRET"
bot_openid  = "ENV:QQ_BOT_OPENID"

Tlon / Urbit

Connects to a Tlon app on an Urbit ship via the Eyre HTTP API. Auth via POST /~/login → session cookie. SSE channel at PUT /~/channel/{uid} with subscription to /updates. Parses both legacy {"text":"..."} and modern {"story":{"inline":[...]}} event formats. Send targets: ~ship (DM), ~host/channel (group), path:/raw/path.

toml
[channels.tlon]
ship_url  = "http://your-urbit-ship:8080"
password  = "ENV:URBIT_PASSWORD"
bot_ship  = "~sampel-palnet"

Facebook Messenger

Meta Graph API v19.0 webhook. HMAC-SHA256 X-Hub-Signature-256 verification. GET hub.challenge handshake. Supports text, image/audio/video attachments, and postback button events. page_id echo guard. Outbound via /me/messages with RESPONSE messaging type.

toml
[channels.messenger]
page_id          = "ENV:MESSENGER_PAGE_ID"
page_access_token = "ENV:MESSENGER_PAGE_ACCESS_TOKEN"
verify_token     = "ENV:MESSENGER_VERIFY_TOKEN"

Rocket.Chat

DDP WebSocket real-time API + REST v1. SHA-256 password digest login. stream-room-messages subscription. Ping/pong keepalive. Bot echo guard via userId. Thread reply support via tmid. Auto-reconnect (5s delay).

toml
[channels.rocketchat]
server_url = "https://your.rocketchat.server"
username   = "ENV:RC_USERNAME"
password   = "ENV:RC_PASSWORD"

Twitch

IRC-over-WebSocket (wss://irc-ws.chat.twitch.tv:443) with IRCv3 tags. Requests twitch.tv/tags + twitch.tv/commands capabilities for structured metadata (display-name, user-id, tmi-sent-ts, message ID). Auto-reconnect with configurable delay. ping() validates OAuth token via GET id.twitch.tv/oauth2/validate.

toml
[channels.twitch]
oauth_token  = "ENV:TWITCH_OAUTH_TOKEN"   # oauth:... prefix stripped automatically
bot_nick     = "neuralcleave_bot"
channels     = ["#yourchannel"]

Bluesky (AT Protocol)

Polls app.bsky.notification.listNotifications every 30s (configurable). App-password auth with com.atproto.server.createSession. JWT auto-refresh on 401 via refreshSession. Posts via com.atproto.repo.createRecord. Threaded reply support. Echo guard via DID. Configurable notify_types filter.

toml
[channels.bluesky]
handle      = "yourbot.bsky.social"
app_password = "ENV:BLUESKY_APP_PASSWORD"
poll_interval_seconds = 30

Viber

REST + webhook. Registers bot via chatapi.viber.com/pa/set_webhook on connect(). HMAC-SHA256 X-Viber-Content-Signature. Supports text, picture, video, file, contact, url, sticker, subscribed, conversation_started events. 7,000-char send limit enforced.

toml
[channels.viber]
auth_token   = "ENV:VIBER_AUTH_TOKEN"
webhook_url  = "https://your-public-url/viber/webhook"
bot_name     = "NeuralCleave"

XMPP / Jabber

slixmpp asyncio-native. 1:1 chat + MUC rooms (XEP-0045). XEP-0030 service discovery. XEP-0199 ping keepalive. SASL PLAIN + SCRAM-SHA-1. Echo guard via bare JID in 1:1, room nick in MUC. 30s connect timeout via asyncio.wait_for.

toml
[channels.xmpp]
jid      = "bot@jabber.example.com"
password = "ENV:XMPP_PASSWORD"
rooms    = ["general@conference.jabber.example.com"]
nick     = "NeuralCleave"

Mattermost

toml
[channels.mattermost]
server_url   = "https://your.mattermost.com"
access_token = "ENV:MATTERMOST_TOKEN"

Mastodon

toml
[channels.mastodon]
instance_url = "https://mastodon.social"
access_token = "ENV:MASTODON_ACCESS_TOKEN"
reply_visibility = "public"  # public | unlisted | private

Nextcloud Talk

toml
[channels.nextcloud]
server_url = "https://your.nextcloud.com"
username   = "ENV:NC_USERNAME"
password   = "ENV:NC_PASSWORD"

Generic Webhook

toml
[channels.webhook]
secret = "ENV:WEBHOOK_SECRET"   # optional HMAC-SHA256 verification
path   = "/webhook/inbound"

Built-in WebSocket / REST

The gateway itself exposes a WebSocket endpoint at /ws/chat and a REST endpoint at POST /api/v1/chat. These are always active and need no additional configuration. See REST API for the protocol details.