Signal 设置

Hermes 通过以 HTTP 模式运行的 signal-cli 守护进程连接到 Signal。适配器通过 SSE(Server-Sent Events,服务器发送事件)实时流式传输消息,并通过 JSON-RPC 发送回复。

Signal 是最注重隐私的主流即时通讯工具——默认端到端加密、开源协议、最小元数据收集。这使得它非常适合安全敏感的 agent 工作流。

:::info 无需新的 Python 依赖 Signal 适配器使用 httpx(已经是 Hermes 的核心依赖)进行所有通信。不需要额外的 Python 包。您只需在外部安装 signal-cli。 :::


前提条件

  • signal-cli — 基于 Java 的 Signal 客户端(GitHub
  • Java 17+ 运行时 — signal-cli 需要
  • 安装了 Signal 的电话号码(用于链接为辅助设备)

安装 signal-cli

# macOS
brew install signal-cli
 
# Linux(下载最新版本)
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} \
  https://github.com/AsamK/signal-cli/releases/latest | sed 's/^.*\/v//')
curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}.tar.gz"
sudo tar xf "signal-cli-${VERSION}.tar.gz" -C /opt
sudo ln -sf "/opt/signal-cli-${VERSION}/bin/signal-cli" /usr/local/bin/

:::caution signal-cli 不在 apt 或 snap 仓库中。上述 Linux 安装直接从 GitHub 发布页下载。 :::


第 1 步:链接您的 Signal 账户

Signal-cli 作为已链接设备工作——就像 WhatsApp Web,但用于 Signal。您的手机保持为主设备。

# 生成链接 URI(显示二维码或链接)
signal-cli link -n "HermesAgent"
  1. 在手机上打开 Signal
  2. 进入 设置 → 已链接设备
  3. 点击 链接新设备
  4. 扫描二维码或输入 URI

第 2 步:启动 signal-cli 守护进程

# 将 +123****7890 替换为您的 Signal 电话号码(E.164 格式)
signal-cli --account +123****7890 daemon --http 127.0.0.1:8080

:::tip 保持它在后台运行。您可以使用 systemdtmuxscreen 或将其作为服务运行。 :::

验证它是否正在运行:

curl http://127.0.0.1:8080/api/v1/check
# 应返回:{"versions":{"signal-cli":...}}

第 3 步:配置 Hermes

最简单的方式:

hermes gateway setup

从平台菜单中选择 Signal。向导将:

  1. 检查 signal-cli 是否已安装
  2. 提示输入 HTTP URL(默认:http://127.0.0.1:8080
  3. 测试与守护进程的连接
  4. 询问您的账户电话号码
  5. 配置允许的用户和访问策略

手动配置

添加到 ~/.hermes/.env

# 必需
SIGNAL_HTTP_URL=http://127.0.0.1:8080
SIGNAL_ACCOUNT=+123****7890
 
# 安全(推荐)
SIGNAL_ALLOWED_USERS=+123****7890,+0987654321    # 逗号分隔的 E.164 号码或 UUID
 
# 可选
SIGNAL_GROUP_ALLOWED_USERS=groupId1,groupId2     # 启用群组(省略以禁用,* 表示全部)
SIGNAL_HOME_CHANNEL=+123****7890                  # 定时任务的默认投递目标

然后启动网关:

hermes gateway              # 前台
hermes gateway install      # 安装为用户服务
sudo hermes gateway install --system   # 仅 Linux:开机自启系统服务

访问控制

DM 访问

DM 访问遵循与所有其他 Hermes 平台相同的模式:

  1. 设置了 SIGNAL_ALLOWED_USERS → 只有这些用户可以发消息
  2. 未设置白名单 → 未知用户获得 DM 配对码(通过 hermes pairing approve signal CODE 批准)
  3. 设置了 SIGNAL_ALLOW_ALL_USERS=true → 任何人都可以发消息(谨慎使用)

群组访问

群组访问由环境变量 SIGNAL_GROUP_ALLOWED_USERS 控制:

配置行为
未设置(默认)所有群组消息被忽略。机器人仅回复私信。
设置了群组 ID仅监控列出的群组(例如 groupId1,groupId2)。
设置为 *机器人在其所属的任何群组中回复。

功能

附件

适配器支持双向发送和接收媒体。

传入(用户 → agent):

  • 图片 — PNG、JPEG、GIF、WebP(通过魔数自动检测)
  • 音频 — MP3、OGG、WAV、M4A(如果配置了 Whisper,语音消息会被转录)
  • 文档 — PDF、ZIP 和其他文件类型

传出(agent → 用户):

agent 可以通过回复中的 MEDIA: 标签发送媒体文件。支持以下投递方式:

  • 图片send_multiple_imagessend_image_file 以原生 Signal 附件发送 PNG、JPEG、GIF、WebP
  • 语音send_voice 以附件形式发送音频文件(OGG、MP3、WAV、M4A、AAC)
  • 视频send_video 发送 MP4 视频文件
  • 文档send_document 发送任意文件类型(PDF、ZIP 等)

所有传出媒体通过 Signal 的标准附件 API 发送。与某些平台不同,Signal 在协议层面上不区分语音消息和文件附件。

附件大小限制:100 MB(双向)。 :::warning Signal 服务器会对附件上传进行速率限制,适配器使用调度器进行多图片发送,将图片按 32 个一组分批,并调整上传速率以匹配 Signal 服务器策略。 :::

原生格式化、引用回复和反应

Signal 消息以原生格式化渲染,而非字面 markdown 字符。适配器将 markdown(**bold***italic*`code`~~strike~~||spoiler||、标题)转换为 Signal bodyRanges,使文本在接收方客户端上显示为真实样式,而非可见的 ** / ` 字符。

引用回复。 当 Hermes 回复特定消息时,现在会发布引用原始消息的原生回复——与 Signal 用户自己使用”回复”时看到的 UI 相同。这是对入站消息生成的回复的自动行为。

反应。 agent 可以通过标准反应 API 对消息做出反应;反应在 Signal 中显示为被引用消息上的表情反应,而不是额外的文本。

这些都不需要额外配置——在最近的 signal-cli 构建中默认开启。如果您的 signal-cli 版本过旧,Hermes 会回退到纯文本投递并记录一次性警告。

输入状态指示器

机器人在处理消息时发送输入状态指示器,每 8 秒刷新一次。

电话号码遮蔽

所有电话号码在日志中自动遮蔽:

  • +155****4567+155****4567
  • 这同时适用于 Hermes 网关日志和全局遮蔽系统

给自己发笔记(单号码设置)

如果您将 signal-cli 作为自己电话号码的已链接辅助设备运行(而非独立的机器人号码),您可以通过 Signal 的”给自己发笔记”功能与 Hermes 交互。

只需从您的手机给自己发送一条消息——signal-cli 会捕获它,Hermes 在同一对话中回复。

工作原理:

  • “给自己发笔记”消息作为 syncMessage.sentMessage 信封到达
  • 适配器检测到这些消息是发送给机器人自己的账户的,并将其作为普通入站消息处理
  • 回显保护(发送时间戳跟踪)防止无限循环——机器人自己的回复会被自动过滤

无需额外配置。 只要 SIGNAL_ACCOUNT 匹配您的电话号码,这就能自动工作。

健康监控

适配器监控 SSE 连接,并在以下情况下自动重连:

  • 连接断开(带有指数退避:2 秒 → 60 秒)
  • 120 秒内未检测到活动(ping signal-cli 以验证)

故障排除

问题解决方案
设置时”Cannot reach signal-cli”确保 signal-cli 守护进程正在运行:signal-cli --account +YOUR_NUMBER daemon --http 127.0.0.1:8080
未收到消息检查 SIGNAL_ALLOWED_USERS 是否包含发送者的 E.164 格式号码(带 + 前缀)
“signal-cli not found on PATH”安装 signal-cli 并确保它在您的 PATH 中,或使用 Docker
连接持续断开检查 signal-cli 日志中的错误。确保已安装 Java 17+。
群组消息被忽略使用特定群组 ID 或 * 配置 SIGNAL_GROUP_ALLOWED_USERS 以允许所有群组。
机器人不对任何人回复配置 SIGNAL_ALLOWED_USERS、使用 DM 配对,或通过网关策略显式允许所有用户以获得更广泛的访问权限。
重复消息确保只有一个 signal-cli 实例在监听您的电话号码

安全性

:::warning 始终配置访问控制。 机器人默认具有终端访问权限。没有 SIGNAL_ALLOWED_USERS 或 DM 配对,网关会拒绝所有传入消息作为安全措施。 :::

  • 电话号码会在所有日志输出中被遮蔽
  • 使用 DM 配对或显式白名单安全地引入新用户
  • 除非您特别需要群组支持,否则保持群组禁用,或仅白名单您信任的群组
  • Signal 的端到端加密保护传输中的消息内容
  • ~/.local/share/signal-cli/ 中的 signal-cli 会话数据包含账户凭证——像保护密码一样保护它

环境变量参考

变量必需默认值描述
SIGNAL_HTTP_URLsignal-cli HTTP 端点
SIGNAL_ACCOUNT机器人电话号码(E.164)
SIGNAL_ALLOWED_USERS逗号分隔的电话号码/UUID
SIGNAL_GROUP_ALLOWED_USERS要监控的群组 ID,或 * 表示全部(省略以禁用群组)
SIGNAL_ALLOW_ALL_USERSfalse允许任何用户交互(跳过白名单)
SIGNAL_HOME_CHANNEL定时任务的默认投递目标