先说个真实的场景:我本地原来跑着三个独立的 Telegram Bot,一个管写作,一个管代码,一个做日常问答。三个 bot 就要三套 token、三份部署配置、三条消息回调链路,每次想调一下模型参数得分别改三个地方。后来我把它们全部收编进了一个 Bot,借助 Telegram 群组的 Topics(话题)功能做消息路由,配合 OpenClaw 这个自托管的 AI 助手网关统一管理,一个 Bot 就同时撑起了多个完全独立的 AI 助手,每个助手有自己独立的 System Prompt、独立的模型配置、独立的上下文记忆,互相不串门。这篇文章就把这套方案的完整部署过程和踩坑记录写出来。适合那些想用 Telegram 做统一 AI 入口、又不想同时维护一大堆 Bot 的人,也适合正在折腾 OpenClaw 但卡在部署或路由配置上的朋友。
1. 为什么是 OpenClaw + Telegram Topics:先理清需求和分工
在设计任何方案之前,我习惯先把"我要解决什么问题"写清楚。这套组合的核心问题只有一个:怎样用最小的维护成本,跑尽可能多的独立 AI 助手。
1.1 一个 Bot 只能一个角色的困境
很多人刚开始玩 AI 助手的时候,都是"一个 Bot 走天下"——把写作、编程、翻译、闲聊全部塞进同一个 System Prompt 里。短期看没问题,用久了就会发现几个很烦的现象:
上下文互相污染。你和它聊了三轮代码调试,转头让它帮你写一段朋友圈文案,它大概率还带着"代码变量"的思维,回出来的文案冷冰冰。原因很简单,同一个会话只有一个上下文窗口,前面聊的内容会一直影响后面的输出。
System Prompt 难以兼顾。想让一个助手既专业又幽默还精通代码,prompt 会写得越来越长,模型对每部分指令的遵循度反而下降。我拆成三个独立助手后,每个 prompt 都短小精悍,效果明显更好。
部署和管理成本线性增长。每新增一个 Bot,就要注册一个 BotFather token,多配一条 webhook 或轮询通道,多维护一份环境变量。时间一长,光理顺这些 token 之间的关系就够喝一壶。
所以我的思路是:入口统一,大脑分叉。也就是一个 Bot 只做"消息收件箱",至于这条消息该交给哪个 AI 助手处理,由上层网关根据消息特征去路由。
1.2 Topics 提供的天然消息隔离舱
Telegram 群组的 Topics 功能(也叫 Forum Mode)本质上是在一个群聊里开多个子线程。每个 Topic 单独拥有自己的消息流、标题和通知设置。最关键的一点是:Bot 在接收消息时,每条消息都会携带一个message_thread_id字段。
这个字段就是天然的"房间号"。Bot 只要读一下房间号,就能判断这条消息应该进哪条处理管线。这意味着:
不需要多个 Bot。一个 Bot 在群里的所有 Topic 中都能收到消息,只需要根据message_thread_id转发给不同的处理逻辑。
不需要自己写复杂的状态机。Telegram 服务端已经帮你把不同话题的消息流隔离开了,你只需要做"映射",不用做"过滤"。
用户侧体验极好。大家还在同一个群里,通过顶部的话题标签切换助手,视觉上清清楚楚,不会出现多 Bot 轰炸聊天列表的情况。
1.3 OpenClaw 在整套方案里扮演什么角色
OpenClaw 是一个自托管的 AI 代理编排框架,简单说它就是一个"AI 助手网关"。它负责三件事:连接各种聊天渠道(Telegram、Teams、Discord 等)、管理多个助手实例(每个实例有自己的模型、人格、工具)、维护会话记忆。
在 Telegram Topics 这套方案里,OpenClaw 处在中间层。Telegram 群组负责"消息入口和隔离",OpenClaw 负责"消息路由和模型调度"。我甚至不需要自己写 bot 代码,只需要在 OpenClaw 的配置文件里声明好各个助手、声明好 Telegram 渠道的接入参数,网关就会自动把不同 Topic 的消息分发到对应的助手。
这套分工的好处是每一层只干一件事,出了问题也容易定位:收不到消息查 Telegram 接入,路由错了查 OpenClaw 配置,回答质量差查模型设置。
2. 先把环境跑起来:OpenClaw 安装与 Windows 下的 WSL2 折腾记录
先说环境结论:如果你有一台 Linux 服务器或者 Mac,安装过程会顺畅很多;如果你跟我一样主力机是 Windows,那大概率会在 WSL2 环节卡一下。
2.1 部署方式怎么选
OpenClaw 官方提供了几种安装方式,我理解下来最适合大部分人的是 Docker Compose 方案。其他几种我也列一下,方便你按自己的情况选:
| 部署方式 | 优点 | 需要注意的坑 |
|---|---|---|
| Docker Compose | 依赖隔离、升级方便、配置文件清晰 | 需要先装 Docker,Windows 下需要 WSL2 后端 |
| 官方一键脚本 | 命令少、上手快 | 脚本依赖特定系统环境,Windows 下经常触发 WSL 检测 |
| 源码手动部署 | 可定制性最高、方便二次开发 | 要自己装 Node.js/Python 依赖,环境变量容易漏配 |
我自己最后选了 Docker Compose。原因很简单:多助手配置、模型接入配置都集中在docker-compose.yml和对应的配置文件里,出了问题可以整个容器删掉重来,不会污染宿主机环境。
2.2 "无法安全验证 WSL2 环境"的排查过程
如果你在 Windows 上运行 OpenClaw 的某些安装脚本,很可能会遇到类似这样的报错提示:
无法安全验证 WSL2 环境。请在 PowerShell 中运行 wsl -- status 检查当前状态。我第一次看到这个提示的时候,第一反应是"OpenClaw 安装脚本在检查什么?",第二反应是"我的 WSL 明明能用啊"。
后来理清楚了:OpenClaw 的安装脚本会检查当前 WSL 是不是 2.0 版本,并且要确认默认发行版已经初始化。如果你的 WSL 内核版本过旧、或者默认版本还是 WSL1,脚本就会拒绝继续执行。
按这个顺序排查:
先打开 PowerShell,运行wsl --status,看输出里有没有 "默认版本: 2" 或者 "Default Version: 2"。如果显示的是 1,就说明系统默认用 WSL1 跑发行版,脚本当然认为环境不安全。
运行wsl --update更新 WSL 内核。这一步很关键,很多人的 WSL 内核停留在 2021 年左右的老版本,OpenClaw 脚本检测到内核太旧就会误判。
如果更新完还是不行,运行wsl --set-default-version 2,强制系统把新装的发行版默认切到 WSL2。
最后重新打开 PowerShell,运行wsl --status确认输出里没有红色错误提示。
其实这个报错有点"虚张声势",说"无法安全验证"听着很吓人,实际上 90% 的情况就是内核版本太老。你先别急着重装 WSL,按上面三步走基本都能解决。
2.3 启动容器并验证服务状态
环境搞定后,Docker Compose 启动就比较顺利了:
docker compose up -d启动完成后,我会习惯性检查三件事:容器状态、日志输出、端口监听。
docker compose ps docker compose logs --tail=100正常状态下,OpenClaw 容器应该是Up状态,日志里能看到成功连接模型 API 的提示。如果你配置了多个助手,启动时日志也会列出每个助手加载的模型和人格信息,这时候基本可以确认网关已经就绪了。
顺带提一句,如果容器一直重启,先别急着看代码错误,优先查网络连通性和模型 API 的 Key 配置。大部分"容器起不来"的问题都出在这两处。
3. 创建 Telegram Bot 并调好 Topics 权限:最容易翻车的一环
很多人部署 OpenClaw 本身很顺利,反而在 Telegram 侧栽了跟头。Telegram Bot 的权限配置非常细,差一个开关就可能导致 Bot 收不到任何普通消息。
3.1 BotFather 创建 Bot 并保存 Token
打开 Telegram,搜索 @BotFather,发送/newbot,按提示输入 Bot 显示名称和用户名。创建完成后 BotFather 会返回一个 token,形如123456:ABC-DEF...。
这个 token 就是 OpenClaw 连接 Telegram 的钥匙。我的建议是立刻把它存到一个本地密码管理器里,不要直接贴在群聊或者代码仓库里。Token 泄露意味着别人可以直接控制你的 Bot。
3.2 关键开关:关闭隐私模式与开启群组模式
这一步是整套方案里最容易踩的坑。
Bot 默认开启隐私模式(Privacy Mode),在这种模式下,Bot 只能收到命令消息(以/开头)以及针对它的回复,收不到普通用户随便发的日常消息。这显然不能满足我们的需求——用户在每个 Topic 里发的都是普通对话,Bot 必须能接收到所有消息。
关闭隐私模式的操作:
给 @BotFather 发送/setprivacy,选择你的 Bot,然后选择Disable。这一步完成后,Bot 才能看到群里的所有消息。
给 @BotFather 发送/setjoingroup,选择Enable,允许 Bot 被加入群组。
做完这两步,Bot 的基本权限才算准备好。
3.3 创建群组并开启 Topics 模式
建群后默认是不开 Topics 的,需要在群设置里手动开启:
进入群设置 ->「群组类型」-> 开启「话题(Topics)」。开启后,群内会自动创建一个General话题,然后你就可以通过群底部的"创建话题"按钮添加新话题了。
在这个方案里,我建议按助手的职责命名话题,比如写作文案、代码调试、日常问答。话题名字将来会直接参与路由匹配,起好名字能省不少事。
3.4 把 Bot 拉进群并给足权限
在群成员管理里把 Bot 添加进来,然后在群设置中检查 Bot 的权限:
| 权限项 | 是否必需 | 原因 |
|---|---|---|
| 读取消息 | 必需 | 读不到消息就没法做任何处理 |
| 发送消息 | 必需 | 回答要发回群里 |
| 管理话题 | 强烈建议 | 部分操作需要创建或归档话题时用得上 |
| 删除消息 | 可选 | 失败场景下清理错误回复时方便 |
需要提醒的是:如果你在 Bot 还在隐私模式下就把它拉进群,之后才用 BotFather 关闭隐私模式,通常需要把 Bot 从群里移除再重新添加一次,权限开关才会真正生效。这个细节我后来是在日志里看到消息一直进不来,排查了半小时才发现的。
4. 把多个 AI 助手绑到不同 Topic:OpenClaw 配置实操
环境通了、Bot 也进群了,接下来就是重头戏——把 OpenClaw 里的助手和 Telegram Topic 映射起来。
4.1 OpenClaw 里一个 assistant 是什么
在 OpenClaw 的语境下,一个 assistant 就是一个独立运行的 AI 助手实例,它包含四样东西:System Prompt(人格与职责设定)、模型选择(GPT 还是本地 Qwen)、推理参数(温度、最大 token 数、上下文长度)、工具或插件(是否需要联网、是否需要读写文件)。
我先配置了两个助手做验证。一个是writer,专门写文章和文案,语气温和、结构化输出;一个是coder,专门处理编程问题,输出代码时带注释。两个助手使用同一个模型后端,但 System Prompt 完全不同,温度设置也不一样——写作用 0.7,代码用 0.2。
4.2 编写多助手配置
OpenClaw 的配置文件是 YAML 格式,大致长这样(具体字段名称以你安装的版本为准,但结构是通用的):
assistants: - name: writer description: 负责写作、文案、创意内容 model: qwen2.5:3b temperature: 0.7 system_prompt: | 你是一位资深文案编辑,擅长中长文写作。 回答要求结构清晰、语言自然,避免空话。 - name: coder description: 负责编程问题、代码调试 model: qwen2.5:3b temperature: 0.2 system_prompt: | 你是一位资深软件工程师,擅长代码编写与调试。 回答时先给出思路,再给出完整可运行的代码。配置文件的要点是:每个 assistant 必须有独立名称,不要重名;description这段将来在日志和路由匹配里很有用;System Prompt 里明确"你是谁、怎么回答",因为这是隔离助手行为的关键。
4.3 拿到 Topic ID 并完成路由映射
Telegram 的 Topic 创建后会自动分配一个message_thread_id,也就是 OpenClaw 做消息路由的依据。怎么拿到这个 ID 呢?最直接的方法是先在群里往某个 Topic 发一条消息,然后去看 OpenClaw 的日志,日志里会打印收到的 Telegram 消息结构,其中就包含message_thread_id字段。
拿到 ID 后在配置里做映射:
telegram: token: "你的Bot Token" routes: - topic_id: 12345 assistant: writer - topic_id: 67890 assistant: coder - fallback: writer这里我默认没有匹配到特定 Topic 的消息会落到fallback指定的助手,避免出现"消息进来了但没人处理"的情况。
关于 Topic ID 我有两个经验:第一,不同环境的 ID 不通用,测试环境拿到的 ID 和生产环境不一样,要重新取;第二,如果你删除了一个 Topic 再重建,即便名字一样,ID 也变了,需要更新配置并重启。后来我更倾向于用 Topic 的标题做匹配,这样对运维友好一些——不过有些版本只支持 ID 匹配,那就老老实实用 ID。
4.4 把本地模型 Qwen2.5-3B 关联到 OpenClaw
热词里有人在问 "qwen2.5-3b 关联到 openclaw",这个操作其实不复杂,关键在于用 Ollama 跑本地模型,然后让 OpenClaw 通过 OpenAI 兼容接口调用它。
先在宿主机(或局域网内另一台机器)安装 Ollama,拉取模型:
ollama pull qwen2.5:3b启动 Ollama 服务后,在 OpenClaw 的模型配置里设置:
model_providers: - name: local-qwen type: ollama base_url: http://host.docker.internal:11434 default_model: qwen2.5:3b这句host.docker.internal是 Docker 容器访问宿主机的专用地址。如果你和我一样把 Ollama 和 OpenClaw 装在同一台电脑上,就必须用这个地址,而不是localhost——容器里的localhost指向容器自己。
关联本地模型最大的价值在于:像"日常问答""草稿生成"这类轻量任务可以完全走本地模型,不消耗 API 配额;只有写作、代码这类高质量需求才走到云端模型。省钱和隐私兼得。
5. 实测:所谓"完全独立"到底做到了什么程度
配置全部完成,重启 OpenClaw,接下来是最让人兴奋的验证环节。我实际测试了三个维度:上下文连续性、跨 Topic 隔离性、路由准确性。
5.1 同一个 Topic 内的上下文连续性
我先在写作文案这个 Topic 里发了一句:"帮我写一段欢迎新员工的致辞,200字以内,语气亲切。"
助手回了一版,我追问了一句:"把第二段改得更正式一些。"
这一轮追问如果能在上下文里生效,说明同一个 Topic 的消息被正确合并到了同一个会话上下文中。实测结果符合预期——助手知道 "第二段" 指的是上一轮回复里的第二段,说明 OpenClaw 按 Topic 隔离会话 ID 的机制是生效的。
5.2 不同 Topic 之间的记忆隔离验证
隔离性是这套方案的核心卖点,我的测试方法比较粗暴:先在日常问答话题里告诉助手"我的名字叫老周,职业是化工行业的项目经理";然后切到代码调试话题,问它"我刚刚告诉你我叫什么名字,你还记得吗?"
如果隔离机制正常,代码调试助手应该完全不知道这段对话历史,它会回答"抱歉,我不清楚"或者"我们没有聊过这个话题"。实测结果确实是后者——两个助手各自维护独立的会话记录,互不干扰。
这背后其实不只是 System Prompt 的隔离,更是会话上下文的隔离。OpenClaw 在内部给每个 Topic+User 的组合生成了独立的 session key,消息进来后按 key 读取对应的历史记录。所以我们说的"完全独立",核心是上下文独立,而不是模型实例必须独立跑一份。
5.3 路由准确性和兜底机制
我分别往两个 Topic 发消息,观察 OpenClaw 日志中路由的结果,确认消息 -> Topic -> Assistant的链路是准确的。
这里还要测试兜底:我故意在General话题(没有配置映射)里发了一条消息,日志显示消息被fallback助手处理了。兜底机制很重要,它保证了即使你新建了一个话题忘了配置,Bot 也不会"装死",至少有个默认助手在干活。
6. 运维记录:我踩过的坑和常用排查顺序
配置跑通之后,剩下的就是日常使用和偶尔排错了。我把自己遇到频率最高的几个问题整理出来,按排查顺序写清楚。
6.1 Bot 收不到任何消息
这是最常见的问题。排查顺序我建议这样来:
先在群里直接发一条普通文本消息,如果 Bot 没有任何反应,第一件事打开 OpenClaw 日志看有没有显示收到 Telegram 更新。如果连日志都没有,说明 webhook 和 getUpdates 之间可能有冲突——Telegram 的 Bot 只能二选一,开着 webhook 就不能用 getUpdates。
然后检查 Bot 的隐私模式是否关闭。我在前面强调过,隐私模式没关的话普通消息根本不会推给 Bot。去 BotFather 重新执行一遍/setprivacy,选 Disable。
最后检查 OpenClaw 配置里的 token 是否正确。这里有个小细节:token 里包含冒号,复制的时候很容易在行首行尾带上多余空格,导致认证失败。建议用编辑器开启"显示空白字符"核对一遍。
6.2 消息路由到了错误的助手
你会发现某个 Topic 里发消息,回答内容明显是另一个助手的风格。这种问题的根因几乎都是message_thread_id配置错了。
建议在 OpenClaw 日志里找到消息的原始结构,核对实际收到的message_thread_id和配置里写的是否一致。另外,注意 Telegram 里"回复某条消息"和"直接在 Topic 里发言"携带的 thread ID 可能不同,尽量以"直接在 Topic 底部输入框发送"为准。
6.3 本地模型响应慢或者超时
Qwen2.5-3B 在纯 CPU 环境下跑,单次响应可能要十几秒甚至更长。如果你的机器没有 N 卡,建议在 OpenClaw 推理配置里把request_timeout调大一些,比如从默认的 30 秒调到 120 秒。
如果实在慢得难受,我的经验是:本地模型负责简单任务(翻译、关键词提取、文本改写),云端模型负责复杂任务(长篇写作、代码生成)。在 OpenClaw 里给不同的 assistant 配不同的模型 provider,就是为这种混合场景准备的。
6.4 常用日志命令
调试期间我反复用的三个命令:
# 查看 OpenClaw 全部日志 docker compose logs -f # 只看最近 200 行,过滤 Telegram 相关 docker compose logs --tail=200 | grep -i telegram # 查看路由命中情况 docker compose logs | grep -i route日志里会打印每条消息的 source、thread_id、assistant 名称,排错时一目了然。
最后再分享一个小技巧:我给每个 Topic 在 Telegram 里配了一个固定表情图标,比如写作话题用笔的图标,代码话题用括号图标。这样不管是谁打开群聊,一眼就能看出哪个话题是干什么的。整套方案我现在用了快两个月,一个 Bot、一个群、六个话题,工作、写作、个人助理各司其职,维护成本几乎为零。如果你也想把所有 AI 助手收拢到一个入口,照着这条路线走,应该能少踩不少坑。