OpenClaw 通道与配对:把助手接进你常用的聊天软件
Posted on Fri 09 October 2026 in AI 编程 • Sucre Liu
通道:门面也是攻击面
通道(Channel)就是一个个渠道插件:Discord、Slack、Telegram、WhatsApp、iMessage、Matrix、Teams、飞书……它们都由 Gateway 统一管理。webchat 是内置的网页聊天通道,不是可配置的出站通道。
接一个通道本身不难,难的是谁有资格和它说话。这就是 OpenClaw 把"配对"单独拎出来的原因。
最省事的入门通道是 Telegram(只需一个 bot token):
openclaw channels add --channel telegram --token <token>
openclaw channels status --probe
接完别急着用,先看一眼安全默认值。
两种"配对",别搞混
OpenClaw 的 pairing 用在两个完全不同的地方:
| DM 配对 | 节点配对 | |
|---|---|---|
| 解决什么 | 谁能私聊 bot | 哪些设备能加入网关 |
| 主体 | 聊天平台上的发件人 | iOS/Android/macOS/headless 设备 |
| 状态位置 | channel_pairing_* 表 |
设备记录 + token |
| 批准入口 | 聊天请求队列 / pairing CLI |
Control UI Devices / devices CLI |
一个常见误解:批准某个人的私聊,不等于给他群权限,也不等于让他能控制 bot。 这三件事是分开的状态。
DM 配对
当通道的 DM 策略是 pairing(默认行为)时,陌生发件人会收到一个短码,在批准前消息不会被处理。短码规则:
- 8 位大写,去掉易混字符(
0O1I); - 1 小时过期;bot 只在创建新请求时发一次(约每小时每个发件人一次);
- 每个通道账号的待批准请求上限 3 个,超出会被忽略直到有过期或被批准。
批准有两个入口。Control UI 走 Settings → Channels → DM access requests,队列会汇总所有 pairing 策略通道的待处理请求,可按通道/账号过滤,看到发件人 ID 与元数据后批准。CLI 走:
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
加 --notify 会通知请求者;多账号通道加 --account <id>。
两个容易忽略的细节:
- 批准只授予私聊。 群聊授权是另一套(
groupAllowFrom、groups等),不会因为批准了 DM 就自动放行。 - Owner 是独立状态,在
commands.ownerAllowFrom。CLI 首次批准且尚无 owner 时,会自动引导出一个 owner(例如telegram:123456789),让特权命令和 exec 审批有明确归属。手工加进 allowlist 的人不会自动成为 owner。
建议在接通道时就顺手把 owner 定下来(channels add 向导里有单独的 Set up my operator account),别等到要跑 /update 或重启网关时才发现没人有权限。
dmPolicy: "open" 不是"公开"
open 只有在生效的 DM allowlist 包含 "*" 时才是真公开。如果历史状态里是 open 但 allowFrom 是具体条目,运行时仍然只放行那些发件人,而且配对记录的批准也不会扩宽 open 的访问范围。想公开就显式写 "*",并清楚代价。
另外,allowFrom: ["*"] 允许的是聊天,不等于允许受限的斜杠命令——命令授权仍是独立的一层。
可复用的发件人分组
同一批可信的人要同时出现在多个通道的 DM 和群 allowlist 里,用顶层 accessGroups 比到处复制更稳:
{
accessGroups: {
operators: {
type: "message.senders",
members: {
discord: ["discord:123456789012345678"],
telegram: ["987654321"],
whatsapp: ["+15551234567"],
},
},
},
channels: {
telegram: { dmPolicy: "allowlist", allowFrom: ["accessGroup:operators"] },
whatsapp: { groupPolicy: "allowlist", groupAllowFrom: ["accessGroup:operators"] },
},
}
一处维护,多处引用。
配对状态存在哪
支持配对 API 的通道,状态存在共享 SQLite:
~/.openclaw/state/openclaw.sqlite
├── channel_pairing_requests # 待批准
└── channel_pairing_allow_entries # 已批准
每个请求和已批准发件人按通道 + 账号存储。老版本写的 <channel>-pairing.json 之类的文件,要靠 openclaw doctor --fix 导入 SQLite 后才生效——正常启动不会读旧文件。
一句提醒:这个数据库把关着谁能访问你的助手,按敏感数据处理。
节点配对:把设备加进来
Nodes(手机、macOS、headless)以 role: node 连入,属于设备层面,需要单独批准。推荐从 Control UI:Settings → Devices → Pair device,选完整/受限访问,生成 setup code,在手机 App 里扫码或粘贴。
setup code 本质是一个 base64 的 JSON,含:
url:Gateway 的 WS 地址(ws://或wss://);urls:可尝试的局域网/Tailnet 路线;bootstrapToken:一次性引导令牌,10 分钟过期。
安全上一句话记牢:明文 ws:// 的 setup code 只能拿到受限访问。要完整访问,就配 wss:// 或 Tailscale,然后重新生成 code。ws:// 只在 loopback、私有局域网、.local Bonjour、Android 模拟器这些场景被接受。
集群内也可以手动批准:
openclaw devices list
openclaw devices approve <requestId>
openclaw devices reject <requestId>
在受控网段里想让新节点首次配对自动通过,可以显式开 CIDR:
{
gateway: {
nodes: {
pairing: { autoApproveCidrs: ["192.168.1.0/24"] },
},
},
}
它只对没有请求任何 scope 的全新 role: node 请求生效;operator、浏览器、Control UI、WebChat 仍需人工批准,角色/scope/公钥变更也仍需人工。
消息是怎么被路由的
路由是确定性的:回复回到消息来的那个通道,模型不选通道。普通路由为每条入站消息挑一个 agent,匹配从最具体到最宽泛:
- 精确 peer(
bindings的peer.kind+peer.id) - 父级 peer(线程继承)
- peer 通配(
peer.id: "*") - Discord:guild + roles
- Discord:guild
- Slack:team
- 账号(
accountId) - 通道(该通道任意账号)
- 兜底 owner
一个 binding 里给了多个匹配字段时,所有字段都必须命中才生效。
会话键的形状也值得记住。默认 session.dmScope: "main",所有通道的私聊都汇到 agent 的主会话:
agent:main:main
群/频道则默认按 session.groupScope: "per-group" 隔离:
agent:<agentId>:<channel>:group:<id>
agent:<agentId>:<channel>:channel:<id>
Slack/Discord 线程在基础键后追加 :thread:<id>;Telegram 论坛话题嵌 :topic:<id>。
这里有个配置决策要提前想:要不要让不同通道的私聊共享同一段上下文? main 方便(一处聊天处处续上),但也会把多个人的私聊并到一条主会话里——多人可发消息时,就该改用 per-peer 或 per-account-channel-peer。
小结
- 通道由 Gateway 管;最快的入口是 Telegram。
- DM 配对管"谁能私聊",节点配对管"哪些设备能加入";批准 DM 不给群、不给 owner。
dmPolicy: "open"只有 allowlist 含"*"才是公开;配对批准不会扩宽它。- setup code 在明文
ws://下只给受限访问;完整访问要wss:///Tailscale。 - 路由确定性、最具体优先;默认私聊汇入主会话,多人场景要调
dmScope。
下一篇讲 agent 与记忆:workspace 里那几个 Markdown 文件到底是什么、它"记住"的东西存在哪,以及多 agent 的正确隔离姿势。