Files
deer-flow/backend/docs/IM_CHANNEL_CONNECTIONS.md
T
2026-06-10 21:07:44 +08:00

4.0 KiB

IM Channel Connections

DeerFlow supports user-owned IM channel connections for Telegram, Slack, and Discord. A logged-in user connects a provider from the frontend, and incoming IM messages run under that DeerFlow user account instead of the raw platform user id.

Configuration

Enable the top-level channel_connections block in config.yaml:

channel_connections:
  enabled: true
  public_base_url: https://deerflow.example.com
  encryption_key: $DEER_FLOW_CHANNEL_CONNECTIONS_KEY

  telegram:
    enabled: true
    bot_token: $TELEGRAM_BOT_TOKEN
    bot_username: $TELEGRAM_BOT_USERNAME
    webhook_secret: $TELEGRAM_WEBHOOK_SECRET

  slack:
    enabled: true
    client_id: $SLACK_CLIENT_ID
    client_secret: $SLACK_CLIENT_SECRET
    signing_secret: $SLACK_SIGNING_SECRET
    event_delivery: http

  discord:
    enabled: true
    client_id: $DISCORD_CLIENT_ID
    client_secret: $DISCORD_CLIENT_SECRET
    bot_token: $DISCORD_BOT_TOKEN
    permissions: "274877975552"

public_base_url must be the externally reachable HTTPS origin used by provider callbacks and webhooks. encryption_key encrypts provider tokens at rest with Fernet. Keep it stable; v1 does not support transparent key rotation, so changing it requires users to reconnect.

Frontend Flow

The workspace sidebar shows a Channels group with Telegram, Slack, and Discord. Settings > Channels exposes the management surface for connect, disconnect, and reconnect. Browser state-changing calls use the existing CSRF-aware frontend fetch wrapper.

Provider Setup

Telegram:

  • Register a bot with BotFather.
  • Configure the bot username, bot token, and a random webhook secret.
  • Users connect with a deep link: https://t.me/<bot_username>?start=<state>.
  • Production webhook path: POST /api/channels/webhooks/telegram, protected by X-Telegram-Bot-Api-Secret-Token.
  • Local/self-hosted long polling still works through the existing Telegram channel worker.

Slack:

  • Create a Slack app with OAuth V2.
  • Redirect URL: https://<public_base_url>/api/channels/slack/callback.
  • Event request URL: https://<public_base_url>/api/channels/webhooks/slack/events.
  • Required signing secret: Slack's request signing secret, not the deprecated verification token.
  • Suggested MVP bot scopes: app_mentions:read, chat:write, channels:history, channels:read.
  • Slack events are signature-verified, deduplicated by event_id, and then routed to a matching user connection.

Discord:

  • Create a Discord application and bot.
  • Redirect URL: https://<public_base_url>/api/channels/discord/callback.
  • DeerFlow starts OAuth with identify guilds bot applications.commands and the configured bot permissions.
  • The Discord Gateway is still handled by discord.py; message content may require the privileged Message Content Intent depending on your bot setup.

Runtime Model

Connection records live in SQL tables under deerflow.persistence.channel_connections:

  • channel_connections: owner user, provider identity, workspace/guild/team, status, metadata.
  • channel_credentials: encrypted access/refresh/bot tokens.
  • channel_oauth_states: one-time OAuth/deep-link states.
  • channel_conversations: connection-scoped IM conversation to DeerFlow thread mapping.
  • channel_webhook_deliveries: provider webhook dedupe records.

Incoming messages that resolve to a connection carry connection_id, owner_user_id, and workspace_id. ChannelManager uses owner_user_id as the DeerFlow run user id and preserves the platform user id as channel_user_id. Legacy operator-owned channels keep the existing JSON ChannelStore behavior when no connection_id is present.

Security Notes

  • OAuth state tokens are one-time and short-lived.
  • Provider tokens are never returned from browser APIs.
  • Public callback/webhook routes bypass cookie auth only because they validate provider state/signatures/secrets themselves.
  • Slack and Telegram webhooks skip CSRF because they are called by providers, not browsers.
  • Logs should never include access tokens, refresh tokens, bot tokens, OAuth codes, or raw signed webhook bodies.