Signal(signal-cli)

狀態:外部 CLI 整合。閘道透過 HTTP JSON-RPC + SSE 與 signal-cli 通訊。

先決條件

  • OpenClaw 已安裝在你的伺服器上(以下 Linux 流程在 Ubuntu 24 上測試過)。
  • signal-cli 在閘道執行的主機上可用。
  • 一個可以接收一條驗證簡訊的電話號碼(用於簡訊註冊路徑)。
  • 註冊期間存取 Signal captcha(signalcaptchas.org)的瀏覽器。

快速設定(新手)

  1. 為 Bot 使用獨立的 Signal 號碼(建議)。
  2. 安裝 signal-cli(使用 JVM 版本需要 Java)。
  3. 選擇一個設定路徑:
    • 路徑 A(QR 連結): signal-cli link -n "OpenClaw" 後在 Signal 中掃描。
    • 路徑 B(簡訊註冊): 使用 captcha + 簡訊驗證註冊專用號碼。
  4. 設定 OpenClaw 並重新啟動閘道。
  5. 發送第一條 DM 並核准配對(openclaw pairing approve signal <CODE>)。

最小設定:

{
  channels: {
    signal: {
      enabled: true,
      account: "+15551234567",
      cliPath: "signal-cli",
      dmPolicy: "pairing",
      allowFrom: ["+15557654321"],
    },
  },
}

欄位參考:

欄位說明
accountE.164 格式的 Bot 電話號碼(+15551234567
cliPathsignal-cli 的路徑(在 PATH 上則為 signal-cli
dmPolicyDM 存取政策(建議 pairing
allowFrom允許 DM 的電話號碼或 uuid:<id>

它是什麼

  • 透過 signal-cli 的 Signal 頻道(非內嵌 libsignal)。
  • 確定性路由:回覆始終返回 Signal。
  • DM 共用代理的主要工作階段;群組被隔離(agent:<agentId>:signal:group:<groupId>)。

設定寫入

預設情況下,Signal 允許由 /config set|unset 觸發的設定更新寫入(需要 commands.config: true)。

透過以下方式停用:

{
  channels: { signal: { configWrites: false } },
}

號碼模型(重要)

  • 閘道連接到一個 Signal 裝置signal-cli 帳號)。
  • 如果你在個人 Signal 帳號上執行 Bot,它會忽略你自己的訊息(迴圈保護)。
  • 要實現「我傳訊給 Bot 然後它回覆」,請使用專用的 Bot 號碼

設定路徑 A:連結現有 Signal 帳號(QR)

  1. 安裝 signal-cli(JVM 或原生版本)。
  2. 連結 Bot 帳號:
    • signal-cli link -n "OpenClaw" 然後在 Signal 中掃描 QR。
  3. 設定 Signal 並啟動閘道。

範例:

{
  channels: {
    signal: {
      enabled: true,
      account: "+15551234567",
      cliPath: "signal-cli",
      dmPolicy: "pairing",
      allowFrom: ["+15557654321"],
    },
  },
}

多帳號支援:使用每帳號設定和可選的 name 設定 channels.signal.accounts。共享模式請參閱 gateway/configuration

設定路徑 B:註冊專用 Bot 號碼(簡訊,Linux)

當你需要專用 Bot 號碼而非連結現有 Signal 應用程式帳號時使用。

  1. 取得可接收簡訊的號碼(固定電話可用語音驗證)。
    • 使用專用 Bot 號碼以避免帳號/工作階段衝突。
  2. 在閘道主機上安裝 signal-cli
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/AsamK/signal-cli/releases/latest | sed -e 's/^.*\/v//')
curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}-Linux-native.tar.gz"
sudo tar xf "signal-cli-${VERSION}-Linux-native.tar.gz" -C /opt
sudo ln -sf /opt/signal-cli /usr/local/bin/
signal-cli --version

如果使用 JVM 版本(signal-cli-${VERSION}.tar.gz),請先安裝 JRE 25+。 上游指出隨著 Signal 伺服器 API 變更,舊版本可能會中斷,因此請保持 signal-cli 更新。

  1. 註冊並驗證號碼:
signal-cli -a +<BOT_PHONE_NUMBER> register

如果需要 captcha:

  1. 開啟 https://signalcaptchas.org/registration/generate.html
  2. 完成 captcha,從「Open Signal」複製 signalcaptcha://... 連結目標。
  3. 盡可能從與瀏覽器工作階段相同的外部 IP 執行。
  4. 立即重新執行註冊(captcha 權杖很快過期):
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
  1. 設定 OpenClaw,重新啟動閘道,驗證頻道:
