name: wecom-app-ops description: 企业微信自建应用(wecom-app)运维与使用技能包。用于:定位并回发图片/语音/文件;使用 saved: 稳定路径做 OCR/MCP/二次处理;规范 target(wecom-app:user:xxx / user:xxx / 裸ID / @accountId);排查发送失败;配置入站媒体保留策略与语音转码策略。
wecom-app 运维/使用规范(本地技能)
本技能针对你这套 OpenClaw + 企业微信自建应用(wecom-app)环境,提供可复用的“怎么做”步骤。
0) 快速判断:你要做哪一类事?
- A. 回发媒体(图片/录音/文件):需要拿到本地路径 + 正确的
target(通常user:<name>) - B. 从消息里拿 saved: 路径做 OCR/二次处理:使用
saved:/.../inbound/YYYY-MM-DD/...的稳定路径 - C. 修复“找不到图片/自动删除”:检查 wecom-app 的
inboundMedia.keepDays/dir/maxBytes - D. 语音发不出去:优先
.amr/.speex,或开启voiceTranscode.enabled
1) target 与 replyTo(最容易踩坑)
1.1 target 是什么
使用 message.send 向 wecom-app 主动发消息时,必须提供可解析 target(否则会报 Action send requires a target.)。
常见可用形式(以本环境为准):
target: "wecom-app:user:<userId>"target: "user:<userId>"target: "<userId>"(裸 ID,插件会按用户 ID 处理)target: "user:<userId>@<accountId>"(多账号场景)
注意:当前 wecom-app 出站实现以用户私聊为主,运维侧不要依赖
chatid:<id>作为通用 target 格式。
1.2 replyTo 怎么用
- 如果你要“回复当前对话”,优先使用消息的
message_id作为replyTo。 replyTo不是 target;target 仍然要填。
1.3 Unknown target 怎么办(排查步骤)
- 显示名(比如
CaiHongYu)不一定能被解析。 - 优先尝试:
target: "user:CaiHongYu"
若仍报 Unknown target:
- 先确认是 私聊 还是 群聊:
- 私聊:使用
user:<userId>(推荐) - 群聊:本技能默认不走该路径(请先确认插件是否已实现对应目标解析)
- 让对方(或你自己)在企业微信里再发一条消息(任意内容),以便系统记录真实标识。
- 从以下任意来源抓取真实的
userId/chatId:- OpenClaw / wecom-app 插件日志(
~/.openclaw/logs/) - 或把“收到消息时的原始字段/报错日志”贴出来,我来反推。
- OpenClaw / wecom-app 插件日志(
- 拿到真实值后再发:
target: "user:<userId>"(或wecom-app:user:<userId>)
2) 媒体文件在哪里?(图片/录音/文件)
2.1 入站媒体(推荐稳定路径)
wecom-app 现在会把入站媒体归档到:
inboundMedia.dir/YYYY-MM-DD/- 默认(跨平台):
~/.openclaw/media/wecom-app/inbound/YYYY-MM-DD/
消息正文会出现:
[image] saved:/.../inbound/YYYY-MM-DD/img_...jpg[voice] saved:/.../inbound/YYYY-MM-DD/voice_...amr
这条 saved 路径用于:OCR、回发、复用。
2.2 临时目录(不建议依赖)
/tmp/wecom-app-media/只作为下载中转,不保证长期存在。- Windows 也同理:临时目录仅中转,不作为业务引用路径。
3) 回发图片/文件/录音(标准做法)
3.1 回发图片(注意:必须是真图片格式)
使用 message 工具:
channel: "wecom-app"target: "user:<name>"path: "<本地文件路径>"replyTo: "<message_id>"(可选但推荐)
格式要求(踩坑高发):
- 优先使用真正的图片格式:
.png/.jpg/.jpeg .svg在企业微信里通常不会按“图片消息”展示。- 新版本插件会把
.svg按文件发送,避免误走图片通道。 - 若你需要“图片预览”:请先把 svg 转 png 再发(可选工具:
rsvg-convert/ ImageMagickconvert/ 或用脚本生成 PNG 兜底)。
- 新版本插件会把
3.2 回发录音(语音格式坑)
- 推荐格式:
.amr(你收到的入站语音也通常是 amr) .wav/.mp3在企业微信自建应用里经常无法作为“语音消息(voice)”发送。
自动兜底(新功能)
- 你可以开启
voiceTranscode.enabled=true:- 系统存在
ffmpeg时:遇到 wav/mp3 会 自动转码为 amr 再按 voice 发送 - 没有
ffmpeg时:会 自动降级为 file 发送(保证可达) - 若
mediaUrl是远程 URL,当前实现会直接走 file 降级(不做“下载后再转码”)
- 系统存在
配置示例(openclaw.json):
{
"channels": {
"wecom-app": {
"voiceTranscode": {
"enabled": true,
"prefer": "amr"
}
}
}
}
手动转码示例(ffmpeg)
ffmpeg -i in.wav -ar 8000 -ac 1 -c:a amr_nb out.amr
- 其他流程同图片。
3.3 回发 README/文本为“文件形式”
- 先写到临时文件(如
/tmp/xxx.md) - 再用
message.send的path作为附件发送。
4) 发送失败的排障清单
4.1 Action send requires a target
- 说明 target 缺失:补
target:"user:..."。
4.2 Unknown target / 发送 ok=false
- 优先确认 target 是否能解析(
user:<name>vs 内部 id)。 - 尝试
wecom-app:user:<id>/user:<id>/<id>三种格式。 - 多账号时追加
@accountId,例如:user:alice@default。 - 检查附件路径是否存在(文件是否被清理)。
4.3 Account not configured for active sending
- 缺少
corpId/corpSecret/agentId任一项时会出现。 - 这类错误先修配置,不是 target 问题。
4.4 图片发不出去但文件存在
- 核对文件大小是否超出渠道限制。
- 若是 inbound 归档文件:确保 OpenClaw 进程对该文件可读。
5) 入站媒体保留策略(产品级默认)
inboundMedia.keepDays:默认 7 天(延迟清理,不会“回复后立刻删”)inboundMedia.dir:可自定义归档目录inboundMedia.maxBytes:单个媒体大小限制(默认 10MB)
要修改:编辑 openclaw.json 的 channels.wecom-app.inboundMedia。
可复制模板:
{
"channels": {
"wecom-app": {
"inboundMedia": {
"enabled": true,
"keepDays": 7,
"maxBytes": 10485760
}
}
}
}
6) 文本与流式发送行为(实现对齐)
- wecom-app webhook 会先返回 stream 占位,再在后台推送最终内容。
- 推送前会做 Markdown 降级(
stripMarkdown)。 - 企业微信单条文本限制 2048 bytes,超出会自动分段发送。
7) MCP OCR(识别图片文字)
当用户说“记得调用 mcp 识别图片”,用 mcporter 调用:
zai-mcp-server.extract_text_from_screenshot(image_source: <saved-path>, prompt: <说明>)
前提:必须拿到真实存在的文件路径(建议用 inbound saved 路径)。
参考
- 详细示例与常用模板见:
references/wecom-app-examples.md