AstrBot 插件:拦截微信消息,调用 LLM 生成 AI 建议回复,只转发给号主本人审核,绝不代发。号主确认后再由 bot 发送(或自定义修改后发送)。
适用于"不想让机器人自动回复,但也不想漏掉重要消息"的场景——所有消息先经过你本人的审核,你决定怎么回。
| 特性 | 说明 |
|---|---|
| 🛡️ 消息拦截审核 | 私聊消息、群聊 @bot 消息进入待审队列,生成 AI 建议回复 |
| 🤫 绝不代发 | 审核通知只发给号主本人,bot 不会自动回复任何人 |
| ⏰ 每小时汇总推送 | 审核通知不逐条实时弹送——每小时整点把该小时内所有待审消息拼成一条 📬 汇总推送 |
| 🔕 无消息不打扰 | 1 小时内没有新通知 → 不推送;推送过的消息打 notified 标记,永不再推 |
| 🌙 夜间免打扰 | 23:00–07:00 消息进队列但不推送(可配置),早上统一查看 |
| 🔁 失败自动补推 | 汇总推送失败标记 push_failed,号主下次发消息时自动以汇总形态重推 |
| 🎓 学习打卡 | 记录每日学习时长(考研/备考场景) |
| 📋 群聊 AI 总结 | 总结 关键词 自动拉取群消息并生成话题/待办总结 |
| 🔌 全部可配置 | 平台 ID、管理员 ID、LLM 地址/key、人设口吻均通过 _conf_schema.json 配置 |
联系人/群聊 → 微信 → 消息平台(inbound) → AstrBot → 本插件拦截
│
├─ 调用 LLM 生成建议回复
├─ 存入待审队列 review_queue.json
└─ 每小时整点汇总推送 → 号主(审核平台会话)
│
▼
号主回复指令:「发」「改:xxx」「跳过」…
│
▼
bot 按号主决定发送回复(或忽略)
- inbound 平台:微信消息入口(如 aiocqhttp 桥接的
wechat_bridge) - 审核平台:号主与 bot 的会话所在平台(如微信 iLink 官方接口的
weixin_personal_horh) - 两个平台可以是同一个,也可以是不同的(本项目实际部署就是微信消息走 bridge、审核走 iLink 官方 bot 会话)
- 将本目录放入 AstrBot 的插件目录(Linux 默认
/root/data/plugins/astrbot_plugin_review_mode/) - 重启 AstrBot:
systemctl restart astrbot.service - 验证加载:
GET /api/plugin/get应出现本插件;GET /api/plugin/source/get-failed-plugins应为空 - 在仪表盘插件配置页填写配置(见下表)
| 配置项 | 必填 | 说明 |
|---|---|---|
inbound_platform |
✅ | 消息入口平台实例 ID(如 wechat_bridge) |
review_platform |
✅ | 审核通道平台实例 ID(如 weixin_personal_horh) |
admin_ids |
✅ | 号主平台用户 ID,多个用逗号分隔(审核通知发往第一个) |
review_chat_id |
可选 | 审核消息发送目标会话 ID,留空自动用 admin_ids[0] |
llm_api_base |
✅ | OpenAI 兼容 API 地址 |
llm_api_key |
✅ | LLM API Key |
llm_model |
✅ | 模型名 |
owner_name |
可选 | 号主称呼,AI 以号主口吻生成建议 |
bot_name |
可选 | bot 昵称,用于指令文案 |
quiet_hours |
可选 | 夜间免打扰时段,如 23-7 |
review_enabled |
可选 | 总开关,关闭后完全不拦截、正常自动回复 |
💡 平台实例 ID 不等于平台类型名!用
event.get_platform_id()获取实际实例 ID(详见下方踩坑记录 #3)。
📬 审核相关:
「发」— 发送最新一条的建议回复
「发 编号」— 发送指定编号(如 发 a1b2c3d4)
「改:内容」— 用自定义内容回复(如 改:好的,晚上见)
「跳过」— 忽略最新一条
「跳过 编号」— 忽略指定编号
「队列」— 查看待审核列表
「清空」— 清空全部待审核
🎓 学习 & 效率:
「打卡」— 记录今日打卡
「打卡 3小时」— 记录学习时长
「总结 关键词」— AI 总结群聊(如 总结 麦当劳)
「状态」— 查看系统状态
💬 其他:
「指令」— 查看完整指令大全
直接发消息 = 和 bot 正常聊天
- 联系人给 bot 发消息(或群聊 @bot)→ 插件拦截,
event.stop_event()阻止 LLM 自动回复 - 异步调用 LLM 生成建议回复,存入待审队列
- 每小时整点向号主推送一条汇总审核通知(该小时内所有待审消息拼在一起):
📬 审核汇总(2 条待审) ──────── 【私聊·张三】张三 📩 在吗?周末出来吃饭吗 💡 建议:在的!周末可以呀,你想吃啥 ⏰ 08-28 18:00 ──────── 【私聊·李四】李四 📩 明天开会别忘了 💡 建议:收到,明天几点? ⏰ 08-28 18:30 ──────── (已转给你,未代发。回复「跳过」忽略,回复「发 N」代发)- 1 小时内没有新消息 → 不推送
- 推送成功后各消息打
notified标记,之后整点不再重复推送
- 号主回复「发」→ bot 将建议回复发给原联系人;「改:xxx」→ 发送修改版;「跳过」→ 忽略
| 版本 | 说明 |
|---|---|
| v1.1.0 | 审核通知改为每小时汇总推送:整点聚合待审消息为一条通知;无新消息不推;推送过的标记 notified 永不再推;补推同样走汇总形态 |
| v1.0.0 | 首个公开版本:消息拦截审核、AI 建议、待审队列、夜间免打扰、失败自动补推、学习打卡、群聊总结 |
以下 Bug 都是本项目实战中踩过、已修复的真实坑:
错误写法 {"schemaVersion": 1, "items": []} 会在加载时报 'int' object is not subscriptable(AstrBot 对每个顶层 value 执行 v["type"])。正确格式:
{
"review_enabled": {
"description": "审核模式开关",
"type": "bool",
"default": true
}
}def __init__(self, context, config=None)——AstrBot 只在存在 _conf_schema.json 时才传入 config,缺省参数会报 missing 1 required positional argument。
event.get_platform_name() 返回平台类型名(如 weixin_oc),不是平台实例 ID(如 weixin_personal_horh)。用类型名匹配实例 ID 永远不相等 → 监听器静默失效,消息从不被拦截。必须用 event.get_platform_id() 做实例匹配。
send_by_session() 成功时返回 None(不是 True),失败时抛异常。判断成功必须用 try/except(不抛异常 = 成功),绝不能检查返回值——把 None 当 False 会导致推送永远误报失败。
队列项推送成功即写 notified 时间戳,小时汇总只选 pending 且未 notified 的项。若旧队列数据没有该字段,重启后首个整点会补推一次(属正常迁移行为)。
astrbot_plugin_review_mode/
├── main.py # 插件主体
├── metadata.yaml # 插件元信息(name/desc/version/repo)
├── _conf_schema.json # 配置 schema(扁平格式!)
└── examples/
└── finance-daily-prompt.md # 定时财经早报 cron 示例(配合 Hermes cron)
运行时数据(review_queue.json、checkins.json、review.log)自动保存在 AstrBot 的 plugin_data/ 目录。
- AstrBot v4.25+(
astrbot.api/astrbot.coreAPI) aiohttp(LLM 调用)- 一个 OpenAI 兼容的 LLM API(任意供应商,如 DeepSeek / 本地 Hermes API Server / OpenAI)
MIT © 2026 Molise