2026-04-21 15:54:00
上一次写 blog 是 2019 年,一晃已经六七年过去了。这段时间里 AI 的形态变了太多——从 GPT-3 出圈、ChatGPT 刷屏,到现在 Coding Agent 已经能替我写大半业务代码、重构老项目。既然这波浪潮这么猛,那就蹭一下热度,用一个最近刚落地的小项目记录点东西。
这次的主角是 wechat-clawbot-gateway——一个微信消息网关。定位很简单一句话:微信是通道,不是应用。下面讲讲它的思路、实现原理,以及我是怎么和 Claude 把它写出来的。
为什么要做这个
我家里跑着一堆零碎的小服务:HomeAssistant 控灯、QNAP 存资料、Transmission 下电影、一堆 IoT 传感器、再加上一些脑洞大开想跑的 AI Agent。它们各自都有告警和交互的需求,但各自的 App 分散、体验割裂。微信是我打开频率最高的 App,如果能把所有这些东西都"通到微信上",那手机端就有了一个统一的控制面板。
市面上的方案大多是"微信机器人 + 某个垂直应用"——比如只做 AI 问答,或者只做 HomeAssistant 通知。我想要一个更底层的东西:微信只负责收发消息,下游接什么业务,通过插件随便接。
整体架构
三层结构,每层职责干净:
WeChat User
↓ iLink 协议(腾讯 OpenClaw 公开 HTTP API)
WxClient ← 只做:扫码登录 + 长轮询收消息 + 发消息
↓ EventEmitter
Gateway ← 事件总线 + 命令路由 + Channel 生命周期
↓
┌─────┬───────┬──────┬──────┬────────┬─────────┬──────┐
TUI Webhook MQTT LLM IFTTT OpenClaw Exec ...
WxClient 是最底下的协议层,封装成一个 EventEmitter:on('message') 吐入站消息、send(userId, text) 发出站消息。扫码凭证落盘到 ~/.wechat-gateway/credentials.json,重启不用重新扫。长轮询 35 秒超时、失败指数退避,和微信之间始终挂着一条连接。
Gateway 往上对接 WxClient,往下管理 Channel。它不包含任何业务逻辑,只做三件事:
1. 解析命令前缀 /xxx args,把消息路由到对应 Channel 的 handler
2. 广播全局 log / debug 事件(TUI 和日志收集都订阅这个)
3. 给每个 Channel 发一个 ChannelContext,Channel 只能通过 Context 和外界交互
Channel 才是具体的业务。接口非常薄:
interface Channel {
readonly name: string;
start(ctx: ChannelContext): Promise<void>;
stop(): Promise<void>;
}
interface ChannelContext {
send(userId, text); // 发给指定用户
notify(text); // 发给默认通知用户
onCommand(cmd, handler); // 注册 /cmd 命令
onDefault(handler); // 无前缀消息兜底
debug(detail); // 调试信息(TUI 会显示)
}
Channel 之间互不感知、互不依赖。要加新能力,新写一个文件 + 在 index.ts 注册一行,完事。
已落地的 Channel
TUI——跑在终端里的系统控制台,实时看所有消息流动,还能直接敲键盘聊天,调试用。
Webhook——对外暴露 HTTP 端点,其他服务 POST 一个 JSON 进来,按模板 {{key}} 渲染后发到微信。HomeAssistant 的 notify.wechat、QNAP 的告警短信、Transmission 下载完成回调全靠它。
MQTT——双向桥接。订阅主题 → 微信通知;微信发 /ha 开客厅灯 → publish 到 wechat/command,HA 接手交给 conversation.process 走自然语言解析。
LLM——命令触发的无状态 AI 问答。/deepseek 黄金和石油价格的关系 直连 DeepSeek API 出答案。多模型各注册一个命令,互不干扰。
IFTTT——/ifttt <event> 触发 Applet;IFTTT 也能反过来通过 Webhook 推消息到微信。
OpenClaw——这是最有意思的一个。把 Gateway 反过来暴露成 OpenClaw 兼容服务端(POST /openclaw/getupdates + POST /openclaw/sendmessage),让外部 AI Agent 直接"订阅"我的微信。消息进来排队,Agent 长轮询拿走,处理完 POST 回来就发到微信。等于给任何 Agent 框架开了一个接入微信的后门。
Exec——最危险也最爽的一个。微信命令映射成 shell 脚本,JSON stdout 自动解析成模板变量。/ping baidu.com 就是真的在家里机器上跑了一遍 ping,结果回到手机。
应用效果
真正跑起来之后,微信聊天框变成了我整个家的控制面板:
出门路上收到 [webhook-ha] 前门已打开——门磁触发自动化 → HA 调 notify.wechat → 网关推过来。
电影下完收到 [webhook-transmission] 任务 ubuntu-24.04.iso 下载完成(4.2GB)——Transmission 的 script-torrent-done 调 webhook。
想问点东西就 /deepseek ...,不想切 App。
临时要开灯就 /ha 打开客厅灯,不用打开 HA 的 App。
关键是所有这些走的都是同一条扫码登录的 iLink 连接,没有二次账号、没有订阅号审核、没有小程序审批——家用场景足够了。
和 Claude 是怎么合作的
这部分比代码本身还值得写——毕竟整个项目从 0 到跑起来,我实际敲键盘写的业务代码不超过 100 行。
第一步:先写设计文档,而不是直接让它写代码。
我先花半个小时和 Claude 聊清楚我的目标:"微信作为通道,下游插件化,我要 HA、LLM、Agent 都能接"。它帮我把想法落成了一份 docs/design.md——有架构图、接口定义、消息流详解、甚至 systemd 部署方案。这份文档后来成了整个项目的"真源",它和我重新对齐上下文时都回去看它。
这一步很关键。如果一上来就让它写代码,写出来的东西可能能跑,但架构会是"它当时的第一反应",而不是我想要的样子。先做架构对齐,再进施工,和带人做项目是一样的道理。
第二步:分 Phase 推进,每个 Phase 都可运行。
我和它把项目切成了 docs/phases.md:
Phase 1:iLink 协议层 + WxClient(扫码能登录、能收发文本)
Phase 2:Gateway + Channel 接口 + TUI(能在终端看到消息了)
Phase 3:Webhook Channel(第一个真正的业务)
Phase 4:MQTT / LLM
Phase 5:OpenClaw 服务端
Phase 6+:多媒体、IFTTT、Exec、命令帮助系统...
每个 Phase 结束有一个明确的"可以扫码登录并看到效果"的验收动作。我扫了码、验证了,再开下一个 Phase。出问题就止步当前阶段,不让它继续往下推。
第三步:用 CLAUDE.md 给它存"工位记忆"。
Claude Code 的惯例是在仓库根放一个 CLAUDE.md,写清楚架构、目录约定、运行命令。这个文件本质上是"给下一次对话的简报"——它每次新起一个会话,第一步就是读 CLAUDE.md,所以我迭代几次后就把 Gateway 和 Channel 的职责边界固化进去。之后它再加新功能,基本不会越界乱动别的 Channel。
第四步:把人类擅长的那一半留给自己。
Claude 擅长"按照一个清晰的接口写实现",不擅长"感知真实运行环境"。所以我的分工是:
我做:扫码、对着手机测真实消息、抓 tcpdump、读微信回的那种没见过的错误码、判断"这个实现虽然 tests 通过但是体感不对"。
它做:协议封装、TypeScript 类型体操、写测试、写文档、想 Channel 抽象的边界、处理重连/退避/超时/鉴权。
碰到那种"消息发出去没反应、也不报错"的玄学 bug,我会抓包 + 贴日志给它看,它很快就能定位到是 contextToken 管理的问题还是长轮询 hang 住了。反过来,纯算法或者协议解析那种,我连看都不想看。
第五步:对话节奏要快、反馈要狠。
Agent 最大的问题是"会自信地写出错误的代码"。我养成了几个习惯:
每个 Phase 跑起来的第一件事不是看代码,是扫码试一下。跑不起来就打断,让它先修。
如果它开始"补充防御性代码""加各种 fallback""封装一个抽象基类",我就立刻打断——"简化,砍掉"。
设计歧义的时候不让它猜,直接问我。我发现它"反问我"的频率越高,最后产出的质量越好。
一些感受
这种协作方式,我体感上已经不是"我在用工具"了,更像是"我带了一个资深工程师结对"。我负责把问题定义清楚、把真实环境反馈回来、对架构拍板;它负责把活干完。
几年前我写 blog 那会儿,所有这一切都得自己敲——查 npm 包、读协议文档、写 TypeScript 类型、调 long-polling 重连、部署 systemd。现在这些环节基本都外包了,我的精力全花在"这个产品该长成什么样"上。
写完回头看,最大的心得其实不是"AI 多能写代码",而是"你有多清楚自己想要什么"——对齐得越清楚,Agent 产出越靠谱。相反,如果自己都说不清要什么,再强的模型也只能帮你做出一个"还行但不对"的东西。
项目开源在 GitHub:https://github.com/fooling/wechat-clawbot-gateway,有兴趣自己 clone 下来扫个码跑跑看,家里的那些小服务都能接进来。
下一篇不会再隔六年了(大概)。