Gatewayアーキテクチャ

最終更新: 2026-01-22

概要

  • 単一の常駐Gatewayがすべてのメッセージングサーフェス(Baileys経由のWhatsApp、grammY経由のTelegram、Slack、Discord、Signal、iMessage、WebChat)を管理します。
  • コントロールプレーンクライアント(macOSアプリ、CLI、Web UI、自動化)は、設定されたバインドホスト(デフォルト 127.0.0.1:18789)上のWebSocketでGatewayに接続します。
  • ノード(macOS/iOS/Android/ヘッドレス)もWebSocketで接続しますが、role: node を宣言し、明示的なcaps/commandsを持ちます。
  • ホストごとにGatewayは1つだけ。WhatsAppセッションを開くのはGatewayだけです。
  • CanvasホストはGateway HTTPサーバーの以下のパスで提供されます:
    • /__openclaw__/canvas/(エージェント編集可能なHTML/CSS/JS)
    • /__openclaw__/a2ui/(A2UIホスト) Gatewayと同じポート(デフォルト 18789)を使用します。

コンポーネントとフロー

Gateway(デーモン)

  • プロバイダー接続を維持します。
  • 型付きWS API(リクエスト、レスポンス、サーバープッシュイベント)を公開します。
  • 受信フレームをJSON Schemaに対して検証します。
  • agentchatpresencehealthheartbeatcronなどのイベントを発行します。

クライアント(macアプリ / CLI / Web管理画面)

  • クライアントごとに1つのWS接続。
  • リクエスト(healthstatussendagentsystem-presence)を送信。
  • イベント(tickagentpresenceshutdown)を購読。

ノード(macOS / iOS / Android / ヘッドレス)

  • 同じWSサーバーrole: node で接続。
  • connect でデバイスIDを提供。ペアリングはデバイスベース(role node)で、承認はデバイスペアリングストアに保持されます。
  • canvas.*camera.*screen.recordlocation.get などのコマンドを公開。

プロトコルの詳細:

WebChat

  • Gateway WS APIを使用してチャット履歴と送信を行う静的UI。
  • リモート構成では、他のクライアントと同じSSH/Tailscaleトンネルを通じて接続します。

接続ライフサイクル(単一クライアント)

sequenceDiagram
    participant Client
    participant Gateway

    Client->>Gateway: req:connect
    Gateway-->>Client: res (ok)
    Note right of Gateway: or res error + close
    Note left of Client: payload=hello-ok<br>snapshot: presence + health

    Gateway-->>Client: event:presence
    Gateway-->>Client: event:tick

    Client->>Gateway: req:agent
    Gateway-->>Client: res:agent<br>ack {runId, status:"accepted"}
    Gateway-->>Client: event:agent<br>(streaming)
    Gateway-->>Client: res:agent<br>final {runId, status, summary}

ワイヤプロトコル(概要)

  • トランスポート: WebSocket、JSONペイロードのテキストフレーム。
  • 最初のフレームは必ず connect でなければなりません。
  • ハンドシェイク後:
    • リクエスト: {type:"req", id, method, params}{type:"res", id, ok, payload|error}
    • イベント: {type:"event", event, payload, seq?, stateVersion?}
  • OPENCLAW_GATEWAY_TOKEN(または --token)が設定されている場合、connect.params.auth.token が一致しないとソケットが閉じられます。
  • 副作用のあるメソッド(sendagent)には安全にリトライするための冪等性キーが必要です。サーバーは短命の重複排除キャッシュを保持しています。
  • ノードは connectrole: "node" に加えてcaps/commands/permissionsを含める必要があります。

ペアリングとローカル信頼

  • すべてのWSクライアント(オペレーター+ノード)はconnect時にデバイスIDを含めます。
  • 新しいデバイスIDはペアリング承認が必要です。Gatewayは以降の接続用にデバイストークンを発行します。
  • ローカル接続(ループバックまたはGatewayホスト自身のtailnetアドレス)は、同一ホストのUXを円滑にするため自動承認できます。
  • すべての接続は connect.challenge ノンスに署名する必要があります。
  • 署名ペイロード v3platform + deviceFamily もバインドします。Gatewayは再接続時にペアリング済みメタデータを固定し、メタデータ変更時には再ペアリングを要求します。
  • 非ローカル接続では明示的な承認が引き続き必要です。
  • Gateway認証(gateway.auth.*)はローカル・リモートを問わずすべての接続に適用されます。

詳細: Gatewayプロトコルペアリングセキュリティ

プロトコルの型定義とコード生成

  • TypeBoxスキーマがプロトコルを定義。
  • JSON Schemaがそれらのスキーマから生成。
  • SwiftモデルがJSON Schemaから生成。

リモートアクセス

  • 推奨: TailscaleまたはVPN。

  • 代替: SSHトンネル

    ssh -N -L 18789:127.0.0.1:18789 user@host
  • トンネル経由でも同じハンドシェイク+認証トークンが適用されます。

  • リモート構成ではWSのTLS+オプションのピンニングを有効にできます。

運用のスナップショット

  • 起動: openclaw gateway(フォアグラウンド、標準出力にログ)。
  • ヘルスチェック: WS経由のhealthhello-okにも含まれる)。
  • 監視: 自動再起動にはlaunchd/systemdを使用。

不変条件

  • 1つのGatewayが1ホストにつき1つのBaileysセッションを制御。
  • ハンドシェイクは必須。非JSONまたは非connectの最初のフレームは即座に切断。
  • イベントはリプレイされません。クライアントはギャップ発生時にリフレッシュが必要。