Connect a messaging channel
Channel concepts, allowlist semantics, polling vs webhook delivery, and how to add your first channel.
A channel is how your agent reaches people on a messaging platform — Telegram, Discord, Slack, Matrix, WhatsApp, email, and more. Each one runs under the daemon, listens for inbound messages, applies an allowlist, and sends the agent’s replies back over the platform’s API. This guide explains the channel model, the deny-all allowlist default you must understand before going live, the difference between polling and webhook delivery, and the revka channel commands that add, inspect, and drive a channel. Use it to connect your first channel from the CLI.
For per-platform setup walkthroughs, see Set up Telegram & Matrix and Set up Mattermost & Nextcloud Talk, or the full Channels overview and its catalog. To run the host process that channels live in, start with Run the dashboard.
Channels overview
Section titled “Channels overview”Every channel is configured under the [channels_config] namespace in ~/.revka/config.toml and managed by the channel supervisor when the daemon runs. The supervisor gives each channel per-sender conversation history, concurrent message processing, and automatic exponential-backoff reconnection.
Channels run inside revka daemon (gateway + channels + heartbeat + cron). You can also start the configured channels on their own with revka channel start. They do not run under a bare revka gateway, which serves only the dashboard and API.
A minimal Telegram channel block looks like this:
[channels_config]message_timeout_secs = 300
[channels_config.telegram]bot_token = "1234567890:ABCDEFabcdef-your-token"allowed_users = ["myusername"]stream_mode = "off"mention_only = falsemessage_timeout_secs (default 300) is the base per-message timeout; it scales with tool-loop depth up to [pacing].message_timeout_scale_max (default 4). Common per-channel fields you will see across platforms include bot_token/api_key, an allowlist field (see below), mention_only, stream_mode, and proxy_url. The exact keys for each platform are documented in Config: channels, tools & integrations and the per-channel catalog pages.
Allowlist semantics (deny all by default)
Section titled “Allowlist semantics (deny all by default)”This is the single most important channel concept: every channel allowlist defaults to an empty list, which means deny all. A freshly added channel will connect and listen, but it will ignore everyone until you explicitly add an identity. This is a security default — it prevents an unknown person who finds your bot from driving your agent.
The two special cases:
- Empty list
[]→ deny all (nobody is allowed). - Single entry
"*"→ allow all (any sender). Use this only when you understand the exposure.
The allowlist field is named differently per platform:
| Channels | Allowlist field |
|---|---|
| Telegram, Discord, Slack, Mattermost, Matrix, IRC, Lark, Feishu, DingTalk, QQ, Nextcloud Talk, WeCom, Mochat, Twitter | allowed_users |
| Signal | allowed_from |
| WhatsApp (Cloud API & Web), WATI | allowed_numbers |
| Email, Linq, Gmail Push | allowed_senders |
| iMessage | allowed_contacts |
| Nostr | allowed_pubkeys |
| ClawdTalk | allowed_destinations |
So a deny-all Discord channel and an allow-everyone one differ only by their allowed_users value:
[channels_config.discord]bot_token = "..."allowed_users = [] # deny all (default)
# vs.
[channels_config.discord]bot_token = "..."allowed_users = ["*"] # allow all sendersPolling vs webhook delivery
Section titled “Polling vs webhook delivery”Channels receive inbound messages in one of two ways, and the difference determines whether you need a public address.
- Polling / outbound-connection channels open the connection from Revka — long-polling, a WebSocket/gateway connection the bot dials out, or periodic REST polls. They work behind NAT and need no public inbound port. Telegram, Discord, Slack, Mattermost, Matrix, Signal, IRC, Bluesky, Reddit, and email (IMAP IDLE) all fall here.
- Webhook / push channels require the platform to POST events to you, so they need a public HTTPS callback URL that reaches the gateway. WhatsApp Cloud API, WATI, Nextcloud Talk, Linq, Gmail Push, and the generic webhook channel work this way.
| Channel | Receive mode | Public inbound port? |
|---|---|---|
| Telegram | long-polling | No |
| Discord | Gateway WebSocket | No |
| Slack | Socket Mode / polling | No |
| Mattermost | REST polling | No |
| Matrix | sync API | No |
| Signal | signal-cli SSE bridge | No |
| IRC | TLS socket | No |
| Email (IMAP) | IMAP IDLE | No |
| WhatsApp Cloud API | webhook (push) | Yes |
| WATI | webhook (push) | Yes |
| Nextcloud Talk | webhook (push) | Yes |
| Linq | webhook (push) | Yes |
| Gmail Push | Pub/Sub webhook | Yes |
| Generic Webhook | HTTP server | Usually yes |
If your platform needs a public callback, expose the gateway with a tunnel rather than binding it to a public address — see Expose your gateway with a tunnel and the Webhook ingress API reference. The full delivery-mode matrix for every platform lives in the Channels overview.
Add your first channel
Section titled “Add your first channel”The fastest path is revka channel add, which takes a channel type and a JSON config blob and writes it into config.toml. Supported types are telegram, discord, slack, whatsapp, matrix, imessage, and email.
-
Add the channel. Include a
nameso you can refer to it later. The allowlist still defaults to deny-all, so plan to add yourself next.Terminal window revka channel add telegram '{"bot_token":"123456:YOUR-TOKEN","name":"my-bot"}' -
Allow yourself. For Telegram there is a dedicated helper — pass either your username (without the
@) or your numeric user ID, and it is appended to the allowlist:Terminal window revka channel bind-telegram revka_userrevka channel bind-telegram 123456789For other platforms, edit the channel’s allowlist field in
config.toml(for exampleallowed_users,allowed_numbers, orallowed_senders). -
Verify the configuration. Run the channel health checks before starting:
Terminal window revka channel doctor -
Start the channels (or start the full runtime with
revka daemon):Terminal window revka channel start -
Send a test message to your bot from the platform. If you used
mention_only = falseand your identity is on the allowlist, the agent replies.
If you would rather be walked through token entry interactively, the onboarding wizard has a channels step, and revka onboard --channels-only re-runs just the channel-repair flow.
The revka channel command
Section titled “The revka channel command”revka channel manages communication channels from the CLI. The subcommands:
| Subcommand | What it does |
|---|---|
revka channel list | List all configured channels |
revka channel start | Start all configured channels |
revka channel doctor | Run health checks for all configured channels |
revka channel add <type> <config_json> | Add a channel (telegram, discord, slack, whatsapp, matrix, imessage, email) |
revka channel remove <name> | Remove a channel by its config name |
revka channel bind-telegram <identity> | Add a Telegram username (no @) or numeric user ID to the allowlist |
revka channel send <message> --channel-id <NAME> --recipient <TARGET> | Send a one-off message |
revka channel listrevka channel add discord '{"bot_token":"...","name":"my-discord"}'revka channel remove my-botSend a one-off message
Section titled “Send a one-off message”revka channel send delivers a single message through an already-configured channel without a conversation. --channel-id is the channel’s config name; --recipient is the platform-specific target (a chat ID, phone number, etc.). It is built for scripted notifications and automation pipelines — sensor alerts, cron job summaries, deploy notices:
revka channel send 'Someone is near your device.' --channel-id telegram --recipient 123456789Hot-reload
Section titled “Hot-reload”When channels are running, the channel runtime watches config.toml and reloads a specific set of keys on the next inbound message, with no daemon restart:
default_providerdefault_modeldefault_temperatureapi_key/api_urlreliability.*(retries and fallback providers)
This lets you swap the provider, model, or API key behind a live channel and have the change picked up on the next message. Other settings — including adding or removing a channel, or changing tokens and allowlists — are not hot-reloaded; restart the channels (revka channel start) or the daemon to apply them.
In-chat runtime commands
Section titled “In-chat runtime commands”On channels that accept text commands (such as Telegram and Discord), allowlisted users can steer the session inline:
| Command | Effect |
|---|---|
/models | Show available providers |
/models <provider> | Switch provider for the current session |
/model | Show the current model |
/model <model-id> | Switch model for the current session |
/new | Clear conversation history and start fresh |
Troubleshooting
Section titled “Troubleshooting”- The bot connects but never replies. Your sender is not on the allowlist. Remember the default is deny-all (
[]). Add your identity (revka channel bind-telegram <you>for Telegram, or edit the allowlist field) and restart the channel. - A webhook channel receives nothing. It needs a public HTTPS callback that reaches the gateway. Confirm the platform’s webhook URL points at your tunnel, not at
127.0.0.1. See Expose your gateway with a tunnel. - A config change isn’t taking effect. Only the hot-reload keys above apply on the next message. For anything else, run
revka channel startor restart the daemon. - Health looks wrong. Run
revka channel doctorfor per-channel health checks, andrevka doctorfor full system diagnostics.