通道配置

所有内嵌通道适配器的配置、每通道行为覆盖以及 Sidecar 通道集成。


[channels]

所有内嵌通道适配器均在 [channels.<name>] 下配置。每个通道采用 Option<T> 类型——省略该节将完全禁用该适配器。即使只写了节头(内容为空),也会以默认值启用该适配器。

通用通道字段: 每个通道适配器除了自身特有的字段外,还支持以下通用字段:

字段类型默认值说明
default_agentstring 或 nullnull默认将消息路由到的 Agent 名称。
account_idstring 或 nullnull当前 Bot 实例的唯一标识符。用于通过 [[bindings]] 匹配规则进行多 Bot 路由。
overridesobject(默认值)每个通道的行为覆盖配置。详见通道行为覆盖

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 APIWeb/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_TOKENWHATSAPP_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.envMATRIX_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),先 LOGINAUTHENTICATE 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

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_SECRETREDDIT_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=1WEBHOOK_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.envQQ_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.envWECOM_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 写法
modelsystem_prompt在 agent(agent.toml)上设置而不是按通道 —— sidecar 把每个入站都路由到同一个 agent。
dm_policygroup_policy写到 [sidecar_channels.env] 块里的 *_DM_POLICY / *_GROUP_POLICY 环境变量(Telegram / Discord / Slack / WhatsApp / Teams 五个 sidecar 都识别这套)。
rate_limit_per_minuterate_limit_per_userSidecar 自己按平台限流;要更严的话,在 sidecar 前面套反向代理。
output_format[[sidecar_channels]] 没暴露这个 knob;需要特定输出格式的 agent 应在 agent 侧切换。
disable_commandsallowed_commandsblocked_commands在 agent 清单(agent.toml)的命令策略区块设置 —— 跨通道统一生效。
threadingusage_footertyping_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 = []
字段类型默认值说明
modelstring 或 nullnull该通道的模型覆盖。为 null 时使用 Agent 的默认模型。
system_promptstring 或 nullnull该通道的系统提示词覆盖。
dm_policystring"respond"Bot 处理私聊消息的方式。见下表。
group_policystring"mention_only"Bot 处理群组消息的方式。见下表。
rate_limit_per_minuteu320该通道的全局速率限制(每分钟消息数)。0 = 无限制。
rate_limit_per_useru320每个用户每分钟的最大消息数。0 = 无限制。
threadingboolfalse启用线程回复(在支持的平台上)。
output_formatstring 或 nullnull覆盖输出格式。见下表。
usage_footerstring 或 nullnull覆盖该通道的用量页脚模式。可选值:offtokenscostfull
typing_modestring 或 nullnull输入状态指示器行为。见下表。默认为 instant
disable_commandsboolfalse关闭该通道所有内置斜杠命令。参见命令策略
allowed_commandslist of strings[]命令名白名单(不带 /)。非空时仅这些命令可用。
blocked_commandslist of strings[]命令名黑名单(不带 /)。仅在 allowed_commands 为空时生效。

dm_policy 值说明:

说明
respond回复所有私聊消息(默认)。
allowed_only仅回复允许列表中用户的私聊消息。
ignore忽略所有私聊消息。

group_policy 值说明:

说明
all回复群聊中的所有消息。
mention_only仅在被 @ 提及时回复(默认)。
commands_only仅回复斜杠命令。
ignore忽略所有群组消息。

output_format 值说明:

说明
markdown标准 Markdown(默认)。
telegram_htmlTelegram HTML 子集(<b><i><code> 等)。
slack_mrkdwnSlack 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"
字段类型默认值说明
namestring必填此适配器的显示名称。
commandstring必填要运行的可执行文件(例如 "python3""/usr/local/bin/my-adapter")。
argslist of strings[]传递给命令的参数。
envmap of string to string{}传递给子进程的额外环境变量。
channel_typestring 或 nullnull通道类型标识符。为 null 时默认为 Custom(<name>)