← Back to Plugins
Channels

Dingtalk

adongguo By adongguo ⭐ 18 stars 👁 41 views ▲ 17 votes

DingTalk (钉钉) channel plugin for OpenClaw.

GitHub

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

Comments

Sign in to leave a comment

Loading comments...