Hermes Decision Trace

Hermes 微信推送样式迁移与 Cron 投递链路收口

本次已将 Hermes 主要主动推送从飞书 / origin 文本投递统一收口到微信文本推送,采用「标题后分隔线 + 区块分隔线 + 手机端短块」样式,提升微信阅读区分度并避免 cron 自动投递造成重复消息。

🧭
推荐路径

保持 script-only + 主动 send_weixin_text + cron deliver=local 作为后续所有轻量通知的默认模式;复杂长内容继续走 HTML/wiki,微信只承载入口和摘要。

🔎
关键依据

晨报、LLM Wiki 治理提醒、备份日报、Skills 月审计、记忆治理提醒、Skill Frontmatter 周审计均已改成同一分区样式;其中晨报和 LLM Wiki 治理提醒已做真实微信发送验证并取得 message_id。

🛠️
落地方式

统一 helper weixin_cron_style.py,各 cron 脚本负责构建微信文本、写 weixin_text_*.txtweixin_send_receipt_*.json,成功时 cron 自身静默。

证据摘要

  • 晨报、LLM Wiki 治理提醒、备份日报、Skills 月审计、记忆治理提醒、Skill Frontmatter 周审计均已改成同一分区样式;其中晨报和 LLM Wiki 治理提醒已做真实微信发送验证并取得 message_id。

行动清单

后续新增通知默认复用本样式;若通知内容超过微信舒适阅读长度,应只发摘要和 HTML 链接;已暂停任务如 CPA 巡检恢复前再单独迁移。

边界 / 风险

暂停任务未纳入生产迁移

cpa-codex-inspection-report 当前是 paused,因此本轮没有切生产。后续恢复前应单独迁移到同样的微信文本样式,或根据内容长度改成 HTML 摘要入口。

微信文本长度仍需控制

微信适合短摘要,不适合长报告。后续如果某个任务输出超过 80 行,应优先改为: 微信发摘要 + HTML/wiki 链接; 完整事实留本地 JSON/Markdown; 不把完整表格塞进微信。

本轮未改微信 adapter

本次只改 cron 脚本和任务定义,没有修改: /home/ht/code/hermes-agent-local/gateway/platforms/weixin.py gateway runtime footer 全局 display config 这是刻意收窄风险:先在推送内容生成层稳定样式,不动平台适配层。

完整记录

Hermes 微信推送样式迁移与 Cron 投递链路收口

背景

涛哥要求将 cron 推送从飞书逐步切到微信,并改善移动端可读性。试点从每日备份日报开始,随后扩展到晨报与治理类提醒。最终确认的微信样式是:

🌅 涛哥晨报|日期 ────────── ✅ 结论:今日晨报已生成 ────────── 🌤️ 天气速览 ...

关键设计点:

  1. 标题后立即加分隔线,让标题成为独立视觉块。
  2. 区块之间统一使用 ──────────,比单纯空行更容易在微信里扫读。
  3. 少用 Markdown 表格和代码块,改成短 bullet / 两行元信息。
  4. footer 保持 ---\nprovider/model,满足来源可追踪但不过度占屏。
  5. cron deliver 改为 local,由脚本主动发微信,避免自动投递重复消息。

本次完成的文件改动

通用 helper

新增:

  • /home/ht/.hermes/scripts/weixin_cron_style.py

职责:

  • footer(provider, model):统一 footer。
  • send_weixin_text(text):通过 hermes send --to weixin --json 主动发送。
  • write_text_payload():落 weixin_text_*.txt
  • write_weixin_receipt():落 weixin_send_receipt_*.json

晨报正式链路

新增:

  • /home/ht/.hermes/scripts/morning_brief_weixin_send.py

职责:

  1. 执行 MORNING_BRIEF_MODE=send python3 fetcher.py
  2. /tmp/morning_brief_data.json 构造微信晨报。
  3. 按权重选择「今日重点」,不是简单取各分类第一条。
  4. 分类速览只显示模块数量。
  5. 主动发送微信。
  6. 保留原有 HTML/wiki/Pages 副作用:morning_brief_to_wiki.pymorning_brief_render_html.pymorning_brief_deploy_pages.py
  7. weixin_side_effects_*.json 记录副作用 returncode。

已迁移脚本

