NEW

免费试用已开放

立即开始

API 网关 · 长连接

企业微信协议机器人怎么做

更新于 2026-08-169 分钟

同样叫机器人,群 Webhook 机器人、企业应用机器人和以账号身份运行的机器人,在代码层面确实很像 —— 都是收事件、跑规则、发消息。真正的差别不在这一层,而在于这个机器人有没有自己的身份。有身份,它就能主动开口、能出现在外部群里、能被客户当成一个人;同时它也变成一份有状态、有配额、会掉线的资源。这四个字带来的连锁反应,才是这条路线上真正要处理的东西。下面按 wecomapi 这类账号托管形态来讲。

三种机器人,分界线是身份

先把三种形态摆在一起。它们的能力差异不是渐进的,而是被「有没有独立身份」这条线一刀切开的。

三种形态的能力与代价text
形态            身份        典型能力              运维形态
--------------  ----------  --------------------  --------------
群 Webhook      无          往固定的群单向推送    无状态,最省事
企业应用机器人  应用身份    在授权范围内被动应答  无状态,前置重
账号机器人      账号身份    主动发起、进外部群    有状态,需保活

第一条判断先给出来:需求只要能被第一种满足,就别往下走。从上到下每一档换来的能力都是真的,付出的运维成本也是真的,而且不是线性增长 —— 从「无状态」跨到「有状态」的那一步,成本是跳变的。很多团队只是想把告警推进一个群,最后却在维护登录态,纯属被能力清单带偏了。

接下来四节讲的都是跨过那条线之后才会遇到的问题。机器人本身的分层、路由与群聊单聊复用,站内讲开发流程那篇已经写透,这里不重复,只讲差异。

差别一:它是有状态的,不能随便水平扩

普通机器人的进程是无状态的:挂了重启、要扩就加副本、发布走滚动更新。账号机器人背后是一个有登录态的账号,副本再多也变不出第二个身份来 —— 你加的只是几个抢同一份配额的消费者。这个差异会直接改写三件事。

  1. 1并发上限由账号的速率预算决定,不由你的 CPU 决定。加机器不会让消息发得更快,只会让被拒绝的请求来得更整齐。容量规划的单位是账号,不是实例。
  2. 2灰度要按账号切,不能按流量百分比切。同一个账号上跑两个版本,客户会在一次对话里遇到两种行为,这种问题极难复现也极难解释。新版本先只挂在一个账号上跑一周,是这条路线上最有效的灰度方式。
  3. 3发布要考虑在途会话。正在多轮问答中的用户,进程一重启上下文就断了。要么把会话状态放进外部存储、让进程真正无状态化,要么在发布前把多轮会话标记为暂停并给一句提示,两条选一条,别什么都不做。

落到调度层,规则很简单:发送前先确认这个账号此刻可用,而不是等发送失败再去发现。用 wecomapi 的实例状态在本地维护一份副本,业务代码只读一个「能不能用」的布尔值加一个原因,调度层负责在不可用时把任务挂起 —— 这样账号掉线的影响面就被关在调度层里,不会渗进每一个处理函数。

一句话概括:按有状态服务的方式部署它,别沿用无状态 Web 服务那套发布模板。这两套模板在演示环境里没有区别,在有真实客户的账号上区别很大。

差别二:同一个号上,人和机器人会抢话

这是账号路线独有的问题,也是最常被漏掉的一个。这个号不只属于机器人:真人可能还在用它,或者转人工之后坐席会从另一端接管同一个会话。两边同时回复的结果,是客户在几秒内收到两条互相矛盾的消息 —— 而且这种事故不报错、不进日志、只在客户截图投诉时才被发现。

解法是会话级的接管互斥,三条规则缺一不可。

  1. 1人工一开口就静默。检测到本账号发出了一条不是机器人发的消息,立刻把该会话置为人工接管,机器人在窗口内闭嘴。判断依据不能只看「是否本账号发出」—— 那个标记同时也用于防自激循环,两个用途混在一起就会互相干扰。
  2. 2接管窗口必须自动过期。指望人工回头点一下「交还」,实际情况是没人点,然后这个会话的机器人永久失能,而且没人知道。给窗口一个默认时长,到期自动收回。
  3. 3接管的开始与结束都要写事件。少了这两条记录,事后你没办法回答「那条消息为什么没回」,只能猜是规则没命中还是被接管压住了。

第一条里那个判断依据值得展开:要区分「机器人发的」和「人发的」,靠平台侧的事件本身通常做不到,得靠自己这边的出向记录。每次机器人发送时同步写一条出向记录,收到本账号消息时用会话加时间窗去匹配,匹配上就是机器人自己,匹配不上就是人工在场。这段逻辑不长,但它是人机协同能不能成立的地基。

示意:人工消息一出现,机器人就让位javascript
// 示意代码:msg 是你归一化之后的结构,字段名仅表意;出向记录也是你自己库里的表
// 平台侧的事件类型与精确字段以 wecomapi 文档为准

