通道配置
所有内嵌通道适配器的配置、每通道行为覆盖以及 Sidecar 通道集成。
[channels]
所有内嵌通道适配器均在 [channels.<name>] 下配置。每个通道采用 Option<T> 类型——省略该节将完全禁用该适配器。即使只写了节头(内容为空),也会以默认值启用该适配器。
通用通道字段: 每个通道适配器除了自身特有的字段外,还支持以下通用字段:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
default_agent | string 或 null | null | 默认将消息路由到的 Agent 名称。 |
account_id | string 或 null | null | 当前 Bot 实例的唯一标识符。用于通过 [[bindings]] 匹配规则进行多 Bot 路由。 |
overrides | object | (默认值) | 每个通道的行为覆盖配置。详见通道行为覆盖。 |
Telegram
Telegram 现已改为 sidecar 模式。[channels.telegram] 配置块不再被接受(#5241 已移除内置适配器)。请改用 [[sidecar_channels]] 声明:
[[sidecar_channels]]
name = "telegram"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.telegram"]
channel_type = "telegram"
[sidecar_channels.env]
TELEGRAM_BOT_TOKEN = "..."
# ALLOWED_USERS = "111,@alice"
Sidecar 适配器保留了与原内置适配器相同的运行语义:TELEGRAM_BOT_TOKEN 环境变量、可选的 ALLOWED_USERS 允许列表、channel_type = "telegram" 以及 channel_role_mapping.telegram 的 RBAC 映射。详见下方 [[sidecar_channels]] 章节。
Rust 版本(自 #5831 起)。 Telegram sidecar 的第一方 Rust 移植在 sdk/rust/librefang-sidecar-telegram/——下列场景适合选 Rust 版:不想在宿主装 Python 运行时、关心 supervisor 每次重启的启动延迟、~3 MB 的剥离后二进制能省下足够镜像体积来抵掉多一步构建。
Wire 形状与访问控制语义与 Python 版字节等价,supervisor 区分不出来。
配置时把 command 换成 /abs/path/to/target/release/librefang-sidecar-telegram,复用同一套 TELEGRAM_BOT_TOKEN / ALLOWED_USERS 环境变量。
完整参考见 Rust Telegram sidecar 适配器。
Discord(sidecar)
Discord 已于 v2026.5 迁移为进程外 sidecar 适配器,请改用 [[sidecar_channels]] 配置。Sidecar 保留原内置适配器的运行语义:DISCORD_BOT_TOKEN 环境变量、Gateway Intents、allowed_guilds / allowed_users 过滤,以及通过 channel_role_mapping.discord 的 RBAC 映射。
[[sidecar_channels]]
name = "discord"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.discord"]
channel_type = "discord"
[sidecar_channels.env]
DISCORD_BOT_TOKEN = "..."
# DISCORD_ALLOWED_GUILDS = "123,456"
# DISCORD_ALLOWED_USERS = "789"
# DISCORD_INTENTS = "37376"
# DISCORD_IGNORE_BOTS = "true"
# DISCORD_MENTION_PATTERNS = "hey bot,!ask"
# DISCORD_ACCOUNT_ID = "guild-42"
完整的 supervisor 字段(restart、backoff、ready timeout、message buffer 等)参见下方 [[sidecar_channels]] 章节。
Slack(sidecar)
Slack 已于 v2026.5 迁移为进程外 sidecar 适配器,请改用 [[sidecar_channels]] 配置。Sidecar 保留原内置适配器的运行语义——Socket Mode WebSocket + Web API、SLACK_ALLOWED_CHANNELS 过滤(DM 豁免)、thread 回复上下文、Block Kit 交互回调、eyes / check 反应,以及通过 SLACK_ACCOUNT_ID 的多 Bot 路由。
[[sidecar_channels]]
name = "slack"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.slack"]
channel_type = "slack"
[sidecar_channels.env]
SLACK_APP_TOKEN = "xapp-..."
SLACK_BOT_TOKEN = "xoxb-..."
# SLACK_ALLOWED_CHANNELS = "C0123,C0456"
# SLACK_UNFURL_LINKS = "false"
# SLACK_FORCE_FLAT_REPLIES = "false"
# SLACK_REACTIONS = "true"
# SLACK_ACCOUNT_ID = "workspace-prod"
完整的 supervisor 字段(restart、backoff、ready timeout、message buffer 等)参见下方 [[sidecar_channels]] 章节。
WhatsApp(Sidecar)
WhatsApp 已从进程内 Rust 适配器迁移到 Python sidecar(librefang.sidecar.adapters.whatsapp,仅依赖标准库)。原 [channels.whatsapp] 块不再识别。sidecar 同时覆盖 Cloud API 和 Web/QR(Baileys)网关 两种模式。
Cloud API 模式(推荐生产使用):
[[sidecar_channels]]
name = "whatsapp"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.whatsapp"]
channel_type = "whatsapp"
[sidecar_channels.env]
WHATSAPP_PHONE_NUMBER_ID = "123456789012345"
WHATSAPP_WEBHOOK_PORT = "8460"
# WHATSAPP_WEBHOOK_PATH = "/webhook"
# WHATSAPP_ALLOWED_USERS = "+15551111,+15552222"
# WHATSAPP_ACCOUNT_ID = "production"
# WHATSAPP_DM_POLICY = "respond" # respond / allowed_only / ignore
# WHATSAPP_GROUP_POLICY = "all" # all / mention_only / commands_only / ignore
WHATSAPP_ACCESS_TOKEN、WHATSAPP_VERIFY_TOKEN(用于 Meta Webhook 订阅握手)、WHATSAPP_APP_SECRET(入站 X-Hub-Signature-256 的 HMAC 密钥)写入 ~/.librefang/secrets.env。sidecar 在 WHATSAPP_WEBHOOK_PORT(默认 8460)上自己跑 webhook server —— Meta 后台填的 Webhook 订阅 URL 变成 https://<host>:<WHATSAPP_WEBHOOK_PORT><WHATSAPP_WEBHOOK_PATH>。
原 Rust 适配器的 start()(whatsapp.rs:454-483)只是一个 TODO 桩——只 log "webhook ready",从未解析入站事件。sidecar 实现了真正的 handler,所以 Cloud API 入站现在不靠任何外部 forwarder 就能工作。
Web/QR 模式(个人号场景,无需 Meta 开发者账号):
[[sidecar_channels]]
name = "whatsapp"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.whatsapp"]
channel_type = "whatsapp"
[sidecar_channels.env]
WHATSAPP_GATEWAY_URL = "http://localhost:3009"
# WHATSAPP_ALLOWED_USERS = "+15551111,+15552222"
# WHATSAPP_ACCOUNT_ID = "personal"
Baileys 网关(@librefang/whatsapp-gateway,Node.js,监听 WHATSAPP_GATEWAY_URL)需要单独启动 —— kernel 不再内嵌或自动 spawn 它。入站消息由网关直接 POST 到 LibreFang REST API(POST /api/agents/{id}/message),绕过 sidecar;出站回复经 sidecar 路由到 {gateway_url}/message/send。
Signal(Sidecar)
Signal 已从进程内 Rust 适配器迁移到进程外 Python sidecar(librefang.sidecar.adapters.signal),后端通过独立运行的 signal-cli-rest-api 容器对接 signal-cli。原有 [channels.signal] 块不再识别 —— 改为声明 [[sidecar_channels]]:
[[sidecar_channels]]
name = "signal"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.signal"]
channel_type = "signal"
[sidecar_channels.env]
SIGNAL_API_URL = "https://signal-cli.example.com"
SIGNAL_NUMBER = "+15555550100"
# SIGNAL_ALLOWED_USERS = "+15555550199,+15555550200" # 可选
# SIGNAL_ACCOUNT_ID = "prod-bot" # 可选
# SIGNAL_POLL_INTERVAL_SECS = "2" # 可选
# SIGNAL_ALLOW_LOCAL = "1" # localhost 部署时显式放行
Sidecar 沿用 Rust 适配器相同的 SSRF 保护:SIGNAL_API_URL 必须解析到公网地址,除非显式设置 SIGNAL_ALLOW_LOCAL=1。可选的 SIGNAL_API_KEY 写入 ~/.librefang/secrets.env。
Matrix(Sidecar)
Matrix 已从进程内 Rust 适配器迁移到进程外 Python sidecar(librefang.sidecar.adapters.matrix),通过 Matrix Client-Server API 的 /sync 长轮询对接 homeserver。原有 [channels.matrix] 块不再识别 —— 改为声明 [[sidecar_channels]]:
[[sidecar_channels]]
name = "matrix"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.matrix"]
channel_type = "matrix"
[sidecar_channels.env]
MATRIX_HOMESERVER_URL = "https://matrix.org"
MATRIX_USER_ID = "@librefang:matrix.org"
# MATRIX_ALLOWED_ROOMS = "!abc:matrix.org,!def:matrix.org" # 可选
# MATRIX_ACCOUNT_ID = "prod-bot" # 可选
# MATRIX_MAX_UPLOAD_BYTES = "52428800" # 可选,默认 50 MiB
密钥放在 ~/.librefang/secrets.env:MATRIX_ACCESS_TOKEN(Bot 在 homeserver 上的 access token,与 Element 一致)。
Email(IMAP + SMTP,sidecar)
Email 现以 Python sidecar 适配器(librefang.sidecar.adapters.email)提供。原 in-process [channels.email] 配置块已被移除。请改为通过 [[sidecar_channels]] 条目声明 Email:
[[sidecar_channels]]
name = "email"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.email"]
channel_type = "email"
[sidecar_channels.env]
EMAIL_IMAP_HOST = "imap.gmail.com"
EMAIL_SMTP_HOST = "smtp.gmail.com"
EMAIL_USERNAME = "bot@example.com"
# EMAIL_IMAP_PORT = "993"
# EMAIL_SMTP_PORT = "587"
# EMAIL_POLL_INTERVAL_SECS = "30" # IMAP 轮询间隔
# EMAIL_FOLDERS = "INBOX" # 逗号分隔
# EMAIL_ALLOWED_SENDERS = "" # 精确地址或 @domain,逗号分隔
# EMAIL_ACCOUNT_ID = "prod" # 多 bot 路由标识
# EMAIL_TLS_ROOT_CA_PATH = "" # 额外信任的 CA 证书包(PEM)
# EMAIL_TLS_ACCEPT_INVALID_CERTS = "" # 临时调试用 escape hatch
EMAIL_PASSWORD(以及可选的分协议覆盖 EMAIL_IMAP_PASSWORD / EMAIL_SMTP_PASSWORD)写入 ~/.librefang/secrets.env——在仪表盘 Channels 页填写 Email 表单时会自动写入。sidecar 用 UID SEARCH UNSEEN UNKEYWORD Librefang-Quarantine 轮询 IMAP(服务器拒绝该关键字时退回 UNSEEN),先 LOGIN 再 AUTHENTICATE PLAIN 兼容只支持 SASL PLAIN 的服务器(Lark 等),通过 per-sender In-Reply-To + References 缓存做外发回复线程化。
Microsoft Teams(Sidecar)
Teams 已从进程内 Rust 适配器迁移到进程外 Python sidecar(librefang.sidecar.adapters.teams)。原有 [channels.teams] 块不再识别——改为声明 [[sidecar_channels]]:
[[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_WEBHOOK_PATH = "/webhook"
# TEAMS_ALLOWED_TENANTS = "tenant-a,tenant-b" # 留空允许全部
# TEAMS_ACCOUNT_ID = "production"
TEAMS_APP_PASSWORD(Bot Framework 客户端密钥)和 TEAMS_SECURITY_TOKEN(Teams 后台 outgoing-webhook 的 base64 token,用于校验每条入站请求的 HMAC-SHA256)写入 ~/.librefang/secrets.env。sidecar 监听自己的 webhook 端口(默认 8459),所以你在 Azure Bot Channel 配置里登记的公网 URL 从 https://<host>/channels/teams/webhook 改为 https://<host>:<TEAMS_WEBHOOK_PORT><TEAMS_WEBHOOK_PATH>。
Mattermost(Sidecar)
Mattermost 已从进程内 Rust 适配器迁移到进程外 Python sidecar(librefang.sidecar.adapters.mattermost)。原有 [channels.mattermost] 块不再识别 —— 改为声明 [[sidecar_channels]]:
[[sidecar_channels]]
name = "mattermost"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.mattermost"]
channel_type = "mattermost"
[sidecar_channels.env]
MATTERMOST_SERVER_URL = "https://mattermost.example.com"
# MATTERMOST_ALLOWED_CHANNELS = "ch-id-1,ch-id-2" # 可选
# MATTERMOST_ACCOUNT_ID = "team-prod" # 可选
MATTERMOST_TOKEN 写入 ~/.librefang/secrets.env。
Google Chat
Google Chat 由 Python sidecar adapter (librefang.sidecar.adapters.google_chat) 提供。Sidecar 迁移已移除进程内 [channels.google_chat] 配置块。请改为 [[sidecar_channels]]:
[[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" # 可选,空 = 所有 space
# GOOGLE_CHAT_ACCOUNT_ID = "prod" # 可选,多机器人路由
# GOOGLE_CHAT_API_BASE = "https://chat.googleapis.com/v1" # 测试覆盖
GOOGLE_CHAT_SERVICE_ACCOUNT_JSON(完整的 JSON blob 字符串 —— 不是 路径)写入 ~/.librefang/secrets.env。Google Cloud Console 上 Bot 配置的 messaging endpoint 改成 https://<host>:<GOOGLE_CHAT_WEBHOOK_PORT>/webhook。
Twitch
Twitch 由 Python sidecar 适配器 (librefang.sidecar.adapters.twitch) 提供。原 in-process [channels.twitch] 配置块已在 sidecar 迁移中移除。请改用 [[sidecar_channels]] 条目:
[[sidecar_channels]]
name = "twitch"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.twitch"]
channel_type = "twitch"
[sidecar_channels.env]
TWITCH_NICK = "librefang-bot"
TWITCH_CHANNELS = "channel1,channel2" # 逗号分隔,不带 '#'
# TWITCH_ACCOUNT_ID = "prod" # 可选,多机器人路由
# TWITCH_RATE_LIMIT_MSGS = "20" # 非 mod 账号 20/30s;mod 可设为 100
# TWITCH_RATE_LIMIT_SECS = "30"
TWITCH_OAUTH_TOKEN 写入 ~/.librefang/secrets.env。Sidecar 默认通过 TLS 连接 irc.chat.twitch.tv:6697;明文模式仅在 TWITCH_PLAINTEXT=1 下用于本地 mock 监听。
Rocket.Chat
Rocket.Chat 现以 Python sidecar 适配器(librefang.sidecar.adapters.rocketchat)提供。原 in-process [channels.rocketchat] 配置块已在 sidecar 迁移中移除。请改为通过 [[sidecar_channels]] 条目声明:
[[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" # 可选;留空 = 所有已加入频道
# ROCKETCHAT_ACCOUNT_ID = "prod" # 可选,多 Bot 路由
ROCKETCHAT_TOKEN 应写入 ~/.librefang/secrets.env——在仪表板的 Channels 页面填写 Rocket.Chat 表单时会自动写入。
Zulip
Zulip 现在由 Python sidecar 适配器(librefang.sidecar.adapters.zulip)提供。原 in-process 的 [channels.zulip] 配置块在 sidecar 迁移中已移除。请改用 [[sidecar_channels]] 声明——完整配置见上文 Configuration 参考的 "Zulip" 一节。
LINE
LINE 由 Python sidecar 适配器(librefang.sidecar.adapters.line)提供,进程内 [channels.line] 配置块已在 sidecar 迁移中移除。请改用 [[sidecar_channels]] 形式声明 —— sidecar 自身运行 HTTP Webhook 服务器(不再挂载在 LibreFang API 端口上),因此你在 LINE Developers 控制台注册的 Webhook URL 现在为 https://<sidecar-host>:<LINE_WEBHOOK_PORT><LINE_WEBHOOK_PATH>:
[[sidecar_channels]]
name = "line"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.line"]
channel_type = "line"
[sidecar_channels.env]
LINE_WEBHOOK_PORT = "9090"
# LINE_WEBHOOK_PATH = "/webhook"
# LINE_ACCOUNT_ID = "production"
LINE_CHANNEL_SECRET(用于验证入站 X-Line-Signature 的 HMAC-SHA256)和 LINE_CHANNEL_ACCESS_TOKEN(出站 POST /v2/bot/message/push 的 Bearer 凭据)需写入 ~/.librefang/secrets.env。
Reddit 由 Python sidecar 适配器(librefang.sidecar.adapters.reddit)提供,进程内 [channels.reddit] 配置块已在 sidecar 迁移中移除。请以 [[sidecar_channels]] 形式声明:
[[sidecar_channels]]
name = "reddit"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.reddit"]
channel_type = "reddit"
[sidecar_channels.env]
REDDIT_CLIENT_ID = "abc123"
REDDIT_USERNAME = "librefang-bot"
REDDIT_SUBREDDITS = "rust,programming" # 逗号分隔
# REDDIT_ACCOUNT_ID = "prod" # 可选,用于多 Bot 路由
# REDDIT_USER_AGENT = "myorg-bot/1.0 (by /u/me)" # 覆盖默认 User-Agent
REDDIT_CLIENT_SECRET 和 REDDIT_PASSWORD 应放在 ~/.librefang/secrets.env 中 —— 仪表盘的 Channels 页面会在你填写 Reddit 表单时自动写入。
Mastodon
Mastodon 由 Python sidecar 适配器 (librefang.sidecar.adapters.mastodon) 提供。原 [channels.mastodon] 配置块已在 sidecar 迁移中移除,请改用 [[sidecar_channels]]:
[[sidecar_channels]]
name = "mastodon"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.mastodon"]
channel_type = "mastodon"
[sidecar_channels.env]
MASTODON_INSTANCE_URL = "https://mastodon.social"
# MASTODON_VISIBILITY = "unlisted" # public | unlisted | private | direct
# MASTODON_MAX_MESSAGE_LEN = "500" # 实例若放宽限制可调高
# MASTODON_ACCOUNT_ID = "prod" # 可选,多 bot 路由键
MASTODON_ACCESS_TOKEN(OAuth bearer)写入 ~/.librefang/secrets.env——在仪表盘 Channels 页填写 Mastodon 表单时会自动写入。sidecar 继承了原适配器的 SSE 主路径 + REST 轮询回退语义。
Bluesky
Bluesky 由 Python sidecar 适配器 (librefang.sidecar.adapters.bluesky) 提供。原 [channels.bluesky] 配置块已在 sidecar 迁移中移除,请改用 [[sidecar_channels]]:
[[sidecar_channels]]
name = "bluesky"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.bluesky"]
channel_type = "bluesky"
[sidecar_channels.env]
BLUESKY_IDENTIFIER = "mybot.bsky.social"
# BLUESKY_SERVICE_URL = "https://bsky.social" # 自定义 PDS
# BLUESKY_ACCOUNT_ID = "prod" # 可选,多 bot 路由键
BLUESKY_APP_PASSWORD 写入 ~/.librefang/secrets.env——在仪表盘 Channels 页填写 Bluesky 表单时会自动写入。sidecar 每 5 秒轮询 app.bsky.notification.listNotifications,并通过内存 LRU 缓存(容量 200)将外发回复线程化关联到原通知。
飞书 / Lark(sidecar)
飞书 / Lark 已迁移为进程外 sidecar 适配器;请通过 [[sidecar_channels]] 条目声明,而不是 [channels.feishu]。
[[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(默认)或 intl(Lark)
# FEISHU_RECEIVE_MODE = "websocket" # websocket(默认)或 webhook
# FEISHU_WEBHOOK_PORT = "8453" # 仅 webhook 模式
# FEISHU_VERIFICATION_TOKEN = "..." # 仅 webhook 模式
# FEISHU_ENCRYPT_KEY = "..." # 仅 webhook 模式(AES-256-CBC 加密载荷)
# FEISHU_ACCOUNT_ID = "prod" # 可选,多 bot 路由标识
FEISHU_APP_SECRET 写入 ~/.librefang/secrets.env——在仪表盘 Channels 页填写飞书表单时会自动写入。默认 websocket 模式与飞书事件网关建立长连接(无需公网 IP)。webhook 模式监听 FEISHU_WEBHOOK_PORT,当配置 FEISHU_ENCRYPT_KEY 时支持解密 AES-256-CBC + PKCS7 加密载荷。
Nextcloud Talk
Nextcloud Talk 现以 Python sidecar 适配器(librefang.sidecar.adapters.nextcloud)提供。原 in-process [channels.nextcloud] 配置块已被移除。请改为通过 [[sidecar_channels]] 条目声明 Nextcloud:
[[sidecar_channels]]
name = "nextcloud"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.nextcloud"]
channel_type = "nextcloud"
[sidecar_channels.env]
NEXTCLOUD_SERVER_URL = "https://cloud.example.com"
# NEXTCLOUD_ROOMS = "abc123,def456" # 可选;留空 = 所有已加入房间
# NEXTCLOUD_ACCOUNT_ID = "prod" # 可选,多 Bot 路由
NEXTCLOUD_TOKEN 写入 ~/.librefang/secrets.env——在仪表板的 Channels 页面填写 Nextcloud 表单时会自动写入。出站回复通过 Talk 的 replyTo 参数串入线程(相对原 Rust 适配器从未发送 replyTo 的改进)。
Webex (sidecar)
Webex 已在 v2026.5 中迁移为 out-of-process sidecar;请使用 [[sidecar_channels]] 块代替 [channels.webex]。
[[sidecar_channels]]
name = "webex"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.webex"]
channel_type = "webex"
[sidecar_channels.env]
# WEBEX_ALLOWED_ROOMS = "Y2lz...A,Y2lz...B" # 可选,留空 = 所有房间
# WEBEX_ACCOUNT_ID = "org-prod" # 可选,多机器人路由键
WEBEX_BOT_TOKEN 写入 ~/.librefang/secrets.env——在仪表板的 Channels 页面填写 Webex 表单时会自动写入。出站回复通过 Webex 的 parentId 参数串入线程(相对原 Rust 适配器从未发送 parentId 的改进)。
钉钉(DingTalk,sidecar)
钉钉现以 Python sidecar 适配器(librefang.sidecar.adapters.dingtalk)提供,仅 stream 模式。原 in-process [channels.dingtalk] 配置块已被移除。请改为通过 [[sidecar_channels]] 条目声明:
[[sidecar_channels]]
name = "dingtalk"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.dingtalk"]
channel_type = "dingtalk"
[sidecar_channels.env]
DINGTALK_APP_KEY = "dingxxx..."
# DINGTALK_ACCOUNT_ID = "prod-bot" # 可选,多 bot 路由
# DINGTALK_ROBOT_CODE = "" # 可选,默认用 app_key
DINGTALK_APP_SECRET 写入 ~/.librefang/secrets.env——在仪表盘 Channels 页填写钉钉表单时会自动写入。sidecar 通过两步端点发现(POST /v1.0/gateway/connections/open)连接到钉钉 Stream Gateway,每条 CALLBACK 都即时 ACK,回复通过事件中携带的 sessionWebhook URL 发出。
legacy in-process webhook 模式(HMAC-SHA256 + 公网 IP)未迁移——依赖 webhook 模式的运维需要在钉钉后台改用 stream 订阅。
ntfy
ntfy 由 Python sidecar adapter (librefang.sidecar.adapters.ntfy) 提供。Sidecar 迁移已移除进程内 [channels.ntfy] 配置块。请改为 [[sidecar_channels]]:
[[sidecar_channels]]
name = "ntfy"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.ntfy"]
channel_type = "ntfy"
[sidecar_channels.env]
NTFY_SERVER_URL = "https://ntfy.sh"
NTFY_TOPIC = "my-agent-topic"
# NTFY_ACCOUNT_ID = "prod" # 可选,多机器人路由
NTFY_TOKEN(认证 token,公开 topic 可选)写入 ~/.librefang/secrets.env。
Gotify
Gotify 由 Python sidecar 适配器 (librefang.sidecar.adapters.gotify) 提供。原 [channels.gotify] 配置块已在 sidecar 迁移中移除,请改用 [[sidecar_channels]]:
[[sidecar_channels]]
name = "gotify"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.gotify"]
channel_type = "gotify"
[sidecar_channels.env]
GOTIFY_SERVER_URL = "https://gotify.example.com"
# GOTIFY_ACCOUNT_ID = "prod" # 可选,多 bot 路由键
GOTIFY_APP_TOKEN(出站发布)和 GOTIFY_CLIENT_TOKEN(入站 WebSocket 订阅)写入 ~/.librefang/secrets.env——在仪表盘 Channels 页填写 Gotify 表单时会自动写入。
Webhook(Sidecar)
Webhook 已从进程内 Rust 适配器迁移到 Python sidecar(librefang.sidecar.adapters.webhook,仅依赖标准库)。原 [channels.webhook] 块不再识别。保留全套 HMAC-SHA256 + 时间戳 + SSRF 防护,外加入站去重和 429 重试(Rust 适配器没有的两项改进)。
[[sidecar_channels]]
name = "webhook"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.webhook"]
channel_type = "webhook"
[sidecar_channels.env]
WEBHOOK_LISTEN_PORT = "8461"
# WEBHOOK_LISTEN_PATH = "/webhook"
# WEBHOOK_CALLBACK_URL = "https://example.com/incoming"
# WEBHOOK_DELIVER_ONLY = "1"
# WEBHOOK_DELIVER = "telegram"
WEBHOOK_SECRET(HMAC-SHA256 签名密钥)写入 ~/.librefang/secrets.env。sidecar 自己监听 WEBHOOK_LISTEN_PORT(默认 8461)的 WEBHOOK_LISTEN_PATH(默认 /webhook)。SSRF 防护(私有 / 回环 / 链路本地 / 多播 / 云元数据 / 100.64-CGN / IPv4-mapped-IPv6 全部拒绝,以及 localhost.、kubernetes.default.svc.cluster.local 等保留主机名)在 sidecar 启动时和每次出站 POST 时都跑——defence in depth:配置热重载把 URL 改成私网时不会泄露签名密钥到 localhost。
WEBHOOK_DELIVER_ONLY=1 时 sidecar 在入站消息上加 __deliver_only__ / __deliver_target__ metadata;kernel 的 bridge 层读这两个字段,把消息直接转发给目标 channel,绕过 LLM。WEBHOOK_DELIVER_ONLY=1 时 WEBHOOK_DELIVER 是必填的 —— sidecar 启动时若缺失直接 fail-closed(原 Rust validator 只在运行时 warn)。
QQ Bot(Sidecar)
QQ 已从进程内 Rust 适配器迁移到进程外 Python sidecar(librefang.sidecar.adapters.qq),通过 WebSocket(网关)+ REST(token + 出站)与 QQ 开放平台通信。原有 [channels.qq] 块不再识别 —— 改为声明 [[sidecar_channels]]:
[[sidecar_channels]]
name = "qq"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.qq"]
channel_type = "qq"
[sidecar_channels.env]
QQ_APP_ID = "your-app-id"
# QQ_ALLOWED_USERS = "openid-1,openid-2" # 可选
# QQ_ACCOUNT_ID = "prod-bot" # 可选
# QQ_INTENTS = "1073746435" # 可选,覆盖 intents bitmask
密钥放在 ~/.librefang/secrets.env:QQ_APP_SECRET(QQ 开放平台控制台里的 clientSecret)。
企业微信(sidecar)
企业微信(WeCom)已从 in-process Rust 适配器迁移到 out-of-process Python sidecar(librefang.sidecar.adapters.wecom)。Sidecar 使用 WebSocket 连接到 wss://openws.work.weixin.qq.com,凭智能机器人的 Bot ID 和 Secret 鉴权。Callback 模式(HTTP webhook + AES-CBC-256 入站解密)不再支持 —— Python 标准库没有 AES,而 sidecar SDK 按惯例只用 stdlib。原先使用 callback 模式的运维人员需要在企业微信管理后台将机器人切换到 WebSocket 模式。
原有 [channels.wecom] 不再识别,请改为 [[sidecar_channels]]:
[[sidecar_channels]]
name = "wecom"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.wecom"]
channel_type = "wecom"
[sidecar_channels.env]
WECOM_BOT_ID = "aibxxxxxxx"
# WECOM_ALLOWED_USERS = "alice,bob"
# WECOM_ACCOUNT_ID = "prod-bot"
密钥放在 ~/.librefang/secrets.env:WECOM_BOT_SECRET(企业微信管理后台里的机器人密钥)。
微信(WeChat,sidecar)
微信(个人账号经 iLink 协议)现以 Python sidecar 适配器(librefang.sidecar.adapters.wechat)提供。原 in-process [channels.wechat] 配置块已被移除。请改为通过 [[sidecar_channels]] 条目声明:
[[sidecar_channels]]
name = "wechat"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.wechat"]
channel_type = "wechat"
[sidecar_channels.env]
# WECHAT_BOT_TOKEN = "" # 留空触发二维码登录
# WECHAT_ALLOWED_USERS = "" # 逗号分隔 hash@im.wechat
# WECHAT_ACCOUNT_ID = "prod" # 可选,多 bot 路由
首次启动时,sidecar 运行二维码登录流程,并把二维码字符串以 INFO 级日志输出 —— 用微信 App 扫描确认即可。拿到的 bot_token 可以填到 WECHAT_BOT_TOKEN 跳过后续二维码(仪表盘 Channels 页填表时会自动写入 ~/.librefang/secrets.env)。
通道行为覆盖(旧版 —— 已移除)
[channels.<name>.overrides] 子表已不再被识别。它原本挂在进程内 ChannelsConfig 上,而 sidecar 迁移已经把这个结构清空(ChannelsConfig 现在只剩 file_download_* / file_upload_max_bytes 这些全局文件传输字段)。下方内容保留作历史参考与迁移映射。
迁移对照表 —— sidecar 模型下的等价做法:
| 旧的 override | 现在对应的 sidecar 写法 |
|---|---|
model、system_prompt | 在 agent(agent.toml)上设置而不是按通道 —— sidecar 把每个入站都路由到同一个 agent。 |
dm_policy、group_policy | 写到 [sidecar_channels.env] 块里的 *_DM_POLICY / *_GROUP_POLICY 环境变量(Telegram / Discord / Slack / WhatsApp / Teams 五个 sidecar 都识别这套)。 |
rate_limit_per_minute、rate_limit_per_user | Sidecar 自己按平台限流;要更严的话,在 sidecar 前面套反向代理。 |
output_format | [[sidecar_channels]] 没暴露这个 knob;需要特定输出格式的 agent 应在 agent 侧切换。 |
disable_commands、allowed_commands、blocked_commands | 在 agent 清单(agent.toml)的命令策略区块设置 —— 跨通道统一生效。 |
threading、usage_footer、typing_mode | 用 sidecar 默认行为(平台支持时启用 threading;不显示用量页脚;instant 打字态)。当前不可按通道配置。 |
下方是已删除的 override 结构 —— 保留作参考;不要复制到当前的 config.toml。
通道行为覆盖(历史参考)
迁移前每个通道适配器都支持 [channels.<name>.overrides] 子表,用于按通道自定义 Agent 行为。
[channels.discord.overrides]
model = "claude-haiku-4-5-20251001"
system_prompt = "You are a concise Discord assistant."
dm_policy = "respond"
group_policy = "mention_only"
rate_limit_per_minute = 0
rate_limit_per_user = 10
threading = true
output_format = "markdown"
usage_footer = "tokens"
typing_mode = "instant"
disable_commands = false
allowed_commands = []
blocked_commands = []
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
model | string 或 null | null | 该通道的模型覆盖。为 null 时使用 Agent 的默认模型。 |
system_prompt | string 或 null | null | 该通道的系统提示词覆盖。 |
dm_policy | string | "respond" | Bot 处理私聊消息的方式。见下表。 |
group_policy | string | "mention_only" | Bot 处理群组消息的方式。见下表。 |
rate_limit_per_minute | u32 | 0 | 该通道的全局速率限制(每分钟消息数)。0 = 无限制。 |
rate_limit_per_user | u32 | 0 | 每个用户每分钟的最大消息数。0 = 无限制。 |
threading | bool | false | 启用线程回复(在支持的平台上)。 |
output_format | string 或 null | null | 覆盖输出格式。见下表。 |
usage_footer | string 或 null | null | 覆盖该通道的用量页脚模式。可选值:off、tokens、cost、full。 |
typing_mode | string 或 null | null | 输入状态指示器行为。见下表。默认为 instant。 |
disable_commands | bool | false | 关闭该通道所有内置斜杠命令。参见命令策略。 |
allowed_commands | list of strings | [] | 命令名白名单(不带 /)。非空时仅这些命令可用。 |
blocked_commands | list of strings | [] | 命令名黑名单(不带 /)。仅在 allowed_commands 为空时生效。 |
dm_policy 值说明:
| 值 | 说明 |
|---|---|
respond | 回复所有私聊消息(默认)。 |
allowed_only | 仅回复允许列表中用户的私聊消息。 |
ignore | 忽略所有私聊消息。 |
group_policy 值说明:
| 值 | 说明 |
|---|---|
all | 回复群聊中的所有消息。 |
mention_only | 仅在被 @ 提及时回复(默认)。 |
commands_only | 仅回复斜杠命令。 |
ignore | 忽略所有群组消息。 |
output_format 值说明:
| 值 | 说明 |
|---|---|
markdown | 标准 Markdown(默认)。 |
telegram_html | Telegram HTML 子集(<b>、<i>、<code> 等)。 |
slack_mrkdwn | Slack mrkdwn 格式(*bold*、_italic_、`code`)。 |
plain_text | 无格式标记。 |
typing_mode 值说明:
| 值 | 说明 |
|---|---|
instant | 收到消息后立即发送输入状态指示(默认)。 |
message | 仅在 LLM 返回第一个文本增量时发送输入状态指示。 |
thinking | 仅在 LLM 推理/思考阶段发送输入状态指示。 |
never | 从不发送输入状态指示。 |
命令策略
每个通道都自带一组内置斜杠命令(/agent、/new、/reboot、/model、/usage 等),可用于切换 Agent、开启新会话、查看用量、触发工作流。在面向公众的 bot(客服、社区助手)上暴露这些命令是安全隐患——任何人都可以打 /agent admin 切到内部 Agent,/new 开一个新会话(旧会话仍保留并可在通道里恢复),或者 /model 换模型。
下面三个字段按通道对内置命令做访问控制。优先级: disable_commands > allowed_commands(白名单) > blocked_commands(黑名单)。
被拦截的命令会作为普通文本转发给 Agent——不会返回错误。所以一个设置了 disable_commands = true 的公共 bot,当用户打 /agent admin 时,会由 Agent 自然语言回复,用户永远不会发现命令系统的存在。
配方:完全锁定的公共 bot(禁用所有命令)
[channels.discord.overrides]
disable_commands = true
配方:保留平台 UX 必需命令的公共 bot
只保留安全的几个内置命令:
[channels.discord.overrides]
allowed_commands = ["start", "help"]
配方:只屏蔽危险命令的管理员 bot
对于面向运维人员的 bot(用 allowed_users 限制访问),你可能仍想屏蔽会改变昂贵状态的命令:
[channels.discord.overrides]
blocked_commands = ["agent", "new", "reboot", "model", "stop"]
命令名是内部使用的裸 token —— TOML 里写 "agent" 或 "/agent" 都行,匹配时会自动去掉前导斜杠。完整命令列表见 /help。
[[sidecar_channels]]
Sidecar 通道适配器允许外部进程(使用任何编程语言编写)充当通道适配器。通过 stdin/stdout 上的换行分隔 JSON 进行通信。
[[sidecar_channels]]
name = "my-custom-channel"
command = "python3"
args = ["adapters/my_adapter.py"]
channel_type = "custom_platform"
[sidecar_channels.env]
MY_API_TOKEN = "secret"
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name | string | 必填 | 此适配器的显示名称。 |
command | string | 必填 | 要运行的可执行文件(例如 "python3"、"/usr/local/bin/my-adapter")。 |
args | list of strings | [] | 传递给命令的参数。 |
env | map of string to string | {} | 传递给子进程的额外环境变量。 |
channel_type | string 或 null | null | 通道类型标识符。为 null 时默认为 Custom(<name>)。 |