DingTalk (钉钉)
DingTalk custom group robot with HMAC-SHA256 signed URL. Stream Mode (WebSocket) is the planned next enhancement.
🟡 Outbound-ready via custom robot, inbound via outgoing webhook. The lowest-friction setup is DingTalk's "custom group robot" with a signed URL. Enterprise self-built apps and Stream Mode (DingTalk's recommended WebSocket transport for new builds) are a future enhancement.
What you get
- Outbound text via
POST https://oapi.dingtalk.com/robot/sendwith HMAC-SHA256 URL signing (timestamp + secret). - Inbound outgoing webhook at
/webhooks/dingtalkfor the custom-robot mention flow. DingTalk POSTs the user's message back to us with a freshtimestamp+signpair Minara verifies the same way it signed outbound. - Text only. Markdown, actionCard, and feedCard message types are deferred.
- 5000-char limit per text message.
Setup
1. Create a custom group robot
- Open the target DingTalk group on desktop or mobile
- Group settings → "Group Assistant" → "Add Robot" → "Custom"
- Pick a name and avatar; for "Security settings" select "Signature" (the signed-URL option, not "Custom keyword" or "IP whitelist")
- Save. Copy two strings:
- Webhook URL (the
https://oapi.dingtalk.com/robot/send?access_token=...URL) - Signing secret (starts with
SEC)
- Webhook URL (the
2. Configure Minara
minara auth messaging add
# pick `dingtalk`; paste the webhook URL + SECxxxx secret.Or set env vars directly:
DINGTALK_WEBHOOK_URL=https://oapi.dingtalk.com/robot/send?access_token=<token>
DINGTALK_WEBHOOK_SECRET=SECxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3. Test
minara auth messaging test dingtalkThe target group receives "✅ Minara gateway test ping" within a second or two.
How outbound signing works
DingTalk requires every POST to carry an HMAC of the millisecond timestamp and the secret, URL-encoded into the request URL:
sign = base64( HmacSHA256( "<timestamp>\n<secret>", secret ) )
url = <webhook URL>?timestamp=<ts>&sign=<urlencoded sig>DingTalk rejects timestamps more than 1 hour from its server clock, so out-of-sync hosts will see "签名错误" / "sign error" responses.
Inbound webhook (outgoing-message mode)
In the custom-robot outgoing-message flow, DingTalk POSTs to:
https://<your-host>/webhooks/dingtalkThe body carries the user's message plus a fresh timestamp and
sign pair in the headers. Minara recomputes the signature using the
same DINGTALK_WEBHOOK_SECRET and rejects mismatches with 401.
Inbound payload shape:
{
"msgtype": "text",
"text": { "content": "@bot hello world" },
"senderId": "user-staff-id",
"senderNick": "Alice",
"conversationId": "cidxxxx",
"msgId": "<unique>",
"createAt": 1700000000000
}Only msgtype === "text" events are forwarded. Other types
(image, audio, markdown, actionCard) are dropped.
Limits & caveats
- Clock skew matters. DingTalk enforces a 1-hour window on
outbound
timestamp. If your host's clock drifts, signing fails. - Outgoing webhook fires on @mention only. The group robot does not see every message, only mentions of itself. This is a DingTalk design choice, not a Minara filter.
- Stream Mode is the future-recommended path. DingTalk officially recommends Stream Mode (WebSocket) for new applications. Minara ships the legacy custom-robot path first; Stream Mode lands in a follow-up.
Troubleshooting
"签名错误" (signature error) on outbound
- Server clock drift. Run
chronyc trackingortimedatectl statusand confirm offset is well under 1 second. - Typo in
DINGTALK_WEBHOOK_SECRET, the SECxxxx string is the full secret, including theSECprefix.
"Inbound webhook returns 401"
- The receiving signature does not match. Most common cause: the
group's "Security settings" was set to "Signature" but the secret
was rotated and the new value is not in
~/.minara/credentials.json.
"Bot does not respond to mention in group"
- Confirm "Outgoing webhook" is enabled on the robot detail page (separate toggle from the inbound URL). Without it, the robot is push-only.
Reference
- Env vars:
DINGTALK_WEBHOOK_URL,DINGTALK_WEBHOOK_SECRET - Outbound:
apps/agent/src/messaging/dingtalk.ts - Inbound spec:
apps/agent/src/messaging/inbound/specs/dingtalk.ts - DingTalk Open Platform: open.dingtalk.com
- Stream Mode (future): protocol description