← Back to Skills Marketplace
kenriou

Dingtalk File Send

by kenriou · GitHub ↗ · v1.2.2 · MIT-0
cross-platform ✓ Security Clean
188
Downloads
1
Stars
0
Active Installs
5
Versions
Install in OpenClaw
/install dingtalk-file-send
Description
Upload and send files to DingTalk users. Auto-detects account from current session. Use when: user asks to send/forward a file/document/PDF/image via DingTalk.
README (SKILL.md)

DingTalk File Send Skill

Upload files to DingTalk media server and send them to specified users.

Automatically detects DingTalk account from current session binding.

When to Use

USE this skill when:

  • "Send this PDF to [user]"
  • "Forward this document via DingTalk"
  • "Share this file with my boss"
  • "Upload and send [filename]"

Configuration (Automatic)

This skill automatically detects the DingTalk account from your current session:

How it works:

  1. Reads current agent ID from OpenClaw runtime context
  2. Looks up the binding in ~/.openclaw/openclaw.json
  3. Matches agentIdaccountId → DingTalk credentials

Binding example:

{
  "bindings": [
    {
      "agentId": "dingtalk-office",
      "match": {
        "channel": "dingtalk",
        "accountId": "office"
      }
    }
  ],
  "channels": {
    "dingtalk": {
      "accounts": {
        "office": {
          "clientId": "your_client_id",
          "clientSecret": "xxx",
          "robotCode": "your_robot_code"
        }
      }
    }
  }
}

Note: In DingTalk's API, clientId is used as appKey for authentication.

Workflow

1. Detect current agentId from session context
2. Look up binding: agentId → accountId
3. Read credentials from OpenClaw config by accountId
4. Get access token
5. Upload file to DingTalk media server
6. Send file message to recipient

Commands

Step 1: Detect Account from Current Session

OPENCLAW_CONFIG=~/.openclaw/openclaw.json

# Get current agent ID from environment (set by OpenClaw runtime)
AGENT_ID="${OPENCLAW_AGENT_ID:-dingtalk-office}"

# Look up accountId from bindings
ACCOUNT_ID=$(jq -r ".bindings[] | select(.agentId == \"$AGENT_ID\") | .match.accountId" $OPENCLAW_CONFIG)

# Fallback: if no binding found, use agent ID suffix
if [ -z "$ACCOUNT_ID" ] || [ "$ACCOUNT_ID" = "null" ]; then
  # Extract account from agent ID (e.g., "dingtalk-office" → "office")
  ACCOUNT_ID=$(echo "$AGENT_ID" | sed 's/dingtalk-//')
fi

# Read credentials (clientId is used as appKey)
APP_KEY=$(jq -r ".channels.dingtalk.accounts[\"$ACCOUNT_ID\"].clientId" $OPENCLAW_CONFIG)
APP_SECRET=$(jq -r ".channels.dingtalk.accounts[\"$ACCOUNT_ID\"].clientSecret" $OPENCLAW_CONFIG)
ROBOT_CODE=$(jq -r ".channels.dingtalk.accounts[\"$ACCOUNT_ID\"].robotCode" $OPENCLAW_CONFIG)

# Validate
if [ "$APP_KEY" = "null" ] || [ "$APP_SECRET" = "null" ] || [ "$ROBOT_CODE" = "null" ]; then
  echo "❌ Account '$ACCOUNT_ID' not found in OpenClaw config."
  echo "Current agent: $AGENT_ID"
  echo "Available accounts: $(jq -r '.channels.dingtalk.accounts | keys | join(", ")' $OPENCLAW_CONFIG)"
  exit 1
fi

Step 2: Get Access Token

ACCESS_TOKEN=$(curl -s -X POST "https://api.dingtalk.com/v1.0/oauth2/accessToken" \
  -H "Content-Type: application/json" \
  -d "{\"appKey\":\"$APP_KEY\",\"appSecret\":\"$APP_SECRET\"}" | jq -r '.accessToken')

if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
  echo "❌ Failed to get access token."
  exit 1
fi

Step 3: Upload File

FILE_PATH="$1"
FILE_NAME=$(basename "$FILE_PATH")

