Skip to content

feat(dingtalk): proactive messaging via Robot OpenAPI + send_message_tool media support - #14336

Open
meng93 wants to merge 1 commit into
NousResearch:mainfrom
PeterGuy326:feat/dingtalk-proactive-messaging-v2
Open

meng93 wants to merge 1 commit into
NousResearch:mainfrom
PeterGuy326:feat/dingtalk-proactive-messaging-v2

Conversation

@meng93

@meng93 meng93 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Enable proactive (non-session-webhook) message delivery for DingTalk via the Robot OpenAPI, and extend send_message_tool to support native media attachments on DingTalk and Feishu.

Stacked on #14335 — merge that first.

Motivation

The DingTalk adapter previously could only reply within a session webhook window. Cron jobs, cross-platform send_message, and delayed deliveries all failed with No valid session_webhook. This PR adds the same proactive-send capability that the Feishu adapter already has — using AppKey/AppSecret to call the Robot OpenAPI directly.

Additionally, send_message_tool was text-only for DingTalk/Feishu. Users asking the agent to "send this image to DingTalk" got an error.

Changes

File What
gateway/platforms/dingtalk.py Token management: _dingtalk_fetch_access_token, _dingtalk_fetch_oapi_token with process-wide cache + Lock
gateway/platforms/dingtalk.py _dingtalk_upload_media() — upload to /media/upload (legacy OAPI token) with mime auto-detection
gateway/platforms/dingtalk.py _dingtalk_classify_chat_id() — route cidXXX== → group, user:<staffId> → 1:1
gateway/platforms/dingtalk.py _dingtalk_build_msg_param() — pick sampleMarkdown/sampleText/sampleImageMsg etc.
gateway/platforms/dingtalk.py dingtalk_send_proactive() — orchestrator: text + per-file media delivery
gateway/platforms/dingtalk.py send() falls back to proactive when no session webhook cached
gateway/run.py /sethome DM fix: persist user:<staffId> instead of DM conversation_id
tools/send_message_tool.py MEDIA:<path> tag + bare-path extraction; native DingTalk/Feishu routing; updated capability description
tests/gateway/test_dingtalk.py Updated assertion for proactive-send error path

Test Plan

  • All existing tests/gateway/test_dingtalk.py tests pass.
  • Manual testing: proactive send to group (cidXXX==), proactive send to DM (user:<staffId>), media upload (image, PDF, audio).
  • Verified send_message_tool MEDIA tag extraction and native routing.
  • Cron job delivery verified end-to-end.

Risk Assessment

Medium. The proactive-send path is new and touches production DingTalk API endpoints. Token caching + Locks mitigate thundering-herd issues. The send() fallback is conservative — it only activates when no session webhook exists (i.e., would have failed before anyway). send_message_tool changes are backward-compatible (media tags are opt-in).

@alt-glitch alt-glitch added type/feature New feature or request P2 Medium — degraded but workaround exists platform/dingtalk DingTalk adapter comp/gateway Gateway runner, session dispatch, delivery comp/tools Tool registry, model_tools, toolsets labels Apr 23, 2026
@alt-glitch

Copy link
Copy Markdown
Contributor

Significant overlap with #12769 (proactive messaging + media pipeline) and #9451 (rich media in&outbound). Stacked PR series: #14333#14334#14335#14336. Review together.

…tool media

- Add DingTalk access-token management (_dingtalk_fetch_access_token,
  _dingtalk_fetch_oapi_token) with process-wide cache, 5 min safety
  margin, and asyncio.Lock for concurrent safety.
- Add _dingtalk_upload_media() — upload local files to /media/upload
  (legacy OAPI token) with mime auto-detection and 20 MB guard.
- Add _dingtalk_classify_chat_id() — route on chat_id shape:
  'cidXXX==' → group /groupMessages/send, plain staffId or
  'user:<staffId>' → 1:1 /oToMessages/batchSend.
- Add dingtalk_send_proactive() orchestrator — text + media delivery.
- In send(), fall back to dingtalk_send_proactive() when no session
  webhook is cached (proactive/cron/cross-platform delivery).
- Fix /sethome DM chat_id: persist 'user:<staffId>' instead of DM
  conversation_id so proactive DM delivery works (gateway/run.py).
- Enhance send_message_tool.py: MEDIA:<path> tag extraction, native
  DingTalk/Feishu routing with media_files support.
- Update test assertions for proactive-send error path.
@meng93
meng93 force-pushed the feat/dingtalk-proactive-messaging-v2 branch from f454ddd to 8221966 Compare April 23, 2026 05:14
@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
@teknium1

Copy link
Copy Markdown
Collaborator

Thanks for implementing the proactive-send and native-media direction; the underlying gap is still present on current main. plugins/platforms/dingtalk/adapter.py:844-856 still fails when no session webhook is available, and :964-999 still rejects local image/document uploads.

Problems

  • This branch targets gateway/platforms/dingtalk.py, but current main removed that file in 476d8d9cc and moved DingTalk to plugins/platforms/dingtalk/adapter.py. GitHub reports the PR as conflicting.
  • Current standalone delivery is plugin-registry based: tools/send_message_tool.py:1071-1074 dispatches through _registry_standalone_send, and the DingTalk plugin registers standalone_sender_fn at plugins/platforms/dingtalk/adapter.py:1688-1704. The proactive/media implementation needs to be ported into that plugin contract rather than reintroducing old core imports and routing.
  • The PR test diff does not cover Robot OpenAPI fallback/routing or media upload outcomes; current tests only preserve the unsupported behavior at tests/gateway/test_dingtalk.py:256-263 and :326-343.

Suggested changes

  • Port the feature to the DingTalk plugin and add mocked group/DM, token-failure, media-only, partial-media-failure, and legacy-static-webhook tests.

Automated hermes-sweeper review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/tools Tool registry, model_tools, toolsets P2 Medium — degraded but workaround exists platform/dingtalk DingTalk adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants