3510 字
18 分钟
次浏览
Building an Autonomous AI Agent on WSL

0. 前言#

最近在捣鼓 AI Agent 方向的内容, 接触到 Hermes Agent —— 一个由 Nous Research 开源的 AI Agent 框架. 它和 Claude Code、OpenAI Codex 属于同一个赛道, 但有一个核心差异点让我很感兴趣: 多平台网关.

也就是说, 我可以通过微信直接给它发消息, 它就帮我去执行命令、操作浏览器、管理文件. 听起来很酷, 对吧?

但实际搞起来, 坑还真不少. 本篇博客记录了从零开始在 WSL (Windows Subsystem for Linux) 上部署 Hermes Agent 的完整过程, 包括几个核心环节:

  1. Hermes 的安装与基础配置
  2. 微信网关的对接
  3. Windows 保活机制(解决 WSL 休眠/重启后服务中断的问题)
  4. Camoufox 反爬浏览器的集成(绕过 Google、百度等网站的反爬检测)

希望对你有帮助.

NOTE

阅读前, 需要你 : 熟悉 Linux 命令行, 了解 WSL 的基本使用, 对 AI Agent 概念有基本认识.

1. Hermes Agent 是什么#

简单来说, Hermes Agent 就是一个可以跑在终端和聊天软件里的 AI 助手.

它不是又一个聊天机器人 —— 它能真正帮你干活. 你可以让它帮你查资料、写代码、操作浏览器、管理文件, 甚至写博客(这篇就是). 支持的工具调用挺丰富的:

  • 20+ 模型供应商: OpenRouter、Anthropic、DeepSeek……想用哪个用哪个
  • 10+ 平台网关: 微信、Telegram、Discord、Slack 都能连
  • 跨会话记忆: 它会记住你的偏好, 不用每次都重新说
  • 技能系统: 复杂的操作流程可以自动保存下来, 下次直接复用

架构上其实就两层, 不复杂:

  1. Gateway (网关): 常驻后台的进程, 负责接收和转发消息. 你可以理解为 7x24 小时值班的”接线员”
  2. Agent (代理): 每次对话创建一个新的 Agent 实例, 执行具体的任务. 相当于”干活的人”

2. 在 WSL 上安装#

我的环境是 Windows 11 + WSL2 (Ubuntu). 安装非常简单, 一行命令搞定:

Terminal window
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash

安装完之后, 需要配置模型供应商. 我这边用的是 OpenRouter 做中转, 因为它的模型选择多, 而且不用绑定某一家:

Terminal window
hermes setup

或者直接编辑配置文件 ~/.hermes/config.yaml:

model:
default: deepseek-v4-flash
provider: custom
base_url: https://your-api-endpoint/v1
api_key: your_api_key

这里有几个我觉得值得调的配置项, 分享一下我的取值:

配置说明我的值
agent.max_turns每次对话最大工具调用轮次, 默认 90100
terminal.timeout单条命令最大执行时间, 默认 180s600s (10分钟)
display.language界面语言zh (中文)
memory.memory_enabled跨会话记忆true

3. 微信网关配置#

这一步的体验还挺神奇的 —— 配好之后, 你给 Hermes 发微信就像给朋友发消息一样自然.

Hermes 用的是 iLink Bot 协议, 通过扫码登录微信:

Terminal window
hermes gateway setup

选择 WeChat 平台, 终端里会出现一个二维码, 掏出手机扫一下就行.

关键的配置项在 ~/.hermes/.env 中:

WEIXIN_ACCOUNT=你的微信账号
WEIXIN_GROUP_POLICY=open

然后启动网关:

Terminal window
hermes gateway run

看到类似下面的日志, 说明网关启动成功了:

[INFO] Weixin gateway connected
[INFO] Gateway running on ...

之后就可以在微信里给 Hermes 发消息了. 它会在微信里直接回复你, 就像在和联系人聊天一样.

不过有一点需要提前知道 —— iLink Bot 协议有一些限制:

  • ✅ 收发文本消息
  • ✅ 发送图片和文件
  • ✅ 执行任意终端命令
  • ✅ 操作浏览器(导航、截图、点击、输入)
  • ❌ 不支持群聊
  • ❌ 不支持给陌生人主动发消息

