Skip to content

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.

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 = false

message_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.

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:

ChannelsAllowlist field
Telegram, Discord, Slack, Mattermost, Matrix, IRC, Lark, Feishu, DingTalk, QQ, Nextcloud Talk, WeCom, Mochat, Twitterallowed_users
Signalallowed_from
WhatsApp (Cloud API & Web), WATIallowed_numbers
Email, Linq, Gmail Pushallowed_senders
iMessageallowed_contacts
Nostrallowed_pubkeys
ClawdTalkallowed_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 senders

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.
ChannelReceive modePublic inbound port?
Telegramlong-pollingNo
DiscordGateway WebSocketNo
SlackSocket Mode / pollingNo
MattermostREST pollingNo
Matrixsync APINo
Signalsignal-cli SSE bridgeNo
IRCTLS socketNo
Email (IMAP)IMAP IDLENo
WhatsApp Cloud APIwebhook (push)Yes
WATIwebhook (push)Yes
Nextcloud Talkwebhook (push)Yes
Linqwebhook (push)Yes
Gmail PushPub/Sub webhookYes
Generic WebhookHTTP serverUsually 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.

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.

  1. Add the channel. Include a name so 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"}'
  2. 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_user
    revka channel bind-telegram 123456789

    For other platforms, edit the channel’s allowlist field in config.toml (for example allowed_users, allowed_numbers, or allowed_senders).

  3. Verify the configuration. Run the channel health checks before starting:

    Terminal window
    revka channel doctor
  4. Start the channels (or start the full runtime with revka daemon):

    Terminal window
    revka channel start
  5. Send a test message to your bot from the platform. If you used mention_only = false and 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.

revka channel manages communication channels from the CLI. The subcommands:

SubcommandWhat it does
revka channel listList all configured channels
revka channel startStart all configured channels
revka channel doctorRun 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
Terminal window
revka channel list
revka channel add discord '{"bot_token":"...","name":"my-discord"}'
revka channel remove my-bot

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:

Terminal window
revka channel send 'Someone is near your device.' --channel-id telegram --recipient 123456789

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_provider
  • default_model
  • default_temperature
  • api_key / api_url
  • reliability.* (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.

On channels that accept text commands (such as Telegram and Discord), allowlisted users can steer the session inline:

CommandEffect
/modelsShow available providers
/models <provider>Switch provider for the current session
/modelShow the current model
/model <model-id>Switch model for the current session
/newClear conversation history and start fresh
  • 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 start or restart the daemon.
  • Health looks wrong. Run revka channel doctor for per-channel health checks, and revka doctor for full system diagnostics.