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):
jsonc
{
"channels": {
"wecom-app": {
"voiceTranscode": {
"enabled": true,
"prefer": "amr"
}
}
}
}
手动转码示例(ffmpeg)
bash
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。
可复制模板:
json
{
"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