Back to home

secret-tangyuan

openclaw-weixin-dsh

dsh-plugin: OpenClaw Weixin channel + DeepSeek Harness adapter — WeChat through DSH agents with a control panel in DSH Settings.

Stars
0
Language
TypeScript
Created
Aug 15, 2026
Updated
Aug 15, 2026

Introduction

WeChat

简体中文

dsh-plugin npm

OpenClaw's WeChat channel plugin, supporting login authorization via QR code scanning.

Compatibility

Plugin VersionOpenClaw Versionnpm dist-tagStatus
2.0.x>=2026.3.22latestActive
1.0.x>=2026.1.0 <2026.3.22legacyMaintenance

The plugin checks the host version at startup and will refuse to load if the running OpenClaw version is outside the supported range.

Prerequisites

OpenClaw must be installed (the openclaw CLI needs to be available).

Check your version: openclaw --version

Quick Install

npx -y @tencent-weixin/openclaw-weixin-cli install

Manual Installation

If the quick install doesn't work, follow these steps manually:

1. Install the plugin

openclaw plugins install "@tencent-weixin/openclaw-weixin"

2. Enable the plugin

openclaw config set plugins.entries.openclaw-weixin.enabled true

3. QR code login

openclaw channels login --channel openclaw-weixin

A QR code will appear in the terminal. Scan it with your phone and confirm the authorization. Once confirmed, the login credentials will be saved locally automatically — no further action is needed.

4. Restart the gateway

openclaw gateway restart

Adding More WeChat Accounts

openclaw channels login --channel openclaw-weixin

Each QR code login creates a new account entry, supporting multiple WeChat accounts online simultaneously.

Multi-Account Context Isolation

By default, DMs can share one session bucket. For multiple logged-in WeChat accounts, isolate by account + channel + sender:

openclaw config set session.dmScope per-account-channel-peer

Custom BotAgent (optional)

Every outbound request to the WeChat backend carries a self-declared bot_agent identifier — analogous to an HTTP User-Agent — used for log attribution and monitoring aggregation. The default is OpenClaw. Declaring your own app name makes it much easier to trace your traffic in backend logs.

Add one line to openclaw.json:

{
  "channels": {
    "openclaw-weixin": {
      "botAgent": "MyBot/1.2.0"
    }
  }
}

Format (UA-style):

  • One or more Name/Version tokens, space-separated
  • Each token may optionally be followed by (comment)
  • ASCII only; total length ≤ 256 bytes
  • Invalid tokens are silently dropped during sanitization; falls back to OpenClaw if nothing valid remains

Examples that pass through unchanged:

  • MyBot/1.2.0
  • MyBot/1.2.0 (region=cn;env=prod)
  • MyBot/1.2.0 LangChain/0.3.5
  • MyBot/1.2.0-rc.1+build.5

Note: bot_agent is for observability only — it is not used for authentication or routing. All registered agents on this plugin instance currently share the same botAgent declaration; per-agent overrides may be added in a future version if needed.

Backend API Protocol

This plugin communicates with the backend gateway via HTTP JSON API. Developers integrating with their own backend need to implement the following interfaces.

All endpoints use POST with JSON request and response bodies. Common request headers:

HeaderDescription
Content-Typeapplication/json
AuthorizationTypeFixed value ilink_bot_token
AuthorizationBearer <token> (obtained after login)
X-WECHAT-UINBase64-encoded random uint32

Endpoint List

EndpointPathDescription
getUpdatesgetupdatesLong-poll for new messages
sendMessagesendmessageSend a message (text/image/video/file)
getUploadUrlgetuploadurlGet CDN upload pre-signed URL
getConfiggetconfigGet account config (typing ticket, etc.)
sendTypingsendtypingSend/cancel typing status indicator

getUpdates

Long-polling endpoint. The server responds when new messages arrive or on timeout.

Request body:

{
  "get_updates_buf": ""
}
FieldTypeDescription
get_updates_bufstringSync cursor from the previous response; empty string for the first request

Response body:

{
  "ret": 0,
  "msgs": [...],
  "get_updates_buf": "<new cursor>",
  "longpolling_timeout_ms": 35000
}
FieldTypeDescription
retnumberReturn code, 0 = success
errcodenumber?Error code (e.g., -14 = session timeout)
errmsgstring?Error description
msgsWeixinMessage[]Message list (structure below)
get_updates_bufstringNew sync cursor to pass in the next request
longpolling_timeout_msnumber?Server-suggested long-poll timeout for the next request (ms)

sendMessage

Send a message to a user.

Request body:

{
  "msg": {
    "to_user_id": "<target user ID>",
    "context_token": "<conversation context token>",
    "item_list": [
      {
        "type": 1,
        "text_item": { "text": "Hello" }
      }
    ]
  }
}

getUploadUrl

Get CDN upload pre-signed parameters. Call this endpoint before uploading a file to obtain upload_param and thumb_upload_param.

Request body:

{
  "filekey": "<file identifier>",
  "media_type": 1,
  "to_user_id": "<target user ID>",
  "rawsize": 12345,
  "rawfilemd5": "<plaintext MD5>",
  "filesize": 12352,
  "thumb_rawsize": 1024,
  "thumb_rawfilemd5": "<thumbnail plaintext MD5>",
  "thumb_filesize": 1040
}
FieldTypeDescription
media_typenumber1 = IMAGE, 2 = VIDEO, 3 = FILE
rawsizenumberOriginal file plaintext size
rawfilemd5stringOriginal file plaintext MD5
filesizenumberCiphertext size after AES-128-ECB encryption
thumb_rawsizenumber?Thumbnail plaintext size (required for IMAGE/VIDEO)
thumb_rawfilemd5string?Thumbnail plaintext MD5 (required for IMAGE/VIDEO)
thumb_filesizenumber?Thumbnail ciphertext size (required for IMAGE/VIDEO)

Response body:

{
  "upload_param": "<original image upload encrypted parameters>",
  "thumb_upload_param": "<thumbnail upload encrypted parameters>"
}

getConfig

Get account configuration, including the typing ticket.

Request body:

{
  "ilink_user_id": "<user ID>",
  "context_token": "<optional, conversation context token>"
}

Response body:

{
  "ret": 0,
  "typing_ticket": "<base64-encoded typing ticket>"
}

sendTyping

Send or cancel the typing status indicator.

Request body:

{
  "ilink_user_id": "<user ID>",
  "typing_ticket": "<obtained from getConfig>",
  "status": 1
}
FieldTypeDescription
statusnumber1 = typing, 2 = cancel typing

Message Structure

WeixinMessage

FieldTypeDescription
seqnumber?Message sequence number
message_idnumber?Unique message ID
from_user_idstring?Sender ID
to_user_idstring?Receiver ID
create_time_msnumber?Creation timestamp (ms)
session_idstring?Session ID
message_typenumber?1 = USER, 2 = BOT
message_statenumber?0 = NEW, 1 = GENERATING, 2 = FINISH
item_listMessageItem[]?Message content list
context_tokenstring?Conversation context token, must be passed back when replying

MessageItem

FieldTypeDescription
typenumber1 TEXT, 2 IMAGE, 3 VOICE, 4 FILE, 5 VIDEO
text_item{ text: string }?Text content
image_itemImageItem?Image (with CDN reference and AES key)
voice_itemVoiceItem?Voice (SILK encoded)
file_itemFileItem?File attachment
video_itemVideoItem?Video
ref_msgRefMessage?Referenced message

CDN Media Reference (CDNMedia)

All media types (image/voice/file/video) are transferred via CDN using AES-128-ECB encryption:

FieldTypeDescription
encrypt_query_paramstring?Encrypted parameters for CDN download/upload
aes_keystring?Base64-encoded AES-128 key

CDN Upload Flow

  1. Calculate the file's plaintext size, MD5, and ciphertext size after AES-128-ECB encryption
  2. If a thumbnail is needed (image/video), calculate the thumbnail's plaintext and ciphertext parameters as well
  3. Call getUploadUrl to get upload_param (and thumb_upload_param)
  4. Encrypt the file content with AES-128-ECB and PUT upload to the CDN URL
  5. Encrypt and upload the thumbnail in the same way
  6. Use the returned encrypt_query_param to construct a CDNMedia reference, include it in the MessageItem, and send

For complete type definitions, see src/api/types.ts. For API call implementations, see src/api/api.ts.

Uninstall

openclaw plugins uninstall @tencent-weixin/openclaw-weixin

Troubleshooting

"requires OpenClaw >=2026.3.22" error

Your OpenClaw version is too old for this plugin version. Check with:

openclaw --version

Install the legacy plugin line instead:

openclaw plugins install @tencent-weixin/openclaw-weixin@legacy

Channel shows "OK" but doesn't connect

Ensure plugins.entries.openclaw-weixin.enabled is true in ~/.openclaw/openclaw.json:

openclaw config set plugins.entries.openclaw-weixin.enabled true
openclaw gateway restart

DeepSeek Harness integration (src/dsh/)

This branch keeps the OpenClaw plugin entry (index.ts) intact and adds a DSH adapter under src/dsh/: WeChat messages are handled by DeepSeek Harness Agents/Sessions, with a dedicated WeChat control panel in DSH Settings (account QR login, monitor start/stop, agent routing, allowlist approval, message log, configuration).

  • Architecture & modules: docs/dsh.md, src/dsh/README.md
  • Build & typecheck: npm run build:dsh / npm run typecheck:dsh
  • Host plugin entry: ./dsh export (dist-dsh/src/dsh/plugin.js)
  • Dependencies (@deepseek-ai/dsh-session, cordis, react, …) are optional peers; the OpenClaw side is unaffected.

Note: src/dsh/client.tsx is a reference port of the verified dynamic-plugin prototype; for real-package mounting follow the "Client wiring" section in docs/dsh.md (connection.api.weixin.* via TypertRemoteService).