Enterprise Channels

Enterprise collaboration platform integrations.


Microsoft Teams (sidecar)

Teams migrated from the in-process Rust adapter to a Python sidecar (librefang.sidecar.adapters.teams, stdlib-only). The in-process [channels.teams] config block is no longer recognised.

Prerequisites

  • A Microsoft Azure account with access to the Azure Bot Service
  • A registered Azure AD application with a client ID and secret
  • python3 on the daemon host (no third-party packages required)

Setup

  1. Go to the Azure Portal and create a new Bot Channels Registration (or Azure Bot resource).
  2. Under Configuration, note the Microsoft App ID.
  3. Go to Certificates & secrets and create a new client secret. Copy it immediately.
  4. In the Teams Admin Center, enable your bot for the organization or upload a custom app manifest.
  5. In the Teams portal Outgoing Webhook settings (or your bot's Channels config), grab the Security Token (base64) — it gates HMAC-SHA256 verification of every inbound activity.
  6. Add to config.toml:
[[sidecar_channels]]
name = "teams"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.teams"]
channel_type = "teams"
[sidecar_channels.env]
TEAMS_APP_ID = "00000000-0000-0000-0000-000000000000"
TEAMS_WEBHOOK_PORT = "8459"
# TEAMS_ALLOWED_TENANTS = "tenant-a,tenant-b"   # empty = all
  1. Put TEAMS_APP_PASSWORD (the client secret) + TEAMS_SECURITY_TOKEN in ~/.librefang/secrets.env (the dashboard's Channels page writes them there).
  2. In Azure Bot Channel configuration, set the messaging endpoint to your LibreFang sidecar URL — e.g. https://your-domain.com:8459/webhook.
  3. Restart the daemon.

How It Works

The sidecar runs its own webhook server (stdlib BaseHTTPRequestHandler), verifies inbound Authorization: HMAC <…> signatures against the base64-decoded TEAMS_SECURITY_TOKEN, and parses the Bot Framework activity JSON. Outbound replies acquire a bearer token via the OAuth2 client-credentials flow (cached with a 5-minute refresh buffer) and POST to {serviceUrl}/v3/conversations/{id}/activities. The per-conversation serviceUrl from the most-recent inbound is cached so replies hit the correct Microsoft region (an improvement over the Rust adapter, which always used the default smba.trafficmanager.net endpoint).


Mattermost (sidecar)

Mattermost migrated from an in-process Rust adapter to an out-of-process Python sidecar (librefang.sidecar.adapters.mattermost).

Prerequisites

  • A Mattermost server (self-hosted or cloud) with admin access
  • A bot account or personal access token
  • Python 3 with the librefang SDK installed (pip install -e sdk/python)

Setup

  1. In Mattermost, go to Integrations > Bot Accounts and create a new bot, or go to Account Settings > Security > Personal Access Tokens and generate a token.
  2. Copy the token and add it to ~/.librefang/secrets.env:
MATTERMOST_TOKEN=your-bot-token
  1. Declare the sidecar in ~/.librefang/config.toml:
[[sidecar_channels]]
name = "mattermost"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.mattermost"]
channel_type = "mattermost"
default_agent = "ops"
[sidecar_channels.env]
MATTERMOST_SERVER_URL = "https://mattermost.example.com"
# MATTERMOST_ALLOWED_CHANNELS = "ch-id-1,ch-id-2"    # optional, empty = all
# MATTERMOST_ACCOUNT_ID = "team-prod"                # optional, multi-bot routing
  1. Restart the daemon.

How It Works

The sidecar connects to the Mattermost server over WebSocket (wss://<host>/api/v4/websocket) and sends an authentication_challenge immediately after the upgrade handshake. It subscribes to posted events, deduplicates on post.id, and emits messages to the kernel over its stdio channel. Outbound messages use POST /api/v4/posts with the inbound root_id round-tripped so threaded replies stay in their thread.


Google Chat

Prerequisites

  • A Google Cloud project with the Google Chat API enabled
  • A service account key file (JSON)

Setup

  1. In the Google Cloud Console, enable the Google Chat API.
  2. Create a service account and download the JSON key file.
  3. Configure a Chat app in the Google Chat API settings, selecting the HTTP endpoint connection type. Set the endpoint URL to your LibreFang instance (e.g., https://your-domain.com:4545/channels/google_chat/webhook).
  4. Set environment variables:
export GOOGLE_CHAT_SA_KEY=/path/to/sa-key.json  # Environment variable
export GOOGLE_CHAT_SPACE=spaces/AAAA_BBBBBB
librefang vault set GOOGLE_CHAT_SA_KEY        # Encrypted vault (recommended)
librefang vault set GOOGLE_CHAT_SPACE
librefang config set-key google_chat          # .env file
# Or set via dashboard "Set API Key" button   # secrets.env
  1. Add to config (Google Chat runs as an out-of-process sidecar adapter, librefang.sidecar.adapters.google_chat):
[[sidecar_channels]]
name = "google_chat"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.google_chat"]
channel_type = "google_chat"
[sidecar_channels.env]
GOOGLE_CHAT_WEBHOOK_PORT = "8090"
# GOOGLE_CHAT_SPACE_IDS = "spaces/AAAA,spaces/BBBB"   # optional, empty = all spaces
# GOOGLE_CHAT_ACCOUNT_ID = "ops"                      # optional, multi-bot routing

GOOGLE_CHAT_SERVICE_ACCOUNT_JSON (the full JSON blob — not a path) belongs in ~/.librefang/secrets.env.

  1. Hot-reload (curl -X POST http://127.0.0.1:4545/api/channels/reload) or restart the daemon.

How It Works

The sidecar authenticates with the service account JSON and runs its own HTTP webhook server on GOOGLE_CHAT_WEBHOOK_PORT (default 8090). The Google Cloud Console Bot configuration messaging endpoint should point at https://<host>:<port>/webhook. Responses go back through the Google Chat REST API using the space and thread identifiers from each inbound message.


Webex (sidecar)

Prerequisites

Setup

Webex migrated to an out-of-process sidecar in v2026.5 (replaces the former in-process Rust adapter). The bot Bearer token belongs in ~/.librefang/secrets.env, not config.toml.

  1. Go to developer.webex.com and sign in.
  2. Navigate to My Webex Apps and create a new Bot.
  3. Copy the bot access token.
  4. Save the token in ~/.librefang/secrets.env (the dashboard's Channels page does this for you):
WEBEX_BOT_TOKEN=your-webex-bot-token
  1. Declare the sidecar in config.toml:
[[sidecar_channels]]
name = "webex"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.webex"]
channel_type = "webex"
default_agent = "assistant"

[sidecar_channels.env]
# WEBEX_ALLOWED_ROOMS = "Y2lz...A,Y2lz...B"  # optional, empty = all rooms
# WEBEX_ACCOUNT_ID = "org-prod"              # optional, multi-bot routing
  1. Restart the daemon.

How It Works

The Webex sidecar (librefang.sidecar.adapters.webex) connects to Cisco's Mercury WebSocket gateway for real-time message activity, then fetches the full message body via the Webex REST API (GET /messages/<id>). Outbound replies are posted via POST /messages, optionally with parentId set to thread under the originating message (improvement over the Rust adapter, which never sent parentId). 429 responses on either side honour the Retry-After header and retry once.


Feishu / Lark

Feishu / Lark is provided by the Python sidecar adapter (librefang.sidecar.adapters.feishu). The in-process [channels.feishu] config block was removed in the sidecar migration. Declare Feishu/Lark as a [[sidecar_channels]] entry instead.

Prerequisites

  • A Feishu (or Lark) custom app with Bot capabilities (from the Feishu Open Platform)
  • python3 on the daemon host (no third-party Python packages required — the sidecar is stdlib-only)

Setup

  1. Go to the Feishu Open Platform and create a custom application.
  2. Enable Bot under the app's capabilities.
  3. Note the App ID and App Secret from the app credentials page.
  4. Add to config.toml:
[[sidecar_channels]]
name = "feishu"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.feishu"]
channel_type = "feishu"
[sidecar_channels.env]
FEISHU_APP_ID = "cli_abc123"
# FEISHU_REGION = "cn"                       # cn (default) or intl (Lark)
# FEISHU_RECEIVE_MODE = "websocket"          # websocket (default) or webhook
# FEISHU_WEBHOOK_PORT = "8453"               # webhook mode only
# FEISHU_VERIFICATION_TOKEN = "..."          # webhook mode only
# FEISHU_ENCRYPT_KEY = "..."                 # webhook mode only — AES-256-CBC payloads
# FEISHU_ACCOUNT_ID = "prod"                 # optional, multi-bot routing key
  1. Put FEISHU_APP_SECRET in ~/.librefang/secrets.env (the dashboard's Channels page writes it for you).
  2. Restart the daemon.

How It Works

The sidecar defaults to websocket mode: it discovers the real wss:// URL via POST /callback/ws/endpoint and opens a long-lived gateway connection (no public IP required). webhook mode listens on FEISHU_WEBHOOK_PORT and accepts both plaintext and AES-256-CBC + PKCS7 encrypted payloads (with FEISHU_ENCRYPT_KEY configured). Outbound replies go through POST /open-apis/im/v1/messages with a tenant access token cached and refreshed automatically (2-hour expiry with a 5-minute refresh buffer).

Processing-State Reactions

Feishu shows live "I'm working on it" feedback by adding a Typing reaction to the user's message on receive and removing it once the reply is sent. Both calls are fire-and-forget — API failures log a warning but never block message processing. See Reactions and Processing State on the channels overview.

@Mention Preservation

The sidecar substitutes each @_user_N placeholder with @<display-name> resolved from the mention payload (falling back to open_id when name is absent), and rewrites @_all to @all. Agents see the original conversational text — "@alice can you check this?" — instead of bare punctuation. See Feishu @Mention Preservation.


Rocket.Chat

Rocket.Chat is provided by the Python sidecar adapter (librefang.sidecar.adapters.rocketchat). The in-process [channels.rocketchat] config block was removed in the sidecar migration. Declare Rocket.Chat as a [[sidecar_channels]] entry instead.

Prerequisites

  • A Rocket.Chat server with admin access
  • A bot user account with a personal access token
  • Python 3.8+ on the daemon host (the sidecar runs as python3 -m librefang.sidecar.adapters.rocketchat)

Setup

  1. In Rocket.Chat, go to Administration > Users and create a bot user (or pick an existing service account).
  2. Sign in as that bot and generate a personal access token via My Account > Personal Access Tokens. Note both the token and the bot's user ID.
  3. Add the sidecar entry to your config.toml:
[[sidecar_channels]]
name = "rocketchat"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.rocketchat"]
channel_type = "rocketchat"
[sidecar_channels.env]
ROCKETCHAT_SERVER_URL = "https://chat.example.com"
ROCKETCHAT_USER_ID = "abc123"
# ROCKETCHAT_CHANNELS = "GENERAL,room2"        # optional; empty = all joined
# ROCKETCHAT_ACCOUNT_ID = "prod"                # optional, multi-bot routing key
# ROCKETCHAT_POLL_INTERVAL_SECS = "2"           # optional, default 2, floor 1
  1. Put ROCKETCHAT_TOKEN (the personal access token) in ~/.librefang/secrets.env — the dashboard's Channels page writes it there when you fill the Rocket.Chat form.
  2. Restart the daemon.

How It Works

The sidecar polls GET /api/v1/channels.history per room at the configured interval (default 2 s) using X-Auth-Token / X-User-Id headers. Slash-command bodies (/cmd args) become Command events; everything else is plain text. Outbound replies go through POST /api/v1/chat.postMessage and thread correctly via tmid when the inbound message lived inside a thread (improvement over the former Rust adapter, which always replied at the room root).


Zulip

Zulip is provided by the out-of-process Python sidecar adapter librefang.sidecar.adapters.zulip. The in-process [channels.zulip] block was removed in the sidecar migration.

Prerequisites

  • A Zulip server account (cloud or self-hosted)
  • A bot created in Settings > Your bots (see Zulip API docs)

Setup

  1. In Zulip, go to Settings > Your bots and click Add a new bot.
  2. Choose Generic bot and create it.
  3. Note the bot's email address and API key.
  4. Declare the sidecar in your config:
[[sidecar_channels]]
name = "zulip"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.zulip"]
channel_type = "zulip"
[sidecar_channels.env]
ZULIP_SERVER_URL = "https://myorg.zulipchat.com"
ZULIP_BOT_EMAIL  = "bot-bot@myorg.zulipchat.com"
# ZULIP_STREAMS = "engineering, general"      # optional; empty = all subscribed
# ZULIP_ACCOUNT_ID = "prod"                   # optional, multi-bot routing key
  1. Put the bot's API key in ~/.librefang/secrets.env:
ZULIP_API_KEY=your-api-key
  1. Restart the daemon.

How It Works

The sidecar uses Zulip's event queue API for long-polling. At startup it calls GET /api/v1/users/me to discover the bot's stable user id, registers an event queue via POST /api/v1/register (narrowed to the configured ZULIP_STREAMS if set), then long-polls GET /api/v1/events until shutdown. Inbound messages are filtered by the bot's own user id (so renames don't break self-skip) and deduped by message.id (so a BAD_EVENT_QUEUE_ID re-register can't re-emit). Outbound responses go through POST /api/v1/messages, using cmd.thread_id as the target topic so replies land in the originating topic. 429 responses on any of the four REST paths honour Retry-After.