| name | openclaw-china-integration |
| description | Expert in integrating OpenClaw AI with Chinese IM platforms (DingTalk, Feishu, QQ, WeChat Work, WeChat Official Account) |
| triggers | ["how do I connect OpenClaw to DingTalk","integrate OpenClaw with WeChat Work","set up OpenClaw China plugin","configure QQ bot with OpenClaw","add Feishu channel to OpenClaw","deploy OpenClaw to Chinese IM platforms","troubleshoot OpenClaw China connection","what Chinese messaging platforms does OpenClaw support"] |
OpenClaw China Integration Skill
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 (ๅพฎไฟกๅฎขๆ).
What OpenClaw China Does
- 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
Installation
Quick Setup (Recommended)
npx @openclaw-china/setup
This interactive installer will:
- Check your OpenClaw installation
- Guide you through platform selection
- Generate configuration files
- Install required dependencies
Manual Installation
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
npm install @openclaw-china/qqbot
npm install @openclaw-china/wecom
Platform 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 |
Configuration
DingTalk Configuration
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
}
]
}
}
}
Environment variables:
DINGTALK_CLIENT_ID=your_client_id
DINGTALK_CLIENT_SECRET=your_client_secret
QQ Bot Configuration
export default {
channels: {
'qqbot-china': {
enabled: true,
appId: process.env.QQ_APP_ID,
token: process.env.QQ_BOT_TOKEN,
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)
export default {
channels: {
wecom: {
enabled: true,
corpId: process.env.WECOM_CORP_ID,
corpSecret: process.env.WECOM_CORP_SECRET,
mode: 'ws',
token: process.env.WECOM_ROBOT_TOKEN,
encodingAESKey: process.env.WECOM_ENCODING_AES_KEY
}
}
}
WeChat Work Self-Built App (Can Connect to Personal WeChat)
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)
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
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,
renderMarkdown: true,
activeDeliveryMode: 'split',
asrConfig: {
enabled: true,
secretId: process.env.TENCENT_CLOUD_SECRET_ID,
secretKey: process.env.TENCENT_CLOUD_SECRET_KEY,
engineType: '16k_zh'
}
}
}
}
Real Code Examples
Handling Incoming Messages
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('Received:', message.content);
const response = await openclawAgent.chat(message.content);
await channel.sendMessage({
conversationId: message.conversationId,
content: response.text,
messageType: 'markdown'
});
});
Sending Proactive Messages (Scheduled Tasks)
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'
});
}
cron.schedule('0 9 * * *', sendDailyReport);
Handling File Uploads
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);
const analysis = await openclawAgent.analyzeFile(fileBuffer);
await wecomApp.sendMessage({
userId: fileMessage.fromUserId,
content: `ๆไปถๅๆ็ปๆ๏ผ\n${analysis}`
});
});
Streaming Response (QQ Bot C2C)
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) => {
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,
: response.
});
}
});
Voice Message with ASR (WeChat Official Account)
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) => {
const text = voiceMessage.recognizedText;
console.log('Voice recognized:', text);
const response = await openclawAgent.chat(text);
await wechatMP.sendMessage({
userId: voiceMessage.fromUserId,
content: response.text
});
});
Common Patterns
Multi-Account Setup
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
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
function formatMessage(text: string, platform: string): string {
switch (platform) {
case 'dingtalk':
case 'wecom':
case 'qqbot':
return text;
case 'wechat-mp':
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
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('WeChat Work error:', error);
});
wecom.on('disconnect', () => {
console.log('Disconnected, reconnecting...');
setTimeout(() => wecom.connect(), 5000);
});
Problem: Callback URL not receiving messages
curl https://your-domain.com/webhook/wecom-app
Message Delivery Issues
Problem: Messages not sending on WeChat Official Account
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
const wechatMP = new WeChatMPChannel({
appId: process.env.WECHAT_MP_APP_ID,
appSecret: process.env.WECHAT_MP_APP_SECRET,
activeDeliveryMode: 'split',
renderMarkdown: true
});
Platform-Specific Issues
QQ Bot: Streaming not working in groups
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
});
}
});
DingTalk: 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);
}
Debug Mode
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']
}
}
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