Skip to main content

Gateway 協議(WebSocket)

Gateway WS 協議是 OpenClaw 的 單一控制平面 + 節點傳輸。所有客戶端(CLI、web UI、macOS 應用、iOS/Android 節點、無頭節點)透過 WebSocket 連接並在握手時聲明其 角色 + 範圍

傳輸

  • WebSocket,具有 JSON 負載的文字框架。
  • 第一個框架 必須connect 請求。

握手(connect)

Gateway → 客戶端(預連接挑戰):
{
  "type": "event",
  "event": "connect.challenge",
  "payload": { "nonce": "…", "ts": 1737264000000 }
}
客戶端 → 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 → 客戶端:
{
  "type": "res",
  "id": "…",
  "ok": true,
  "payload": { "type": "hello-ok", "protocol": 3, "policy": { "tickIntervalMs": 15000 } }
}
當發出設備權杖時,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": "…"
    }
  }
}

框架

  • 請求{type:"req", id, method, params}
  • 回應{type:"res", id, ok, payload|error}
  • 事件{type:"event", event, payload, seq?, stateVersion?}
副作用方法需要 冪等鍵(見綱要)。

角色 + 範圍

角色

  • operator = 控制平面客戶端(CLI/UI/自動化)。
  • node = 能力主機(攝影機/螢幕/畫布/system.run)。

範圍(operator)

常見範圍:
  • operator.read
  • operator.write
  • operator.admin
  • operator.approvals
  • operator.pairing
方法範圍僅是第一道門。透過 chat.send 到達的某些斜線指令在頂部套用更嚴格的指令級檢查。例如,持久 /config set/config unset 寫入需要 operator.admin

能力/指令/權限(node)

節點在連接時聲明能力聲明:
  • caps:高級能力類別。
  • commands:用於 invoke 的指令允許清單。
  • permissions:細粒度切換(例如 screen.recordcamera.capture)。
Gateway 將這些視為 聲明 並強制執行伺服器端允許清單。

存在

  • system-presence 回傳由設備身分索引的項目。
  • 存在項目包括 deviceIdrolesscopes,讓 UI 可顯示每個設備一行,即使它同時連接為 operatornode

節點協助方法

  • 節點可呼叫 skills.bins 以取得目前技能可執行檔清單進行自動允許檢查。

Operator 協助方法

  • Operator 可呼叫 tools.catalogoperator.read)以取得代理的執行時工具目錄。回應包括已分組工具和出處中繼資料:
    • sourcecoreplugin
    • pluginId:當 source="plugin" 時的外掛所有者
    • optional:外掛工具是否可選

執行批准

  • 當執行請求需要批准時,Gateway 廣播 exec.approval.requested
  • Operator 客戶端透過呼叫 exec.approval.resolve 解析(需要 operator.approvals 範圍)。
  • 對於 host=nodeexec.approval.request 必須包括 systemRunPlan(正規 argv/cwd/rawCommand/會話中繼資料)。遺失 systemRunPlan 的請求被拒絕。

版本控制

  • PROTOCOL_VERSION 駐留在 src/gateway/protocol/schema.ts 中。
  • 客戶端發送 minProtocol + maxProtocol;伺服器拒絕不匹配。
  • 綱要 + 模型從 TypeBox 定義產生:
    • pnpm protocol:gen
    • pnpm protocol:gen:swift
    • pnpm protocol:check

驗證

  • 如果設定 OPENCLAW_GATEWAY_TOKEN(或 --token),connect.params.auth.token 必須符合或 socket 關閉。
  • 配對後,Gateway 發出針對連接角色 + 範圍的 設備權杖。它在 hello-ok.auth.deviceToken 中回傳,應由客戶端持久化以供未來連接。
  • 設備權杖可透過 device.token.rotatedevice.token.revoke 輪換/撤銷(需要 operator.pairing 範圍)。
  • 驗證失敗包括 error.details.code 加上復原提示:
    • error.details.canRetryWithDeviceToken(布林值)
    • error.details.recommendedNextStepretry_with_device_tokenupdate_auth_configurationupdate_auth_credentialswait_then_retryreview_auth_configuration
  • 客戶端行為針對 AUTH_TOKEN_MISMATCH
    • 受信任客戶端可嘗試一次有界重試與快取逐設備權杖。
    • 如果該重試失敗,客戶端應停止自動重新連接迴圈並表面 operator 動作指導。

設備身分 + 配對

  • 節點應包括穩定設備身分(device.id)衍生自金鑰對指紋。
  • Gateway 發出各設備 + 角色的權杖。
  • 新設備 ID 需要配對批准,除非啟用本地自動批准。
  • 本地 連接包括環回和 Gateway 主機自身的 tailnet 地址(所以相同主機 tailnet 繫結仍可自動批准)。
  • 所有 WS 客戶端必須在 connect 期間包括 device 身分(operator + node)。 Control UI 只能在這些模式中省略它:
    • gateway.controlUi.allowInsecureAuth=true 用於 localhost 唯一不安全 HTTP 相容性。
    • gateway.controlUi.dangerouslyDisableDeviceAuth=true(破裂玻璃,嚴重安全降級)。
  • 所有連接必須簽署伺服器提供的 connect.challenge nonce。

設備驗證遷移診斷

對於仍使用預挑戰簽署行為的遺留客戶端,connect 現在在 error.details.code 下回傳 DEVICE_AUTH_* 細節代碼與穩定的 error.details.reason 常見遷移失敗:
訊息details.codedetails.reason含義
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 負載。
  • connect.params.device.nonce 中發送相同 nonce。
  • 偏好簽署負載是 v3,它除了設備/客戶端/角色/範圍/權杖/nonce 欄位外還繫結 platformdeviceFamily
  • 遺留 v2 簽署保持相容接受,但配對設備中繼資料釘選仍控制重新連接時的指令政策。

TLS + 釘選

  • TLS 對 WS 連接支援。
  • 客戶端可選用釘選 Gateway 憑證指紋(見 gateway.tls 設定加上 gateway.remote.tlsFingerprint 或 CLI --tls-fingerprint)。

範圍

此協議暴露 完整 Gateway API(狀態、通道、模型、聊天、代理、會話、節點、批准等)。確切表面由 src/gateway/protocol/schema.ts 中的 TypeBox 綱要定義。