UPLOAD_RESULT=$(curl -s -X POST "https://oapi.dingtalk.com/media/upload?access_token=$ACCESS_TOKEN&type=file&robotCode=$ROBOT_CODE" \
  -F "media=@$FILE_PATH;filename=$FILE_NAME" \
  -H "Expect:")

MEDIA_ID=$(echo "$UPLOAD_RESULT" | jq -r '.media_id')

if [ -z "$MEDIA_ID" ] || [ "$MEDIA_ID" = "null" ]; then
  echo "❌ Upload failed: $UPLOAD_RESULT"
  exit 1
fi

Step 4: Send File Message

USER_ID="$2"
FILE_EXT="${FILE_NAME##*.}"

PAYLOAD=$(jq -n \
  --arg robotCode "$ROBOT_CODE" \
  --arg msgKey "sampleFile" \
  --arg mediaId "$MEDIA_ID" \
  --arg fileName "$FILE_NAME" \
  --arg fileType "$FILE_EXT" \
  --arg userId "$USER_ID" \
  '{
    robotCode: $robotCode,
    msgKey: $msgKey,
    msgParam: ({
      mediaId: $mediaId,
      fileName: $fileName,
      fileType: $fileType
    } | tojson),
    userIds: [$userId]
  }')

SEND_RESULT=$(curl -s -X POST "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend" \
  -H "Content-Type: application/json" \
  -H "x-acs-dingtalk-access-token: $ACCESS_TOKEN" \
  -d "$PAYLOAD")

PROCESS_KEY=$(echo "$SEND_RESULT" | jq -r '.processQueryKey // empty')

if [ -n "$PROCESS_KEY" ]; then
  echo "✅ File sent successfully!"
  echo "ProcessQueryKey: $PROCESS_KEY"
else
  echo "❌ Send failed: $SEND_RESULT"
  exit 1
fi

Complete Script

#!/bin/bash
# Usage: send_dingtalk_file.sh \x3Cfile_path> \x3Cuser_id>
# Automatically detects DingTalk account from current session

set -e

OPENCLAW_CONFIG=~/.openclaw/openclaw.json

# Check config file
if [ ! -f "$OPENCLAW_CONFIG" ]; then
  echo "❌ OpenClaw config not found: $OPENCLAW_CONFIG"
  exit 1
fi

# Check file argument
FILE_PATH="$1"
USER_ID="$2"

if [ -z "$FILE_PATH" ] || [ -z "$USER_ID" ]; then
  echo "Usage: $0 \x3Cfile_path> \x3Cuser_id>"
  exit 1
fi

if [ ! -f "$FILE_PATH" ]; then
  echo "❌ File not found: $FILE_PATH"
  exit 1
fi

# Get current agent ID from environment (set by OpenClaw runtime)
AGENT_ID="${OPENCLAW_AGENT_ID:-dingtalk-office}"

# Look up accountId from bindings
ACCOUNT_ID=$(jq -r ".bindings[] | select(.agentId == \"$AGENT_ID\") | .match.accountId" $OPENCLAW_CONFIG)

# Fallback: if no binding found, use agent ID suffix
if [ -z "$ACCOUNT_ID" ] || [ "$ACCOUNT_ID" = "null" ]; then
  ACCOUNT_ID=$(echo "$AGENT_ID" | sed 's/dingtalk-//')
fi

# Read credentials from OpenClaw config
APP_KEY=$(jq -r ".channels.dingtalk.accounts[\"$ACCOUNT_ID\"].clientId" $OPENCLAW_CONFIG)
APP_SECRET=$(jq -r ".channels.dingtalk.accounts[\"$ACCOUNT_ID\"].clientSecret" $OPENCLAW_CONFIG)
ROBOT_CODE=$(jq -r ".channels.dingtalk.accounts[\"$ACCOUNT_ID\"].robotCode" $OPENCLAW_CONFIG)

# Validate credentials
if [ "$APP_KEY" = "null" ] || [ "$APP_SECRET" = "null" ] || [ "$ROBOT_CODE" = "null" ]; then
  echo "❌ Account '$ACCOUNT_ID' not found in OpenClaw config."
  echo "Current agent: $AGENT_ID"
  echo "Available accounts: $(jq -r '.channels.dingtalk.accounts | keys | join(", ")' $OPENCLAW_CONFIG)"
  exit 1
