# wecom-openclaw-plugin
**Repository Path**: mstitop/wecom-openclaw-plugin
## Basic Information
- **Project Name**: wecom-openclaw-plugin
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-04-20
- **Last Updated**: 2026-04-22
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
> 💡 **快速上手指引 & 交流群**
>
> 📖 [点击查看完整接入指引文档](https://doc.weixin.qq.com/doc/w3_AFYA1wY6ACoCNRxfnyGRJQaSa6jjJ?scode=AJEAIQdfAAo0RJmzxLAFYA1wY6ACo) — 包含配置步骤、产品介绍、常见问题解答等。
>
> 💬 扫码加入企业微信交流群:
>
>
# 特别说明
> ****2026.3.22 版本 OpenClaw 兼容说明****
>
> 如果你的 OpenClaw 是 2026.3.22 及以上的版本,请升级插件到 2026.3.24 及以上版本。
>
> 如果你的 OpenClaw 是 2026.3.22 以下的版本,请保持插件版本在 2026.3.20 版本。
>
> 你可以使用以下命令快速安装: `npx -y @wecom/wecom-openclaw-cli install --force`
# 🤖 WeCom OpenClaw Plugin
**WeCom channel plugin for [OpenClaw](https://github.com/openclaw)** — by the Tencent WeCom team.
> A channel plugin powered by WeCom. Supports **Bot mode** (WebSocket long-polling or HTTP webhook with JSON callbacks) and **Agent mode** (HTTP webhook with XML encrypted callbacks). Direct messages, group chats, streaming replies, and proactive messaging.
---
📖 [WeCom AI Bot Official Documentation](https://open.work.weixin.qq.com/help?doc_id=21657)
## ✨ Features
- 🔗 **Dual-mode**: Bot (WebSocket / Webhook) and Agent (HTTP webhook) can run independently or together
- 💬 Supports both direct messages (DM) and group chat
- 📤 Proactive messaging to specific users, groups, departments, or tags
- 🖼️ Receives and processes image, voice, video, file, and **mixed (图文混排)** messages with automatic downloading
- 🗣️ Voice-to-text: automatically extracts transcribed text from voice messages
- 💬 Quote message support: processes quoted text, image, voice, and file messages
- ⏳ Streaming replies with "thinking" placeholder messages (Bot mode)
- 🔐 Agent mode: AES-256-CBC encrypted XML callbacks with SHA1 signature verification
- 📝 Markdown formatting support for replies
- 🃏 Template card messages (text_notice, news_notice, button_interaction, vote_interaction, multiple_interaction) with **event callback handling**
- 🔒 Built-in access control: DM Policy (pairing / open / allowlist / disabled) and Group Policy (open / allowlist / disabled)
- 🔑 Command authorization: per-account command permission control with access group support
- 👥 Multi-account support: run multiple WeCom accounts with independent bot/agent configs
- 🧩 MCP tool integration (`wecom_mcp`) with interceptor pipeline (biz-error, media, smartpage-create, smartpage-export)
- 🎯 **15 built-in Skills**: contact lookup, doc management, todo, meeting, schedule, messaging, smartsheet, template cards, and more
- 🔀 Dynamic Agent routing: auto-create isolated agents per user/group
- 📁 Local file sending with configurable media path allowlist (`mediaLocalRoots`)
- 📊 Smart media size limits with auto-downgrade (image 10MB → file, video 10MB → file, voice 2MB/AMR-only → file, max 20MB)
- 🔄 **Bot-first, Agent-fallback** outbound delivery: auto fallback to Agent HTTP API when Bot WS is unavailable
- ⚡ Auto heartbeat keep-alive and reconnection (up to 10 reconnect attempts, 5 auth failure retries)
- 🛡️ Anti-kick protection: suppresses auto-restart on server-side disconnection to prevent mutual kicking loops
- 🧙 Interactive CLI setup wizard
---
## 🚀 Getting Started
### Requirements
- OpenClaw `>= 2026.3.28`
### Quick Install
Use the CLI tool to automatically install the plugin and complete bot configuration in one step:
```shell
# Automatically install the channel plugin and quickly complete configuration; also works for updates
npx -y @wecom/wecom-openclaw-cli install
```
More Options
```shell
# If installation fails, try force install
npx -y @wecom/wecom-openclaw-cli install --force
# Use --help to learn more about the tool
npx -y @wecom/wecom-openclaw-cli --help
```
### Manual Install
```shell
openclaw plugins install @wecom/wecom-openclaw-plugin
```
### Configuration
#### Option 1: Interactive Setup
```shell
openclaw channels add
```
Follow the prompts to enter your WeCom bot's **Bot ID** and **Secret**.
#### Option 2: CLI Quick Setup
```shell
openclaw config set channels.wecom.botId
openclaw config set channels.wecom.secret
openclaw config set channels.wecom.enabled true
openclaw gateway restart
```
### Mode Overview
The plugin supports two connection modes that can be used independently or together:
| Mode | Connection | Message Format | Use Case |
|------|-----------|---------------|----------|
| **Bot** (智能体) | WebSocket (default) or HTTP webhook | JSON | Quick setup, streaming replies |
| **Agent** (自建应用) | HTTP webhook callbacks | XML | Enterprise apps, API-driven messaging |
> **Note**: Bot mode supports two connection methods via `connectionMode`:
> - `websocket` (default) — WebSocket long-polling, requires `botId` + `secret`
> - `webhook` — HTTP callback, requires `token` + `encodingAESKey`
### Bot Mode Configuration
#### Core Settings
| Config Path | Description | Options | Default |
|---|---|---|---|
| `channels.wecom.enabled` | Enable the channel | `true` / `false` | `false` |
| `channels.wecom.connectionMode` | Bot connection mode | `websocket` / `webhook` | `websocket` |
| `channels.wecom.name` | Account display name | — | `企业微信` |
#### WebSocket Mode (default)
| Config Path | Description | Options | Default |
|---|---|---|---|
| `channels.wecom.botId` | WeCom bot ID | — | — |
| `channels.wecom.secret` | WeCom bot secret | — | — |
| `channels.wecom.websocketUrl` | WebSocket endpoint | — | `wss://openws.work.weixin.qq.com` |
| `channels.wecom.sendThinkingMessage` | Send "thinking" placeholder | `true` / `false` | `true` |
#### Webhook Mode (`connectionMode: "webhook"`)
| Config Path | Description | Options | Default |
|---|---|---|---|
| `channels.wecom.token` | Webhook verification token | — | — |
| `channels.wecom.encodingAESKey` | AES encryption key (43 chars Base64) | — | — |
| `channels.wecom.receiveId` | Receiver ID (for decryption verification) | — | — |
| `channels.wecom.welcomeText` | Welcome message on enter_chat event | — | — |
| `channels.wecom.streamPlaceholderContent` | Stream placeholder content | — | — |
#### Access Control
| Config Path | Description | Options | Default |
|---|---|---|---|
| `channels.wecom.dmPolicy` | DM access policy | `pairing` / `open` / `allowlist` / `disabled` | `open` |
| `channels.wecom.allowFrom` | DM allowlist (user IDs) | — | `[]` |
| `channels.wecom.groupPolicy` | Group chat access policy | `open` / `allowlist` / `disabled` | `open` |
| `channels.wecom.groupAllowFrom` | Group allowlist (group IDs) | — | `[]` |
| `channels.wecom.groups` | Per-group config (e.g. sender allowlist) | — | `{}` |
#### Media Settings
| Config Path | Description | Default |
|---|---|---|
| `channels.wecom.mediaLocalRoots` | Extra local paths allowed for media sending (supports `~`) | `[]` |
| `channels.wecom.media.maxBytes` | Max media file size in bytes | `20971520` (20MB) |
| `channels.wecom.media.tempDir` | Temp directory for media processing | — |
| `channels.wecom.media.retentionHours` | Media file retention hours | — |
| `channels.wecom.media.cleanupOnStart` | Clean temp media on startup | — |
**Media Size Limits & Auto-Downgrade:**
| Media Type | Max Size | Downgrade Behavior |
|---|---|---|
| Image | 10 MB | Exceeds → sent as file |
| Video | 10 MB | Exceeds → sent as file |
| Voice | 2 MB (AMR only) | Non-AMR format or exceeds → sent as file |
| File | 20 MB | Exceeds → rejected (cannot send) |
#### Network Settings
| Config Path | Description | Default |
|---|---|---|
| `channels.wecom.network.timeoutMs` | HTTP request timeout (ms) | — |
| `channels.wecom.network.retries` | Number of retries | — |
| `channels.wecom.network.retryDelayMs` | Delay between retries (ms) | — |
| `channels.wecom.network.egressProxyUrl` | Egress proxy URL for trusted IP scenarios | — |
> **Egress Proxy Priority**: `channels.wecom.network.egressProxyUrl` > `OPENCLAW_WECOM_EGRESS_PROXY_URL` > `WECOM_EGRESS_PROXY_URL` > `HTTPS_PROXY` > `ALL_PROXY` > `HTTP_PROXY`
### Agent Mode Configuration
Agent mode uses HTTP webhook callbacks with XML encrypted messages. You need to configure the callback URL in the WeCom admin console under "API Receive" settings.
#### Prerequisites
1. Create a self-built app in [WeCom Admin Console](https://work.weixin.qq.com/wework_admin/frame#apps)
2. Note down the **CorpID**, **CorpSecret** (from app settings), and **AgentId**
3. In the app settings, go to "API Receive" (API接收):
- Note down the **Token** and **EncodingAESKey** (auto-generated or custom)
- **Do NOT click save yet** — WeCom will verify the callback URL immediately when you save
#### Setup Steps
> **Important**: You must configure the Gateway **before** saving the callback URL in WeCom admin console. WeCom sends a verification request (GET with `echostr`) immediately when you save, and the Gateway needs the `token` and `encodingAESKey` to decrypt and respond correctly.
**Step 1: Configure Gateway**
```shell
openclaw config set channels.wecom.agent.corpId
openclaw config set channels.wecom.agent.corpSecret
openclaw config set channels.wecom.agent.agentId
openclaw config set channels.wecom.agent.token
openclaw config set channels.wecom.agent.encodingAESKey
openclaw config set channels.wecom.enabled true
openclaw gateway restart
```
**Step 2: Save callback URL in WeCom admin console**
Go back to the "API Receive" settings and enter the callback URL:
- **URL**: `https:///plugins/wecom/agent/` (e.g. `/plugins/wecom/agent/default`); single-account mode can also use `/plugins/wecom/agent`
Now click save — the verification should pass.
#### JSON Configuration
```json
{
"channels": {
"wecom": {
"enabled": true,
"agent": {
"corpId": "ww1234567890abcdef",
"corpSecret": "your-corp-secret",
"agentId": 1000002,
"token": "your-callback-token",
"encodingAESKey": "your-encoding-aes-key-43-chars"
}
}
}
}
```
#### Agent Config Reference
| Config Path | Description | Required |
|---|---|---|
| `channels.wecom.agent.corpId` | Enterprise Corp ID | Yes |
| `channels.wecom.agent.corpSecret` | App secret | Yes |
| `channels.wecom.agent.agentId` | App agent ID | No (needed for proactive messaging) |
| `channels.wecom.agent.token` | Callback verification token | Yes |
| `channels.wecom.agent.encodingAESKey` | Callback encryption key (43 chars) | Yes |
| `channels.wecom.agent.welcomeText` | Welcome message | No |
| `channels.wecom.agent.dmPolicy` | DM access policy (overrides top-level) | No |
| `channels.wecom.agent.allowFrom` | DM allowlist (overrides top-level) | No |
#### Webhook Paths
**Agent Mode:**
| Path | Description |
|---|---|
| `/plugins/wecom/agent/` | 推荐路径(例如 `/plugins/wecom/agent/default`) |
| `/plugins/wecom/agent/default` | 多账号模式下自动路由到默认账号(即使默认账号 ID 不是 `default`) |
| `/plugins/wecom/agent` | 兼容路径(单账号 / 多账号签名匹配) |
| `/wecom/agent` | Legacy 兼容路径 |
**Bot Webhook Mode** (`connectionMode: "webhook"`):
| Path | Description |
|---|---|
| `/plugins/wecom/bot` | Recommended path (single account) |
| `/plugins/wecom/bot/` | Multi-account path |
| `/wecom/bot` | Legacy compatible path |
| `/wecom` | Legacy compatible path |
### Outbound Delivery (Bot WS → Agent HTTP Fallback)
The plugin uses a **Bot-first, Agent-fallback** strategy for outbound message delivery:
1. **Bot WebSocket available** → send via WS (supports markdown, streaming)
2. **Bot WS unavailable** → automatically fallback to **Agent HTTP API** (`cgi-bin/message/send`)
This means:
- **Agent-only accounts** (no Bot configured) can still send proactive messages, cron deliveries, and broadcasts
- **Target formats** like `party:1`, `tag:Ops`, `user:zhangsan` are fully supported in both paths
- **Media fallback**: when Bot WS is unavailable, media files are downloaded, uploaded to WeCom via Agent API, then sent; if upload fails, falls back to text + URL
- No manual switching needed — the plugin handles fallback transparently
### Using Both Modes Together
Bot and Agent can run simultaneously on the same account. Bot handles WebSocket streaming; Agent handles HTTP webhook callbacks with API-driven replies.
```json
{
"channels": {
"wecom": {
"enabled": true,
"botId": "your-bot-id",
"secret": "your-bot-secret",
"agent": {
"corpId": "ww1234567890abcdef",
"corpSecret": "your-corp-secret",
"agentId": 1000002,
"token": "your-callback-token",
"encodingAESKey": "your-encoding-aes-key-43-chars"
}
}
}
}
```
### Multi-Account Configuration
Use `accounts` to configure multiple WeCom accounts, each with optional bot and/or agent sub-configs. Account-level fields override top-level fields of the same name.
```json
{
"channels": {
"wecom": {
"enabled": true,
"defaultAccount": "main",
"dmPolicy": "open",
"accounts": {
"main": {
"botId": "bot-id-1",
"secret": "secret-1",
"agent": {
"corpId": "ww1234567890abcdef",
"corpSecret": "secret-a",
"agentId": 1000002,
"token": "token-a",
"encodingAESKey": "aes-key-a"
}
},
"support": {
"dmPolicy": "allowlist",
"allowFrom": ["admin1"],
"agent": {
"corpId": "ww1234567890abcdef",
"corpSecret": "secret-b",
"agentId": 1000003,
"token": "token-b",
"encodingAESKey": "aes-key-b"
}
}
}
}
}
}
```
> **Note**: In multi-account mode, accounts without explicit `bindings` will not fall back to the default agent. Configure bindings for each account:
> ```json
> {
> "bindings": [
> { "agentId": "your-agent", "match": { "channel": "wecom", "accountId": "main" } }
> ]
> }
> ```
### Dynamic Agent Configuration
Dynamic Agent routing automatically creates isolated agents per user or group, enabling session isolation.
```json
{
"channels": {
"wecom": {
"dynamicAgents": {
"enabled": true,
"dmCreateAgent": true,
"groupEnabled": true,
"adminUsers": ["admin_user_id"]
}
}
}
}
```
| Config Path | Description | Default |
|---|---|---|
| `channels.wecom.dynamicAgents.enabled` | Enable dynamic agent routing | `false` |
| `channels.wecom.dynamicAgents.dmCreateAgent` | Create isolated agent per DM user | `true` |
| `channels.wecom.dynamicAgents.groupEnabled` | Enable dynamic agent for group chats | `true` |
| `channels.wecom.dynamicAgents.adminUsers` | Admin users (bypass dynamic routing, use main agent) | `[]` |
---
## 🔒 Access Control
### DM (Direct Message) Access
**Default**: `dmPolicy: "open"` — all users can send direct messages without approval.
#### Approve Pairing
```shell
openclaw pairing list wecom # View pending pairing requests
openclaw pairing approve wecom # Approve a pairing request
```
#### Allowlist Mode
Configure allowed user IDs via `channels.wecom.allowFrom`:
```json
{
"channels": {
"wecom": {
"dmPolicy": "allowlist",
"allowFrom": ["user_id_1", "user_id_2"]
}
}
}
```
#### Open Mode
Set `dmPolicy: "open"` to allow all users to send direct messages without approval.
#### Disabled Mode
Set `dmPolicy: "disabled"` to completely block all direct messages.
### Group Access
#### Group Policy (`channels.wecom.groupPolicy`)
- `"open"` — Allow messages from all groups (default)
- `"allowlist"` — Only allow groups listed in `groupAllowFrom`
- `"disabled"` — Disable all group messages
### Group Configuration Examples
#### Allow All Groups (Default Behavior)
```json
{
"channels": {
"wecom": {
"groupPolicy": "open"
}
}
}
```
#### Allow Only Specific Groups
```json
{
"channels": {
"wecom": {
"groupPolicy": "allowlist",
"groupAllowFrom": ["group_id_1", "group_id_2"]
}
}
}
```
#### Allow Only Specific Senders Within a Group (Sender Allowlist)
In addition to the group allowlist, you can restrict which members within a group are allowed to interact with the bot. Only messages from users listed in `groups..allowFrom` will be processed; messages from other members will be silently ignored. This is a sender-level allowlist that applies to **all messages**.
```json
{
"channels": {
"wecom": {
"groupPolicy": "allowlist",
"groupAllowFrom": ["group_id_1"],
"groups": {
"group_id_1": {
"allowFrom": ["user_id_1", "user_id_2"]
}
}
}
}
}
```
---
## ⏰ Cronjob (Scheduled Tasks)
The plugin supports scheduled message delivery via OpenClaw's built-in Cron service. Cron jobs run through the **Agent outbound** channel, so Agent mode must be configured.
### Target Formats
The `delivery.to` field supports the following target formats:
| Format | Target | Example |
|--------|--------|--------|
| `party:` | Department (all members) | `party:1` (root dept = all employees) |
| `dept:` | Department (alias for party) | `dept:5` |
| `tag:` | Tag group | `tag:Ops` |
| `user:` | Specific user | `user:zhangsan` |
| `group:` | External group chat | `group:wr123abc` |
| `chat:` | Group chat (alias for group) | `chat:wc456def` |
| Pure number | Auto-detected as department | `1` → `party:1` |
| `wr...` / `wc...` | Auto-detected as group chat | `wr123` → `chatid` |
| Other string | Auto-detected as user | `zhangsan` → `touser` |
> **Namespace prefixes** (`wecom:`, `qywx:`, `wework:`, `wechatwork:`, `wecom-agent:`) are automatically stripped before parsing.
### Method 1: CLI (Recommended — takes effect immediately)
```shell
openclaw cron add \
--name "daily-report" \
--agent main \
--cron "0 9 * * 1-5" \
--tz "Asia/Shanghai" \
--message "Good morning! Here is your daily briefing." \
--announce \
--channel wecom \
--to "party:1"
```
> **Note**: `--announce` enables delivery mode (broadcasts the AI response to the target chat). Use `--no-deliver` to keep output internal. The deprecated `--deliver` flag is an alias for `--announce`.
Common CLI commands:
```shell
openclaw cron list # List all cron jobs
openclaw cron show # Show job details
openclaw cron enable # Enable a job
openclaw cron disable # Disable a job
openclaw cron remove # Remove a job
openclaw cron run # Manually trigger a job
openclaw cron runs --id # View run history
openclaw cron edit --message "New prompt" # Edit a job
```
### Method 2: Edit `jobs.json` (requires gateway restart)
File path: `~/.openclaw/cron/jobs.json`
```json
{
"version": 1,
"jobs": [
{
"id": "daily-report",
"name": "Daily Report",
"agentId": "main",
"enabled": true,
"schedule": { "kind": "cron", "expr": "0 9 * * 1-5", "tz": "Asia/Shanghai" },
"sessionTarget": "isolated",
"wakeMode": "now",
"payload": {
"kind": "agentTurn",
"message": "Generate today's briefing and send it."
},
"delivery": {
"mode": "announce",
"channel": "wecom",
"to": "party:1",
"accountId": "main"
},
"state": {}
}
]
}
```
After editing, restart the gateway:
```shell
openclaw gateway restart
```
### Method 3: Create via chat (takes effect immediately)
You can ask the AI agent directly in a WeCom conversation:
> "Create a scheduled task: send a daily briefing to the entire company at 9am every weekday"
The agent will call the Cron API to create the job — no restart needed.
### Notes
- Cron jobs use the **Agent outbound** path — Agent mode (`corpId` / `corpSecret` / `agentId`) must be configured.
- The server IP must be in the WeCom trusted IP allowlist, or configure `egressProxyUrl` for a fixed egress proxy.
- Jobs created via CLI or chat API take effect immediately. Manual edits to `jobs.json` require `openclaw gateway restart`.
- For multi-account setups, set `delivery.accountId` to the target account (e.g. `"main"`, `"support"`).
---
## 📦 Update
```shell
openclaw plugins update wecom-openclaw-plugin
```
---
## 📄 License
MIT