← 返回文章列表

从微信对话到线上博客:我用 Hermes Agent 打通 Trilium 自动化发布链路

记录如何用 Hermes Agent 打通微信对话到 Trilium 博客的自动化发布链路:MCP 配置、图片处理、云端 poller 轮询、GitHub + EdgeOne 部署,以及数据一致性修复实践。

#Trilium#Hermes#MCP#自动化#博客#AI

前言

你有没有过这样的体验:灵感来的时候在微信里跟 AI 聊得火热,聊完却要手动整理成文章、找图、排版、上传、发布,一套流程走下来热情已经凉了一半。我一直在折腾自己的博客(longBlog,基于 Astro 搭建),最大的痛点就是写文章的成本:内容生产、图片处理、发布流程,每一步都在消耗精力。

这篇文章记录的是我最近做的一件事:把「微信对话 → 文章整理 → Trilium 笔记 → 自动发布到互联网」整条链路打通。现在我在微信里跟 Hermes Agent 说一声"把这篇发到博客",剩下的全部自动化完成。

先放一张全貌架构图,本文就是围绕这条链路展开的:

背景:我的博客架构

在开始之前,先交代一下我的博客整体架构。longBlog 是一套三层分离的自动化系统:

本地 Trilium(NAS,写作后台)
  ↓ 自动同步
云端 Trilium(blog.ssaw.top)
  ↓ poller 轮询 + 同步脚本
GitHub 仓库
  ↓ EdgeOne Pages 自动部署
https://huowenlong.com/

这个架构里,Trilium 是文章编辑后台,也是标签状态管理中心。文章写在哪、打什么标签、是否发布,都由 Trilium 里的笔记属性控制。

第一部分:把 Hermes 接进 Trilium

为什么需要 Hermes

Trilium 本身是一个强大的笔记软件,支持脚本、标签、关系、附件,甚至可以通过 ETAPI(REST API)完全编程控制。但它没有一个"智能代理"来帮你完成端到端的任务——比如从微信对话里提取内容、整理成文章、处理好图片、再导入 Trilium。

Hermes Agent 是我运行在 NAS 上的 AI 代理,通过微信接入。它的价值在于:能理解上下文、能调用工具、能自主完成多步骤任务

配置 MCP 连接

让 Hermes 操作 Trilium,最优雅的方式是 MCP(Model Context Protocol)。Hermes 内置 MCP 客户端,我在 config.yaml 里配置了 Trilium 的 MCP 服务器:

mcp_servers:
  trilium:
    url: "http://192.168.10.100:25399/mcp"
    headers:
      Authorization: "Bearer <ETAPI_TOKEN>"
    timeout: 180
    connect_timeout: 60

配置完成后,Hermes 启动时会自动发现 Trilium 的 23 个工具:搜索笔记、读取内容、创建笔记、设置属性、移动笔记、删除笔记等。这些工具直接以 mcp_trilium_* 的形式出现在 Hermes 的工具箱里,我可以在微信里直接指挥它操作 Trilium。

连通性验证

配置完成后第一件事是验证连通性。我在微信里让 Hermes 搜索 Trilium 里的笔记,它成功返回了我的博客文章列表,还能完整读取《Overleaf 部署实战指南》这样的长文。这证明了:微信 → Hermes → Trilium 的链路完全打通

第二部分:图片处理(关键细节)

博客文章通常需要配图。Trilium 的图片是作为笔记的附件存储的,引用格式是 api/attachments/{attachmentId}/image/{title}

三种图片来源

  1. 微信发的图片:用户直接发图给 Hermes,图片自动缓存在 NAS 上,Hermes 可以读取
  2. 自己寻找的图片:截图、网页图片,Hermes 可以自行获取
  3. Excalidraw 绘制:通过 Docker 里的 Excalidraw 应用辅助绘制示意图

上传流程

MCP 工具里没有"上传附件"的能力,所以图片上传要走 Trilium 的 ETAPI。实测正确的格式是 JSON body + base64 编码:

import json, base64, urllib.request

payload = {
    "ownerId": "<笔记ID>",          # 图片所属的笔记
    "role": "image",                 # 角色:图片
    "mime": "image/png",
    "title": "image.png",
    "content": base64.b64encode(图片数据).decode(),
    "position": 1
}
req = urllib.request.Request(
    "http://192.168.10.100:25399/etapi/attachments",
    data=json.dumps(payload).encode(),
    headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"},
    method="POST"
)

上传成功返回 201 + attachmentId,然后在笔记正文里插入引用即可。注意不要创建子文件夹放图片——Trilium 的附件机制天然把图片挂在笔记下,这正好符合博客的需求。

第三部分:文章发布流程

创建笔记

Hermes 通过 MCP 在 longBlog 目录下创建一篇新笔记:

parentNoteId: zB8WioyKlvOw   # longBlog 目录
title: 文章标题
content: Markdown 正文
type: text

设置模板

longBlog 有一个 longTemplate 模板笔记,定义了博客需要的所有属性:publish、tags、summary、slug、sync、publishedAt、updatedAt 等。新笔记通过 ~template 关系关联到模板:

type: relation
name: template
value: MC7PtiChdF5S   # longTemplate 笔记 ID

设置标签

发布前需要设置几个关键标签:

标签 说明
publish false 先不发布,等确认
tags 逗号分隔 文章标签
summary 一句话摘要 博客列表页显示
slug URL 标识 通常 = 标题

自动同步到云端

Trilium 的同步是全自动的数据库级同步:本地改动会自动推送到云端 Trilium(blog.ssaw.top),全程不需要手动点击任何按钮

发布流程中没有任何手动同步操作——用户只需要聊天和确认内容,剩下的全部自动化。

勾选发布

确认文章无误后,把 publish 标签设为 true,Trilium 自动同步到云端,云端 poller 检测到发布状态变化后自动完成后续所有工作。

第四部分:云端自动化链路(重点)

这里我要重点介绍一下云端服务器上的自动化——这是整个系统最核心的部分,也是我踩过最多坑的地方。

主链路:服务器轮询

最初的设计是依赖 Trilium 内部的后端脚本(runOnAttributeChange)在标签变化时主动发 webhook。但实际使用中发现,TriliumNext 新版的后端脚本事件触发不一定稳定,而且其他客户端同步来的属性变化不一定能触发服务器端脚本。

所以我把主链路改成了服务器端轮询

poll_trilium_changes.py
  ↓ 每分钟轮询 Trilium ETAPI,检测变化
run_sync_and_build.sh
  ↓ 调度器:并发锁 + 准备 Git 工作区 + 构建
sync_trilium_posts.py
  ↓ 同步文章/附件,生成 Astro 数据,push GitHub
GitHub 仓库 → EdgeOne Pages 自动部署

三个脚本各司其职:

poll_trilium_changes.py(主触发器):每分钟调用 Trilium ETAPI,扫描 longBlog 根节点下的文章,读取标题、标签、正文,与上一次快照对比。检测字段包括:title、publish、sync、pinned、aiRefresh、contentHash。

run_sync_and_build.sh(调度器):把触发事件转成一次完整同步任务。它做并发锁(避免多个任务同时操作 Git 工作区)、准备 Git 工作区、调用同步脚本、执行构建验证。

sync_trilium_posts.py(核心同步):真正把 Trilium 内容转成博客仓库数据的脚本。它读取文章树、正文、标签,下载并本地化附件,生成 Astro 前端数据文件(trilium-posts.content.generated.tstrilium-posts.meta.generated.ts),判断 Git 是否有变化,然后自动 commit + push。

关键的标签系统

云端同步脚本处理这些 Trilium 标签:

标签 作用
publish 控制文章是否发布到博客
sync 手动请求同步
pinned 控制是否置顶
aiRefresh 请求刷新 AI 摘要 / 标签
syncStatus 同步状态(publishing、published、error)
syncHash 内容同步 hash,判断是否变化
publishedAt / updatedAt 发布时间 / 更新时间
slug 文章 URL 标识
summary 摘要
tags 标签

排序规则:置顶文章优先;非置顶文章按原始 publishedAt 排序。

systemd 定时器

云端通过 systemd 定时器实现每分钟轮询:

longblog-poller.timer  → 每分钟触发
longblog-poller.service → 执行一次 poll_trilium_changes.py

排查文件

这套系统最实用的部分是完整的日志体系。出问题时按这个顺序查:

tail -80 /root/longblog-automation/runtime/logs/poller.log   # poller 是否发现变化
cat /root/longblog-automation/runtime/reports/last_report.json  # 同步/构建/push 结果
cd /root/longblog-automation/workspace/current && git log -5 --oneline  # GitHub 提交

poller 日志的关键信息:

no changes notes=14          # 没有检测到变化
changes=1 event=pinned_changed noteId=xxx title=xxx changed=['pinned']  # 检测到变化
runner ok; snapshot updated  # runner 执行成功
ERROR runner failed; snapshot not updated  # 同步失败,快照不更新,下次继续尝试

为什么不用 webhook 作主链路

旧的 webhook 服务(trilium_sync_webhook.py)仍然在运行,但不再作为稳定主链路依赖。原因:

  1. TriliumNext 新版本中,后端脚本事件触发不一定稳定
  2. 其他客户端同步来的属性变化,不一定触发服务器端 runOnAttributeChange
  3. 后端脚本安全权限较高

所以现在的理解是:poller 是主链路,webhook 是备用实时入口

第五部分:数据一致性修复

在整套系统跑起来的过程中,我遇到过一个很典型的问题:升级 Trilium 后同步失败

现象

升级 Trilium 到 v0.105 后,同步一直失败,日志里大量报错:

ERROR: Cannot find entity for entity change {...}
Sync failed: Cannot read properties of undefined (reading 'entityChange')

根因

数据库的 entity_changes 表里有大量"悬空记录"——指向已删除实体的变更记录。这些是升级时 Demo 内容、损坏主题的变更残留。同步时逐个查找这些记录对应的实体,发现不存在 → 报错 → 同步崩溃。

解决

清理 entity_changes 表里的悬空记录(指向不存在实体的记录):

# 对 notes / attributes / branches 三类实体
DELETE FROM entity_changes
WHERE entityName = 'xxx'
AND entityId NOT IN (SELECT id FROM xxx)

清理了 1489 条悬空记录后,同步恢复正常。这个坑提醒我:升级后如果同步异常,先检查 entity_changes 表的一致性

总结

现在我的写作流程变成了这样:

  1. 在微信里跟 Hermes 聊天,聊出内容
  2. 让 Hermes 整理成文章(自动处理图片)
  3. Hermes 通过 MCP 创建 Trilium 笔记、设置模板和标签
  4. 云端自动完成:自动同步 → poller 轮询 → 构建 → 推送 GitHub → 部署上线

整个链路中,人只需要做一件事:聊天。剩下的内容整理、图片处理、笔记创建、云端发布,全部由自动化完成。

这套系统的核心设计理念是:

  • Trilium 是内容中枢:所有文章以笔记形式存在,标签控制状态
  • Hermes 是智能入口:理解对话、调用工具、完成任务
  • 云端 poller 是可靠触发器:轮询代替 webhook,稳定可靠
  • GitHub + EdgeOne 是发布通道:仓库更新即部署

如果你也在折腾个人博客,希望这篇文章能给你一些启发:写博客最贵的不是服务器,是你的注意力。把重复劳动交给自动化,把精力留给真正重要的内容创作。

本文由 Hermes Agent 根据微信对话与实践过程整理,从对话整理到同步上云的完整自动化流程记录。