对我来说, 这些限制基本不影响日常使用. 大多数场景就是自己跟它对话, 不需要群聊功能.

4. 保活机制#

这是整个部署过程中最折腾的部分, 没有之一. 问题很简单:

WSL 在 Windows 休眠或重启后, Gateway 进程就挂了. 下次打开微信想用它的时候, 发现没反应了.

为了解决这个问题, 我搞了一个三层保活架构:

NOTE

以下各层的代码片段为核心流程展示, 实际脚本包含了更多的边界处理、错误恢复和安全保护(互斥锁降级、进程状态检测、多级 fallback 等)。

第一层: Windows Startup 启动#

在 Windows 的启动文件夹里放一个 VBS 脚本, 每次开机自动运行:

C:\Users\<用户名>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\start-hermes-watchdog.vbs

VBS 脚本使用动态路径检测, 自动找同目录下的 hermes-watchdog.ps1, 不需要硬编码路径:

' 自动检测脚本所在目录,无需硬编码路径
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("Wscript.Shell")
strPath = objFSO.GetParentFolderName(Wscript.ScriptFullName)
strPS1 = objFSO.BuildPath(strPath, "hermes-watchdog.ps1")
' 参数: 隐藏窗口(0), 不等待(False)
objShell.Run "powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File """ & strPS1 & """", 0, False

0 这个参数是关键 —— 表示不显示窗口, 后台静默运行.

第二层: PowerShell 自循环守护脚本#

核心剧本是 hermes-watchdog.ps1, 它每隔 5 分钟调用 WSL 端的 /root/hermes-watchdog.sh 检查 Gateway 的状态. v2.0 版本做了几个重要改进:

  • 分片睡眠 + 60s 心跳: 每 5 分钟的主循环间隔被拆成 60 秒一片, 每片写一次 heartbeat.txt, 这样随时可以从 Windows 端确认看门狗是否还活着(即使主循环 sleep 期间)
  • WSL 可达性预检: 调用 WSL 前先检查 WSL 是否可达, 不可达时尝试唤起而非直接超时跳过
  • 兜底启动: WSL 脚本返回 exit=2(重启失败)时, PS1 直接尝试 hermes gateway run & 兜底启动
  • exit code 正确捕获: 通过 Job 的 hashtable 返回值修复 Start-Job 中 $LASTEXITCODE 丢失问题

以下是简化版逻辑(完整脚本含互斥锁、日志、兜底恢复等辅助功能):

Terminal window
# 全局命名 Mutex 防止多实例竞跑
$mutex = New-Object System.Threading.Mutex($false, "Global\HermesGatewayWatchdog")
if (-not $mutex.WaitOne(0)) { exit 0 }
# 主循环: 分片睡眠 + 60s 心跳
while ($true) {
# 分片 60s 睡眠, 每片写心跳文件
for ($i = 0; $i -lt 5; $i++) {
Start-Sleep -Seconds 60
Get-Date -Format "yyyy-MM-dd HH:mm:ss" |
Out-File $heartbeatFile -Encoding utf8 -Force
}
# Step 1: WSL 可达性预检
if (-not (Test-WslAlive)) {
# 尝试唤起 WSL, 失败则跳过本轮
wsl.exe -d Ubuntu -- echo "kick" 2>&1
continue
}
# Step 2: 调用 WSL 侧的检测脚本
$output, $exitCode, $timedOut = Invoke-WslScript
if ($timedOut) { continue } # WSL 超时
if ($exitCode -eq 0) { /* 正常 */ } # 仅每5周期写一次日志
if ($exitCode -eq 1) { Write-Log "Gateway 已重启" }
if ($exitCode -eq 2) {
# 兜底: WSL 脚本失败, PS1 直接启动
Invoke-WslScript -Command "hermes gateway run &" -TimeoutSeconds 15
}
}

完整的 WSL 端检测脚本 /root/hermes-watchdog.sh 负责真正的进程检查与重启(以下展示核心流程, 完整脚本含 PID 文件 inode 保护、多级别启动降级等额外加固):

#!/bin/bash
# 锁: flock + PID 文件, 防多实例也防 inode 替换绕过
LOCKFILE="/var/run/hermes-watchdog.lock"
exec 200>"$LOCKFILE"; flock -n 200 || exit 0
echo "$$" > "$LOCKFILE"
# find_gateway_pid: 遍历 pgrep 结果
# 用 /proc/PID/exe 确认是 Python 进程 (排除 shell 包装)
# 用 /proc/PID/status 跳过 Zombie 和 D 状态
find_gateway_pid() {
for pid in $(pgrep -f "hermes gateway run"); do
[ ! -d "/proc/$pid" ] && continue
[ "$pid" = "$$" ] && continue # 跳过自身
state=$(grep -o '^State:\\s*[A-Z]' /proc/$pid/status | grep -o '[A-Z]$')
case "$state" in Z|D) continue ;; esac
exe=$(readlink /proc/$pid/exe)
case "$exe" in */python|*/python3|*/python3.*) echo "$pid"; return 0 ;; esac
done; return 1
}
GW_PID=$(find_gateway_pid)
[ -n "$GW_PID" ] && echo "0" && exit 0 # 正常运行
# 三级 fallback 启动
VENV="/usr/local/lib/hermes-agent/venv/bin/hermes"
for cmd in "$VENV" "hermes" "python3 -m hermes"; do
nohup $cmd gateway run </dev/null >/dev/null 2>&1 &
for i in {1..15}; do
sleep 2
[ -n "$(find_gateway_pid)" ] && echo "1" && exit 1 # 启动成功
done
done
echo "2" && exit 2 # 启动失败

第三层: Windows 计划任务(兜底)#

即使 PowerShell 脚本意外退出了, 还有计划任务兜底. 兜底脚本 check-watchdog.ps1 做了双重确认: 先尝试获取互斥锁, 若能获取(说明 PS1 可能死了), 再检查 heartbeat.txt 是否新鲜——只有心跳也过期了才确认 PS1 死亡, 接手启动 Gateway.

Terminal window
# 任务: 开机启动看门狗 (启动目录备用入口)
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"C:\...\hermes-watchdog.ps1`""
Register-ScheduledTask -TaskName "HermesWatchdog" -Action $action -Force
# 兜底: 每5分钟检查 (通过独立的 check-watchdog.ps1)
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-File `"C:\...\check-watchdog.ps1`""
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
-RepetitionInterval (New-TimeSpan -Minutes 5) `
-RepetitionDuration ([TimeSpan]::FromDays(365))
Register-ScheduledTask -TaskName "HermesWatchdogHealthCheck" -Action $action -Trigger $trigger -Force

兜底脚本 check-watchdog.ps1 会先尝试获取互斥锁 Global\HermesGatewayWatchdog——如果能拿到(说明 PS1 可能死了), 再检查 heartbeat.txt 是否在 7 分钟内更新过. 只有 Mutex 释放 && 心跳过期 才确认 PS1 已死, 接手重启 Gateway.

这解决了 TOCTOU 竞态问题: 兜底脚本在 持有 Mutex 期间 执行 WSL 检查, 防止并发冲突.

全链路故障恢复#

这三层下来, 我做了两轮共 63 项压力测试 + 攻击测试, 包括:

  • kill -9 Gateway: 看门狗检测到进程死亡, 自动重启 ✅ (实测 PID 从 287817 恢复到 290825)
  • pgrep 误匹配: 修复为通过 /proc/PID/exe 确认 Python 进程, 排除 bash 包装进程
  • PS1 崩溃: 计划任务检测到 Mutex 释放后接管, 5 分钟内恢复
  • 锁文件 inode 替换: flock + PID 文件双重保护, 防绕过
  • 僵尸 / D 状态进程: /proc/PID/status 状态检查, 跳过不可用进程
  • venv 二进制被删: 三级 fallback (venv/hermeshermespython3 -m hermes)

即使电脑重启、休眠、甚至脚本崩了, Hermes 都会在 5 分钟内自动恢复. 实测下来, 基本能做到”无感恢复”.

5. Camoufox 反爬浏览器#

这是另一个让我踩了不少坑的部分.

Hermes 内置的浏览器工具默认用的是 Playwright 的浏览器. 问题在于: 很多国内网站(百度、天气网)和 Google 都会检测并拦截自动化浏览器. 我第一次试的时候就碰了一鼻子灰 —— 打开百度直接给个验证码, 天天气网直接 403.

解决方案是装一个反检测浏览器: Camoufox.

Camoufox 本质上就是 一个经过魔改的 Firefox, 它通过随机化浏览器指纹(屏幕分辨率、WebGL、字体、时区、语言等)来伪装成普通用户. 简单理解就是 —— 它让网站以为你是一个真实的用户在浏览.

安装过程#

Terminal window
# 1. 安装 Camoufox Python 包
pip install camoufox
# 2. 安装 camofox-browser (Node.js REST API 服务)
git clone https://github.com/jo-inc/camofox-browser.git ~/.hermes/camofox-browser
cd ~/.hermes/camofox-browser && npm install

这里有个小坑: camoufox server 命令存在一个已知的 Node.js/Playwright 兼容性问题(报错 “proxy: expected object, got null”), 所以推荐用 camofox-browser 这个方案.

启动服务#

Terminal window
cd ~/.hermes/camofox-browser && PORT=9377 npm start

检查服务是否正常:

Terminal window
curl http://localhost:9377/health
# {"ok":true,"engine":"camoufox","browserConnected":true,"browserRunning":true}

集成到 Hermes#

.env 中设置环境变量:

CAMOFOX_URL=http://localhost:9377

然后在配置文件中启用:

browser:
engine: auto
camofox:
managed_persistence: false

重启 Hermes 会话后, browser_navigate 等命令就会自动通过 Camoufox 执行了.

效果对比#

安装前后的差别还是很明显的:

测试站点默认 Playwright 浏览器Camoufox
baidu.com❌ 被拦截✅ 正常访问
weather.com.cn❌ 被拦截✅ 正常访问 + 搜索
google.com❌ 验证码✅ 正常搜索

为了方便日常管理, 我写了个简单的启动脚本 camofoxctl.sh:

Terminal window
/root/.hermes/camofoxctl.sh start # 启动
/root/.hermes/camofoxctl.sh status # 查看状态
/root/.hermes/camofoxctl.sh stop # 停止

6. 灵魂画手: 架构总览#

下面用一张图总结整个系统的架构:

Hermes Agent on WSL 架构图

上图展示了从用户手机微信端 → WeChat Gateway → Hermes Agent → Camoufox 浏览器 → 外部 Web 服务的完整链路, 以及底部的三层保活系统.

7. 总结#

整个部署过程踩了不少坑, 总结几个关键经验:

  1. WSL 的稳定性: 电脑休眠后 WSL 可能丢网络或进程, 保活脚本是必需品, 别偷懒
  2. 网关协议有限制: iLink Bot 不支持群聊、不能主动给陌生人发消息, 但核心功能——收发消息、传文件——完全够用
  3. 反爬是个绕不过去的坎: 默认的 Playwright 浏览器在中文互联网上基本寸步难行, Camoufox 是目前试下来最省心的方案
  4. Hermes 的技能系统是真香: 用多了它会自己积累工作流, 越来越顺手

最终的效果就是——我躺在沙发上, 掏出来手机打开微信, 就可以让 Hermes 帮我查天气、搜 Google、管理代码、甚至写博客. 这感觉, 确实爽. 👍


▼ 滚动到这里有惊喜 ▼
hermes-agent@self-disclosure — bash

如果你也在折腾 AI Agent, 欢迎交流.

Building an Autonomous AI Agent on WSL
https://xuchenhui.cc/posts/2026-05-15-hermes-agent-wsl-setup/
作者
CHENHUI
发布于
2026-05-15
许可协议
CC BY-NC-SA 4.0
📖 目录