fi

FILE_NAME=$(basename "$FILE_PATH")
FILE_EXT="${FILE_NAME##*.}"

# Get access token
ACCESS_TOKEN=$(curl -s -X POST "https://api.dingtalk.com/v1.0/oauth2/accessToken" \
  -H "Content-Type: application/json" \
  -d "{\"appKey\":\"$APP_KEY\",\"appSecret\":\"$APP_SECRET\"}" | jq -r '.accessToken')

if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
  echo "❌ Failed to get access token."
  exit 1
fi

# Upload file
UPLOAD_RESULT=$(curl -s -X POST "https://oapi.dingtalk.com/media/upload?access_token=$ACCESS_TOKEN&type=file&robotCode=$ROBOT_CODE" \
  -F "media=@$FILE_PATH;filename=$FILE_NAME" \
  -H "Expect:")

MEDIA_ID=$(echo "$UPLOAD_RESULT" | jq -r '.media_id')

if [ -z "$MEDIA_ID" ] || [ "$MEDIA_ID" = "null" ]; then
  echo "❌ Upload failed: $UPLOAD_RESULT"
  exit 1
fi

# Send file
PAYLOAD=$(jq -n \
  --arg robotCode "$ROBOT_CODE" \
  --arg msgKey "sampleFile" \
  --arg mediaId "$MEDIA_ID" \
  --arg fileName "$FILE_NAME" \
  --arg fileType "$FILE_EXT" \
  --arg userId "$USER_ID" \
  '{robotCode:$robotCode,msgKey:$msgKey,msgParam:({mediaId:$mediaId,fileName:$fileName,fileType:$fileType}|tojson),userIds:[$userId]}')

SEND_RESULT=$(curl -s -X POST "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend" \
  -H "Content-Type: application/json" \
  -H "x-acs-dingtalk-access-token: $ACCESS_TOKEN" \
  -d "$PAYLOAD")

PROCESS_KEY=$(echo "$SEND_RESULT" | jq -r '.processQueryKey // empty')

if [ -n "$PROCESS_KEY" ]; then
  echo "✅ File sent successfully!"
  echo "ProcessQueryKey: $PROCESS_KEY"
else
  echo "❌ Send failed: $SEND_RESULT"
  exit 1
fi

Supported File Types

Type Extensions Max Size
PDF .pdf 20 MB
Document .doc, .docx, .xls, .xlsx, .ppt, .pptx 20 MB
Image .jpg, .jpeg, .png, .gif, .bmp 10 MB
Other .txt, .zip, .rar 20 MB

Environment Variables

Variable Description Required
OPENCLAW_AGENT_ID Current agent ID (auto-set by OpenClaw runtime) Auto

Response Handling

Success response:

{
  "flowControlledStaffIdList": [],
  "invalidStaffIdList": [],
  "processQueryKey": "xxx="
}

Check delivery status:

curl -s -X GET "https://api.dingtalk.com/v1.0/robot/oToMessages/status?processQueryKey=$PROCESS_KEY" \
  -H "x-acs-dingtalk-access-token: $ACCESS_TOKEN"

Notes

  • Fully automatic — detects account from current session, no configuration needed
  • Media files expire after 30 days on DingTalk server
  • Max file size: 20 MB for files, 10 MB for images
  • Access token expires after 2 hours
  • Rate limit: ~100 requests/second per app
  • Works with any DingTalk account bound in OpenClaw config

Common Issues

"Account not found in OpenClaw config" → Check bindings: jq '.bindings[] | select(.agentId == "current-agent-id")' ~/.openclaw/openclaw.json → Verify account exists: jq '.channels.dingtalk.accounts | keys' ~/.openclaw/openclaw.json

"Failed to get access token" → Verify clientId/clientSecret in OpenClaw config are correct and not expired.

"Invalid media_id" → File upload failed or expired. Re-upload and get new media_id.

"Invalid userId" → Check the recipient's DingTalk user ID format.

File shows but can't open → Ensure file is valid (not HTML renamed to .pdf, etc.)