onMessage(async (msg) => {
  if (msg.fromSelf) {
    // 本账号发出,但不一定是机器人发的 —— 匹配出向记录才能区分
    if (!(await matchOutbound(msg))) {
      await takeover.open(msg.chatId, DEFAULT_WINDOW); // 人工在场,让位
    }
    return;                                            // 顺带挡住自激循环
  }

  if (await takeover.active(msg.chatId)) return;       // 接管期内不抢话

  const reply = await handle(msg);
  if (reply) {
    await recordOutbound(msg.chatId, reply);           // 先记,再发
    await deliver(msg.chatId, reply);
  }
});

差别三:能主动开口,约束就得写在你这边

被动应答的机器人做坏事的上限很低 —— 没人问它就不说话。能主动发起会话、能群发、能加好友的机器人,事故半径直接等于你的客户总数。平台侧当然有约束,但那是最后一道闸,不该是你唯一那道。

  • 每次主动触达都要有可追溯的触发来源:依据哪个事件、谁批准的、命中哪条规则。做成「运营在后台点一下就群发」,出事时你连影响范围都说不清。
  • 限速要按会话和账号双维度分桶,分桶维度本身站内讲机器人开发流程那篇已经拆过;账号路线上要多守一条:主动触达和被动应答不能共用同一个桶,否则一次群发就能把应答那一侧的速率占满,而客户看到的只是机器人突然不理人。
  • 静默时段和单客户触达上限做成硬约束,写在发送通道里,不是写在运营规范里。规范会被绕过,代码不会。
  • 退订与转人工入口始终保留。一个能主动开口却关不掉的机器人,投诉来得比效果快。

这一节的判断是:能力越强的接入形态,越要把约束前移到发送通道这一层。因为主动触达的错误是不可撤回的 —— 消息发出去了就是发出去了,没有回滚按钮。

差别四:故障表现从「报错」变成「沉默」

普通机器人挂掉,健康检查会红、错误率会涨、告警会响。账号机器人掉线的表现完全不同:回调不再进来,你的服务一切正常、日志干干净净、监控全绿,唯一的现象是「没人说话」。这种故障靠常规监控发现不了,因为你的系统确实没出错,它只是没事可做。

对策是把「没有事件」本身变成一个可观测信号:按账号统计事件到达的间隔,超过基线就告警。基线要分时段 —— 工作日上午十分钟没消息很反常,周末凌晨两小时没消息很正常,用一个固定阈值必然要么太吵要么太钝。这条监控实现成本很低,但它是这类系统里唯一能赶在客户投诉之前发现问题的手段。

另一半是主动探测:定期读一次 wecomapi 侧的账号状态,而不是等着事件告诉你。这两条要一起做 —— 事件间隔告警覆盖「链路通但没消息」,状态探测覆盖「账号已经掉了但你还不知道」,各自都有盲区,合起来才完整。

什么时候不该走这条路

反向判断往往比正向选型更省事。下面三条按顺序问,命中就停。

  1. 1只需要把系统告警、日报、构建结果推进固定的几个群 —— 用最轻的那档,别引入任何有状态的东西。这类需求占了「我要做个机器人」里的大多数。
  2. 2只服务内部成员、能拿到管理员配合、不需要触达外部客户 —— 走官方应用形态,前置虽重但长期维护最省心,也不用管登录态。
  3. 3需要主动触达外部客户、需要以一个人的身份出现在外部群里、需要跨多个账号统一编排 —— 这时候前两档都做不到,才轮到这条路线,也才值得为它付出上面四节的成本。

本文讲的是形态差异与工程取舍,不涉及具体接口定义。事件类型、账号状态语义、精确字段与端点以 wecomapi 线上文档为准,示意代码只用于表达链路顺序。

常见问题

群 Webhook 机器人和账号机器人能不能混着用?
能,而且往往是最经济的组合:单向播报交给群 Webhook,需要对话、需要主动触达外部客户的部分才用账号身份。切分标准是「这条消息需不需要有一个人格」。混用时唯一要注意的是别让两者同时往一个群里说话,否则群里会出现两个来源不同、语气也不一致的机器人。
客户问了问题机器人没回,怎么排查?
按四层依次看:账号是不是掉线了(回调根本没进来)、会话是不是处在人工接管窗口内、规则有没有命中、发送有没有被限速挡住。这四层各留一条日志,排查就是几分钟的事。第一层可以直接对着 wecomapi 的实例状态确认,不用猜;接管窗口那层最容易被忽略,因为它「本来就该不回」。
一套代码怎么同时管多个账号的机器人?
配置化那一套(处理函数无状态、策略与话术按实例查表)站内讲机器人开发流程那篇已经写过,账号路线要在它上面再加一列:表里得有「此刻能不能用」,调度前先读它,掉线的实例直接跳过,而不是把任务打过去等它失败。这一列和其它配置的区别在于它会自己变,所以必须有一条明确的更新来源,不能靠人工维护。多账号的实例标识与状态语义以 wecomapi 文档为准,站内讲多账号托管那篇有更细的数据模型。

准备好动手了?

精确字段、鉴权与端点以线上文档为准;可在控制台创建密钥后联调。

相关文章