多渠道最容易出错的地方不是“少接了一个平台”,而是四个结果无法解释:谁被允许、哪个 Agent 接手、上下文存在哪里、回复最终送到哪里。本篇把旧的“WhatsApp + Telegram + Dashboard 案例”合并为一套可检查的路由练习。
**本站验证范围:**配置文件已通过 OpenClaw 2026.9.2 的隔离 schema 校验,但没有连接真实渠道或模型。下载的验收表是空白记录,不是成功截图。
先画路由意图表
本练习假设有两个 Agent:
main:通过明确的 WhatsApp channel binding 处理已授权操作员私聊。support:只处理一个指定 Telegram 工作群。
先用自己的真实 ID 替换占位值,再执行验证。Telegram 用户 ID 与群 ID 的区别见配置入门;WhatsApp 号码和扫码流程见一站式接入。
| 输入 | 准入条件 | 目标 Agent | 会话预期 | 回复位置 |
|---|---|---|---|---|
| WhatsApp 操作员私聊 | 号码在 allowFrom | main | 按渠道与用户隔离 | 原 WhatsApp 私聊 |
| 指定 Telegram 工作群 | 群 ID、发送者均允许且提及 Bot | support | 该 Telegram 群独立会话 | 原 Telegram 群 |
| 其他已允许但没有 matching binding 的消息 | 渠道自身准入通过 | 不选择 Agent | 不应启动任务 | 不应生成普通回复 |
| 未授权用户或群 | 准入失败 | 不应进入 Agent | 不应创建可用任务上下文 | 不应执行任务 |
不要把 Dashboard / Control UI 写成所有审批的强制归宿。它可以用于查看和管理会话;某些审批也能按产品配置转发到渠道。审批规则要单独设计,不能由路由表替代。
配置两个 Agent 和一条精确 binding
下载路由练习配置。它只是一段需要合入现有配置的示例,其中 token 文件、号码、群 ID 和工作区路径都要替换。
{
"session": {
"dmScope": "per-channel-peer",
"groupScope": "per-group"
},
"agents": {
"ownership": "explicit",
"entries": {
"main": {
"name": "Main",
"workspace": "/REPLACE/workspace-main"
},
"support": {
"name": "Support",
"workspace": "/REPLACE/workspace-support"
}
}
},
"channels": {
"whatsapp": {
"dmPolicy": "allowlist",
"allowFrom": ["+15551234567"],
"selfChatMode": false,
"groupPolicy": "disabled"
},
"telegram": {
"enabled": true,
"tokenFile": "/REPLACE/telegram-token.txt",
"dmPolicy": "disabled",
"groupPolicy": "allowlist",
"groupAllowFrom": ["123456789"],
"groups": {
"-1001234567890": {
"requireMention": true
}
}
}
},
"bindings": [
{
"agentId": "support",
"match": {
"channel": "telegram",
"peer": {
"kind": "group",
"id": "-1001234567890"
}
}
},
{
"agentId": "main",
"match": {
"channel": "whatsapp"
}
}
]
}
这段配置有三个刻意的选择:多 Agent roster 使用 ownership: "explicit";Telegram 群与 WhatsApp 默认账号分别有 binding;私聊使用 per-channel-peer,避免不同渠道和发送者挤进同一会话。
下载文件没有 WhatsApp 登录凭据,也不包含模型配置。WhatsApp 渠道是否能加载还取决于插件是否安装;Telegram token 文件也必须真实存在。不要用下载文件覆盖完整生产配置。
配置校验只解决第一层
合入测试实例后运行:
openclaw config validate --json
检查输出中的配置路径、valid 和所有 warnings。本站的隔离校验只能证明示例字段满足 2026.9.2 schema;它没有证明占位路径存在、渠道在线或消息会命中预期 Agent。
查看本站的脱敏校验记录。最终结果为 valid:true,并保留一条警告:显式多 Agent 配置没有为 ambient heartbeat 指定 owner,因此 heartbeat 保持关闭。本练习不使用 heartbeat,所以没有为了消除警告而额外授予 owner;如果你的任务需要 heartbeat,应单独选择 owner、权限和投递目标并重新验证。
若你有两个以上同渠道账号,显式设置 channels.<channel>.defaultAccount 或提供名为 default 的账号,并把 accountId 写入相应 binding。当前文档说明,缺少明确默认值时,出站 fallback 可能选择规范化排序后的第一个账号。
bindings 是怎样命中的
当前固定版本的 Agent 配置文档说明:显式多 Agent fleet 没有默认 Agent;没有 matching binding 时关闭处理。精确 peer 比 channel-wide binding 更具体,同一层级则由第一条匹配规则胜出。一个 binding 同时包含多个条件时,所有条件都必须匹配。
这意味着:
- 上例的指定 Telegram 群进入
support。 - 同渠道的另一个准入群不会因为“也是 Telegram”而命中这条精确 binding。
- WhatsApp 默认账号消息命中 channel binding 后进入
main。 - 其他没有 matching binding 的消息不会回落到
main。 - matched Agent 决定 workspace 和 session store;提示词不能把已经选定的 workspace 换掉。
如果多个业务群都交给 support,可以逐个写精确 peer;先不要用 peer.id: "*" 扩大范围。新增一条 binding 后重新跑原有样本,避免更具体的规则改变旧消息的去向。
会话隔离需要单独验收
路由到同一个 Agent,不代表必须共享一段对话。默认情况下,同一 Agent 的直接消息会合入 main 会话;这适合一个完全可信的单人助手,但多人入口可能让不同发送者共享私聊上下文。
session.dmScope | 会话分隔方式 | 适用考虑 |
|---|---|---|
main | 同一 Agent 的 DM 共用主会话 | 单一可信用户需要跨渠道连续上下文 |
per-peer | 按发送者隔离,可跨渠道合并同一身份 | 需要正确维护身份关联 |
per-channel-peer | 按渠道与发送者隔离 | 多渠道、多用户的保守起点 |
per-account-channel-peer | 再加入账号维度 | 同渠道多个账号需要进一步隔离 |
群默认按 channel 与群 ID 隔离。本练习保留 per-group。修改 groupScope 只会改变上下文存储,不能改变 mention、发送者授权或回复目的地。
用四条消息完成验收
下载路由与会话验收表,每条消息使用唯一标记,避免只凭内容相似判断会话。
- WhatsApp 授权操作员发送
AC-ROUTE-WA-01:请只回复当前 Agent 名称和这个标记。 - Telegram 指定群里的授权用户提及 Bot,发送
AC-ROUTE-TG-02:请只回复当前 Agent 名称和这个标记。 - 经同意,用非授权 Telegram 测试身份在同群提及 Bot,确认任务没有执行。
- 在一个已允许但没有 matching binding 的隔离测试入口发送
AC-ROUTE-NOMATCH-03,确认它关闭处理。没有安全的额外入口时,该项写“未验证”,不要临时开放公开访问。
检查日志和会话列表时,记录每条消息对应的 channel、account、peer、agentId 和 session key。只看模型自报“我是 support”不可靠;模型可以说错,路由元数据才是依据。
普通回复应回到来源渠道。若任务需要跨渠道通知,应使用已授权的显式发送工具、channel、account 和目标,并把它作为另一项高权限功能测试,不要修改 prompt 试图让普通回复改道。
检查是否发生上下文串线
先在 WhatsApp 私聊提供一个仅用于测试的临时标记,例如 WA-CONTEXT-71;随后在 Telegram 群中询问该标记,但不要把答案写进问题。
在本练习的两个 Agent 配置下,Telegram 群不应从 WhatsApp 私聊的会话上下文得到该值。如果它正确回答,检查共享 workspace memory、检索功能、系统提示和其他数据源,不能直接断言 session 串线。测试后删除临时信息。
对于同一 Agent 的两个 DM,per-channel-peer 也应产生不同会话。使用 openclaw sessions --json 检查实际条目;不要公开完整 transcript。
按结果定位故障层
| 现象 | 优先检查 |
|---|---|
| 消息完全没有进入 | 渠道在线状态、群/用户准入、mention 和身份格式 |
| 消息进入但 Agent 错误 | binding 的 channel、account、peer 条件及匹配优先级 |
| Agent 正确但上下文串线 | dmScope、groupScope、身份关联和共享 memory |
| 生成了回答但发错账号 | 同渠道 defaultAccount 和显式出站 account |
| 回答出现在另一渠道 | 是否调用了显式发送工具;普通回复不会由模型自由改道 |
| 已准入但报告没有路由所有者 | 是否缺少 matching binding,或其 account / peer 条件不一致 |
| 重启后路由变化 | 实际加载配置、账号覆盖、配置警告和持久化状态 |
一次只修改一层。把 allowlist、binding、session scope 和 prompt 同时重写,会让成功也无法归因。
扩展到更多渠道前
保留已经通过的消息矩阵,将新入口作为一行加入。先定义准入、Agent、会话和回复位置,再写配置。高风险 Agent 应使用独立 workspace、凭据和工具策略;不同 Agent 的 session store 分开并不自动保证外部资源权限也隔离。
完成本篇后,你应该能够从一条消息追踪到准入结果、命中的 binding、Agent、session key 和回复渠道,并能用正例与负例证明这条路径,而不是只说“两个渠道都能聊天”。