Gateway プロトコル(WebSocket)

Gateway WS プロトコルは、OpenClaw の単一のコントロールプレーン + ノードトランスポートです。すべてのクライアント(CLI、Web UI、macOS アプリ、iOS/Android ノード、ヘッドレスノード)が WebSocket 経由で接続し、ハンドシェイク時にロール + スコープを宣言します。

トランスポート

  • WebSocket、JSON ペイロードを持つテキストフレーム
  • 最初のフレームは connect リクエストでなければなりません

ハンドシェイク(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 } }
}

デバイストークンが発行されると、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 = 機能ホスト(camera/screen/canvas/system.run)

スコープ(operator)

一般的なスコープ:

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

機能/コマンド/権限(node)

ノードは接続時に機能クレームを宣言します:

  • caps:高レベルの機能カテゴリ
  • commands:invoke 用のコマンド許可リスト
  • permissions:細かい切り替え(例:screen.recordcamera.capture

Gateway はこれらをクレームとして扱い、サーバー側の許可リストを強制します。

プレゼンス

  • system-presence はデバイスアイデンティティでキー付けされたエントリを返します。
  • プレゼンスエントリには deviceIdrolesscopes が含まれるため、UI はoperatornode の両方として接続している場合でも、デバイスごとに単一の行を表示できます。

ノードヘルパーメソッド

  • ノードは skills.bins を呼び出して、自動許可チェック用のスキル実行可能ファイルの現在のリストを取得できます。

Exec 承認

  • exec リクエストが承認を必要とする場合、Gateway は exec.approval.requested をブロードキャストします。
  • オペレータークライアントは exec.approval.resolve を呼び出して解決します(operator.approvals スコープが必要)。

バージョニング

  • PROTOCOL_VERSIONsrc/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 が一致する必要があります。そうでない場合、ソケットは閉じられます。
  • ペアリング後、Gateway は接続ロール + スコープにスコープされたデバイストークンを発行します。これは hello-ok.auth.deviceToken で返され、クライアントは将来の接続のために永続化する必要があります。
  • デバイストークンは device.token.rotate および device.token.revoke でローテーション/取り消しできます(operator.pairing スコープが必要)。

デバイスアイデンティティ + ペアリング

  • ノードは、キーペア fingerprint から派生した安定したデバイスアイデンティティ(device.id)を含める必要があります。
  • Gateway はデバイス + ロールごとにトークンを発行します。
  • ローカル自動承認が有効でない限り、新しいデバイス ID にはペアリング承認が必要です。
  • ローカル接続には、loopback および Gateway ホスト自身の tailnet アドレスが含まれます(同一ホスト tailnet バインドでも自動承認できます)。
  • すべての WS クライアントは connect 中に device アイデンティティを含める必要があります(operator + node)。Control UI は、gateway.controlUi.allowInsecureAuth が有効の場合(または緊急用に gateway.controlUi.dangerouslyDisableDeviceAuthのみ省略できます。
  • 非ローカル接続は、サーバー提供の connect.challenge nonce に署名する必要があります。

TLS + ピニング

  • WS 接続で TLS がサポートされています。
  • クライアントは、オプションで Gateway 証明書 fingerprint をピン留めできます(gateway.tls config + gateway.remote.tlsFingerprint または CLI --tls-fingerprint を参照)。

スコープ

このプロトコルは、完全な Gateway API(status、channels、models、chat、agent、sessions、nodes、approvals など)を公開します。正確なサーフェスは src/gateway/protocol/schema.ts の TypeBox スキーマで定義されています。