Channels
Dingtalk
DingTalk (钉钉) channel plugin for OpenClaw.
Install
npm install @adongguo/dingtalk`
Configuration Example
> plugins:
> load:
> paths:
> - "./node_modules/@adongguo/dingtalk"
>
README
# openclaw-dingtalk
DingTalk (钉钉) channel plugin for [OpenClaw](https://github.com/openclaw/openclaw).
[English](#english) | [中文](#中文)
---
## English
### Installation
```bash
openclaw plugins install @adongguo/dingtalk
```
> **Note:** `npm install @adongguo/dingtalk` alone is **not enough** — OpenClaw does not auto-discover plugins from `node_modules`. You must use `openclaw plugins install` as shown above, or manually add the plugin path to your config:
>
> ```yaml
> plugins:
> load:
> paths:
> - "./node_modules/@adongguo/dingtalk"
> ```
### Configuration
1. Create an enterprise internal application on [DingTalk Open Platform](https://open-dev.dingtalk.com)
2. Get your AppKey (ClientID) and AppSecret (ClientSecret) from the Credentials page
3. Enable Robot capability and select **Stream mode**
4. Configure event subscriptions (see below)
5. Configure the plugin:
#### Required Steps
1. **Create Application**: Go to DingTalk Developer Console → Application Development → Enterprise Internal Development → Create Application
2. **Enable Robot**: In your application, go to Application Capabilities → Robot → Enable Robot Configuration → Select **Stream mode**
3. **Get Credentials**: Go to Basic Information → Application Information to get AppKey and AppSecret
4. **Publish Application**: Publish the app (at least to test version) to make the bot available
```bash
openclaw config set channels.dingtalk.appKey "dingXXXXXXXX"
openclaw config set channels.dingtalk.appSecret "your_app_secret"
openclaw config set channels.dingtalk.enabled true
```
### Configuration Options
```yaml
channels:
dingtalk:
enabled: true
appKey: "dingXXXXXXXX"
appSecret: "secret"
# Robot code (optional, for media download)
robotCode: "dingXXXXXXXX"
# Connection mode: "stream" (recommended) or "webhook"
connectionMode: "stream"
# DM policy: "pairing" | "open" | "allowlist"
dmPolicy: "pairing"
# Group policy: "open" | "allowlist" | "disabled"
groupPolicy: "allowlist"
# Group session scope: "per-group" | "per-user"
groupSessionScope: "per-group"
# Max media size in MB (default: 30)
mediaMaxMb: 30
# Render mode for bot replies: "auto" | "raw" | "card"
renderMode: "auto"
# AI Card streaming mode: "enabled" | "disabled"
aiCardMode: "enabled"
# Show thinking indicator before response
showThinking: true
# Session timeout in ms (default: 30 minutes)
sessionTimeout: 1800000
# Enable local image auto-upload in agent responses
enableMediaUpload: true
# Custom system prompt for the agent
systemPrompt: "You are a helpful assistant."
# Gateway integration (required for AI Card streaming)
gatewayToken: "your_gateway_token"
gatewayPort: 18789
# Custom slash commands
commands:
faq:
description: "Show FAQ"
action: "reply"
response: "Visit https://example.com/faq for help."
expert:
description: "Switch to expert mode"
action: "system-prompt"
systemPrompt: "You are a domain expert..."
response: "Switched to expert mode."
# Customize standard message text
templates:
thinking:
text: "Processing..."
enabled: true
error:
text: "Sorry, an error occurred: {message}"
welcome:
enabled: true
title: "My AI Bot"
# Per-DM configuration
dms:
"staffId123":
systemPrompt: "Personalized prompt for this user."
# Per-group configuration
groups:
"chatId456":
systemPrompt: "Group-specific instructions."
skills:
- "data-analysis"
- "code-review"
allowFrom:
- "*"
# Multi-account support
accounts:
sales-bot:
appKey: "dingSALES"
appSecret: "sales_secret"
robotCode: "salesBot"
systemPrompt: "You are the sales assistant."
```
#### Render Mode
| Mode | Description |
|------|-------------|
| `auto` | (Default) Automatically detect: use ActionCard for messages with code blocks, tables, or images; plain text otherwise. |
| `raw` | Always send replies as plain text. Markdown tables are converted to ASCII. |
| `card` | Always send replies as ActionCard with full markdown rendering. |
#### Access Control Policies
| Option | Values | Description |
|--------|--------|-------------|
| `dmPolicy` | `pairing` / `open` / `allowlist` | Controls who can DM the bot. `pairing` requires approval flow; `open` requires `allowFrom` with `*`; `allowlist` checks `allowFrom` list. |
| `groupPolicy` | `open` / `allowlist` / `disabled` | Controls group access. `allowlist` checks `groupAllowFrom`. |
| `groupSessionScope` | `per-group` / `per-user` | Session isolation in groups. `per-group` shares one session; `per-user` gives each member their own session. |
#### Session Isolation
| Chat Type | Scope | Session Key Pattern |
|-----------|-------|---------------------|
| DM | Per user | `dingtalk:<senderId>` |
| Group (per-group) | Shared per group | `dingtalk:<conversationId>` |
| Group (per-user) | Per user in group | `dingtalk:<conversationId>:<senderId>` |
Sessions expire after `sessionTimeout` (default 30 minutes). Expired sessions are automatically cleaned up every 5 minutes.
### Features
#### Messaging
- Stream mode connection (WebSocket-based, auto-reconnect with exponential backoff)
- Direct messages and group chats with configurable policies
- Text, Markdown, ActionCard, and Link message types
- Smart render mode auto-detection (code blocks, tables, images)
- Message chunking for long responses (configurable limit, default 4000 chars)
- Message deduplication (5-minute TTL window)
#### AI Card Streaming
- Real-time streaming responses via AI Card with typewriter effect
- Gateway SSE integration for inference streaming
- Automatic fallback to regular message if card creation fails
- Card lifecycle management (Processing → Inputting → Finished/Failed)
#### Media Handling
- Inbound image download and forwarding to agent (with vision support)
- RichText message parsing (mixed text + images)
- Agent response auto-upload: local image paths in markdown are automatically uploaded
- File marker syntax for sending file cards: `[DINGTALK_FILE]{"path": "...", "name": "..."}[/DINGTALK_FILE]`
- Inline image rendering via ActionCard
#### Commands
- Built-in commands: `/help`, `/status`, `/whoami`
- Session commands: `/new`, `/reset`, `/clear`, `新会话`, `重新开始`, `清空对话`
- User-defined commands via config with three action types:
- `reply` — Send a static response
- `system-prompt` — Override the agent system prompt
- `new-session` — Reset the conversation session
#### Message Templates
- Configurable message text for thinking indicator, error messages, welcome, access denied, new session, etc.
- Variable substitution: `{senderId}`, `{senderName}`, `{message}`
- Enable/disable individual templates
#### Context Enhancements
- DingTalk metadata injected into agent context (chat type, sender info, admin status, @mention status)
- Per-DM system prompts (`dms.<staffId>.systemPrompt`)
- Per-group system prompts (`groups.<chatId>.systemPrompt`)
- Per-group skill injection (`groups.<chatId>.skills`)
- Custom global system prompt
#### Multi-Account Support
- Multiple DingTalk bots from a single plugin instance
- Per-account credential overrides (appKey, appSecret, robotCode)
- Per-account config overrides (systemPrompt, policies, etc.)
- Independent stream connections per account
#### OpenClaw SDK Integration
- CLI commands: `dingtalk-status`, `dingtalk-sessions`, `dingtalk-whoami`
- Agent tools: `dingtalk_send_card` (send ActionCard), `dingtalk_list_group_members` (list tracked members)
- Shipped skills for agent knowledge (messaging, cards, media best practices)
#### Connection Resilience
- Health check every 10 seconds
- Exponential backoff reconnect (2s → 120s)
- Soft reconnect (2 attempts) before hard reconnect
- Reconnect counter capped to prevent unbounded growth
- Credential masking in logs
#### Other
- Pairing flow for DM approval
- User and group directory lookup (config-based)
- Interactive onboarding wizard
- Bot health probe (`probeDingTalk`)
- Passive group member tracking from message flow
### Limitations
- **No message editing**: DingTalk doesn't support editing messages via sessionWebhook
- **No reactions**: Bot API doesn't support message reactions
- **No typing indicator**: DingTalk has no native typing indicator API
- **sessionWebhook expiration**: Reply URLs are temporary and expire
- **Group @mention required**: In group chats, messages must @mention the bot to be received — this is a DingTalk platform limitation and cannot be changed via configuration
### FAQ
#### Bot cannot receive messages
Check the following:
1. Is Robot capability enabled in your application?
2. Is **Stream mode** selected (not HTTP mode)?
3. Is the application published?
4. Are the appKey and appSecret correct?
#### Failed to send messages
1. Check if sessionWebhook has expired
2. Verify message format is correct
3. Ensure bot has necessary permissions
#### How to clear history / start new conversation
Send one of these commands in the chat: `/new`, `/reset`, `/clear`, `新会话`, `重新开始`, or `清空对话`.
#### How to add custom commands
Add commands to your config under `channels.dingtalk.commands`:
```yaml
channels:
dingtalk:
commands:
faq:
description: "Show FAQ"
action: "reply"
response: "Visit our FAQ page."
coder:
description: "Switch to coding mode"
action: "system-prompt"
systemPrompt: "You are a senior software engineer."
response: "Switched to coding mode."
```
#### Why is the output not streaming
AI Card streaming requires both `aiCardMode: "enabled"` and a configured Gateway (`gatewayToken`). Without these, the bot uses complete-then-send approach. DingTalk API has rate limits, so streaming updates are throttled.
###
channels
By
Comments
Sign in to leave a comment