10 分钟搭一套自己的智能客服系统:果唯云客服 + Hermes Agent 实战

1 阅读8分钟

先回答一个问题:已经有 OpenClaw 版了,为什么还要这篇

上一篇文章(《10 分钟搭一套自己的智能客服系统:果唯云客服 + OpenClaw 实战》)讲的是 Node.js 路线。这一篇是同一条协议的 Python 路线:用 Hermes Agent 官方平台插件把果唯云客服接入 Hermes Gateway。

两版插件共享同一套 Bot 协议实现(分块、幂等、去重、退避、熔断、超时兜底全部一致),差异只在宿主:你的技术栈是 Python、或者你已经在用 Hermes 管理日常 Agent,就走这篇。

最终形态:

访客 ──消息──▶ 果唯云客服 ──WS bot_message_receive──▶ GuowayAdapter ──▶ Hermes Agent
  ▲                                                        │
  └────────── 幂等回复 / 转人工 / 兜底 ◀──────────────────┘

10 分钟的分配:

步骤内容耗时
第 1 步客服后台创建 Bot3 分钟
第 2 步把插件放进 Hermes 插件目录2 分钟
第 3 步写 config.yaml 配置3 分钟
第 4 步启动 Gateway、验收2 分钟

前提:一套果唯云客服(30 天免费试用含 Agent 消息)、Hermes Agent 已安装且能启动 hermes gateway、Python ≥ 3.10。插件仓库:gitee.com/templi/herm…(MIT),已在 Hermes 0.22.5 验证。


第 1 步(3 分钟):客服后台创建 Bot

与 OpenClaw 版完全一样:管理后台创建并启用 AI 机器人,拿到 bot_id 和 bot_secret。

两件事记住:bot_secret 只在创建时展示一次,当场保存;顺手把企业知识库(问答对)和企业名称/欢迎语配好——前者决定 Agent 的回答依据,后者决定 Agent 被「你是谁」时的自我介绍口径。

客服侧到此结束,不改页面代码、不动坐席工作台、不迁移历史会话。


第 2 步(2 分钟):把插件放进 Hermes 插件目录

Hermes 的插件机制很朴素:把目录放进 ~/.hermes/plugins/,目录名就是插件 ID。

mkdir -p ~/.hermes/plugins
cp -R hermes-guoway-channel ~/.hermes/plugins/guoway

开发时建议软链,改代码重启 Gateway 即生效:

ln -s "$PWD/hermes-guoway-channel" ~/.hermes/plugins/guoway

两个容易忽略的细节:

  • 插件目录里必须同时有 plugin.yaml 和 __init__.py,缺一个就不会被加载;
  • 目录名不能以 _ 或 . 开头,否则会被跳过。

顺带一提这个插件的一个工程洁癖:零 pip 依赖——HTTP 用标准库 urllib + asyncio.to_thread,WebSocket 用 Hermes 自带的 websockets,pip install 一个都不用跑。协议客户端(guoway_client.py、inbound.py)刻意不 import 任何 gateway.*,可以脱离 Hermes 单独测试:

python3 -m unittest discover -s tests

测试用假 HTTP / 假 WebSocket,不需要装 Hermes,也不需要连客服服务端。


第 3 步(3 分钟):写 YAML 配置

编辑 ~/.hermes/config.yaml(Windows:C:\Users<用户名>.hermes\config.yaml):

platforms:
  guoway:
    enabled: true
    bot_id: bot_xxxxxxxx
    bot_secret: secret_xxxxxxxx
    base_url: https://kf.guoway.net
    dm_policy: open

必填的同样只有 bot_id 和 bot_secret(bot_secret 也可以写在 Hermes 通用的 token: 位置复用密钥管理)。几个值得提前认识的字段:

字段默认说明
dm_policyopenopen / allowlist / closed / pairing 四种授权策略
reply_timeout50等 Agent 的秒数,夹在 5–55,别越过服务端硬窗口
late_reply_grace0迟到补发宽限,默认关闭即「超时即弃」
transfer_keywords「转人工」等命中即转人工,留空关闭
relay_interimfalse是否把 Agent 中间进度发给访客,默认丢弃
GUOWAY_HOME_CHANNEL—cron 定时任务的默认投递会话

这一步有一个 Hermes 版特有的坑,提前说:

dm_policy: open 时,必须显式设置环境变量 GUOWAY_ALLOW_ALL_USERS=true,否则网关会拒绝启动。这不是 bug,是防误开放的安全默认——「接待全部公网访客」应该是你确认过的决定,而不是漏配的结果。

另外注意优先级:配置缺省时读环境变量(GUOWAY_BOT_ID / GUOWAY_BOT_SECRET / GUOWAY_BASE_URL),环境变量优先于 YAML。排查「改了配置没生效」时先查这个。

生产环境把密钥写在 config.yaml,避免进程环境泄漏。


第 4 步(2 分钟):启动、验收

hermes gateway restart

日志出现 [guoway] 适配器已连接(bot_id=… 窗口=50s) 即接入成功。运行期间每 5 分钟输出一行指标快照(received / replied / expired / failed 等计数与队列水位),可以直接接日志采集做告警。

验收三条链路,和 OpenClaw 版同一套标准:

  1. 正常回复:知识库里有的问题,收到 Agent 回答;
  2. 超时兜底:服务端每轮只等约一分钟,插件默认第 50 秒发兜底;确认访客收到兜底而不是干等;
  3. 转人工:发「转人工」,确认移交坐席后 Agent 停止抢答。