# 如果以使用者 systemd 服務執行閘道:
systemctl --user restart openclaw-gateway

# 然後驗證:
openclaw doctor
openclaw channels status --probe
  1. 配對你的 DM 發送者:
    • 向 Bot 號碼發送任何訊息。
    • 在伺服器上核准代碼:openclaw pairing approve signal <PAIRING_CODE>
    • 將 Bot 號碼儲存為手機聯絡人以避免「未知聯絡人」。

注意: 使用 signal-cli 註冊電話號碼帳號可能會取消該號碼主要 Signal 應用程式工作階段的認證。建議使用專用 Bot 號碼,或如果需要保留現有手機應用程式設定,請使用 QR 連結模式。

上游參考:

  • signal-cli README:https://github.com/AsamK/signal-cli
  • captcha 流程:https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
  • 連結流程:https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

外部常駐程式模式(httpUrl)

如果你想自行管理 signal-cli(JVM 冷啟動慢、容器初始化或共享 CPU),可以單獨執行常駐程式並將 OpenClaw 指向它:

{
  channels: {
    signal: {
      httpUrl: "http://127.0.0.1:8080",
      autoStart: false,
    },
  },
}

這會跳過自動啟動和 OpenClaw 內的啟動等待。對於自動啟動時啟動較慢的情況,設定 channels.signal.startupTimeoutMs

存取控制(DM + 群組)

DM:

  • 預設:channels.signal.dmPolicy = "pairing"
  • 未知發送者會收到配對代碼;在核准前訊息會被忽略(代碼 1 小時後過期)。
  • 透過以下方式核准:
    • openclaw pairing list signal
    • openclaw pairing approve signal <CODE>
  • 配對是 Signal DM 的預設權杖交換。詳情:配對
  • 僅 UUID 的發送者(來自 sourceUuid)以 uuid:<id> 儲存在 channels.signal.allowFrom 中。

群組:

  • channels.signal.groupPolicy = open | allowlist | disabled
  • 設定 allowlist 時,channels.signal.groupAllowFrom 控制誰能在群組中觸發。
  • channels.signal.groups["<group-id>" | "*"] 可以用 requireMentiontoolstoolsBySender 覆寫群組行為。
  • 在多帳號設定中,使用 channels.signal.accounts.<id>.groups 進行每帳號覆寫。
  • 執行階段注意:如果 channels.signal 完全缺失,執行階段會在群組檢查時回退到 groupPolicy="allowlist"(即使設定了 channels.defaults.groupPolicy)。

運作方式(行為)

  • signal-cli 作為常駐程式執行;閘道透過 SSE 讀取事件。
  • 入站訊息被正規化為共享頻道信封。
  • 回覆始終路由回同一號碼或群組。

媒體 + 限制

  • 出站文字按 channels.signal.textChunkLimit(預設 4000)分塊。
  • 選用換行分塊:設定 channels.signal.chunkMode="newline" 在長度分塊前先依空行(段落邊界)分割。
  • 支援附件(從 signal-cli 取得 base64)。
  • 預設媒體上限:channels.signal.mediaMaxMb(預設 8)。
  • 使用 channels.signal.ignoreAttachments 跳過下載媒體。
  • 群組歷史記錄上下文使用 channels.signal.historyLimit(或 channels.signal.accounts.*.historyLimit),回退到 messages.groupChat.historyLimit。設定 0 停用(預設 50)。

輸入中 + 已讀回條

  • 輸入中指示器:OpenClaw 透過 signal-cli sendTyping 發送輸入中信號,並在回覆執行期間重新整理。
  • 已讀回條:當 channels.signal.sendReadReceipts 為 true 時,OpenClaw 為允許的 DM 轉發已讀回條。
  • signal-cli 不公開群組的已讀回條。

反應(message 工具)

  • 使用 message action=react 搭配 channel=signal
  • 目標:發送者的 E.164 或 UUID(使用配對輸出中的 uuid:<id>;裸 UUID 也可以)。
  • messageId 是你要反應的訊息的 Signal 時間戳記。
  • 群組反應需要 targetAuthortargetAuthorUuid

範例:

message action=react channel=signal target=uuid:123e4567-e89b-12d3-a456-426614174000 messageId=1737630212345 emoji=🔥
message action=react channel=signal target=+15551234567 messageId=1737630212345 emoji=🔥 remove=true
message action=react channel=signal target=signal:group:<groupId> targetAuthor=uuid:<sender-uuid> messageId=1737630212345 emoji=✅

設定:

  • channels.signal.actions.reactions:啟用/停用反應動作(預設 true)。
  • channels.signal.reactionLeveloff | ack | minimal | extensive
    • off/ack 停用代理反應(message 工具 react 會報錯)。
    • minimal/extensive 啟用代理反應並設定指引等級。
  • 每帳號覆寫:channels.signal.accounts.<id>.actions.reactionschannels.signal.accounts.<id>.reactionLevel

傳送目標(CLI/cron)

  • DM:signal:+15551234567(或純 E.164)。
  • UUID DM:uuid:<id>(或裸 UUID)。
  • 群組:signal:group:<groupId>
  • 使用者名稱:username:<name>(如果你的 Signal 帳號支援)。

疑難排解

先執行以下步驟:

openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probe

如有需要,確認 DM 配對狀態:

openclaw pairing list signal

常見問題:

  • 常駐程式可達但無回覆:驗證帳號/常駐程式設定(httpUrlaccount)和接收模式。
  • DM 被忽略:發送者正在等待配對核准。
  • 群組訊息被忽略:群組發送者/提及門檻阻止了傳送。
  • 編輯後的設定驗證錯誤:執行 openclaw doctor --fix
  • 診斷中缺少 Signal:確認 channels.signal.enabled: true

額外檢查:

openclaw pairing list signal
pgrep -af signal-cli
grep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20

疑難排解流程:/channels/troubleshooting

安全注意事項

  • signal-cli 將帳號金鑰儲存在本地(通常在 ~/.local/share/signal-cli/data/)。
  • 在伺服器遷移或重建前備份 Signal 帳號狀態。
  • 除非你明確想要更廣泛的 DM 存取,否則保持 channels.signal.dmPolicy: "pairing"
  • 簡訊驗證僅在註冊或復原流程中需要,但失去號碼/帳號的控制可能會使重新註冊變得複雜。

設定參考(Signal)

完整設定:Configuration

提供者選項:

  • channels.signal.enabled:啟用/停用頻道啟動。
  • channels.signal.account:Bot 帳號的 E.164。
  • channels.signal.cliPathsignal-cli 的路徑。
  • channels.signal.httpUrl:完整常駐程式 URL(覆寫 host/port)。
  • channels.signal.httpHostchannels.signal.httpPort:常駐程式繫結(預設 127.0.0.1:8080)。
  • channels.signal.autoStart:自動啟動常駐程式(httpUrl 未設定時預設 true)。
  • channels.signal.startupTimeoutMs:啟動等待逾時(毫秒)(上限 120000)。
  • channels.signal.receiveModeon-start | manual
  • channels.signal.ignoreAttachments:跳過附件下載。
  • channels.signal.ignoreStories:忽略常駐程式的限時動態。
  • channels.signal.sendReadReceipts:轉發已讀回條。
  • channels.signal.dmPolicypairing | allowlist | open | disabled(預設:pairing)。
  • channels.signal.allowFrom:DM 允許清單(E.164 或 uuid:<id>)。open 需要 "*"。Signal 沒有使用者名稱;使用電話/UUID ID。
  • channels.signal.groupPolicyopen | allowlist | disabled(預設:allowlist)。
  • channels.signal.groupAllowFrom:群組發送者允許清單。
  • channels.signal.groups:以 Signal 群組 ID 為鍵的每群組覆寫(或 "*")。支援欄位:requireMentiontoolstoolsBySender
  • channels.signal.accounts.<id>.groups:多帳號設定用的 channels.signal.groups 每帳號版本。
  • channels.signal.historyLimit:作為上下文包含的最大群組訊息數(0 停用)。
  • channels.signal.dmHistoryLimit:以使用者回合計的 DM 歷史限制。每使用者覆寫:channels.signal.dms["<phone_or_uuid>"].historyLimit
  • channels.signal.textChunkLimit:出站分塊大小(字元數)。
  • channels.signal.chunkModelength(預設)或 newline(在長度分塊前先依空行分割)。
  • channels.signal.mediaMaxMb:入站/出站媒體上限(MB)。

相關全域選項:

  • agents.list[].groupChat.mentionPatterns(Signal 不支援原生提及)。
  • messages.groupChat.mentionPatterns(全域後備)。
  • messages.responsePrefix