前言
微信官方终于推出了 ClawBot 用于接入 OpenClaw 了。但对于个人来说,依然必须要一个个人专属的 Claw 应用,不论是 在云端安装,还是说在自己手头的 电脑安装。
笔者这几天在研究云端共享化的 Claw 方案时就思考:大模型对外的接口协议是开放的,OpenClaw 对外也应该是开放的,在这个开放的环境下,微信也应该是以一种开放的协议接入的。只要满足了这个协议,微信才不会管你是不是一个 Claw 呢,收发消息就完了。
啥?接入微信的 Skill 是一个 TypeScript 脚本?那太好了,读一下代码就行了。这个协议似乎叫做 iLink,并不复杂,下面我们就来讲一下这个协议的接入方式。
扫码绑定微信
如果用微信的 Skill 在 OpenClaw 中接入,微信会在命令行中返回一个网址或者是展示一个二维码。我们可以用手机打开这个网址或者扫这个二维码,实现扫码绑定。
这步操作,在微信的 Skill 中,首先是请求 https://ilinkai.weixin.qq.com/ilink/bot/get_bot_qrcode?bot_type=3,这个接口会返回下面的数据:
代码语言:JSON
自动换行
AI代码解释
{
"qrcode":"34e57804cc094652cb8068e093be6eb4",
"qrcode_img_content":"https://liteapp.weixin.qq.com/q/7GiQu1?qrcode=34e57804cc094652cb8068e093be6eb4&bot_type=3",
"ret":0
}
我们需要关注的就是 qrcode_img_content。通过 PC 浏览器打开这个网址,就会展示一个二维码,提示需要用手机微信扫描。你也可以把这个网址生成一个二维码,让用户直接使用手机微信扫描。无论是什么方法,手机微信扫描后都会提示是否绑定 OpenClaw 账号。
轮询扫码结果
给用户展示这个二维码之后,程序后台就可以调用 https://ilinkai.weixin.qq.com/ilink/bot/get_qrcode_status?qrcode=${qrcode},获取用户扫码的状态。
如果用户扫码成功并绑定了,那么微信服务器会返回类似于以下格式的数据:
展开
代码语言:JSON
自动换行
AI代码解释
{
"status": "confirmed",
"bot_token": "eyJhbG...",
"ilink_bot_id": "a1b2c3d4@im.bot",
"baseurl": "https://ilinkai.weixin.qq.com",
"ilink_user_id": "wxid_abc@im.wechat"
}
各个参数说明如下:
ilink_bot_id在微信侧,应该是被映射到了一个虚拟的 AI 机器人身份,每次重新扫码,这个 ID 都会发生改变。baseurl是微信根据用户扫码后,更新返回的,可能会根据用户实际接入的地址、网络环境等有所变化。应该缓存下来,以后都使用这个 HOST 向微信发起后续调用ilink_user_id这是在微信侧对微信账号的一个标识,我怀疑跟openid的算法是类似的,同一个微信号扫不同的二维码,这个参数不会改变。bot_token用来向微信发送消息的令牌,要保存下来以后使用
看到这里我实在忍不住想吐槽:微信参数命名风格不统一的习惯什么时候能改改?为啥 bot_token 中间有分隔,而 baseurl 就是连着的呢?这只有五个参数也能打架?
轮询接收消息
我们知道,做微信公众号的时候,需要在微信公众号的管理平台上配置一个服务器 URL 用来接收用户向公众号发的消息。但是微信的 ClawBot 支持用户本地自己搭建的 OpenClaw 应用,无需云端服务就可以用自己的微信给自己电脑上的 OpenClaw 发消息。这是如何实现的?
很简单,Skill 在本地不断地向微信轮询,获取新的消息,这样就不需要云服务器了。
如果轮询到消息,返回的数据中除了消息内容之外,还包括一个称为 get_updates_buf 的字段,这其实可以视作一个翻页符,也类似于 Kafka 的 offset 参数的概念,方便调用方重试。
此外,每一个消息还包含 context_token 字段,从微信的交互来看,这似乎是用来标记消息上下文的,但没有它似乎逻辑也能成立——下文会再提及。
发送消息
文本消息
如果用户向微信 ClawBot 插件发送了一条消息,那么应用通过轮询就可以获得这个信息。此时,应用可以基于用户的消息进行回复(管你怎么回复,OpenClaw 也好,搞一个真人后台打字也好——笑)。当回复时,如果要发送一个文本消息的话,就是向微信 POST 一条消息即可。
发送消息限制
原则上,在进行此次 POST 的时候,需要带上前面提到的 context_token 参数,用来标记回复的是哪一条信息。但是实测发现,这个参数不传也是没问题的。有些开源项目中,号称可以主动向用户推送消息,用的就是这个机制——context token 参数留空。
然而,这里我们需要说一下 主动向用户发送消息 的限制了:
当用户向 ClawBot 发送了一条消息之后,Claw 应用在接下来的 24 小时内,最多可以向用户发送 10 条独立的消息,包括回复的一条。换句话说,真正自由地向用户发送消息是不可能的,除非用户 24 小时内主动发送过消息,同时应用没有用完这 10 条消息的配额。如果用户再发了一条消息,那么配额会重置为 10。
这个限制,不论 context_token 参数是否设置,都是一样的效果。
“流式” 回复
在微信官方的 Skills 中似乎封装了一个所谓的 “流式” 回复,但这其实并不是真正的流式,而只是帮你将要发送的内容,强行切割成多个消息气泡发出而已,而这每一个气泡,会占用上面说到的 10 条消息的配额,所以业务方还是谨慎使用(要不就别用了)。
多媒体消息
微信也支持图片、音频、视频等多媒体消息,发送方式大同小异,只是你需要事先将多媒体文件上传到一个网络存储中,然后再调用发送接口即可。
“对方正在输入…” 标识
如果要回复的消息很耗时间,推荐应用可以先调用一个接口,让用户的 ClawBot 界面上展示 “对方正在输入…” 的标记:

不过个人觉得这个接口挺奇怪,它需要先 POST {creds.BaseURL}/ilink/bot/getconfig 接口获取一个专用的 ticket,然后再 POST {creds.BaseURL}/ilink/bot/sendtyping 来显示这个效果。不知道微信是怎么考虑的。
需要注意的是,“正在输入” 的指示器会在微信侧显示几秒钟后自动消失,如需持续显示应定期重发(每 5-8 秒一次)。
示例代码和后记
微信的 TypeScript 代码是公开的,大家可以自行阅读。我则用 Go 重写了,读者如果感兴趣可以阅读我的 代码和 README。
至于研究这玩意有什么用?因为笔者一直是很喜欢学习底层原理的,有了这套协议,我就可以跟我的微信 ClawBot 直接交互了,我用不着安装 OpenClaw 之类的,我想怎么玩就怎么玩啦~~
当然也给大家另外的一个启示:我们可以使用微信的这个口子,做其他的一些中心化的、无需用户安装的其他 AI 机器人应用,就看各位产品经理的脑洞有多大啦。
发表回复