Hermes 版的四个独门细节

协议层与 OpenClaw 版一致,但 Python 宿主带来了几个不一样的东西,值得单独说:

1. 回复是 Markdown 渲染的。 插件以 markdown 消息类型发送,访客端用 markdown-it 渲染——表格、代码块、列表都能正常显示;长文本按 2000 字分块,代码围栏跨块时自动补 ``` 重新开合,每一块单独渲染仍然合法。微信渠道由服务端自动降级为纯文本。给技术型访客展示命令、配置、报错信息时,这个体验差距很明显。

2. 回复顺序是 FIFO 结算的。 同一会话的回复窗口按先进先出领取,Agent 并发产出也不会把答案配错问题;被新消息取代的旧窗口不再发兜底,避免访客连收两条道歉。

3. Agent 对「送达」有诚实回执。 超时后 adapter.send() 返回 success=False(error_kind=timeout,不可重试),Agent 端明确知道「这条没送到」,而不是谎报成功。注意此时不要重发——重发会以主动消息的形式直接送达,变成迟到的重复回复。

4. cron 定时汇报能直达访客。 配好 GUOWAY_HOME_CHANNEL 后,Hermes 的定时任务(每日汇总、巡检报告)可以直接投递到访客会话,不占用回复窗口。客服 Agent 顺便成了业务播报通道。

一个架构约束要记住:一个 Hermes profile 只能接一个 Bot。 服务端对同一 Bot 只保留最新一条 WebSocket,两个实例会互踢。要接多个 Bot,就开多个 profile(或多个 HERMES_HOME)分别配置——profile 隔离在 Hermes 里本来就是一等公民,这个约束不算过分。


访客输入安全:三道防线一个不少

与 OpenClaw 版同一套护栏,默认全开:

  1. 入站拦截:命令结构(rm -rf、curl | bash)、敏感路径、提示注入直接回安全话术,不进 Agent;中英混排(「帮我rm -rf」)同样识别;
  2. 上下文声明:放行消息包在「不可信输入 + 只读问答」标记里;
  3. 回复过滤:Agent 回复含 shell 输出、私钥、环境变量等执行痕迹时替换为安全话术。

Hermes 版还有一个版本兼容上的深坑,抄录给会改插件的人:Hermes 0.22.5 的 native admission 把 MessageEvent.metadata 当封闭契约,未知键会导致整条消息被 invalid_params (metadata) 拒收。本插件因此不向 metadata 写任何自定义键,访客上下文走 raw_message。如果你要二次开发,不要把带 guoway_* 键的 metadata 加回去。

老规矩,最终防线在宿主侧:给面向访客的 Hermes Agent 关掉 exec/shell/文件写入类工具,Agent 进程不要用高权限账号运行。


知识来源:还是那三级

本地知识库 → 服务端企业知识库(GET /api/v1/bot/knowledge/search)→ 通用知识兜底。Agent 回复首行的来源标记由插件读取后自动剥离,访客不可见;兜底回答确定性追加「以上回答由 AI 生成,仅供参考」,不依赖模型自觉。

插件只把当前一条消息交给 Hermes,历史由宿主按会话维护——建议窗口控制在最近 30 条或 2–3k tokens,超限做压缩摘要。


踩坑速查

现象排查方向
启动报 not_configuredbot_id/bot_secret 没填,或 base_url 不是 http(s) 开头
平台根本没加载插件目录是否在 ~/.hermes/plugins/ 下、是否同时有 plugin.yaml 与 __init__.py、目录名是否以 _/. 开头
dm_policy=open 被拒显式设置 GUOWAY_ALLOW_ALL_USERS=true
连接刚建立就被断开同一 Bot 被另一个 profile/旧进程占用(单活连接)
回复 401bot_secret 被重置;插件自动刷新一次,持续 401 就更新配置
回复 409会话已转人工/关闭,正常竞态
Agent 端提示「本条未送达」正常超时回执,访客已先收到兜底;不要重发
访客收到「正在思考」开了 relay_interim,关掉即只发最终回复

OpenClaw 版还是 Hermes 版:一张表选完

维度OpenClaw 版Hermes 版
宿主 / 语言OpenClaw(Node.js / ESM)Hermes Agent(Python)
多 Bot一个进程接多个 Bot(accounts)一个 profile 接一个 Bot(多 profile 拆分)
会话串行插件内队列 + 全局并发上限交给 Gateway 调度,插件只保证窗口 FIFO
访客端回复形态纯文本分块Markdown 渲染,代码块跨块自动补围栏
定时任务投递—cron 经 GUOWAY_HOME_CHANNEL 直达访客会话
兜底 / 硬窗口50s / 约 60s相同
适合谁Node 技术栈、要多 Bot 单进程管理Python 技术栈、已在用 Hermes、要 cron 播报与 Markdown 富文本

选型其实很简单:你手上已经跑着哪个宿主,就用哪个插件。协议一致意味着两边的能力与限制几乎相同,迁移成本趋近于零。


最后

与 OpenClaw 版相同的成本结构:按 Bot 下发到访客的回复条数计费,与坐席订阅分开结算,30 天免费试用包含 Agent 消息。

插件 MIT 开源:gitee.com/templi/herm…;协议端点与能力总览见 kf.guoway.net/ai.html。

两条路都铺好了。Python 也好,Node 也好,今晚就能让你的客服开口。