Job ID名称脚本样式状态投递状态
bc0fef84c33ahermes-morning-briefmorning_brief_weixin_send.py已统一deliver=local,脚本主动发微信
2e8a99d99d49daily-backup-notifydaily_backup_notify_cron.py已统一deliver=local,脚本主动发微信
60350e570c0bmonthly-skill-exit-auditmonthly_skill_exit_audit.py已统一deliver=local,脚本主动发微信
596d649eada4memory-governance-day-evaluatememory_governance_day_eval.py已统一deliver=local,脚本条件发微信
c07e89032631skill-frontmatter-weekly-auditskill_frontmatter_weekly_audit.py已统一deliver=local,脚本主动发微信
cdd914f97df7llm-wikis-governance-alertllm_wikis_governance_alert_weixin.py已统一deliver=local,异常时发微信

Cron 定义收口

本次对上述 6 条任务的目标状态是:

no_agent=true script=<对应脚本> deliver=local repeat=forever

这样做的原因:

  • no-agent script-only 比 agent prompt 更稳定,避免模型自由发挥。
  • 主动调用微信发送函数,能拿到平台 receipt 和 message_id。
  • cron 自身 deliver=local,避免脚本已经发微信后,scheduler 再把 stdout 投一遍。
  • 成功时 stdout 为空,符合 script-only cron 的静默语义。

已验证证据

晨报最终样式

实发 message_id:

  • hermes-weixin-26019aa1cec54acfbfc83be6725424dc

本地证据:

  • 文本:/home/ht/.hermes/cron/output/bc0fef84c33a/weixin_text_20260607-223447.txt
  • receipt:/home/ht/.hermes/cron/output/bc0fef84c33a/weixin_send_receipt_20260607-223453.json

验证点:

  • 标题后有 ──────────
  • 天气速览有城市 icon、温度、湿度、风速、降雨分时段。
  • 今日重点标题完整展示。
  • 分类速览只显示数量。
  • footer 为 ctyun/DeepSeek-V4-Flash

LLM Wiki 治理提醒

实发 message_id:

  • hermes-weixin-1f21618cf83440ff9fa0a33d32fd3aa4

本地证据:

  • 文本:/home/ht/.hermes/cron/output/cdd914f97df7/weixin_text_20260607-224209.txt
  • receipt:/home/ht/.hermes/cron/output/cdd914f97df7/weixin_send_receipt_20260607-224215.json

验证点:

  • 标题后有分隔线。
  • action-needed 时主动发微信。
  • healthy 时脚本静默。

晨报生产链路副作用

  • /home/ht/.hermes/cron/output/bc0fef84c33a/weixin_side_effects_20260607-222834.json

记录显示:

  • fetcher returncode = 0
  • HTML render returncode = 0
  • Pages deploy returncode = 0

风险与边界

风险 1:暂停任务未纳入生产迁移

cpa-codex-inspection-report 当前是 paused,因此本轮没有切生产。后续恢复前应单独迁移到同样的微信文本样式,或根据内容长度改成 HTML 摘要入口。

风险 2:微信文本长度仍需控制

微信适合短摘要,不适合长报告。后续如果某个任务输出超过 80 行,应优先改为:

  • 微信发摘要 + HTML/wiki 链接;
  • 完整事实留本地 JSON/Markdown;
  • 不把完整表格塞进微信。

风险 3:本轮未改微信 adapter

本次只改 cron 脚本和任务定义,没有修改:

  • /home/ht/code/hermes-agent-local/gateway/platforms/weixin.py
  • gateway runtime footer
  • 全局 display config

这是刻意收窄风险:先在推送内容生成层稳定样式,不动平台适配层。

回滚路径

本轮备份目录:

  • /home/ht/.hermes/backups/weixin-cron-style-final-20260607-222105/

关键备份:

  • jobs.json
  • jobs-before-final-switch.json
  • jobs-before-llm-wikis-alert-switch.json
  • 相关脚本备份

如果需要回滚:

  1. 恢复对应脚本。
  2. 恢复 ~/.hermes/cron/jobs.json 中对应 job 的 script/no_agent/deliver/origin/skills/model/provider 字段。
  3. cronjob list 验证 repeat=forever、schedule 未丢。
  4. 对目标任务手动 run 或等自然触发后检查 output 与平台消息。

后续建议

  1. weixin_cron_style.py 作为后续轻量推送 canonical helper。
  2. 暂停任务恢复前先按同样样式迁移,不要恢复旧飞书卡片链路。
  3. 如果同类样式继续稳定,可将 hermes-cronjob-safe-update 的微信迁移 reference 更新为本页结论。
  4. 后续新增推送脚本默认输出:标题、标题分隔线、结论、分区块、footer、receipt。