从一条微信消息到 AI 回复:wechat-bot 消息链路的接力逻辑
【免费下载链接】wechat-bot🤖 Multi-platform IM AI Agent for Telegram, WhatsApp, Lark, and WeChat. Connects ChatGPT / Claude / Kimi / DeepSeek / Ollama / Pi for auto-replies, community analysis, contact management, and inactive-friend detection.项目地址: https://gitcode.com/GitHub_Trending/we/wechat-bot
读完本文,你会弄明白 wechat-bot 的消息链路子系统如何接管一条微信消息:它如何被捕获进本地 JSONL 文件、如何被门禁与路由、如何交给十几种模型服务商之一。包含最小可运行路径、一条消息的接力时间线,以及服务商插件契约。
第一层:跑通一次自动回复的最小知识集
如果你只关心"让 wechat-bot 在微信里回消息",需要知道的事实只有五条:
- IM 接入层是 Wechaty(一个抽象多种 IM 的机器人框架),项目使用 wechat4u 这个 puppet(Wechaty 对"协议适配器"的称呼),底层是用无头 Chromium 驱动微信网页版,登录方式只有终端里的二维码。
- 运行行为全部由
.env决定:BOT_NAME(机器人名字)、ALIAS_WHITELIST(私聊白名单)、ROOM_WHITELIST(群白名单)、AUTO_REPLY_PREFIX(触发前缀)。 SERVICE_TYPE选择模型服务商,可选十几种,每一种要求的必填环境变量不同。- 非文本消息默认一律不处理;群聊必须 @ 机器人。
npm i+npm link+wb agent --im wechat --agent pi就能拉起完整链路,没有别的依赖。
没有框架、没有数据库,就是一个 Node 进程。
第二层:追踪 wechat-bot 消息链路的接力路径
以"白名单好友私聊发来一条带前缀的消息"为例,按时间线逐角色看:
Wechaty 消息事件:Wechaty 收到网页版事件后触发message,src/platforms/wechat/bot.js里的bot.on('message')回调是整条链路的唯一入口,它把同一条消息交给下游两个角色。
捕获层:src/platforms/wechat/messageStore.js 的captureWechatMessage把发送人、群名、时间戳、文本序列化成 JSON,往.data/wechat/messages.jsonl追加一行,原文原样传给回复层。这步受WECHAT_STORE_MESSAGES开关控制。
门禁层:src/wechaty/sendMessage.js 的defaultMessage做四次连续判断:发送人是不是机器人自己、消息是不是文本、发送人是否白名单、内容是否以命令前缀或回复前缀开头。任一不过就丢弃消息,通过则把原文交给路由。核心判断逻辑如下:
const isAuthorizedCommand = (room && isRoom) || (!room && isAlias) if ((isBotSelf && !isBotSelfDebug) || !isText) return if (content.replace(`${botName}`, '').trimStart().startsWith(commandPrefix)) { if (!isAuthorizedCommand) return const commandResult = await handleWechatCommand(content, { serviceType: ServiceType, roomName, alias, name, }) if (commandResult.handled) { if (commandResult.reply) await (room || contact).say(commandResult.reply) return } }路由层:带/前缀的消息进handleWechatCommand(定义在 commandRouter.js),可以触发本地统计等动作;未识别的命令返回handled: false,消息继续掉进回复分支。普通消息则直接进入取服务商一步。
服务商层:src/wechaty/serve.js 的getServe(ServiceType)按名字找到对应模块并动态 import——惰性加载,即首次调用才拉入该模型的依赖,然后执行getXxxReply(prompt),把返回的字符串交给发送层。
发送层:contact.say(response)或room.say(response)经 Wechaty 把文本发回微信,链路结束。
第三层:新增一个模型服务商要改哪三个地方
服务商层的契约很简单:任意服务商模块导出一个getXxxReply(prompt) => Promise<string>的异步函数,接收字符串提问、返回字符串答复。以 src/deepseek/index.js 为例,整个文件只有 20 行:构造 OpenAI 兼容客户端,把 system 消息与用户提问塞进chat.completions.create,返回choices[0].message.content。
接入一个新服务商,恰好要动三处:
- 新建
src/<name>/index.js,导出getXxxReply; - 在 src/wechaty/serve.js 的
getServe加一个 case,外包一层lazyServe,这个包装函数只有 5 行:
function lazyServe(loader, exportName) { return async (...args) => { const module = await loader() return moduleexportName } }- 在 src/index.js 的
serveList加入名字,并在getMissingConfig里写好该服务商缺哪些环境变量——这样你没配 key 启动时,终端会直接告诉你要补哪个变量。
十几种服务商就是一张字符串列表加动态 import,没有任何注册框架;新增服务商不需要改动消息链路的任何一行代码。
第四层:回复没发生时如何定位问题
最短诊断路径是三个检查点,按顺序查:
- 消息进没进来:
WECHAT_STORE_MESSAGES不为false时,捕获数据全在.data/wechat/messages.jsonl(目录可用WECHAT_DATA_DIR改)。tail 这个文件就知道 Wechaty 有没有收到消息;文件不增长,问题在扫码登录或 puppet 这一侧。 - 过没过门禁:链路全程留了日志——门禁处会输出以
/ question结尾的日志行,每个服务商模块会输出/ prompt与/ reply两组日志。看到 question 行却没有任何 prompt 行,说明消息卡白名单或前缀判断,对照.env里两个白名单变量与发送人的备注名、微信号(代码先匹配alias再匹配name)。 - 数据能不能读回:执行
wb analyze --stats-only读回同一份 JSONL。统计里消息数正常而机器人不回复,问题几乎必在门禁逻辑而非接入层。
这条命令不需要配置模型 key,随时可跑,是验证"捕获层是否工作"的低成本探针。另外bot.on('error')会输出bot error handle,看到它说明错误发生在 Wechaty 内部。
延伸:分析子系统如何复用 wechat-bot 消息链路
消息链路里的"捕获"一步不只是留日志。src/analysis/wechatAnalyzer.js 读取同一份messages.jsonl,算出发言人、群、时段三组统计,再复用同一个getServe服务商,把统计结果加最近 120 条消息拼成分析 prompt。"群聊分析、不活跃好友检测"这些能力都构建在同一条数据之上。
反过来看,src/adapters/下的 lark / opencli / pi 适配器不走消息链路,它们通过src/utils/process.js的streamCommand直接调起外部 CLI(命令行界面)进程,与消息链路共享src/config/env.js这一层配置。前者是"消息进、回复出"的管道,后者是"命令透传"的通道,两者只在配置层交汇。
克隆仓库,跑一次真实私聊回复,验证整条链路:
git clone https://gitcode.com/GitHub_Trending/we/wechat-bot && cd wechat-bot && npm i && npm link如果你的模型服务商不在列表里,最快的贡献方式就是按第三层的契约补一个getXxxReply并加进getServe。
【免费下载链接】wechat-bot🤖 Multi-platform IM AI Agent for Telegram, WhatsApp, Lark, and WeChat. Connects ChatGPT / Claude / Kimi / DeepSeek / Ollama / Pi for auto-replies, community analysis, contact management, and inactive-friend detection.项目地址: https://gitcode.com/GitHub_Trending/we/wechat-bot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考