跳到主要内容

Signal 配置

Hermes 通过在 HTTP 模式下运行的 signal-cli 守护进程连接到 Signal。适配器通过 SSE(服务器推送事件)实时流式接收消息,并通过 JSON-RPC 发送响应。

Signal 是隐私保护最强的主流即时通讯工具——默认端对端加密、开源协议、最少的元数据收集。这使其非常适合对安全敏感的 Agent 工作流。

无需新 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/
警告

signal-cli 在 apt 或 snap 仓库中。上面的 Linux 安装直接从 GitHub releases 下载。


步骤 1:关联你的 Signal 账户

Signal-cli 作为关联设备工作——类似 WhatsApp Web,但针对 Signal。你的手机保持为主设备。

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

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

# 将 +1234567890 替换为你的 Signal 手机号(E.164 格式)
signal-cli --account +1234567890 daemon --http 127.0.0.1:8080
提示

让它在后台运行。你可以使用 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=+1234567890

# 安全(推荐)
SIGNAL_ALLOWED_USERS=+1234567890,+0987654321 # 逗号分隔的 E.164 号码或 UUID

# 可选
SIGNAL_GROUP_ALLOWED_USERS=groupId1,groupId2 # 启用群组(省略则禁用,* 表示所有)
SIGNAL_HOME_CHANNEL=+1234567890 # 定时任务的默认发送目标

然后启动网关:

hermes gateway # 前台运行
hermes gateway install # 安装为用户服务
sudo hermes gateway install --system # 仅 Linux:启动时运行的系统服务

访问控制

私信访问

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

  1. 设置了 SIGNAL_ALLOWED_USERS → 只有这些用户可以发消息
  2. 未设置允许列表 → 未知用户收到私信配对码(通过 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 将 PNG、JPEG、GIF、WebP 作为原生 Signal 附件发送
  • 语音——send_voice 发送音频文件(OGG、MP3、WAV、M4A、AAC)作为附件
  • 视频——send_video 发送 MP4 视频文件
  • 文档——send_document 发送任何文件类型(PDF、ZIP 等)

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

附件大小限制:100 MB(双向)。

注意

Signal 服务器会限制附件上传频率,适配器使用调度器批量发送多张图片,将图片分成每组 32 张并控制上传速度以匹配 Signal 服务器策略。

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

Signal 消息使用原生格式化而非字面 Markdown 字符渲染。适配器将 Markdown(**粗体***斜体*`代码`~~删除线~~||剧透||、标题)转换为 Signal bodyRanges,使文本在接收方客户端显示为真正的样式,而不是可见的 ** / ` 字符。

引用回复。 当 Hermes 回复特定消息时,它现在会发布一个引用原始消息的原生回复——与 Signal 用户使用"回复"功能时看到的 UI 效果相同。这对于响应入站消息生成的回复是自动的。

表情反应。 Agent 可以通过标准反应 API 对消息进行表情反应;反应在 Signal 中以被引用消息上的表情反应形式显示,而不是额外的文本。

这些功能无需额外配置——在近期 signal-cli 版本中默认开启。如果你的 signal-cli 版本过旧,Hermes 会回退到纯文本发送并记录一次性警告。

输入指示器

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

手机号脱敏

所有手机号在日志中自动脱敏:

  • +15551234567+155****4567
  • 这适用于 Hermes 网关日志和全局脱敏系统

给自己发消息(单号码设置)

如果你以关联辅助设备的方式在自己的手机号上运行 signal-cli(而不是独立的机器人号码),你可以通过 Signal 的"给自己发消息"功能与 Hermes 互动。

只需从手机向自己发送消息——signal-cli 会接收并由 Hermes 在同一对话中响应。

工作原理:

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

无需额外配置。 只要 SIGNAL_ACCOUNT 与你的手机号匹配,这就会自动工作。

健康监控

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

  • 连接断开(使用指数退避:2s → 60s)
  • 120 秒内未检测到任何活动(ping signal-cli 进行验证)

故障排除

问题解决方案
设置期间"无法连接到 signal-cli"确保 signal-cli 守护进程正在运行:signal-cli --account +YOUR_NUMBER daemon --http 127.0.0.1:8080
未收到消息检查 SIGNAL_ALLOWED_USERS 是否包含 E.164 格式(带 + 前缀)的发送者号码
"PATH 中找不到 signal-cli"安装 signal-cli 并确保它在你的 PATH 中,或使用 Docker
连接持续断开检查 signal-cli 日志中的错误。确保安装了 Java 17+。
忽略群组消息使用特定群组 ID 配置 SIGNAL_GROUP_ALLOWED_USERS,或使用 * 允许所有群组。
机器人不响应任何人配置 SIGNAL_ALLOWED_USERS,使用私信配对,或通过网关策略明确允许所有用户(如果你需要更广泛的访问)。
重复消息确保只有一个 signal-cli 实例在监听你的手机号

安全

注意

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

  • 手机号在所有日志输出中都经过脱敏
  • 使用私信配对或明确的允许列表来安全地引入新用户
  • 除非你特别需要群组支持,否则禁用群组,或只将你信任的群组加入白名单
  • 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定时任务的默认发送目标