Skip to content

Channels

Channels are communication plugins that connect assistants to different platforms. Each channel handles inbound messages from a platform, routes them to the appropriate assistant, and delivers responses back.

Available Channels

ChannelTypeDescription
Browser InternalBrowserIn-app chat for logged-in admin and staff users
Staff AccessBrowserStaff-specific chat experience
SlackMessagingDirect messages via a Slack bot
TelegramMessagingChat via a Telegram bot
PostmarkEmailSend and receive email via Postmark
WebRTCVoiceVoice conversations via OpenAI Realtime API
Web TriggerAPIHTTP trigger for external services (Zapier, Make, n8n)

The Embeddable Widget is a browser-based channel for external websites and has its own dedicated section.

Additional channel plugins may be available depending on your installation. Check the channels tab on your assistant for the full list.

How Channels Work

All inbound messages from channels flow through a generic webhook endpoint that routes by plugin name and assistant ID (e.g., /webhooks/channels/slack/42/inbound). New channel plugins get webhook routing automatically without changes to the routing layer.

Request Verification

Each channel plugin implements its own request verification. Slack uses HMAC signature verification (comparing a computed hash of the request body against the X-Slack-Signature header). Telegram uses a secret token comparison via X-Telegram-Bot-Api-Secret-Token. Unverified requests are rejected before any processing occurs.

Message Routing

The system uses two routing strategies depending on the channel type. Email-style channels embed a reply_token in reply-to addresses to match replies to existing conversations. Chat-style channels (like Telegram) use a channel_address (the sender’s chat ID) combined with the assistant ID to find or create conversations. Both strategies include deduplication by message ID to prevent double-processing from webhook retries.

Async Processing

After parsing and validation, the webhook handler dispatches message processing as an asynchronous background task and returns an immediate 200 response to the channel provider. This prevents timeout errors from providers that expect fast responses while the agent loop runs in the background.

One Conversation, Many Channels

Every message — both inbound from a user and outbound from the assistant — is stored in a canonical, channel-agnostic form. The agent doesn’t write Telegram-flavoured Markdown or Postmark-flavoured HTML; it produces a structured list of content blocks, and each channel converts that to whatever its medium needs at the moment of delivery.

The block kinds the system understands today are:

BlockUsed for
TextMarkdown prose. Renderers translate to channel-native formatting.
MediaImages, files, and audio attachments.
CardA rich content card (title, body, optional inline image and actions). Backed by a generated content row, so the same card can also appear on the assistant canvas.
Data tableStructured rows and columns (e.g. dataset query results).
ActionsButtons that the user can click to drive the conversation forward (see Interactive actions below).

Because the blocks are stored on the message itself, an exchange that happened over Telegram can be reopened in the browser with text, images, and action buttons all visible. A reply email can carry the same image attachment that arrived inline on Slack. There’s no per-channel rewriting pass — the content travels untouched between mediums.

What each channel renders natively

Channels do their best with what the medium supports and fall back gracefully where it doesn’t. The matrix below summarises the v1 rendering capability:

BlockBrowserPostmark emailTelegramSlackWebRTC voice
TextHTMLHTMLMarkdownV2mrkdwnTTS
Media (image)inline <img>MIME inlinesendPhotoimage blockspoken summary
Media (file)linkMIME attachmentsendDocumentfiles APIspoken summary
Cardrich cardHTML cardtext + photoBlock Kitspoken summary
Data tableHTML tableHTML tablemarkdown tableBlock Kit fieldsspoken summary
ActionsHTMX buttonsURL linksinline keyboardblock actionsspoken summary

A channel that doesn’t render a block kind natively falls back to a markdown rendering, so every block always reaches the recipient in some form.

Interactive actions

Assistants can present the user with a small set of buttons rather than asking for a free-text reply. Clicking a button is treated like a structured response: the channel routes the click back through a webhook, the conversation resumes from where it paused, and the agent receives the chosen option as the result of its question.

Action buttons render as native interactive controls where the channel supports them — Telegram inline keyboards, Slack Block Kit buttons, in-browser HTMX buttons. Where the channel can only carry text and links (email, voice transcripts), each option is rendered as a signed URL that resolves the same way when clicked. The agent’s prompt is identical regardless of which channel the user clicks from.

Configuring Channels on Assistants

Channels are enabled and configured per assistant. See Assistant Channel Configuration for details on enabling channels, setting access control, and managing feedback settings.

Want to add your own communication channel? See Channel Plugins for a guide to building custom channel plugins.