跳到內容

OpenClaw Gateway 協議指南:WebSocket 連線實作

搞過分散式系統的人都知道,要讓一堆不同平台的客戶端(像是 CLI、網頁 UI、手機 App)跟後端節點乖乖聽話,通訊協定設計起來真的很頭大。如果你也曾經為了同步狀態或處理權限搞到心力交瘁,OpenClaw 的 Gateway WS 協定應該會讓你覺得親切許多。

這套協定是 OpenClaw 的核心,它把控制平面(Control Plane)跟節點傳輸合而為一。不管是你的 macOS App 還是跑在 Android 上的節點,通通都透過 WebSocket 連線,並在握手階段就直接表明自己的身份(Role)跟權限(Scope)。

  • 使用 WebSocket,傳輸內容為 JSON 格式的 text frames。
  • 第一個發出的 frame 必須是 connect 請求。

Gateway → Client (連線前的挑戰碼挑戰):

{
"type": "event",
"event": "connect.challenge",
"payload": { "nonce": "…", "ts": 1737264000000 }
}

Client → Gateway:

{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"client": {
"id": "cli",
"version": "1.2.3",
"platform": "macos",
"mode": "operator"
},
"role": "operator",
"scopes": ["operator.read", "operator.write"],
"caps": [],
"commands": [],
"permissions": {},
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "openclaw-cli/1.2.3",
"device": {
"id": "device_fingerprint",
"publicKey": "…",
"signature": "…",
"signedAt": 1737264000000,
"nonce": "…"
}
}
}

Gateway → Client:

{
"type": "res",
"id": "…",
"ok": true,
"payload": { "type": "hello-ok", "protocol": 3, "policy": { "tickIntervalMs": 15000 } }
}

當裝置 token 核發後,hello-ok 也會包含:

{
"auth": {
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.read", "operator.write"]
}
}
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"client": {
"id": "ios-node",
"version": "1.2.3",
"platform": "ios",
"mode": "node"
},
"role": "node",
"scopes": [],
"caps": ["camera", "canvas", "screen", "location", "voice"],
"commands": ["camera.snap", "canvas.navigate", "screen.record", "location.get"],
"permissions": { "camera.capture": true, "screen.record": false },
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "openclaw-ios/1.2.3",
"device": {
"id": "device_fingerprint",
"publicKey": "…",
"signature": "…",
"signedAt": 1737264000000,
"nonce": "…"
}
}
}
  • Request: {type:"req", id, method, params}
  • Response: {type:"res", id, ok, payload|error}
  • Event: {type:"event", event, payload, seq?, stateVersion?}

具有副作用(Side-effecting)的方法需要提供 idempotency keys(請參考 schema)。

  • operator = 控制平面客戶端(CLI/UI/自動化工具)。
  • node = 能力提供者(負責 camera/screen/canvas/system.run 等硬體或系統操作)。

常見的權限範圍:

  • operator.read
  • operator.write
  • operator.admin
  • operator.approvals
  • operator.pairing

方法的權限範圍只是第一道門檻。某些透過 chat.send 執行的斜線指令(slash commands)會有更嚴格的指令級檢查。例如,涉及持久化修改的 /config set 和 /config unset 就需要 operator.admin 權限。

節點在連線時會宣告它擁有的能力:

  • caps: 高階能力分類。
  • commands: 允許呼叫的指令白名單。
  • permissions: 細粒度的開關(例如 screen.record, camera.capture)。

