DeepAI Paper Hermes Agent 教程 Agent 排障时一条 pkill 把自己杀了:Hermes Gateway 自终止为什么需要危险命令拦截

Agent 排障时一条 pkill 把自己杀了:Hermes Gateway 自终止为什么需要危险命令拦截

自动化 Agent 能执行终端命令,是效率来源,也是风险来源。

NousResearch/hermes-agent issue #3397 记录了一个很典型的“控制平面误伤自己”问题:Telegram Gateway 里的 Agent 想设置提醒,误判 Gateway 没运行,于是执行:

pkill -f "cli.py --gateway"

结果这条命令不是清理无关进程,而是直接把正在承载自己的 Gateway 进程杀掉了。

systemd 看到的是一次“正常退出”:

hermes-gateway.service: Deactivated successfully.

但从用户角度看,机器人突然离线,直到人工重启。


表面现象:Agent 说 gateway 没跑,然后真的把 gateway 干掉了

issue 里的日志很有画面感。

Agent 先得出一个错误判断:

gateway çalışmıyor (port 8000/8080'de dinleme yok)

翻译过来就是:

gateway 没有运行,因为 8000/8080 端口没有监听。

问题是,这个判断本身就不稳。

Telegram Gateway 可以是 polling 模式,不一定监听 HTTP 端口。

于是 Agent 基于错误的健康检查,继续执行“清理命令”:

pkill -f "cli.py --gateway"

然后 journalctl 里出现:

[tool] pkill -f "cli.py --gateway"...
systemd[1]: hermes-gateway.service: Deactivated successfully.

这就是典型的:

排障动作比原问题更致命。

根因:DANGEROUS_PATTERNS 拦了 pkill -9,却没拦 pkill -f

issue 指向 tools/approval.pyDANGEROUS_PATTERNS

当时的危险命令拦截覆盖了类似:

r'\bpkill\s+-9\b'

也就是强杀:

pkill -9 ...

但没有覆盖:

pkill -f "cli.py --gateway"

-f 的危险性在于:它按完整命令行匹配。

如果匹配对象是:

hermes
gateway
cli.py --gateway

那就很可能是在杀 Agent 自己的控制平面。

所以危险不只来自 -9

危险来自:

kill / pkill / killall 的目标是不是 Hermes/Gateway 本身。

为什么这是 Gateway 场景里的高危命令?

Gateway 是 Agent 和用户之间的通道。

如果 Agent 在 Gateway 内运行,又执行命令杀 Gateway,就会出现悖论:

Agent 通过 Gateway 接收指令
→ Agent 判断 Gateway 状态
→ Agent 杀掉 Gateway
→ Agent 失去接收/回复通道

这类问题和普通进程管理不同。

普通 shell 里用户自己敲:

pkill -f "cli.py --gateway"

至少用户知道自己在停服务。

但 Agent 自动执行这条命令时,应该进入审批流,给用户一次确认机会。


正确的安全边界:杀控制平面必须审批

issue 的预期行为很明确:

pkill -f "cli.py --gateway" should be caught by DANGEROUS_PATTERNS and trigger approval flow.

也就是说,不一定完全禁止,但至少不能静默执行。

更合理的拦截规则类似:

(r'\b(pkill|killall)\b.*\b(hermes|gateway|cli\.py)\b',
 "kill hermes/gateway process (self-termination)")

这个 pattern 的重点是组合判断:

  • 命令是 pkillkillall
  • 目标包含 hermesgatewaycli.py 等控制平面关键词。

这样不会把所有 pkill 都一刀切,但会拦住高风险自终止。


后续修复线索:PR #9895 扩大了审批拦截范围

issue 评论里提到,该问题已经修复:

pkill -f "cli.py --gateway"

会被已有的 pkill.*hermes/gateway dangerous command pattern 捕获。

评论还提到 PR #9895 扩展了拦截范围,包括:

  • hermes gateway stop/restart
  • hermes update
  • systemctl restart

这些都属于“可能影响当前 Agent 运行环境”的操作。

这很合理。

因为真正需要保护的不是某一个命令字符串,而是一类动作:

让 Agent 所在服务停止、重启、升级或失联。

为什么“检查端口”会误判 Gateway 状态?

这个 issue 里还有一个隐藏教训:不要用不匹配的健康检查判断服务是否运行。

Agent 之所以动手杀进程,是因为它检查了:

port 8000/8080

发现没有监听,就认为 Gateway 没跑。

但 Telegram polling bot 不一定需要在本机监听 HTTP 端口。

所以正确排查应该看:

systemctl status hermes-gateway
journalctl -u hermes-gateway -n 100 --no-pager
ps aux | grep hermes

而不是简单假设:

没监听 8000/8080 = gateway 不运行

错误诊断 + 高权限清理命令,是危险组合。


Windows 评论:execute_code 绕过 DANGEROUS_PATTERNS 的另一个风险

issue 后续评论还提到 Windows native 场景:Agent 可能通过 execute_code + schtasks /end 强制重启宿主进程。

重点不是 Windows 本身,而是:

如果危险命令只在 terminal tool 层拦截,而 execute_code 里的 subprocess 绕过拦截,那仍然会自终止。

这说明安全边界不能只看“用户输入的 shell 命令”。

还要考虑:

  • terminal tool;
  • code execution tool;
  • Python subprocess;
  • scheduled task;
  • service manager;
  • systemctl / launchctl / schtasks。

只要能停止 Gateway,就应该进入更严格的审批或防护策略。


排查建议:先问“我是不是在杀自己?”

如果 Agent 或自动化脚本准备执行这些命令,先停一下:

pkill -f "hermes"
pkill -f "gateway"
pkill -f "cli.py --gateway"
killall hermes
systemctl restart hermes-gateway
hermes gateway restart

这些不是不能执行。

但应该满足至少一个条件:

  • 用户明确要求重启/停止 Gateway;
  • 有审批流确认;
  • 当前会话不依赖这个 Gateway;
  • 有 supervisor 自动拉起,并且用户知道会丢失 inflight session;
  • 命令目标经过精确确认,不是模糊 pkill -f

否则,Agent 很可能一边“修复”,一边把自己断线。


更安全的替代做法

1. 只读检查优先

先运行:

systemctl status hermes-gateway
journalctl -u hermes-gateway -n 100 --no-pager

不要先 kill。

2. 用服务管理器,不用 pkill

如果确实要重启:

systemctl restart hermes-gateway

但这也应该触发审批,因为它会中断服务。

3. 避免模糊匹配

少用:

pkill -f something

因为 -f 会匹配完整命令行,误伤概率高。

4. Gateway 内部不要随意管理 Gateway 本身

如果 Agent 正通过 Gateway 和用户通信,停止 Gateway 等于切断自己的控制通道。

这种操作应该更像“维护模式”,而不是普通排障动作。


对 DeepAI API 中转站用户的边界说明

如果 Hermes 后端使用 DeepAI API 中转站,完整链路可能是:

Telegram / Discord / Mattermost → Hermes Gateway → Agent → DeepAI / OpenAI-compatible API

#3397 出错在最前面的 Gateway 控制平面。

也就是说:

  • 消息通道被 Agent 自己杀掉;
  • 请求不会继续到 Agent;
  • 更不会到 DeepAI;
  • 换 Base URL、换模型、换 API Key 都解决不了 Gateway 被 pkill 的问题。

DeepAI 可以作为稳定的 OpenAI-compatible API 后端,例如:

https://api.deepai.wang/v1

但它不能防止本地 Agent 执行 pkill -f "cli.py --gateway"

要先保证控制平面活着,再谈模型调用质量。


FAQ

为什么 pkill -fpkill -9 更值得拦?

-9 是强杀信号,危险很明显;-f 按完整命令行匹配,可能悄悄命中 Gateway 自己,同样危险。

Agent 为什么会误判 gateway 没运行?

它检查了 HTTP 端口 8000/8080,但 Telegram polling gateway 不一定监听这些端口。

这个问题修复了吗?

issue 评论称已修复,pkill -f "cli.py --gateway" 会被 pkill.*hermes/gateway dangerous command pattern 捕获,PR #9895 还扩大了相关 blocklist。

systemctl restart 也要审批吗?

在 Gateway Agent 场景下应该要。它会中断当前消息通道,可能丢失进行中的 session。

DeepAI 能解决这个问题吗?

不能。这是本地 Gateway / terminal safety / approval flow 问题,不是模型 API 问题。


总结

#3397 的核心教训是:

Agent 不能静默执行会杀死自己控制平面的命令。

尤其是:

pkill -f "cli.py --gateway"

这种看似普通的清理命令,在 Gateway 内部就是自终止。

安全拦截不应该只盯着 pkill -9,而应该识别“kill 命令 + Hermes/Gateway 目标”的组合,并把它交给用户审批。

Related Post

Hermes Agent 接 DeepAI API 中转站后联网工具不稳定?从已解决 issue 看排查方法Hermes Agent 接 DeepAI API 中转站后联网工具不稳定?从已解决 issue 看排查方法

面向 DeepAI API 中转站用户的 Hermes Agent 排查教程:从已关闭 GitHub issue 看 web_tools 批量网页提取为什么会因单个任务失败丢掉整批结果,并区分模型、API 中转站和 Agent 工具层问题。

少了一个 api_mode,模型目录就串台:Hermes 自定义 Provider 为什么把 Anthropic 当 OpenAI 校验少了一个 api_mode,模型目录就串台:Hermes 自定义 Provider 为什么把 Anthropic 当 OpenAI 校验

Hermes 自定义 provider 明明配置了 api_mode: anthropic_messages,/model 校验却丢掉 api_mode,导致按 OpenAI catalog 探测并提示 gpt-5-pro 等相似模型。本文复盘 #9146:为什么协议模式必须贯穿 validate_requested_model、probe_api_models 与 fetch_api_models。

/reload-mcp 一按就卡死:Hermes CLI 为什么会在确认框里等不到回车?/reload-mcp 一按就卡死:Hermes CLI 为什么会在确认框里等不到回车?

Hermes CLI 执行 /reload-mcp 后确认框显示出来,却无法输入 1/2/3,SSH 会话像被冻住。本文客观复盘 #23853:prompt_toolkit raw mode、daemon thread 中的 input() fallback、 / 行结束符错位、TUI slash worker pipe 死锁,以及 prompt_toolkit-native modal 的修复方向。