企微智能机器人SDK支持一个进程管理多个企微机器人
背景
企业微信官方 AI 机器人 SDK(@wecom/aibot-node-sdk)的设计是:一个 WSClient 实例 = 一个机器人。要跑多个机器人?起多个进程。
这在小规模场景下没问题,但当你的企业有销售部、客服部、运维部各一个机器人,甚至每个业务线都有自己的 bot 时,管理成本就上来了——多个进程、多份配置、多套监控、多次部署。
我们的开源项目 WeComAiBot(企业微信 AI 机器人 PHP SDK)刚刚发布了多机器人实例管理功能,据我们所知,这是目前第一个在 SDK 层面原生支持单进程多 bot 的实现。
一句话:一个进程,多个 bot,完全隔离
$manager = new BotManager([
['bot_id' => 'sales-bot', 'secret' => 'xxx'],
['bot_id' => 'support-bot', 'secret' => 'yyy'],
['bot_id' => 'ops-bot', 'secret' => 'zzz'],
]);
$manager->start(); // 一个进程,三个 bot 同时在线
每个 bot 拥有独立的 WebSocket 连接、心跳定时器、断线重连和发送队列。一个 bot 掉线不影响其他 bot,一个 bot 认证失败不阻塞其他 bot。
核心设计:共享 Handler + botId 隔离
多 bot 场景下最常见的需求是:多个机器人共享一套消息处理逻辑,但需要知道消息是哪个 bot 收到的。
我们的做法是在 Message 和 Event 对象上注入 botId 字段:
// 一个 handler 服务所有 bot
$sharedHandler = function (Message $message, Reply $reply) {
$botId = $message->botId;
// 根据 botId 走不同的处理逻辑
match (true) {
str_contains($botId, 'sales') => $reply->text("【销售】{$message->text}"),
str_contains($botId, 'support') => $reply->text("【客服】{$message->text}"),
default => $reply->text("收到: {$message->text}"),
};
};
// 所有 bot 注册同一个 handler
foreach ($manager->getAllBots() as $bot) {
$bot->onMessage($sharedHandler);
}
当然,你也可以为每个 bot 注册专属的 handler:
$manager->getBot('sales-bot')->onText(function (Message $msg, Reply $reply) {
// 只有销售 bot 收到文本消息时触发
$reply->text("请问您需要什么产品?");
});
两种方式可以混用,灵活组合。
隔离保证
有人会问:消息会不会串?Bot A 的消息会不会跑到 Bot B 的 handler 里?
不会。 隔离是多层的:
| 层级 | 隔离方式 |
|——|———-|
| WebSocket 连接 | 每个 bot 独立的 AsyncTcpConnection |
| 认证 | 各自的 bot_id + secret,服务端按连接推送 |
| 消息分发 | 每个 WeComBot 实例有独立的 handler 列表 |
| 回复通道 | Reply 绑定对应 bot 的连接,不会发错 |
| 发送队列 | 独立的串行队列,互不阻塞 |
| 心跳 / 重连 | 独立的定时器,互不干扰 |
| 消息去重 | 独立的 processedMsgIds 缓存 |
企微服务端的行为保证了传输层的隔离——它只会把属于 Bot A 的消息推送到 Bot A 的 WebSocket 连接。botId 字段是 SDK 层面的额外标识,让你在共享 handler 中也能轻松区分来源。
为什么不起多个进程?
当然可以。但单进程多 bot 有几个实际优势:
1. 运维简单
一个 Supervisor 配置、一个进程、一份日志。不用为每个 bot 写一套部署脚本。
2. 资源更省
多个 bot 共享一个 Workerman 事件循环,不需要额外的进程开销。对于消息量不大的场景(绝大多数企业内部机器人),单进程绑绑有余。
3. 跨 bot 协作更容易
在同一个进程内,bot 之间可以直接共享状态,不需要走 IPC 或消息队列。比如:
$manager->getBot('ops-bot')->onMessage(function (Message $msg, Reply $reply) use ($manager) {
// 运维 bot 收到告警,转发给销售 bot 的用户
$manager->getBot('sales-bot')->pushToUser('zhangsan', "运维告警: {$msg->text}");
$reply->text('已转发给销售团队');
});
Laravel 集成
配置文件里写个数组就行,不用改一行代码:
// config/wecomaibot.php
'bots' => [
[
'bot_id' => 'sales-bot',
'secret' => 'xxx',
'handler' => \App\Bots\SalesHandler::class,
],
[
'bot_id' => 'support-bot',
'secret' => 'yyy',
'handler' => \App\Bots\SupportHandler::class,
],
],
php artisan wecom:serve
# 输出:
# 正在连接企业微信(2 个机器人)...
# [sales-bot] 已上线,等待消息...
# [support-bot] 已上线,等待消息...
Artisan 命令自动检测配置模式:有 bots 数组就走多 bot,没有就走单 bot。已有的单 bot 项目零改动升级。
每个 bot 的 handler 类独立,也可以多个 bot 指向同一个 handler 类——handler 中通过 $message->botId 区分来源即可。
BotManager API 一览
// 构造时批量注册
$manager = new BotManager([
['bot_id' => '...', 'secret' => '...'],
['bot_id' => '...', 'secret' => '...'],
]);
// 也可以逐个添加
$bot = $manager->addBot(['bot_id' => '...', 'secret' => '...']);
// 操作
$manager->getBot('bot-id'); // 获取机器人实例(按 bot_id)
$manager->getAllBots(); // 获取全部
$manager->removeBot('bot-id'); // 移除(自动断开连接)
$manager->start(); // 启动(阻塞)
日志自动带前缀,多 bot 日志不混淆:
[sales-bot] WebSocket connected, sending auth...
[sales-bot] Authenticated successfully
[support-bot] WebSocket connected, sending auth...
[support-bot] Authenticated successfully
安装
composer require bangbangda/wecomaibot
PHP >= 8.1,不需要 Swoole,不需要任何额外扩展。
链接
GitHub: github.com/bangbangda/wecomaibot
Packagist:
composer require bangbangda/wecomaibot协议: MIT
欢迎 Star、Issue、PR。有问题直接在 GitHub 提 Issue。
官方不做的事,社区来做。这就是开源的意义。
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu