如何通过 signal-cli 在 Signal 上部署 Hermes Agent
通过 signal-cli 守护进程在 Signal 上部署 Hermes Agent:关联设备、设置 SIGNAL_HTTP_URL、锁定白名单,搭建私密端对端加密 AI 机器人。

为什么要在 Signal 上运行 Hermes Agent
如果你的威胁模型将元数据保护置于首位,Signal 就是你本已信赖的通讯工具。端对端加密默认开启,服务器几乎不存储任何数据(仅保存电话号码和最后连接时间戳),协议本身也是开源的。将 AI 智能体部署在同一平台,可以让每一条提示词、每一条回复以及你传递的每一个文件都处于同一层加密保护之下。
Hermes Agent 通过 signal-cli 原生支持 Signal。signal-cli 是一个非官方但维护良好的守护进程,代替你与 Signal 协议通信。Hermes 网关通过 HTTP 与 signal-cli 交互,发送操作使用 JSON-RPC,接收消息使用 Server-Sent Events,因此整套运行环境可以部署在一台 $5 VPS、你的笔记本电脑,甚至 NAT 后面的树莓派上,仍能实时收发消息。
本指南涵盖完整的配置流程:安装 signal-cli、将其作为辅助设备关联到你的 Signal 账户、启动 HTTP 守护进程、接入 Hermes 运行时,以及初次安装时常见的坑。如果你已经在更开放的平台上部署过 Hermes,Slack 配置指南和 Telegram 部署指南覆盖了相同的技术栈,值得一并参考。
开始前的准备
一次干净的 Signal 部署需要在宿主机上满足以下五个条件:
- 已运行的 Hermes Agent 实例。如果你尚未安装,Hermes Agent Docker 指南是最简洁的起点。
- 模型服务商密钥。Anthropic、OpenAI、OpenRouter 以及任何兼容 OpenAI 的端点均可使用。运行时使用此密钥实际响应消息。
- 已在主设备(手机)上激活的 Signal 账户。
signal-cli以辅助设备身份关联,与 Signal Desktop 的方式完全相同,不会注册新账户。 - Java 运行时环境 21 或更新版本。当前版本的
signal-clijar 无法在 JRE 17 上启动。如果你偏好单一可执行文件,GraalVM 原生二进制版本可跳过此要求。 - 首次安装约需 20 分钟。后续重新部署不到一分钟。
你使用的电话号码不必是日常手机号。许多自托管用户会专门申请一个备用号码(便宜的 eSIM、Twilio 号码,或可接收短信的 Google Voice 号码),以便让机器人账户在运营上保持独立。
第一步 - 在宿主机上安装 signal-cli
在 Debian 或 Ubuntu 上,安装 Java 并下载最新版 signal-cli:
sudo apt update
sudo apt install -y curl openjdk-21-jre
VERSION=$(curl -s https://api.github.com/repos/AsamK/signal-cli/releases/latest | jq -r .tag_name | sed 's/^v//')
curl -L -o /tmp/signal-cli.tar.gz \
"https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}-Linux.tar.gz"
sudo tar -xf /tmp/signal-cli.tar.gz -C /opt
sudo ln -sf "/opt/signal-cli-${VERSION}/bin/signal-cli" /usr/local/bin/signal-cli
signal-cli --version
如果你希望使用无需 JRE 依赖的单一静态二进制文件,可从项目发布页下载 GraalVM 原生构建版本,直接替换使用,彻底避免 Java 版本升级带来的麻烦。
第二步 - 将 signal-cli 关联到你的 Signal 账户
signal-cli 以关联设备的身份加入你的账户,方式与 Signal Desktop 完全相同。生成一个配置 URL,让守护进程在终端打印二维码:
signal-cli link -n "hermes-agent"
该命令会在终端输出一个 sgnl://linkdevice?... URL 和一个二维码。在你的手机上打开 Signal,进入 设置 -> 已关联的设备 -> 关联新设备,然后扫描二维码。几秒钟后,终端会输出类似以下内容:
Associated with: +12025550123
这个 E.164 格式的号码就是后续配置中 SIGNAL_ACCOUNT 的值。已关联身份的本地状态保存在 ~/.local/share/signal-cli/ 目录下。在销毁宿主机之前,请务必备份该目录——关联设备的密钥仅存储在此处,重新关联会使待处理的消息历史失效。
第三步 - 启动 signal-cli HTTP 守护进程
Hermes 网关通过 HTTP 与 signal-cli 通信,因此守护进程需要以 HTTP 模式运行,并绑定到仅本地可访问的端口:
signal-cli -a +12025550123 daemon --http 127.0.0.1:8080
--http 标志会暴露一个 JSON-RPC 端点用于发送消息,以及一个 Server-Sent Events 流用于接收消息。务必将其绑定到 127.0.0.1 而非其他地址;守护进程本身不做任何身份验证,任何能访问该端口的进程都可以以你的身份发送消息。如果网关在同一宿主机上的 Docker 中运行,可以使用 host.docker.internal:8080 或共享 Docker 网络,而无需将端口暴露给局域网。
对于长期运行的部署,建议添加一个 systemd 服务单元,以便守护进程在重启后自动恢复。signal-cli wiki 提供了现成的单元模板,你只需填写账户号码和绑定地址即可。

第四步 - 配置 Hermes 运行时
打开 ~/.hermes/.env(或你的容器所读取的 .env 文件),添加以下内容:
SIGNAL_HTTP_URL=http://127.0.0.1:8080
SIGNAL_ACCOUNT=+12025550123
SIGNAL_ALLOWED_USERS=+34611222333,+12025557788
SIGNAL_GROUP_ALLOWED_USERS=group.abc123==
SIGNAL_HOME_CHANNEL=+34611222333
各配置项说明:
SIGNAL_HTTP_URL- 第三步中本地守护进程的端点。始终使用http://,始终指向回环地址或私有网络。SIGNAL_ACCOUNT- 已关联 Signal 身份的 E.164 号码。必须与signal-cli link报告的号码完全一致。SIGNAL_ALLOWED_USERS- 允许与机器人通话的 E.164 号码或 Signal UUID,多个值用逗号分隔。若未设置此项(且未配置私信配对),网关默认拒绝所有传入消息,这是安全的默认行为。这是整个技术栈中最重要的单一安全控制手段。SIGNAL_GROUP_ALLOWED_USERS(可选)- 允许机器人响应的群组 ID,多个值用逗号分隔。群组 ID 可通过signal-cli listGroups -d获取。留空则禁用群组支持。SIGNAL_HOME_CHANNEL(可选)- 计划任务、定时任务和技能触发通知的默认投递目标。若未设置,主动输出将发送给第一个允许的用户。
保存后执行 chmod 600 ~/.hermes/.env。已关联的 Signal 身份与模型服务商密钥的组合,使任何能读取该文件的人都可以冒充机器人并消耗你的额度——请像对待 SSH 密钥一样保管此文件。
第五步 - 启动网关并发送第一条消息
重启 Hermes 网关以加载新的环境配置:
hermes gateway restart
跟踪日志,依次等待以下两行输出:
signal: connecting to http://127.0.0.1:8080
signal: subscribed to receive stream for +12025550123
从已授权的手机上,打开 Signal 并向机器人号码发送私信。Hermes 会在同一对话线程中回复,持久化记忆和技能上下文完整保留——记忆与技能详解介绍了底层的工作原理。最大 100 MB 的附件与普通消息使用相同的 Signal 上传 API,因此截图、语音备忘录和 PDF 均可直接传输,无需额外配置。

常见故障模式
以下五个错误几乎涵盖了所有"Signal 配置失败"的支持案例:
忘记关联设备。 对未关联账户运行 signal-cli daemon 不会报错——守护进程会启动,但静默拒绝所有消息。如果日志中没有任何事件和发送尝试,请运行 signal-cli listAccounts 确认你的号码已出现在列表中。
JRE 版本错误。 当前 signal-cli 版本需要 JRE 21。在仍固定使用 JRE 17 或 11 的长期服务器上,调用 --http 时 jar 会因类版本不匹配而立即失败。请升级 Java 或改用 GraalVM 原生二进制版本。
SIGNAL_ALLOWED_USERS 为空。 默认拒绝所有人。这是有意为之——否则一旦机器人账户的电话号码泄露,世界上任何人都可以发送消息并消耗你的模型额度。初次测试时忘记添加自己号码导致机器人"看起来没反应",是最常见的误报情况。
守护进程绑定到 0.0.0.0。 HTTP 守护进程不做身份验证。将其绑定到公网接口意味着任何能访问该端口的人都可以以你的身份发送 Signal 消息。始终绑定到 127.0.0.1 或私有 Docker 网络。
关联设备状态过期。 重新运行 signal-cli link 会覆盖本地状态目录。新的关联没有问题,但 Hermes 此时指向的身份与 env 文件中声明的不一致。重新关联时,要么保留旧的 SIGNAL_ACCOUNT 值,要么将 env 更新为关联命令输出的新号码。
如果问题看起来与 Signal 有关,但症状更像通用问题——缺少回复、记忆漂移、服务商报错——Telegram 故障排除指南对底层网关和服务商问题有更深入的介绍,大多数问题与具体平台无关。
Signal 与 Telegram 和 Slack 的对比
| 关注点 | Signal | Telegram | Slack |
|---|---|---|---|
| 配置时间 | 20 分钟(关联 + 守护进程) | 5 分钟(BotFather 令牌) | 15 分钟(清单 + 2 个令牌) |
| 加密方式 | 默认端对端加密 | 可选秘密聊天 | 仅服务器端加密 |
| 元数据存储 | 几乎不存储 | 服务器端历史记录 | 工作区全范围保留 |
| 账户模型 | 关联电话号码 | 机器人账户,无需号码 | 工作区内的机器人用户 |
| 白名单字段 | SIGNAL_ALLOWED_USERS(E.164) |
TELEGRAM_ALLOWED_USERS(数字 ID) |
SLACK_ALLOWED_USERS(数字 ID) |
| 最适合 | 注重隐私的个人和小团队 | 个人使用、移动端优先、语音模式 | 团队工作流和频道场景 |
这三个平台并不互斥。同一个 Hermes 运行时可以同时投递到所有平台,共享单一记忆存储。创始人在 Signal 上运行个人智能体、同时在 Slack 上运行面向团队的智能体,从同一实例启动,这是很常见的使用模式。
跳过 Signal 配置繁琐步骤
上述步骤可行,但你仍需自行负责宿主机的维护:保持 signal-cli 版本更新、备份关联设备状态、轮换 JRE、监控守护进程重启。对于个人部署来说无妨。但如果你希望在几分钟内上线并从此不再操心,Hermify 提供托管 Hermes 运行时,Signal 桥接开箱即可关联,SIGNAL_* 配置静态加密存储,signal-cli 守护进程在你无需 SSH 登录的持久服务器上稳定运行。
你只需提供 Signal 号码和模型服务商密钥,平台处理一切底层事务。如果你想对比自己掌控的部分与托管服务接管的部分,自托管与托管服务对比从维护成本和费用角度做了详细拆解。如果费用是主要顾虑,低价 VPS 指南详细介绍了 $5/月自托管的实际情况。准备好跳过繁琐配置时,立即开始使用 Hermify。