Security Notes

  • No hardcoded credentials — reads from OpenClaw config only
  • Session-based account detection — uses current agent's bound account
  • Access token is generated on-demand and not stored
  • Credentials never leave your machine except for DingTalk API calls
Usage Guidance
This skill appears to do what it says: it reads your OpenClaw config (~/.openclaw/openclaw.json) to obtain DingTalk credentials, gets an access token, uploads the file, and sends it. Before installing or running it, verify the skill source (unknown here), inspect the SKILL.md yourself, and confirm the config file only contains accounts you expect. Treat the clientSecret/robotCode as sensitive: only use this skill if you trust it and consider testing in an isolated account or environment first. Also ensure curl/jq on your system are the real binaries (not replaced by malicious wrappers). If you lose confidence in the skill or its origin, rotate the DingTalk credentials referenced in your OpenClaw config.
Capability Assessment
Purpose & Capability
Name and description describe sending files via DingTalk; the SKILL.md only requires curl/jq and access to the OpenClaw config to obtain DingTalk credentials and tokens, which is coherent with that purpose.
Instruction Scope
Instructions explicitly read ~/.openclaw/openclaw.json to extract clientId/clientSecret/robotCode and the optional OPENCLAW_AGENT_ID from environment, then call DingTalk APIs to upload and send files — all actions stay within the declared task but do involve reading local credentials.
Install Mechanism
Instruction-only skill with no install spec and no code files; it requires only common CLI tools (curl and jq) that are expected for the provided shell examples.
Credentials
Access to clientId/clientSecret/robotCode in the OpenClaw config is necessary to obtain an access token and is proportionate to the task; however the registry metadata lists no required env vars while the SKILL.md reads OPENCLAW_AGENT_ID (optional) and the local config, a minor metadata mismatch and a sensitive operation (reads secrets).
Persistence & Privilege
Skill does not request always:true, does not modify other skills, and does not install persistent components; autonomous invocation is allowed (platform default) but not elevated by the skill itself.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install dingtalk-file-send
  3. After installation, invoke the skill by name or use /dingtalk-file-send
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.2.2
Fix: Add config and env access declarations to metadata
v1.2.1
Fix: Replace example credentials with placeholders
v1.2.0
**Now auto-detects DingTalk account from OpenClaw session instead of requiring a separate config file.** - Automatically selects the correct DingTalk credentials by mapping the current agent/session to account profile in `~/.openclaw/openclaw.json`. - Removed manual config file setup; uses OpenClaw’s session and credentials for a more seamless experience. - Example bindings and config layout for multi-account support are documented. - All scripts updated to fetch credentials and robot code dynamically from OpenClaw runtime context. - Error messages guide users if account lookup or credential detection fails.
v1.1.0
**Now reads API credentials from a config file instead of inline.** - Requires a config file at `~/.clawhub/dingtalk-config.json` with `appKey`, `appSecret`, and `robotCode`. - All example scripts updated to load credentials from the config file. - Additional security instructions and file validation added. - Improved documentation on permissions, usage, and file validation steps. - Warns if the config file is missing or misconfigured.
v1.0.0
Initial release of the dingtalk-file-send skill. - Upload and send files (PDFs, documents, images, etc.) directly to DingTalk users via robot API. - Requires DingTalk robot credentials (appKey, appSecret, robotCode) and recipient userId. - Supports easy bash workflow: obtain access token, upload file, and send message. - Includes usage guide, troubleshooting, file type and size limits. - Provides complete example script for automated sending.
Metadata
Slug dingtalk-file-send
Version 1.2.2
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 5
Frequently Asked Questions

What is Dingtalk File Send?

Upload and send files to DingTalk users. Auto-detects account from current session. Use when: user asks to send/forward a file/document/PDF/image via DingTalk. It is an AI Agent Skill for Claude Code / OpenClaw, with 188 downloads so far.

How do I install Dingtalk File Send?

Run "/install dingtalk-file-send" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Dingtalk File Send free?

Yes, Dingtalk File Send is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Dingtalk File Send support?

Dingtalk File Send is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Dingtalk File Send?

It is built and maintained by kenriou (@kenriou); the current version is v1.2.2.

💬 Comments