openclaw-china-integration
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOpenClaw China Integration Skill
OpenClaw China 集成技能
Skill by ara.so — Hermes Skills collection.
OpenClaw China is a comprehensive plugin collection that extends OpenClaw to support major Chinese instant messaging platforms including DingTalk (钉钉), Feishu (飞书), QQ, WeChat Work (企业微信), WeChat Official Account (微信公众号), and WeChat Customer Service (微信客服).
由 ara.so 提供的技能 — 属于Hermes技能合集。
OpenClaw China是一套全面的插件集合,可扩展OpenClaw使其支持主流国内即时通讯平台,包括钉钉、飞书、QQ、企业微信、微信公众号以及微信客服。
What OpenClaw China Does
OpenClaw China 功能介绍
- Multi-Platform Support: Connects OpenClaw AI agents to 6+ Chinese IM platforms
- Unified Interface: Provides consistent message handling across different platforms
- Rich Features: Supports text, Markdown, images, files, voice messages, and streaming responses
- Enterprise Ready: Handles both internal (WeChat Work) and external (WeChat Customer Service) users
- Low Configuration: Simplified setup process with guided installation
- 多平台支持:将OpenClaw AI Agent连接至6+个国内IM平台
- 统一接口:在不同平台间提供一致的消息处理方式
- 丰富功能:支持文本、Markdown、图片、文件、语音消息及流式响应
- 企业级就绪:支持内部(企业微信)和外部(微信客服)用户场景
- 低配置成本:简化的设置流程,搭配引导式安装
Installation
安装步骤
Quick Setup (Recommended)
快速设置(推荐)
bash
npx @openclaw-china/setupThis interactive installer will:
- Check your OpenClaw installation
- Guide you through platform selection
- Generate configuration files
- Install required dependencies
bash
npx @openclaw-china/setup该交互式安装工具将:
- 检查OpenClaw安装情况
- 引导您完成平台选择
- 生成配置文件
- 安装所需依赖
Manual Installation
手动安装
bash
undefinedbash
undefinedInstall OpenClaw China packages
安装OpenClaw China全量包
npm install @openclaw-china/dingtalk @openclaw-china/qqbot @openclaw-china/wecom @openclaw-china/wecom-app @openclaw-china/wecom-kf @openclaw-china/wechat-mp
npm install @openclaw-china/dingtalk @openclaw-china/qqbot @openclaw-china/wecom @openclaw-china/wecom-app @openclaw-china/wecom-kf @openclaw-china/wechat-mp
Or install specific channels
或仅安装特定平台插件
npm install @openclaw-china/dingtalk # DingTalk only
npm install @openclaw-china/qqbot # QQ Bot only
npm install @openclaw-china/wecom # WeChat Work Robot only
undefinednpm install @openclaw-china/dingtalk # 仅钉钉
npm install @openclaw-china/qqbot # 仅QQ Bot
npm install @openclaw-china/wecom # 仅企业微信机器人
undefinedPlatform Selection Guide
平台选择指南
| Platform | Complexity | Public IP Required | Use Case |
|---|---|---|---|
| DingTalk | Simple | No | Enterprise internal |
| QQ Bot | Simple | No | Public bot service |
| WeChat Work Robot | Simple | No | Enterprise internal (recommended) |
| WeChat Work App | Medium | Yes | Connect to personal WeChat |
| WeChat Customer Service | Medium | Yes | External customer support |
| WeChat Official Account | Medium | Yes | Public followers |
| 平台 | 复杂度 | 是否需要公网IP | 适用场景 |
|---|---|---|---|
| 钉钉 | 简单 | 否 | 企业内部场景 |
| QQ Bot | 简单 | 否 | 公开机器人服务 |
| 企业微信机器人 | 简单 | 否 | 企业内部场景(推荐) |
| 企业微信自建应用 | 中等 | 是 | 对接个人微信 |
| 微信客服 | 中等 | 是 | 外部客户支持 |
| 微信公众号 | 中等 | 是 | 粉丝运营 |
Configuration
配置说明
DingTalk Configuration
钉钉配置
typescript
// config/channels.dingtalk.ts
export default {
channels: {
dingtalk: {
enabled: true,
clientId: process.env.DINGTALK_CLIENT_ID,
clientSecret: process.env.DINGTALK_CLIENT_SECRET,
// Optional: Enable multiple accounts
accounts: [
{
clientId: process.env.DINGTALK_CLIENT_ID_1,
clientSecret: process.env.DINGTALK_CLIENT_SECRET_1
}
]
}
}
}Environment variables:
bash
DINGTALK_CLIENT_ID=your_client_id
DINGTALK_CLIENT_SECRET=your_client_secrettypescript
// config/channels.dingtalk.ts
export default {
channels: {
dingtalk: {
enabled: true,
clientId: process.env.DINGTALK_CLIENT_ID,
clientSecret: process.env.DINGTALK_CLIENT_SECRET,
// 可选:启用多账号
accounts: [
{
clientId: process.env.DINGTALK_CLIENT_ID_1,
clientSecret: process.env.DINGTALK_CLIENT_SECRET_1
}
]
}
}
}环境变量:
bash
DINGTALK_CLIENT_ID=your_client_id
DINGTALK_CLIENT_SECRET=your_client_secretQQ Bot Configuration
QQ Bot配置
typescript
// config/channels.qqbot-china.ts
export default {
channels: {
'qqbot-china': {
enabled: true,
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN,
// Enable streaming for C2C (private chat)
streaming: true,
// Optional: Enable multiple bots
accounts: [
{
appId: process.env.QQ_APP_ID_1,
token: process.env.QQ_BOT_TOKEN_1,
secret: process.env.QQ_BOT_SECRET_1
}
]
}
}
}typescript
// config/channels.qqbot-china.ts
export default {
channels: {
'qqbot-china': {
enabled: true,
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN,
// 启用C2C(私聊)流式响应
streaming: true,
// 可选:启用多机器人
accounts: [
{
appId: process.env.QQ_APP_ID_1,
token: process.env.QQ_BOT_TOKEN_1,
secret: process.env.QQ_BOT_SECRET_1
}
]
}
}
}WeChat Work Robot (Long Connection)
企业微信机器人(长连接模式)
typescript
// config/channels.wecom.ts
export default {
channels: {
wecom: {
enabled: true,
corpId: process.env.WECOM_CORP_ID,
corpSecret: process.env.WECOM_CORP_SECRET,
// Connection mode: 'ws' (WebSocket) or 'webhook'
mode: 'ws',
// Optional: Robot token for webhook mode
token: process.env.WECOM_ROBOT_TOKEN,
encodingAESKey: process.env.WECOM_ENCODING_AES_KEY
}
}
}typescript
// config/channels.wecom.ts
export default {
channels: {
wecom: {
enabled: true,
corpId: process.env.WECOM_CORP_ID,
corpSecret: process.env.WECOM_CORP_SECRET,
// 连接模式:'ws'(WebSocket)或 'webhook'
mode: 'ws',
// 可选:Webhook模式下的机器人令牌
token: process.env.WECOM_ROBOT_TOKEN,
encodingAESKey: process.env.WECOM_ENCODING_AES_KEY
}
}
}WeChat Work Self-Built App (Can Connect to Personal WeChat)
企业微信自建应用(可对接个人微信)
typescript
// config/channels.wecom-app.ts
export default {
channels: {
'wecom-app': {
enabled: true,
corpId: process.env.WECOM_APP_CORP_ID,
agentId: process.env.WECOM_APP_AGENT_ID,
secret: process.env.WECOM_APP_SECRET,
token: process.env.WECOM_APP_TOKEN,
encodingAESKey: process.env.WECOM_APP_ENCODING_AES_KEY,
// Public URL for callbacks
callbackUrl: process.env.WECOM_APP_CALLBACK_URL
}
}
}typescript
// config/channels.wecom-app.ts
export default {
channels: {
'wecom-app': {
enabled: true,
corpId: process.env.WECOM_APP_CORP_ID,
agentId: process.env.WECOM_APP_AGENT_ID,
secret: process.env.WECOM_APP_SECRET,
token: process.env.WECOM_APP_TOKEN,
encodingAESKey: process.env.WECOM_APP_ENCODING_AES_KEY,
// 回调接口公网地址
callbackUrl: process.env.WECOM_APP_CALLBACK_URL
}
}
}WeChat Customer Service (External Users)
微信客服(外部用户场景)
typescript
// config/channels.wecom-kf.ts
export default {
channels: {
'wecom-kf': {
enabled: true,
corpId: process.env.WECOM_KF_CORP_ID,
secret: process.env.WECOM_KF_SECRET,
token: process.env.WECOM_KF_TOKEN,
encodingAESKey: process.env.WECOM_KF_ENCODING_AES_KEY,
// Welcome message when user enters session
welcomeMessage: '您好!我是AI助手,有什么可以帮您?'
}
}
}typescript
// config/channels.wecom-kf.ts
export default {
channels: {
'wecom-kf': {
enabled: true,
corpId: process.env.WECOM_KF_CORP_ID,
secret: process.env.WECOM_KF_SECRET,
token: process.env.WECOM_KF_TOKEN,
encodingAESKey: process.env.WECOM_KF_ENCODING_AES_KEY,
// 用户进入会话时的欢迎语
welcomeMessage: '您好!我是AI助手,有什么可以帮您?'
}
}
}WeChat Official Account
微信公众号配置
typescript
// config/channels.wechat-mp.ts
export default {
channels: {
'wechat-mp': {
enabled: true,
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET,
token: process.env.WECHAT_MP_TOKEN,
encodingAESKey: process.env.WECHAT_MP_ENCODING_AES_KEY,
// Render Markdown to plain text for WeChat compatibility
renderMarkdown: true,
// Active delivery mode: 'split' (multiple messages) or 'merged' (single message)
activeDeliveryMode: 'split',
// ASR (Automatic Speech Recognition) for voice messages
asrConfig: {
enabled: true,
secretId: process.env.TENCENT_CLOUD_SECRET_ID,
secretKey: process.env.TENCENT_CLOUD_SECRET_KEY,
engineType: '16k_zh' // 16kHz Chinese
}
}
}
}typescript
// config/channels.wechat-mp.ts
export default {
channels: {
'wechat-mp': {
enabled: true,
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET,
token: process.env.WECHAT_MP_TOKEN,
encodingAESKey: process.env.WECHAT_MP_ENCODING_AES_KEY,
// 将Markdown转换为纯文本以适配微信
renderMarkdown: true,
// 主动消息发送模式:'split'(分多条发送)或 'merged'(合并为单条)
activeDeliveryMode: 'split',
// 语音消息自动识别(ASR)配置
asrConfig: {
enabled: true,
secretId: process.env.TENCENT_CLOUD_SECRET_ID,
secretKey: process.env.TENCENT_CLOUD_SECRET_KEY,
engineType: '16k_zh' // 16kHz中文识别
}
}
}
}Real Code Examples
实战代码示例
Handling Incoming Messages
处理接收消息
typescript
// Custom message handler for DingTalk
import { DingTalkChannel } from '@openclaw-china/dingtalk';
const channel = new DingTalkChannel({
clientId: process.env.DINGTALK_CLIENT_ID,
clientSecret: process.env.DINGTALK_CLIENT_SECRET
});
// Listen for messages
channel.on('message', async (message) => {
console.log('Received:', message.content);
// Process with OpenClaw
const response = await openclawAgent.chat(message.content);
// Send response
await channel.sendMessage({
conversationId: message.conversationId,
content: response.text,
messageType: 'markdown' // or 'text'
});
});typescript
// 钉钉自定义消息处理器
import { DingTalkChannel } from '@openclaw-china/dingtalk';
const channel = new DingTalkChannel({
clientId: process.env.DINGTALK_CLIENT_ID,
clientSecret: process.env.DINGTALK_CLIENT_SECRET
});
// 监听消息
channel.on('message', async (message) => {
console.log('收到消息:', message.content);
// 用OpenClaw处理消息
const response = await openclawAgent.chat(message.content);
// 发送响应
await channel.sendMessage({
conversationId: message.conversationId,
content: response.text,
messageType: 'markdown' // 或 'text'
});
});Sending Proactive Messages (Scheduled Tasks)
主动发送消息(定时任务)
typescript
// Send scheduled message via QQ Bot
import { QQBotChannel } from '@openclaw-china/qqbot';
const qqBot = new QQBotChannel({
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN
});
async function sendDailyReport() {
const report = await generateReport();
await qqBot.sendMessage({
userId: 'user_openid',
content: report,
messageType: 'markdown'
});
}
// Schedule daily at 9 AM
cron.schedule('0 9 * * *', sendDailyReport);typescript
// 通过QQ Bot发送日报
import { QQBotChannel } from '@openclaw-china/qqbot';
const qqBot = new QQBotChannel({
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN
});
async function sendDailyReport() {
const report = await generateReport();
await qqBot.sendMessage({
userId: 'user_openid',
content: report,
messageType: 'markdown'
});
}
// 每天上午9点执行
cron.schedule('0 9 * * *', sendDailyReport);Handling File Uploads
处理文件上传
typescript
// Process file from WeChat Work
import { WeComAppChannel } from '@openclaw-china/wecom-app';
const wecomApp = new WeComAppChannel({
corpId: process.env.WECOM_APP_CORP_ID,
agentId: process.env.WECOM_APP_AGENT_ID,
secret: process.env.WECOM_APP_SECRET
});
wecomApp.on('file', async (fileMessage) => {
// Download file
const fileBuffer = await wecomApp.downloadMedia(fileMessage.mediaId);
// Process with OpenClaw
const analysis = await openclawAgent.analyzeFile(fileBuffer);
// Send response
await wecomApp.sendMessage({
userId: fileMessage.fromUserId,
content: `文件分析结果:\n${analysis}`
});
});typescript
// 处理企业微信文件
import { WeComAppChannel } from '@openclaw-china/wecom-app';
const wecomApp = new WeComAppChannel({
corpId: process.env.WECOM_APP_CORP_ID,
agentId: process.env.WECOM_APP_AGENT_ID,
secret: process.env.WECOM_APP_SECRET
});
wecomApp.on('file', async (fileMessage) => {
// 下载文件
const fileBuffer = await wecomApp.downloadMedia(fileMessage.mediaId);
// 用OpenClaw分析文件
const analysis = await openclawAgent.analyzeFile(fileBuffer);
// 发送分析结果
await wecomApp.sendMessage({
userId: fileMessage.fromUserId,
content: `文件分析结果:\n${analysis}`
});
});Streaming Response (QQ Bot C2C)
流式响应(QQ Bot私聊)
typescript
// Enable streaming for real-time chat experience
import { QQBotChannel } from '@openclaw-china/qqbot';
const qqBot = new QQBotChannel({
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN,
streaming: true // Enable streaming for private chat
});
qqBot.on('message', async (message) => {
// Streaming only works for C2C (private chat)
if (message.messageType === 'C2C') {
const stream = await openclawAgent.chatStream(message.content);
for await (const chunk of stream) {
await qqBot.updateStreamMessage({
messageId: message.id,
content: chunk.text
});
}
} else {
// Group chat falls back to regular message
const response = await openclawAgent.chat(message.content);
await qqBot.sendMessage({
groupId: message.groupId,
content: response.text
});
}
});typescript
// 启用流式响应实现实时聊天体验
import { QQBotChannel } from '@openclaw-china/qqbot';
const qqBot = new QQBotChannel({
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN,
streaming: true // 为私聊启用流式响应
});
qqBot.on('message', async (message) => {
// 流式响应仅支持C2C(私聊)
if (message.messageType === 'C2C') {
const stream = await openclawAgent.chatStream(message.content);
for await (const chunk of stream) {
await qqBot.updateStreamMessage({
messageId: message.id,
content: chunk.text
});
}
} else {
// 群聊回退到普通消息模式
const response = await openclawAgent.chat(message.content);
await qqBot.sendMessage({
groupId: message.groupId,
content: response.text
});
}
});Voice Message with ASR (WeChat Official Account)
语音消息自动识别(微信公众号)
typescript
// Automatic voice-to-text conversion
import { WeChatMPChannel } from '@openclaw-china/wechat-mp';
const wechatMP = new WeChatMPChannel({
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET,
asrConfig: {
enabled: true,
secretId: process.env.TENCENT_CLOUD_SECRET_ID,
secretKey: process.env.TENCENT_CLOUD_SECRET_KEY,
engineType: '16k_zh'
}
});
wechatMP.on('voice', async (voiceMessage) => {
// ASR automatically converts voice to text
const text = voiceMessage.recognizedText;
console.log('Voice recognized:', text);
// Process with OpenClaw
const response = await openclawAgent.chat(text);
await wechatMP.sendMessage({
userId: voiceMessage.fromUserId,
content: response.text
});
});typescript
// 自动语音转文字
import { WeChatMPChannel } from '@openclaw-china/wechat-mp';
const wechatMP = new WeChatMPChannel({
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET,
asrConfig: {
enabled: true,
secretId: process.env.TENCENT_CLOUD_SECRET_ID,
secretKey: process.env.TENCENT_CLOUD_SECRET_KEY,
engineType: '16k_zh'
}
});
wechatMP.on('voice', async (voiceMessage) => {
// ASR自动将语音转换为文本
const text = voiceMessage.recognizedText;
console.log('语音识别结果:', text);
// 用OpenClaw处理文本
const response = await openclawAgent.chat(text);
await wechatMP.sendMessage({
userId: voiceMessage.fromUserId,
content: response.text
});
});Common Patterns
常见实现模式
Multi-Account Setup
多账号配置
typescript
// config/channels.dingtalk.ts
export default {
channels: {
dingtalk: {
enabled: true,
accounts: [
{
name: 'team-a',
clientId: process.env.DINGTALK_TEAM_A_CLIENT_ID,
clientSecret: process.env.DINGTALK_TEAM_A_CLIENT_SECRET
},
{
name: 'team-b',
clientId: process.env.DINGTALK_TEAM_B_CLIENT_ID,
clientSecret: process.env.DINGTALK_TEAM_B_CLIENT_SECRET
}
]
}
}
}typescript
// config/channels.dingtalk.ts
export default {
channels: {
dingtalk: {
enabled: true,
accounts: [
{
name: 'team-a',
clientId: process.env.DINGTALK_TEAM_A_CLIENT_ID,
clientSecret: process.env.DINGTALK_TEAM_A_CLIENT_SECRET
},
{
name: 'team-b',
clientId: process.env.DINGTALK_TEAM_B_CLIENT_ID,
clientSecret: process.env.DINGTALK_TEAM_B_CLIENT_SECRET
}
]
}
}
}Group Chat Management
群聊消息管理
typescript
// Handle @mentions in WeChat Work group
import { WeComChannel } from '@openclaw-china/wecom';
const wecom = new WeComChannel({
corpId: process.env.WECOM_CORP_ID,
corpSecret: process.env.WECOM_CORP_SECRET,
mode: 'ws'
});
wecom.on('message', async (message) => {
// Check if bot is mentioned in group
if (message.isGroupChat && message.isMentioned) {
const cleanContent = message.content.replace(/@\w+/g, '').trim();
const response = await openclawAgent.chat(cleanContent, {
context: {
groupId: message.groupId,
userId: message.fromUserId
}
});
await wecom.sendMessage({
groupId: message.groupId,
content: response.text,
mentionedUsers: [message.fromUserId] // @user in response
});
}
});typescript
// 处理企业微信群聊@提及
import { WeComChannel } from '@openclaw-china/wecom';
const wecom = new WeComChannel({
corpId: process.env.WECOM_CORP_ID,
corpSecret: process.env.WECOM_CORP_SECRET,
mode: 'ws'
});
wecom.on('message', async (message) => {
// 检查是否在群聊中被@提及
if (message.isGroupChat && message.isMentioned) {
const cleanContent = message.content.replace(/@\w+/g, '').trim();
const response = await openclawAgent.chat(cleanContent, {
context: {
groupId: message.groupId,
userId: message.fromUserId
}
});
await wecom.sendMessage({
groupId: message.groupId,
content: response.text,
mentionedUsers: [message.fromUserId] // 回复时@用户
});
}
});Message Formatting
消息格式适配
typescript
// Convert Markdown to platform-specific format
function formatMessage(text: string, platform: string): string {
switch (platform) {
case 'dingtalk':
case 'wecom':
case 'qqbot':
// These support Markdown
return text;
case 'wechat-mp':
// Convert Markdown to plain text
return text
.replace(/\*\*(.+?)\*\*/g, '$1') // Bold
.replace(/\*(.+?)\*/g, '$1') // Italic
.replace(/`(.+?)`/g, '$1') // Code
.replace(/^#+\s+(.+)$/gm, '$1'); // Headers
default:
return text;
}
}typescript
// 将Markdown转换为平台专属格式
function formatMessage(text: string, platform: string): string {
switch (platform) {
case 'dingtalk':
case 'wecom':
case 'qqbot':
// 这些平台原生支持Markdown
return text;
case 'wechat-mp':
// 将Markdown转换为纯文本
return text
.replace(/\*\*(.+?)\*\*/g, '$1') // 移除粗体标记
.replace(/\*(.+?)\*/g, '$1') // 移除斜体标记
.replace(/`(.+?)`/g, '$1') // 移除代码标记
.replace(/^#+\s+(.+)$/gm, '$1'); // 移除标题标记
default:
return text;
}
}Troubleshooting
故障排查
Connection Issues
连接问题
Problem: WebSocket connection fails for WeChat Work Robot
typescript
// Solution: Check network and enable debug logging
const wecom = new WeComChannel({
corpId: process.env.WECOM_CORP_ID,
corpSecret: process.env.WECOM_CORP_SECRET,
mode: 'ws',
debug: true // Enable debug logs
});
wecom.on('error', (error) => {
console.error('WeChat Work error:', error);
// Implement retry logic
});
wecom.on('disconnect', () => {
console.log('Disconnected, reconnecting...');
setTimeout(() => wecom.connect(), 5000);
});Problem: Callback URL not receiving messages
bash
undefined问题:企业微信机器人WebSocket连接失败
typescript
// 解决方案:检查网络并启用调试日志
const wecom = new WeComChannel({
corpId: process.env.WECOM_CORP_ID,
corpSecret: process.env.WECOM_CORP_SECRET,
mode: 'ws',
debug: true // 启用调试日志
});
wecom.on('error', (error) => {
console.error('企业微信错误:', error);
// 实现重连逻辑
});
wecom.on('disconnect', () => {
console.log('连接断开,正在重连...');
setTimeout(() => wecom.connect(), 5000);
});问题:回调地址无法接收消息
bash
undefinedVerify your public URL is accessible
验证公网地址可访问
Check nginx/reverse proxy configuration
检查nginx/反向代理配置
Ensure SSL certificate is valid
确保SSL证书有效
Verify firewall allows incoming connections
验证防火墙允许入站连接
undefinedundefinedMessage Delivery Issues
消息发送问题
Problem: Messages not sending on WeChat Official Account
typescript
// Check 48-hour interaction window
import { WeChatMPChannel } from '@openclaw-china/wechat-mp';
const wechatMP = new WeChatMPChannel({
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET
});
try {
await wechatMP.sendMessage({
userId: 'user_openid',
content: 'Hello'
});
} catch (error) {
if (error.code === 45015) {
console.error('Outside 48-hour window, use template message instead');
await wechatMP.sendTemplateMessage({
userId: 'user_openid',
templateId: process.env.TEMPLATE_ID,
data: { message: 'Hello' }
});
}
}Problem: Messages truncated or not displaying
typescript
// Enable automatic message splitting for long content
const wechatMP = new WeChatMPChannel({
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET,
activeDeliveryMode: 'split', // Split long messages automatically
renderMarkdown: true // Convert Markdown to plain text
});问题:微信公众号消息发送失败
typescript
undefinedPlatform-Specific Issues
检查48小时互动窗口限制
QQ Bot: Streaming not working in groups
typescript
// Streaming only supports C2C (private chat)
const qqBot = new QQBotChannel({
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN,
streaming: true // Only applies to private chat
});
// For groups, use regular messages
qqBot.on('message', async (message) => {
if (message.messageType === 'GROUP') {
// No streaming in groups, send complete message
const response = await openclawAgent.chat(message.content);
await qqBot.sendMessage({
groupId: message.groupId,
content: response.text
});
}
});DingTalk: Rate limiting
typescript
// Implement rate limiting
import { RateLimiter } from 'limiter';
const limiter = new RateLimiter({
tokensPerInterval: 20,
interval: 'minute'
});
async function sendDingTalkMessage(message) {
await limiter.removeTokens(1);
return dingtalk.sendMessage(message);
}import { WeChatMPChannel } from '@openclaw-china/wechat-mp';
const wechatMP = new WeChatMPChannel({
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET
});
try {
await wechatMP.sendMessage({
userId: 'user_openid',
content: 'Hello'
});
} catch (error) {
if (error.code === 45015) {
console.error('超出48小时互动窗口,改用模板消息');
await wechatMP.sendTemplateMessage({
userId: 'user_openid',
templateId: process.env.TEMPLATE_ID,
data: { message: 'Hello' }
});
}
}
**问题**:消息被截断或无法正常显示
```typescript
// 启用长消息自动拆分
const wechatMP = new WeChatMPChannel({
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET,
activeDeliveryMode: 'split', // 自动拆分长消息
renderMarkdown: true // 将Markdown转换为纯文本
});Debug Mode
平台专属问题
typescript
// Enable verbose logging for troubleshooting
export default {
channels: {
'qqbot-china': {
enabled: true,
debug: true, // Enable debug logs
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN
}
},
logging: {
level: 'debug', // Set global log level
channels: ['qqbot-china'] // Log specific channels
}
}QQ Bot:群聊无法使用流式响应
typescript
// 流式响应仅支持C2C(私聊)
const qqBot = new QQBotChannel({
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN,
streaming: true // 仅对私聊生效
});
// 群聊使用普通消息模式
qqBot.on('message', async (message) => {
if (message.messageType === 'GROUP') {
// 群聊不支持流式响应,发送完整消息
const response = await openclawAgent.chat(message.content);
await qqBot.sendMessage({
groupId: message.groupId,
content: response.text
});
}
});钉钉:请求频率限制
typescript
// 实现请求频率限制
import { RateLimiter } from 'limiter';
const limiter = new RateLimiter({
tokensPerInterval: 20,
interval: 'minute'
});
async function sendDingTalkMessage(message) {
await limiter.removeTokens(1);
return dingtalk.sendMessage(message);
}Feature Support Matrix
调试模式
| Feature | DingTalk | QQ Bot | WeChat Work Robot | WeChat Work App | WeChat Customer Service | WeChat Official Account |
|---|---|---|---|---|---|---|
| Text Messages | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Markdown | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ (converted) |
| Streaming | ✅ | ✅ (C2C only) | ✅ | ❌ | ❌ | ❌ |
| Images/Files | ✅ | ✅ | ✅ | ✅ | 🚧 | ✅ (images only) |
| Voice | ✅ | ✅ | ✅ | ✅ | 🚧 | ✅ (with ASR) |
| Group Chat | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Multi-Account | ✅ | ✅ | ✅ | ✅ | 🚧 | 🚧 |
| Proactive Send | ✅ | ✅ | ✅ | ✅ | 🚧 | 🚧 |
Legend: ✅ Supported | ❌ Not Supported | 🚧 In Development
typescript
// 启用详细日志用于故障排查
export default {
channels: {
'qqbot-china': {
enabled: true,
debug: true, // 启用调试日志
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN
}
},
logging: {
level: 'debug', // 设置全局日志级别
channels: ['qqbot-china'] // 仅记录指定平台日志
}
}—
功能支持矩阵
—
| 功能 | 钉钉 | QQ Bot | 企业微信机器人 | 企业微信自建应用 | 微信客服 | 微信公众号 |
|---|---|---|---|---|---|---|
| 文本消息 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Markdown | ✅ | ✅ | ✅ | ✅ | ❌ | ✅(需转换) |
| 流式响应 | ✅ | ✅(仅私聊) | ✅ | ❌ | ❌ | ❌ |
| 图片/文件 | ✅ | ✅ | ✅ | ✅ | 🚧 | ✅(仅图片) |
| 语音消息 | ✅ | ✅ | ✅ | ✅ | 🚧 | ✅(搭配ASR) |
| 群聊支持 | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| 多账号 | ✅ | ✅ | ✅ | ✅ | 🚧 | 🚧 |
| 主动发送 | ✅ | ✅ | ✅ | ✅ | 🚧 | 🚧 |
图例:✅ 已支持 | ❌ 不支持 | 🚧 开发中