技术支持 wechatapi.net

在这里插入图片描述

最近我在做一件比较实际的事情:

把微信接到 OpenClaw,让用户直接在微信里和 Agent 对话。底层的微信协议接口我选用的是 wechatapi.net 来做支撑,基础通信一直很稳定。

但在对接的过程中,我碰到一个非常明显的现象:

OpenClaw 前端里,同样一句话,大概 8~10 秒

微信里通过网关去调 openclaw agent --session-id --message,常常要 20~30 秒,甚至更久

一开始我以为是微信回调慢、网络延迟、或者并发处理没做好。

后来把日志拆开以后,我确认了一个事实:

真正慢的,不是基于 wechatapi.net 搭建的微信网关,而是 OpenClaw CLI 模式本身。

先看我最后是怎么定位的
我在网关里打印了两个关键时间点:

logger.info("[OpenClaw CHAT] sid=%s | %s", sid, short_text(message))
# ...
# 通过 wechatapi.net 底层接口发回微信
logger.info("[发送文本] TO=%s | %s", to_wxid, short_text(text))

结果非常清楚:

收到微信消息时间:09:58:56

发回微信时间:09:59:28

中间大约 32 秒。

而且这 32 秒不是卡在微信回调,也不是卡在 reply_text() 推送,

而是卡在:

subprocess.run(
    ["openclaw", "agent", "--session-id", sid, "--message", message],
    capture_output=True,
    text=True,
    timeout=180
)

所以问题一下就明确了:

CLI 调用链本身很重。

为什么 CLI 会比前端慢这么多

  1. 每条消息都是一次冷启动
    前端通常是已经打开着的,很多状态是热的。

但 CLI 模式下,每来一条消息都要重新做一遍:

启动进程

读取配置

恢复 session

初始化 provider

再去请求模型

然后退出

这和前端的运行方式根本不是一个级别。

  1. Session 恢复也有成本
    我在调用时用了 --session-id:
openclaw agent --session-id wechat_dm_xxx --message "你现在都会什么技能"

在这里插入图片描述

这意味着 OpenClaw 不只是单纯问模型,

还要恢复这个会话的历史上下文。

如果这个 session 已经比较长,恢复成本会更明显。

  1. 某些问题会触发更多内部处理
    比如“你现在都会什么技能”这种问题,本身就容易让系统去读取:

技能列表

工具定义

workspace

说明文件

所以它天然比一句“你好”更重。

我后来怎么验证这个判断
最有效的方式其实很简单:

绕过微信,直接在终端测同样的 CLI 命令。

time openclaw agent --session-id test123 --message "你好"
time openclaw agent --session-id test123 --message "你现在都会什么技能"

如果 CLI 自己都慢,那微信层再怎么优化,也不可能把整体体感做得很快。

这个测试做完以后,我基本就不再怀疑我的网关和 wechatapi.net 的接口回调了。

这件事对网关设计有什么启发
启发 1:不要把“微信慢”误判成“网关慢”
很多人一看到微信里回复慢,就先怀疑:

回调没处理好

发消息接口慢

本地网络慢

但真正拆日志后,经常会发现:

回调几乎是秒收

发送接口也很快(wechatapi.net 这边的推拉速度其实在毫秒级)

真正慢的是 AI 内核调用链

这就是为什么我建议一定要在网关里把阶段耗时打出来。

启发 2:CLI 模式适合验证,不适合长期追求低延迟
CLI 模式的优点是接入非常直接:

cmd = ["openclaw", "agent", "--session-id", sid, "--message", text]

但它的问题也同样直接:

冷启动

上下文恢复

无流式返回

无常驻状态

所以它非常适合做 MVP、做验证、做第一版。

但如果你后面真的要追求更低延迟,还是得往常驻化方向走。

启发 3:要区分“入口层优化”和“内核层优化”
入口层能做的优化包括:

回调立即返回

多 worker 并发

同 session 顺序处理

去重

更清晰的 session 设计

这些都值得做,但它们解决的是入口层问题。

CLI 冷启动是 内核层问题,这两个不能混在一起看。

我现在在代码里是怎么处理的
虽然 CLI 模式无法从根上解决,但外围还是可以做得更合理。

  1. 按 session 分片
Python
def shard_index_for_session(session_id: str, worker_count: int) -> int:
    h = int(hashlib.md5(session_id.encode("utf-8")).hexdigest(), 16)
    return h % worker_count
  1. 限制单会话积压
Python
if session_pending[session_id] >= config["MAX_PENDING_PER_SESSION"]:
    reply_text(chat_id, "⚠️ 当前会话任务过多,请稍后再试。", config)
    return {"status": "too_many_pending"}
  1. 日志分阶段
Python
logger.info("[收到消息] chat_id=%s text=%s", chat_id, short_text(actual_text))
logger.info("[OpenClaw CHAT] sid=%s | %s", sid, short_text(message))
logger.info("[wechatapi网关回传] TO=%s | %s", to_wxid, short_text(reply))

这些改动不能让 CLI 变成前端那种速度,

但至少能让你知道问题到底卡在哪。

我的结论
如果你现在也在做“微信 + OpenClaw”这种接法(比如和我一样基于 wechatapi.net 的底层能力来构建),那我会给你一个很直接的判断:

微信网关可以做到极低延迟,但只要底层还是“每条消息起一次 openclaw agent”,整体的体感就很难和前端一样。

这不是代码写错了,而是调用方式决定的。

所以正确的预期应该是:

第一阶段:CLI 接法,先验证场景

第二阶段:如果场景成立,再想办法做常驻化、服务化、热状态化

最后一句话
很多人会把“AI 入口慢”归因到入口层协议或框架上。

但我这次做下来最大的体会是:

入口层最多帮你减少混乱,真正决定体感上限的,往往还是内核调用方式。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