Agent Skills
返回列表
Hermes 钉钉媒体收发助手

Hermes 钉钉媒体收发助手

开发编程 更新于 2026.08.29

将以下提示词粘贴到你的 AI 对话框中:

请根据 https://skillhub.cn/install/skillhub.md,安装 @user_9ab57f1a/hermes-dingtalk-media。

技能介绍

要解决的问题

Hermes 对接钉钉机器人时,助手按惯例返回 MEDIA:/absolute/path/to/file,期望对方收到一张独立图片或一个文件附件。但实际结果是消息发出去了,钉钉侧却没有出现对应的媒体卡片。排查起来很容易误判:回调日志显示网关已经触发发送逻辑,上传接口也返回了 media_id,可群里的机器人就是不显示图片。

常见诱因有两个。一是把一对一私聊回复打到了 privateChatMessages/send,这条路径对 Hermes 的媒体回复并不友好,即使上传成功也可能抛 resource.not.found。二是没有把入站回调上下文保留下来,发送时只能退回到配置文件里的 app/client id,一旦 robotCode 或接收人不对,同样报 resource.not.found 或「robot 不存在」。

技能如何工作

这个技能不重写 Hermes 核心,而是补齐两处:路由规则和辅助脚本。

路由规则

  • 群聊媒体走 POST https://api.dingtalk.com/v1.0/robot/groupMessages/send,接收方填 openConversationId。
  • 一对一媒体走 POST https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend,接收方填 userIds: [sender_staff_id]。
  • robot_code 优先取回调消息里的 message.robot_code,只在没有回调上下文时才用配置兜底。
  • 用 chat_id 把回调上下文串起来,因为它同时提供了 conversation_type、robot_code 和 sender_staff_id。
  • 本地文件先上传到 POST https://oapi.dingtalk.com/media/upload,图片扩展名用 type=image,其他用 type=file,multipart 字段名为 media,拿到 media_id 后再发。

辅助脚本

  • scripts/fix_dingtalk_media_support.py:检查 Hermes 源码树里是否已实现钉钉媒体逻辑、依赖的 Python 模块是否齐全、语法是否正确,并可选择重启某个 profile 的网关。仓库根路径通过 --repo-root 传入,也可以用环境变量 HERMES_REPO 指定,脚本本身不含任何凭据。
  • scripts/send_dingtalk_file.py:用某个 profile 的凭据,通过机器人媒体接口直发一个本地图片或文件,用来验证原生投递是否正常,同样不改动 Hermes 源码。一对一发送时需要传入钉钉 staff/user id。

在 Hermes 侧要落地的实现点

  • gateway/platforms/dingtalk.py:实现 send_image_file、send_document、send_video;把入站 downloadCode 解析成本地缓存文件;如果关闭或重连会卡住,改用可取消的 Stream 循环替代 dingtalk_stream.DingTalkStreamClient.start(),并在打开连接前调用 pre_start()。
  • tools/send_message_tool.py:支持解析钉钉 MEDIA: 前缀;没有回调上下文的直接发送场景下,一对一媒体必须显式给出钉钉 user id,否则默认走群发。
  • agent/prompt_builder.py:加入钉钉平台提示,说明原生媒体可以用 MEDIA:/absolute/path/to/file 发送。

适用边界与注意点

这个技能的前提是回调已经能正常到达 Hermes。如果日志里连「DingTalk callback received」和 platform=dingtalk 都没有,说明问题出在 Stream Mode、网络连通性或网关进程上,应该先修连接,而不是继续调媒体逻辑。

判读失败信号时要分清层次:上传之后才报 resource.not.found,说明上传是成功的,问题在发送端点或 robotCode/接收人;一对一私聊里报 HTTP 400 resource.not.found,就该从 privateChatMessages/send 切到 oToMessages/batchSend;robot 不存在 基本都是 robotCode 取错,回到回调里拿。

另外,群消息接口的鉴权字段叫 access_token,机器人新接口用的是 robotCode,两套写法不要混用。日志里记录媒体路由时记得脱敏,例如只输出 Sending DingTalk media via oto robot API; robot_code_source=callback recipient_source=sender_staff_id。

使用场景

  • Hermes 机器人回复里写了 `MEDIA:/absolute/path`,但用户没收到图片;需要用 `send_dingtalk_file.py` 从当前 profile 单独直发一次,确认问题在路由还是上传。
  • 一对一私聊的媒体回复被打到 `privateChatMessages/send`,上传成功却报 `resource.not.found`;需要改走 `oToMessages/batchSend`,并从回调里取 `sender_staff_id`。
  • 修改了 `gateway/platforms/dingtalk.py`、`send_message_tool.py`、`prompt_builder.py` 后,需要运行 `fix_dingtalk_media_support.py` 验证实现是否完整、语法是否通过。
  • 群里的机器人发文件提示 `robot 不存在`;需要确认发送时是否用了回调里的 `message.robot_code`,而不是配置里可能过期的 `robotCode`。

适合人员

  • 正在搭建 Hermes 钉钉机器人并要让 `MEDIA:` 图片/文件真正独立送达的后端工程师。
  • 维护多个 Hermes profile 网关、需要不改核心代码就能验证各 profile 媒体直发的开发者。
  • 正在修改 Hermes 平台层源码,需要快速跑通实现检查和语法校验的开发者。
  • 排查 Hermes 到钉钉媒体链路问题,需要按上传与发送两段日志区分失败点的工程师。