OpenClaw插件dingding(OpenClaw China)

375 阅读4分钟

OpenClaw与dingding交互逻辑

2026.2.28

版本情况:OpenClaw26.2.26,插件: @openclaw-china/dingtalk@0.1.38 + dingtalk-stream@2.1.

来自🦞 OpenClaw China — China IM Channels

结论先说

  1. 本机 OpenClaw -> 钉钉 走的是 Stream 模式,底层是 HTTPS + WebSocket(实际建连地址来自钉钉网关返回的 endpoint,通常是 wss)。
  2. 心跳是两层:
    1. dingtalk-stream 的 WebSocket ping/pong 心跳,默认 8 秒。
    2. 钉钉 SYSTEM 消息里的 KEEPALIVE/ping。
  3. 发起方向:
    1. OpenClaw 主动发起建连和 ws ping。
    2. 钉钉回复 pong,并主动下发 KEEPALIVE/ping/消息回调。
    3. OpenClaw 对钉钉回调消息主动 ACK(避免服务端重试)。

关键证据与调用链:

  1. OpenClaw 启动钉钉账户连接:startAccount -> monitorDingtalkProvider dist/index.js:9818
  2. 创建客户端时明确 keepAlive: true、autoReconnect: false(重连由插件自己的 loop 管) dist/index.js:9259
  3. dingtalk-stream 先 POST 钉钉网关拿 endpoint + ticket,再 new WebSocket(endpoint?ticket) client.mjs:97 client.mjs:133 constants.mjs:1
  4. 回调 topic 订阅和消息 ACK client.mjs:66 dist/index.js:8975 dist/index.js:8938 client.mjs:291

心跳细节(关注重点):

  1. 默认间隔:heartbeat_interval = 8e3(8000ms) client.mjs:29
  2. 发起方与逻辑:
    1. OpenClaw 侧定时 socket.ping()(每 8s) client.mjs:139 client.mjs:148
    2. 收到 pong 后标记存活 client.mjs:152
    3. 若一个周期内未恢复存活,客户端 terminate() 主动断开 client.mjs:141
  3. 钉钉侧系统心跳:SYSTEM/KEEPALIVE、SYSTEM/ping 下发给客户端;客户端分别 heartbeat() 或回 code:200 client.mjs:227 client.mjs:231
  4. OpenClaw 额外连接守护(非 WS 心跳):5s 轮询、30s connect/register 超时、15s 断连宽限、指数退避重连 dist/index.js:9008 dist/index.js:9009 dist/index.js:9010 dist/index.js:9011 dist/index.js:9139

补充一个容易混淆点:

  1. openclaw.plugin.json 里声明了 connectionMode: stream|webhook,但运行时代码 schema 实际没有用这个字段,实际实现是 dingtalk-stream 路线(即 stream)。 openclaw.plugin.json:14 dist/index.js:4218 dist/index.js:9845

运行态佐证(2026-02-28 本机日志):

  1. 有 state idle -> connecting -> connected、socket connected、registration not confirmed after 30000ms、state connected -> running reason=traffic confirmed。 /tmp/openclaw/openclaw-2026-02-28.log:735 /tmp/openclaw/openclaw-2026-02-28.log:744 /tmp/openclaw/openclaw-2026-02-28.log:790 /tmp/openclaw/openclaw-2026-02-28.log:811

如果你要,我可以下一步把这条链路画成一张时序图(建连、收消息、ACK、心跳、断线重连)。

一、OpenClaw 连接 DingTalk:方式、协议与心跳机制

更新时间:2026-02-28
适用环境:本机已安装 @openclaw-china/dingtalk@0.1.38 + dingtalk-stream@2.1.4

