技术支持 wechatapi.net

最近我一直在做一个比较实际的方向:
把微信接成 OpenClaw 的一个真实入口。

不是做一个简单的“消息转发脚本”,而是希望做到下面这种完整链路:

  • 用户在微信里发消息
  • 本地网关接收回调
  • 根据私聊 / 群聊 / 会话类型做路由
  • 调用 OpenClaw
  • 再把结果发回微信

这个项目做到后面,我越来越觉得:
真正有价值的不是“机器人脚本”,而是“入口层”。


一、为什么我会做这个方向

现在很多 AI Agent、工作流、自动化平台,能力已经很强了:

  • 大模型调用
  • 工具执行
  • 工作流编排
  • 任务状态管理

但这些东西最后经常卡在一个问题上:

用户到底从哪里进入?

如果只是网页入口,那适合部分场景。
但对于很多国内真实业务来说,微信仍然是最高频、最自然的入口之一。

所以我想验证一件事:

能不能把微信变成 OpenClaw 的一个可用入口,而不是单纯做个演示脚本?

我手里本身就有微信接口能力,所以这次的底层接入是基于 wechatapi.net 这类接口能力来完成的。对我来说,这个项目一方面是技术验证,另一方面也在反过来检验微信接口在真实 Agent 场景里的可用性。


二、整体架构是怎么设计的

我最后没有把它继续写成一个“收到消息就直接调用 AI”的短脚本,而是拆成了几层:

微信回调
   ↓
FastAPI 接口层
   ↓
回调解析层
   ↓
消息标准化
   ↓
Session 路由
   ↓
Worker 队列
   ↓
OpenClaw 调用层
   ↓
微信发送层

这样设计的原因很简单:

  • 回调层只负责接和拆
  • 路由层负责区分私聊 / 群聊 / 会话
  • 执行层负责真正调用 OpenClaw
  • 发送层统一做文本 / 图片回发

如果把这些全堆在一个函数里,项目一旦变复杂,基本就很难继续维护。


三、先说一个最容易踩的坑:微信回调不能按想当然来解析

一开始我以为只要拿到 Content.string 就够了,后来发现不是这样。

根据真实回调结构,至少要关心这些字段:

  • TypeName
  • Wxid
  • Data.MsgType
  • Data.FromUserName.string
  • Data.ToUserName.string
  • Data.Content.string

而且有几个逻辑一定要做对。

1. 是否自己发送

不能只看 FromUserName,而要结合 Wxid 判断:

is_self = bool(wxid and from_user == wxid)

2. 是否群消息

群消息不能只看一个字段,要结合发送人和接收人判断:

is_group = from_user.endswith("@chatroom") or to_user.endswith("@chatroom")

3. 群内真实发送人

群消息里真实发送人,可能在 Content.string 前半段:

if is_group and raw_content and ":\n" in raw_content:
    possible_sender, possible_text = raw_content.split(":\n", 1)
    if possible_sender.startswith("wxid_"):
        sender_wxid = possible_sender
        actual_text = possible_text.strip()

如果这些解析不做严谨,后面上下文一定会乱。


四、我为什么没有把它继续做成“简单聊天脚本”

如果只是最小 demo,其实一段逻辑就能跑:

@app.post("/wechat/callback")
async def handle_wechat(request: Request):
    data = await request.json()
    text = extract_text(data)
    result = call_openclaw(text)
    send_back(result)
    return {"ok": True}

但这种写法有几个明显问题:

  • 群聊和私聊混在一起
  • 没有会话层
  • 没有去重
  • 没有排队
  • 没有白名单
  • 后续很难扩展到企微、TG 或别的入口

所以我后来改成了 网关思维,而不是脚本思维。


五、我最终保留了哪些关键能力

1. 首次命令行初始化

第一次运行时直接输入:

  • WX_API_TOKEN
  • PUBLIC_URL
  • 群触发词
  • 地区 ID

并自动生成 config.ini

这里我故意把初始化做得更像“产品入口”,因为我越来越觉得:
如果连接入体验都很糟糕,别人根本不会认真评估这套方案。

2. 配置自动生成

配置文件自动写出,并保留中文注释,后续可调。

3. 白名单

私聊不做白名单限制的话,很快就会失控。

4. 群触发词

群里不是所有消息都应该触发机器人,至少先用触发词收口。

5. 同会话串行,不同会话并行

这是入口层最关键的一点之一:

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

这样不同用户不会互相阻塞,但同一个会话也不会乱序。


六、这套东西最核心的瓶颈其实不在微信

这一点我一开始判断错了。

我最开始以为慢,主要是微信回调慢。
但后来打日志后发现,真正慢的是这一段:

cmd = ["openclaw", "agent", "--session-id", sid, "--message", message.strip()]
res = subprocess.run(cmd, ...)

也就是说,每来一条微信消息,我实际上都在重新起一次 OpenClaw CLI 进程。

这意味着每次都要:

  • 启动进程
  • 读取配置
  • 恢复上下文
  • 初始化 provider
  • 再请求模型
  • 再退出

所以体感上一定比前端慢。

这一点后来也让我更明确地认识到:
微信入口层是值得做的,但要想做到真正流畅,后面还是要考虑 OpenClaw 常驻化,而不是长期依赖 CLI 单次调用。


七、这个项目对我最大的价值是什么

说实话,一开始我以为它最大的价值是“做出一个机器人”。
但做到后面,我的判断变了。

我现在觉得,它真正的价值是:

1. 验证微信是不是一个值得投入的 Agent 入口

答案是:是。

2. 验证微信 API 在真实场景里能不能承接 AI 工作流

答案也是:可以,但前提是入口层要认真做。

3. 验证接口能力是不是应该只卖“API”

我现在越来越觉得,单卖接口太抽象。
相比之下,把接口能力做成一个可见、可跑、可理解的入口方案,更容易让别人看懂价值。

这也是为什么我这次做下来,对 wechatapi.net 这种底层能力的看法更明确了:
底层接口当然重要,但真正放大价值的,往往是入口方案和场景包装。


八、这套方案适合哪些场景

目前我觉得比较适合这些:

  • 微信 AI 助手
  • 私域群聊问答
  • 知识库入口
  • 指令型机器人
  • 自动客服
  • 业务流程触发器

尤其适合已经有:

  • 模型能力
  • OpenClaw 工作流
  • 私有知识库

但缺“用户入口”的团队。


九、我现在的结论

如果只是做一个 demo,
把微信接上 OpenClaw 并不难。

但如果想让它变成 真实可用的入口层,需要做的事情会比想象中多很多:

  • 解析回调
  • 做好群聊判断
  • 过滤自己消息
  • 做会话路由
  • 控制上下文
  • 做并发与顺序
  • 处理 CLI 延迟问题

不过这件事依然值得做。

因为在很多真实业务里,
用户不会先问你用了什么模型、什么框架。
他们先问的是:

能不能在微信里直接用?

而这,恰恰就是入口层的价值。


十、最后

这篇文章更多是我当前阶段的技术总结。
如果后面我把这套东西再往前推一步,我更想继续做两件事:

  1. 把微信入口层做得更稳定
  2. 把微信 / 企微这类入口能力逐渐抽象成可复用网关

如果你也在做类似方向,欢迎交流。

我这次的底层接入验证主要基于 wechatapi.net 这类能力做的,后面如果我继续往下打磨,应该也会围绕“入口层 + 场景方案”这个方向继续展开。

Logo

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

更多推荐