Gateway 會將這些視為宣告(claims),並在伺服器端強制執行白名單檢查。

  • system-presence 會回傳以裝置身份為 key 的項目。
  • 在線項目包含 deviceId, roles, 和 scopes,這樣 UI 就能為同一個裝置顯示單一橫列,即使該裝置同時以 operator 和 node 身份連線。
  • 節點可以呼叫 skills.bins 來獲取目前的技能執行檔列表,用於自動允許檢查。
  • 操作者可以呼叫 tools.catalog (operator.read) 來獲取 Agent 的執行階段工具目錄。回應內容包含工具分組與來源元數據:
    • source: core 或 plugin
    • pluginId: 當 source="plugin" 時的插件擁有者
    • optional: 插件工具是否為選用
  • 操作者可以呼叫 tools.effective (operator.read) 來獲取當前 session 實際生效的工具清單。
    • 必須提供 sessionKey。
    • Gateway 會從伺服器端的 session 衍生出受信任的執行環境,而不是直接接受呼叫者提供的認證或交付環境。
    • 回應內容僅限於該 session 範圍,反映了當前對話可以使用的工具(包含核心、插件與頻道工具)。
  • 當執行請求需要審核時,Gateway 會廣播 exec.approval.requested。
  • 操作者客戶端透過呼叫 exec.approval.resolve 來處理(需要 operator.approvals 權限)。
  • 對於 host=node 的情況,exec.approval.request 必須包含 systemRunPlan(標準的 argv/cwd/rawCommand/session 元數據)。缺少 systemRunPlan 的請求會被拒絕。
  • agent 請求可以包含 deliver=true 來要求對外交付。
  • bestEffortDeliver=false 會維持嚴格行為:無法解析或僅限內部的交付目標會回傳 INVALID_REQUEST。
  • bestEffortDeliver=true 允許在無法解析外部交付路徑時(例如內部/網頁聊天 session 或模糊的多頻道設定),回退到僅限 session 的執行模式。
  • PROTOCOL_VERSION 定義在 src/gateway/protocol/schema.ts。
  • 客戶端會發送 minProtocol 與 maxProtocol;如果版本不匹配,伺服器會拒絕連線。
  • Schema 與模型是從 TypeBox 定義產生的:
    • pnpm protocol:gen
    • pnpm protocol:gen:swift
    • pnpm protocol:check
  • 如果設定了 OPENCLAW_GATEWAY_TOKEN (或 --token),connect.params.auth.token 必須匹配,否則 Socket 會被關閉。
  • 配對成功後,Gateway 會核發一個針對該連線角色與權限的 device token。它會透過 hello-ok.auth.deviceToken 回傳,客戶端應該儲存它以便下次連線使用。
  • 裝置 token 可以透過 device.token.rotate 和 device.token.revoke 進行輪換或撤銷(需要 operator.pairing 權限)。
  • 認證失敗會包含 error.details.code 以及修復建議:
    • error.details.canRetryWithDeviceToken (布林值)
    • error.details.recommendedNextStep (retry_with_device_token, update_auth_configuration, update_auth_credentials, wait_then_retry, review_auth_configuration)
  • 針對 AUTH_TOKEN_MISMATCH 的客戶端行為:
    • 受信任的客戶端可以使用快取的裝置 token 嘗試一次重試。
    • 如果重試失敗,客戶端應停止自動重連迴圈,並引導操作者進行處理。
  • 節點應該包含一個穩定的裝置識別碼 (device.id),這通常衍生自金鑰對的指紋(fingerprint)。
  • Gateway 會根據每個裝置與角色核發 token。
  • 新的裝置 ID 需要配對審核,除非啟用了本地自動審核。
  • 本地連線包含 loopback 以及 Gateway 主機自身的 tailnet 位址(因此同主機的 tailnet 綁定仍可自動審核)。
  • 所有 WS 客戶端在 connect 時都必須包含 device 身份(包括 operator 與 node)。控制 UI 只有在以下模式可以省略:
    • gateway.controlUi.allowInsecureAuth=true:用於 localhost 的非安全 HTTP 相容性。
    • gateway.controlUi.dangerouslyDisableDeviceAuth=true:這是緊急救援開關,會嚴重降低安全性。
  • 所有連線都必須對伺服器提供的 connect.challenge nonce 進行簽名。

對於仍在使用舊版(挑戰碼前)簽名行為的客戶端,connect 現在會在 error.details.code 下回傳 DEVICE_AUTH_* 代碼,並附帶穩定的 error.details.reason。

常見的遷移失敗原因:

Messagedetails.codedetails.reasonMeaning
device nonce requiredDEVICE_AUTH_NONCE_REQUIREDdevice-nonce-missing客戶端漏傳 device.nonce(或傳送空值)。
device nonce mismatchDEVICE_AUTH_NONCE_MISMATCHdevice-nonce-mismatch客戶端使用了過期或錯誤的 nonce 進行簽名。
device signature invalidDEVICE_AUTH_SIGNATURE_INVALIDdevice-signature簽名內容與 v2 格式不符。
device signature expiredDEVICE_AUTH_SIGNATURE_EXPIREDdevice-signature-stale簽名時間戳記超出允許的誤差範圍。
device identity mismatchDEVICE_AUTH_DEVICE_ID_MISMATCHdevice-id-mismatchdevice.id 與公鑰指紋不符。
device public key invalidDEVICE_AUTH_PUBLIC_KEY_INVALIDdevice-public-key公鑰格式或標準化處理失敗。

遷移目標:

  • 務必等待 connect.challenge。
  • 簽署包含伺服器 nonce 的 v2 payload。
  • 在 connect.params.device.nonce 中傳送相同的 nonce。
  • 建議使用 v3 簽名格式,它除了裝置/客戶端/角色/權限/token/nonce 之外,還綁定了 platform 和 deviceFamily。
  • 為了相容性,目前仍接受舊版 v2 簽名,但已配對裝置的元數據固定(pinning)在重連時仍會控制指令策略。
  • WS 連線支援 TLS。
  • 客戶端可以選擇性地固定 Gateway 的憑證指紋(請參考 gateway.tls 設定,以及 gateway.remote.tlsFingerprint 或 CLI 的 --tls-fingerprint 參數)。

此協定公開了完整的 Gateway API(包含狀態、頻道、模型、聊天、Agent、session、節點、審核等)。具體的介面定義請參考 src/gateway/protocol/schema.ts 中的 TypeBox schemas。

想要實際動手試試看嗎?你可以參考 AI Setup Assistant 來快速完成設定。

OpenClaw

OpenClaw Expert

還是卡住了?

如果這篇文件沒有解決你的情境,直接問 OpenClaw Expert,拿到可執行步驟。