Skip to main content
OpenFang connects to messaging platforms through 40 channel adapters, allowing users to interact with agents across every major communication platform. All adapters share common features: graceful shutdown, exponential backoff, secret zeroization, automatic message splitting, per-channel overrides, DM/group policies, rate limiting, and output formatting.

All 40 Supported Channels

Core Messaging (7)

Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email

Enterprise (8)

Microsoft Teams, Mattermost, Google Chat, Webex, Feishu/Lark, Rocket.Chat, Zulip, XMPP

Social (8)

LINE, Viber, Facebook Messenger, Mastodon, Bluesky, Reddit, LinkedIn, Twitch

Community (6)

IRC, Guilded, Revolt, Keybase, Discourse, Gitter

Privacy (3)

Threema, Nostr, Mumble

Workplace (4)

Pumble, Flock, Twist, DingTalk

Notification (2)

ntfy, Gotify

Integration (2)

Webhook (Generic HTTP), Nextcloud Talk

Quick Start — Core Channels

Prerequisites

Setup

  1. Open Telegram and message @BotFather
  2. Send /newbot and follow the prompts
  3. Copy the bot token
export TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz

Configuration

[channels.telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
default_agent = "assistant"
# Optional: restrict to specific user IDs
# allowed_users = ["123456789"]

[channels.telegram.overrides]
# Telegram-native HTML formatting
output_format = "telegram_html"
group_policy = "mention_only"

How It Works

Long-polling via getUpdates API. Polls every few seconds with 30-second timeout. Messages from authorized users route to the configured agent. Responses sent via sendMessage API. Long messages automatically split at Telegram’s 4096-character limit.

Channel Configuration

All channels are configured in ~/.openfang/config.toml under the [channels] section:
[channels.telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
default_agent = "assistant"
allowed_users = ["123456789"]

[channels.discord]
bot_token_env = "DISCORD_BOT_TOKEN"
default_agent = "coder"

[channels.slack]
bot_token_env = "SLACK_BOT_TOKEN"
app_token_env = "SLACK_APP_TOKEN"
default_agent = "ops"

Common Configuration Fields

bot_token_env
string
required
Environment variable holding the bot/access token. All secrets stored as Zeroizing<String> and wiped from memory on drop.
default_agent
string
Agent name or ID that receives messages when no specific routing applies.
allowed_users
array
Optional list of platform user IDs allowed to interact. Empty means allow all.
overrides
object
Per-channel behavior overrides (see Channel Overrides section below).

Channel Overrides

Customize agent behavior per channel without modifying agent manifests:
[channels.telegram.overrides]
model = "gemini-2.5-flash"              # Override LLM model
system_prompt = "Brief responses only"  # Override system prompt
dm_policy = "respond"                   # How to handle DMs
group_policy = "mention_only"           # How to handle group messages
rate_limit_per_user = 10                # Max messages per minute per user
threading = true                        # Send replies as threads
output_format = "telegram_html"         # Output format for this channel
usage_footer = "compact"                # Usage info display

Override Fields

model
string
Override the LLM model for this channel. Uses agent’s default if not set.
system_prompt
string
Override the system prompt for this channel.
dm_policy
string
default:"respond"
How to handle direct messages:
  • respond — Respond to all DMs (default)
  • allowed_only — Only respond to DMs from users in allowed_users
  • ignore — Silently drop all DMs
group_policy
string
default:"mention_only"
How to handle group/channel messages:
  • all — Respond to all messages in the group
  • mention_only — Only respond when bot is @mentioned (default)
  • commands_only — Only respond to /command messages
  • ignore — Ignore all group messages
rate_limit_per_user
number
default:0
Max messages per minute per user. 0 = unlimited. Uses sliding-window rate limiter.
threading
boolean
default:false
Send replies as thread responses on platforms that support it (Slack, Discord, etc.).
output_format
string
default:"markdown"
Output format for this channel:
  • markdown — Standard Markdown (default)
  • telegram_html — Telegram HTML subset (<b>, <i>, <code>)
  • slack_mrkdwn — Slack mrkdwn format (*bold*, _italic_, `code`)
  • plain_text — No formatting markup
Override usage footer mode for this channel: off, tokens, cost, or full.

Output Formatter

The formatter converts Markdown output from the LLM into platform-native formats:
Standard Markdown passed through as-is. Works on most platforms.

Rate Limiting

Per-user rate limiting uses a sliding-window algorithm. When rate_limit_per_user is set, the limiter tracks message counts per user. Excess messages receive a polite rejection. Rate limits are enforced before messages reach the agent loop, consuming zero LLM tokens.

DM and Group Policies

Policy enforcement happens in dispatch_message() before messages reach the agent:

DM Policy Behavior

PolicyBehavior
respondRespond to all DMs (default)
allowed_onlyOnly respond to DMs from users in allowed_users
ignoreSilently drop all DMs

Group Policy Behavior

PolicyBehavior
allRespond to every message in the group
mention_onlyOnly respond when bot is @mentioned (default)
commands_onlyOnly respond to /command messages
ignoreSilently ignore all group messages
Ignored messages consume zero LLM tokens since they’re filtered before reaching the agent.

Enterprise Channels

Protocol: Bot Framework v3 webhook + OAuth2Environment Variables:
  • TEAMS_APP_ID — Azure Bot App ID
  • TEAMS_APP_PASSWORD — Azure Bot Framework app password
Configuration:
[channels.teams]
app_id = ""
app_password_env = "TEAMS_APP_PASSWORD"
webhook_port = 3978
allowed_tenants = []  # Empty = allow all
default_agent = "ops"
Protocol: WebSocket + REST v4Environment Variables:
  • MATTERMOST_TOKEN — Bot token
  • MATTERMOST_URL — Server URL
Configuration:
[channels.mattermost]
server_url = "https://mattermost.example.com"
token_env = "MATTERMOST_TOKEN"
allowed_channels = []  # Empty = all
default_agent = "assistant"
Protocol: Service account webhookEnvironment Variables:
  • GOOGLE_CHAT_SERVICE_ACCOUNT — Service account JSON key
Configuration:
[channels.google_chat]
service_account_env = "GOOGLE_CHAT_SERVICE_ACCOUNT"
space_ids = []  # Google Chat space IDs
webhook_port = 8444
default_agent = "assistant"
Environment Variables: WEBEX_BOT_TOKEN
[channels.webex]
bot_token_env = "WEBEX_BOT_TOKEN"
allowed_rooms = []
Environment Variables: FEISHU_APP_ID, FEISHU_APP_SECRET
[channels.feishu]
app_id = ""
app_secret_env = "FEISHU_APP_SECRET"
webhook_port = 8453

Social Platforms

Protocol: Streaming API WebSocket
[channels.mastodon]
instance_url = "https://mastodon.social"
access_token_env = "MASTODON_ACCESS_TOKEN"
default_agent = "social-media"
Protocol: AT Protocol WebSocket
[channels.bluesky]
identifier = "mybot.bsky.social"
app_password_env = "BLUESKY_APP_PASSWORD"
service_url = "https://bsky.social"
Protocol: OAuth2 polling
[channels.reddit]
client_id = ""
client_secret_env = "REDDIT_CLIENT_SECRET"
username = ""
password_env = "REDDIT_PASSWORD"
subreddits = []
Protocol: IRC gateway
[channels.twitch]
oauth_token_env = "TWITCH_OAUTH_TOKEN"
channels = ["mychannel"]
nick = "openfang"

Privacy-Focused Channels

Protocol: signal-cli REST/JSON-RPC
[channels.signal]
api_url = "http://localhost:8080"
phone_number = ""
allowed_users = []
Setup: Requires signal-cli running as a service

Agent Routing

The AgentRouter determines which agent receives incoming messages:
  1. Per-channel default — Each channel config has a default_agent field
  2. User-agent binding — Users previously associated with specific agents route to those agents
  3. Command prefix — Users can switch agents: /agent coder
  4. Fallback — Messages go to the first available agent

Environment Variables Reference

TELEGRAM_BOT_TOKEN
string
Telegram Bot API token from @BotFather
DISCORD_BOT_TOKEN
string
Discord bot token
SLACK_BOT_TOKEN
string
Slack bot token (xoxb-) for REST API
SLACK_APP_TOKEN
string
Slack app-level token (xapp-) for Socket Mode
WHATSAPP_ACCESS_TOKEN
string
WhatsApp Cloud API access token
WHATSAPP_VERIFY_TOKEN
string
Webhook verification token
MATRIX_ACCESS_TOKEN
string
Matrix homeserver access token
EMAIL_PASSWORD
string
Email account password or app password
TEAMS_APP_PASSWORD
string
Azure Bot Framework app password
MATTERMOST_TOKEN
string
Mattermost bot token
See full environment variable reference in configuration.md for all 40 channels.

Security

  • All secrets wrapped in Zeroizing<String> — wiped from memory on drop
  • Subprocess environment cleared with env_clear() — only whitelisted vars passed through
  • Webhook endpoints validate signatures (HMAC-SHA256) where supported
  • Rate limiting protects against abuse
  • Policy enforcement happens before agent loop — ignored messages consume zero LLM tokens

Build docs developers (and LLMs) love