3.15脚本只支持单个机器人
钉钉企业内部机器人 Channel 插件,使用 Stream 模式(无需公网 IP)。
- ✅ Stream 模式 — WebSocket 长连接,无需公网 IP 或 Webhook
- ✅ 私聊支持 — 直接与机器人对话
- ✅ 群聊支持 — 在群里 @机器人
- ✅ 多种消息类型 — 文本、图片、语音(自带识别)、视频、文件
- ✅ Markdown 回复 — 支持富文本格式回复
- ✅ 互动卡片 — 支持流式更新,适用于 AI 实时输出
- ✅ 完整 AI 对话 — 接入 Clawdbot 消息处理管道
直接运行 openclaw 插件安装命令,openclaw 会自动处理下载、安装依赖和注册:
openclaw plugins install https://github.com/soimy/clawdbot-channel-dingtalk.git如果你想对插件进行二次开发,可以先克隆仓库:
# 1. 克隆仓库
git clone https://github.com/soimy/openclaw-channel-dingtalk.git
cd openclaw-channel-dingtalk
# 2. 安装依赖 (必需)
npm install
# 3. 以链接模式安装 (方便修改代码后实时生效)
openclaw plugins install -l .- 将本目录下载或复制到
~/.openclaw/extensions/dingtalk。 - 确保包含
index.ts,openclaw.plugin.json和package.json。 - 运行
openclaw plugins list确认dingtalk已显示在列表中。
openclaw plugins update dingtalk
- 访问 钉钉开发者后台
- 创建企业内部应用
- 添加「机器人」能力
- 配置消息接收模式为 Stream 模式
- 发布应用
在应用的权限管理页面,需要开启以下权限:
- ✅ Card.Instance.Write — 创建和投放卡片实例
- ✅ Card.Streaming.Write — 对卡片进行流式更新
步骤:
- 进入应用 → 权限管理
- 搜索「Card」相关权限
- 勾选上述两个权限
- 保存权限配置
步骤:
- 访问 钉钉卡片平台
- 进入「我的模板」
- 点击「创建模板」
- 卡片模板场景选择 「AI 卡片」
- 按需设计卡片排版,点击保存并发布
- 记下模板中定义的内容字段名称
- 复制模板 ID(格式如:
xxxxx-xxxxx-xxxxx.schema) - 将 templateId 配置到
openclaw.json的cardTemplateId字段 - 或在OpenClaw控制台的Channel标签->Dingtalk配置面板-> Card Template Id填入
- 将记下的内容字段变量名配置到
openclaw.json的cardTemplateKey字段 - 或在OpenClaw控制台的Channel标签->Dingtalk配置面板-> Card Template Key填入
说明:
- 使用 DingTalk 官方 AI 卡片模板时,
cardTemplateKey默认为'msgContent',无需修改 - 如果您创建自定义卡片模板,需要确保模板中包含相应的内容字段,并将
cardTemplateKey配置为该字段名称
模板配置示例:
{
"channels": {
"dingtalk": {
...
"messageType": 'card',
"cardTemplateId": '你复制的模板ID',
"cardTemplateKey": '你模板的内容变量',
...
},
},
}从开发者后台获取:
- Client ID (AppKey)
- Client Secret (AppSecret)
- Robot Code (与 Client ID 相同)
- Corp ID (企业 ID)
- Agent ID (应用 ID)
在 ~/.openclaw/openclaw.json 的 channels 下添加:
只添加dingtalk部分,内容自己替换
{
...
"channels": {
"telegram": { ... },
"dingtalk": {
"enabled": true,
"clientId": "dingxxxxxx",
"clientSecret": "your-app-secret",
"robotCode": "dingxxxxxx",
"corpId": "dingxxxxxx",
"agentId": "123456789",
"dmPolicy": "open",
"groupPolicy": "open",
"messageType": "markdown",
"debug": false
}
},
...
}openclaw gateway restart| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | true | 是否启用 |
clientId | string | 必填 | 应用的 AppKey |
clientSecret | string | 必填 | 应用的 AppSecret |
robotCode | string | - | 机器人代码(用于下载媒体和发送卡片) |
corpId | string | - | 企业 ID |
agentId | string | - | 应用 ID |
dmPolicy | string | "open" | 私聊策略:open/pairing/allowlist |
groupPolicy | string | "open" | 群聊策略:open/allowlist |
allowFrom | string[] | [] | 允许的发送者 ID 列表 |
messageType | string | "markdown" | 消息类型:markdown/card |
cardTemplateId | string | AI 互动卡片模板 ID(仅当 messageType=card) | |
cardTemplateKey | string | "content" | 卡片模板内容字段键(仅当 messageType=card) |
debug | boolean | false | 是否开启调试日志 |
maxConnectionAttempts | number | 10 | 最大连接尝试次数 |
initialReconnectDelay | number | 1000 | 初始重连延迟(毫秒) |
maxReconnectDelay | number | 60000 | 最大重连延迟(毫秒) |
reconnectJitter | number | 0.3 | 重连延迟抖动因子(0-1) |
为提高连接稳定性,插件支持以下高级配置:
- maxConnectionAttempts: 连接失败后的最大重试次数,超过后将停止尝试并报警。
- initialReconnectDelay: 第一次重连的初始延迟(毫秒),后续重连会按指数增长。
- maxReconnectDelay: 重连延迟的上限(毫秒),防止等待时间过长。
- reconnectJitter: 延迟抖动因子,在延迟基础上增加随机变化(±30%),避免多个客户端同时重连。
重连延迟计算公式:delay = min(initialDelay × 2^attempt, maxDelay) × (1 ± jitter)
示例延迟序列(默认配置):~1s, ~2s, ~4s, ~8s, ~16s, ~32s, ~60s(达到上限)
更多详情请参阅 CONNECTION_ROBUSTNESS.md。
open— 任何人都可以私聊机器人pairing— 新用户需要通过配对码验证allowlist— 只有 allowFrom 列表中的用户可以使用
open— 任何群都可以 @机器人allowlist— 只有配置的群可以使用
| 类型 | 支持 | 说明 |
|---|---|---|
| 文本 | ✅ | 完整支持 |
| 富文本 | ✅ | 提取文本内容 |
| 图片 | ✅ | 下载并传递给 AI |
| 语音 | ✅ | 使用钉钉语音识别结果 |
| 视频 | ✅ | 下载并传递给 AI |
| 文件 | ✅ | 下载并传递给 AI |
| 类型 | 支持 | 说明 |
|---|---|---|
| 文本 | ✅ | 完整支持 |
| Markdown | ✅ | 自动检测或手动指定 |
| 互动卡片 | ✅ | 支持流式更新,适用于 AI 实时输出 |
| 图片 | ⏳ | 需要通过媒体上传 API |
| 操作 | API 调用次数 | 说明 |
|---|---|---|
| 获取 Token | 1 | 共享/缓存(60 秒检查过期一次) |
| 发送消息 | 1 | 使用 /v1.0/robot/oToMessages/batchSend 或 /v1.0/robot/groupMessages/send |
| 总计 | 2 | 每条回复 1 次 |
| 阶段 | API 调用 | 说明 |
|---|---|---|
| 创建卡片 | 1 | POST /v1.0/card/instances/createAndDeliver |
| 流式更新 | M | M = 回复块数量,每块一次 PUT /v1.0/card/streaming |
| 完成卡片 | 包含在最后一次流更新中 | 使用 isFinalize=true 标记 |
| 总计 | 1 + M | M = Agent 产生的回复块数 |
| 场景 | Text/Markdown | Card | 节省 |
|---|---|---|---|
| 简短回复(1 块) | 2 | 2 | ✓ 相同 |
| 中等回复(5 块) | 6 | 6 | ✓ 相同 |
| 长回复(10 块) | 12 | 11 | ✓ 1 次 |
降低 API 调用的方法:
- 合并回复块 — 通过调整 Agent 输出配置,减少块数量
- 使用缓存 — Token 自动缓存(60 秒),无需每次都获取
- Buffer 模式 — 使用
dispatchReplyWithBufferedBlockDispatcher合并多个小块
成本建议:
- ✅ 推荐 — Card 模式:流式体验更好,成本与 Text/Markdown 相当或更低
⚠️ 谨慎 — 频繁调用需要监测配额,建议使用钉钉开发者后台查看 API 调用量
插件支持两种消息回复类型,可通过 messageType 配置:
- 支持富文本格式(标题、粗体、列表等)
- 自动检测消息是否包含 Markdown 语法
- 适用于大多数场景
- 支持流式更新(实时显示 AI 生成内容)
- 更好的视觉呈现和交互体验
- 支持 Markdown 格式渲染
- 通过
cardTemplateId指定模板 - 通过
cardTemplateKey指定内容字段 - 适用于 AI 对话场景
AI Card API 特性: 当配置 messageType: 'card' 时:
- 使用
/v1.0/card/instances/createAndDeliver创建并投放卡片 - 使用
/v1.0/card/streaming实现真正的流式更新 - 自动状态管理(PROCESSING → INPUTING → FINISHED)
- 更稳定的流式体验,无需手动节流
配置示例:
{
messageType: 'card', // 启用 AI 互动卡片模式
cardTemplateId: '382e4302-551d-4880-bf29-a30acfab2e71.schema', // AI 卡片模板 ID(默认值)
cardTemplateKey: 'msgContent', // 卡片内容字段键(默认值:msgContent)
}注意:
cardTemplateKey应与您的卡片模板中定义的字段名称一致。默认值为'msgContent',适用于 DingTalk 官方 AI 卡片模板。如果您使用自定义模板,请根据模板定义的字段名称进行配置。
配置完成后,直接在钉钉中:
- 私聊机器人 — 找到机器人,发送消息
- 群聊 @机器人 — 在群里 @机器人名称 + 消息
- 确认应用已发布
- 确认消息接收模式是 Stream
- 检查 Gateway 日志:
openclaw logs | grep dingtalk
- 确认机器人已添加到群
- 确认正确 @机器人(使用机器人名称)
- 确认群是企业内部群
- 检查 clientId 和 clientSecret 是否正确
- 确认网络可以访问钉钉 API
- 克隆仓库并安装依赖
git clone https://github.com/soimy/openclaw-channel-dingtalk.git
cd openclaw-channel-dingtalk
npm install- 验证开发环境
npm run type-check # TypeScript 类型检查
npm run lint # ESLint 代码检查| 命令 | 说明 |
|---|---|
npm run type-check | TypeScript 类型检查 |
npm run lint | ESLint 代码检查 |
npm run lint:fix | 自动修复格式问题 |
src/
channel.ts - 插件定义和辅助函数(535 行)
runtime.ts - 运行时管理(14 行)
types.ts - 类型定义(30+ interfaces)
index.ts - 插件注册(29 行)
utils.ts - 工具函数(110 行)
openclaw.plugin.json - 插件配置
package.json - 项目配置
README.md - 本文件
- TypeScript: 严格模式,0 错误
- ESLint: 自动检查和修复
- Type Safety: 完整的类型注解(30+ 接口)
核心类型定义在 src/types.ts 中,包括:
// 配置
DingTalkConfig; // 插件配置
DingTalkChannelConfig; // 多账户配置
// 消息处理
DingTalkInboundMessage; // 收到的钉钉消息
MessageContent; // 解析后的消息内容
HandleDingTalkMessageParams; // 消息处理参数
// AI 互动卡片
AICardInstance; // AI 卡片实例
AICardCreateAndDeliverRequest; // 创建并投放卡片请求
AICardStreamingRequest; // 流式更新请求
AICardStatus; // 卡片状态常量
// 工具函数类型
Logger; // 日志接口
RetryOptions; // 重试选项
MediaFile; // 下载的媒体文件插件导出以下低级 API 函数,可用于自定义集成:
// 文本/Markdown 消息
sendBySession(config, sessionWebhook, text, options); // 通过会话发送
// AI 互动卡片
createAICard(config, conversationId, data, log); // 创建并投放 AI 卡片
streamAICard(card, content, finished, log); // 流式更新卡片内容
finishAICard(card, content, log); // 完成并关闭卡片
// 自动模式选择
sendMessage(config, conversationId, text, options); // 根据配置自动选择(含卡片/文本回退)
// 认证
getAccessToken(config, log); // 获取访问令牌使用示例:
import { createAICard, streamAICard, finishAICard } from './src/channel';
// 创建 AI 卡片
const card = await createAICard(config, conversationId, messageData, log);
// 流式更新内容
for (const chunk of aiResponseChunks) {
await streamAICard(card, currentText + chunk, false, log);
}
// 完成并关闭卡片
await finishAICard(card, finalText, log);
0 评论