1. 总体结论

  • 连接方式:OpenClaw dingtalk 插件 通过 dingtalk-stream SDK 连接钉钉 Stream 网关。
  • 协议栈:先走 HTTPS 获取连接参数,再走 WebSocket 长连接(通常是 wss://...)。
  • 当前本机是 Stream 路线,不是 webhook 入站路由。
  • 心跳是双通道:
    • 客户端 WS ping/pong(默认 8 秒,客户端发起 ping)。
    • 钉钉 SYSTEM 消息 KEEPALIVE/ping(服务端下发,客户端应答/标记存活)。

2. 连接建立时序图

sequenceDiagram
    participant GW as OpenClaw Gateway
    participant PL as dingtalk 插件
    participant SDK as dingtalk-stream(DWClient)
    participant DTAPI as DingTalk HTTPS API
    participant DTS as DingTalk Stream WS

    GW->>PL: startAccount(ctx)
    PL->>PL: monitorDingtalkProvider()
    PL->>PL: runGatewayLoop()
    PL->>SDK: createDingtalkClientFromConfig(keepAlive=true, autoReconnect=false)
    SDK->>DTAPI: POST /v1.0/gateway/connections/open
    DTAPI-->>SDK: endpoint + ticket
    SDK->>DTS: WebSocket connect(endpoint?ticket)
    DTS-->>SDK: SYSTEM.CONNECTED
    DTS-->>SDK: SYSTEM.REGISTERED
    SDK-->>PL: client.connected=true / client.registered=true
    PL-->>GW: 状态连接成功(connected/running)

3. 消息交互与 ACK 时序图

sequenceDiagram
    participant DTS as DingTalk Stream WS
    participant SDK as dingtalk-stream(DWClient)
    participant PL as dingtalk 插件
    participant GW as OpenClaw Gateway/Agent
    participant DTAPI as DingTalk OpenAPI

    PL->>SDK: registerCallbackListener(TOPIC_ROBOT)
    DTS-->>SDK: CALLBACK /v1.0/im/bot/messages/get
    SDK-->>PL: payload(messageId, data)
    PL->>SDK: socketCallBackResponse(messageId,{success:true})
    Note over PL,SDK: 先 ACK,避免钉钉在超时窗口内重试推送
    PL->>GW: handleDingtalkMessage() 路由到会话/模型
    GW-->>PL: 回复内容
    PL->>DTAPI: 发送文本/媒体/卡片回复

4. 心跳机制(重点)

4.1 WS ping/pong 心跳

  • 默认周期:8000ms
  • 发起方:客户端(OpenClaw 侧的 dingtalk-stream)。
  • 过程:
    • 每 8 秒客户端执行一次 socket.ping()
    • 若收到 pong,标记连接存活。
    • 若一个心跳周期内未恢复存活,客户端主动 terminate() 断开,交给上层重连逻辑处理。
sequenceDiagram
    participant SDK as dingtalk-stream Client
    participant DTS as DingTalk Stream WS

    loop Every 8s
        SDK->>DTS: WS ping
        DTS-->>SDK: WS pong
        SDK->>SDK: isAlive=true
    end
    alt 未在周期内收到有效心跳
        SDK->>SDK: terminate socket
    end

4.2 钉钉 SYSTEM 心跳

  • 触发方:服务端(DingTalk)。
  • 事件:
    • SYSTEM/KEEPALIVE:客户端调用 heartbeat() 标记活跃。
    • SYSTEM/ping:客户端返回 code=200 应答。

5. 断线检测与重连(插件层)

  • WATCHDOG_INTERVAL_MS = 5000(5 秒轮询连接状态)。
  • CONNECT_TIMEOUT_MS = 30000(30 秒建连超时)。
  • REGISTER_TIMEOUT_MS = 30000(30 秒注册确认超时,先告警但保持连接观察)。
  • DISCONNECT_GRACE_MS = 15000(断连宽限 15 秒)。
  • 重连退避:
    • 基础延迟 1000ms,指数增长,最大 60000ms,带 ±20% 抖动。
  • 设计要点:SDK 自动重连被关闭(autoReconnect=false),由插件统一管理重连节奏和状态机。

6. “谁调用谁”清单

  • OpenClaw Gateway 调用 dingtalk 插件 startAccount()
  • 插件调用 DWClient.connect() 发起连接。
  • DWClient 先调用钉钉 HTTPS 网关接口拿 endpoint/ticket,再发起 WebSocket。
  • 钉钉服务端向客户端下发 CALLBACK / SYSTEM 消息。
  • 插件收到 CALLBACK 后主动调用 socketCallBackResponse() 进行 ACK。
  • 心跳上,客户端主动发 WS ping;服务端返回 pong 并可下发 SYSTEM KEEPALIVE/ping。

7. 关键实现定位(本机)

  • 插件入口与连接启动:
    • /root/.openclaw/extensions/dingtalk/dist/index.js:9818
  • 客户端创建参数(keepAlive=true, autoReconnect=false):
    • /root/.openclaw/extensions/dingtalk/dist/index.js:9259
  • 消息回调注册与 ACK:
    • /root/.openclaw/extensions/dingtalk/dist/index.js:8975
    • /root/.openclaw/extensions/dingtalk/dist/index.js:8938
  • SDK 协议核心(获取 endpoint + 建立 WS):
    • /root/.openclaw/extensions/dingtalk/node_modules/dingtalk-stream/dist/client.mjs:97
    • /root/.openclaw/extensions/dingtalk/node_modules/dingtalk-stream/dist/client.mjs:133
  • SDK 心跳实现(8 秒 ping/pong):
    • /root/.openclaw/extensions/dingtalk/node_modules/dingtalk-stream/dist/client.mjs:29
    • /root/.openclaw/extensions/dingtalk/node_modules/dingtalk-stream/dist/client.mjs:139
    • /root/.openclaw/extensions/dingtalk/node_modules/dingtalk-stream/dist/client.mjs:152
  • SDK 系统心跳与 ping 处理:
    • /root/.openclaw/extensions/dingtalk/node_modules/dingtalk-stream/dist/client.mjs:227
    • /root/.openclaw/extensions/dingtalk/node_modules/dingtalk-stream/dist/client.mjs:231
  • 网关地址常量:
    • /root/.openclaw/extensions/dingtalk/node_modules/dingtalk-stream/dist/constants.mjs:1

8. 运行态佐证(本机日志)

  • 已出现连接状态迁移与 socket connected:
    • /tmp/openclaw/openclaw-2026-02-28.log:735
    • /tmp/openclaw/openclaw-2026-02-28.log:744
  • 出现注册超时告警(30s)后继续保活:
    • /tmp/openclaw/openclaw-2026-02-28.log:790
  • 出现 connected -> running(traffic confirmed):
    • /tmp/openclaw/openclaw-2026-02-28.log:811

如果后续要做抓包或压测,建议优先观测三类指标:ACK 成功率pong 丢失率reconnect reason 分布

二、钉钉开发者平台,资源管理查询相关使用次数。

image.png