Gatewayプロトコル(WebSocket)
Gateway WSプロトコルは、OpenClawの単一のコントロールプレーン + ノード転送です。 すべてのクライアント(CLI、web UI、macOSアプリ、iOS/Androidノード、ヘッドレス ノード)は、WebSocket経由で接続し、ハンドシェイク時に自分のroleとscopeを 宣言します。転送
- WebSocket、JSONペイロードを含むテキストフレーム。
- 最初のフレームは必ず
connectリクエストでなければなりません。
ハンドシェイク(connect)
Gateway → Client(接続前チャレンジ):hello-ok には次も含まれます:
hello-ok.auth には
deviceTokens に追加の制限付きroleエントリが含まれる場合もあります:
scopes: [] のままで、引き渡されたoperatorトークンはブートストラップ
operator許可リスト(operator.approvals, operator.read,
operator.talk.secrets, operator.write)に制限されたままです。
ブートストラップのscopeチェックは引き続きroleプレフィックス付きです:
operatorエントリはoperatorリクエストのみを満たし、non-operator
roleは引き続き自身のroleプレフィックス配下のscopeを必要とします。
Nodeの例
フレーミング
- リクエスト:
{type:"req", id, method, params} - レスポンス:
{type:"res", id, ok, payload|error} - イベント:
{type:"event", event, payload, seq?, stateVersion?}
role + scope
role
operator= コントロールプレーンクライアント(CLI/UI/自動化)。node= 機能ホスト(camera/screen/canvas/system.run)。
scope(operator)
一般的なscope:operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
includeSecrets: true を伴う talk.config には operator.talk.secrets
(または operator.admin)が必要です。
プラグイン登録されたGateway RPCメソッドは独自のoperator scopeを要求する場合がありますが、
予約済みのコアadminプレフィックス(config.*, exec.approvals.*, wizard.*,
update.*)は常に operator.admin に解決されます。
メソッドscopeは最初のゲートにすぎません。chat.send を通じて到達する
一部のスラッシュコマンドには、さらに厳しいコマンドレベルのチェックが適用されます。
たとえば、永続的な /config set と /config unset の書き込みには
operator.admin が必要です。
node.pair.approve には、ベースメソッドscopeに加えて承認時の追加scopeチェックもあります:
- コマンドなしのリクエスト:
operator.pairing - non-exec nodeコマンドを伴うリクエスト:
operator.pairing+operator.write system.run,system.run.prepare,system.whichを含むリクエスト:operator.pairing+operator.admin
caps/commands/permissions(node)
ノードは接続時に機能クレームを宣言します:caps: 高レベルな機能カテゴリ。commands: invoke用のコマンド許可リスト。permissions: 詳細なトグル(例:screen.record,camera.capture)。
プレゼンス
system-presenceはデバイスアイデンティティをキーとしたエントリを返します。- プレゼンスエントリには
deviceId,roles,scopesが含まれるため、UIは 同一デバイスが operator と node の両方として接続していても 1行で表示できます。
よく使われるRPCメソッドファミリー
このページは生成された完全なダンプではありませんが、公開WSサーフェスは 上記のハンドシェイク/認証の例よりも広範です。これらは現在Gatewayが公開している 主なメソッドファミリーです。hello-ok.features.methods は、
src/gateway/server-methods-list.ts と、読み込まれたプラグイン/チャネルの
メソッドエクスポートから構築された保守的な検出リストです。
これを機能検出として扱ってください。src/gateway/server-methods/*.ts に実装された
呼び出し可能なすべてのヘルパーの生成ダンプではありません。
systemとidentity
healthは、キャッシュされた、または新たにプローブされたGatewayヘルススナップショットを返します。statusは/statusスタイルのGatewayサマリーを返します。機密フィールドは admin scopeを持つoperatorクライアントにのみ含まれます。gateway.identity.getは、relayおよびpairingフローで使われるGatewayデバイスIDを返します。system-presenceは、接続中のoperator/nodeデバイスの現在のプレゼンススナップショットを返します。system-eventはsystemイベントを追加し、プレゼンスコンテキストを更新/ブロードキャストできます。last-heartbeatは、最後に永続化されたheartbeatイベントを返します。set-heartbeatsは、Gatewayでのheartbeat処理を切り替えます。
modelとusage
models.listは、ランタイムで許可されたモデルカタログを返します。usage.statusは、プロバイダー使用量ウィンドウ/残りクォータのサマリーを返します。usage.costは、日付範囲の集計済みコスト使用量サマリーを返します。doctor.memory.statusは、アクティブなデフォルトagentワークスペース向けの ベクターメモリ / embedding準備状態を返します。sessions.usageは、セッションごとの使用量サマリーを返します。sessions.usage.timeseriesは、1つのセッションの時系列使用量を返します。sessions.usage.logsは、1つのセッションの使用量ログエントリを返します。
チャネルとログインヘルパー
channels.statusは、組み込み + バンドルされたチャネル/プラグインのステータスサマリーを返します。channels.logoutは、ログアウト対応のチャネルで特定のチャネル/アカウントをログアウトします。web.login.startは、現在のQR対応webチャネルプロバイダー向けのQR/webログインフローを開始します。web.login.waitは、そのQR/webログインフローの完了を待ち、成功時にチャネルを開始します。push.testは、登録済みiOSノードにテストAPNsプッシュを送信します。voicewake.getは、保存されたウェイクワードトリガーを返します。voicewake.setは、ウェイクワードトリガーを更新し、その変更をブロードキャストします。
メッセージングとログ
sendは、chat runner外でのチャネル/アカウント/threadターゲット送信向けの 直接のアウトバウンド配信RPCです。logs.tailは、カーソル/上限および最大バイト制御付きで、 設定されたGatewayファイルログの末尾を返します。
TalkとTTS
talk.configは、有効なTalk設定ペイロードを返します。includeSecretsにはoperator.talk.secrets(またはoperator.admin)が必要です。talk.modeは、WebChat/Control UIクライアント向けの現在のTalkモード状態を設定/ブロードキャストします。talk.speakは、アクティブなTalk speechプロバイダーを通じて音声を合成します。tts.statusは、TTS有効状態、アクティブプロバイダー、フォールバックプロバイダー、 およびプロバイダー設定状態を返します。tts.providersは、表示可能なTTSプロバイダーのインベントリを返します。tts.enableとtts.disableは、TTS設定状態を切り替えます。tts.setProviderは、優先TTSプロバイダーを更新します。tts.convertは、単発のtext-to-speech変換を実行します。
シークレット、設定、更新、およびウィザード
secrets.reloadは、アクティブなSecretRefを再解決し、完全成功時にのみランタイムのシークレット状態を切り替えます。secrets.resolveは、特定のコマンド/ターゲットセット向けにコマンド対象のシークレット割り当てを解決します。config.getは、現在の設定スナップショットとハッシュを返します。config.setは、検証済みの設定ペイロードを書き込みます。config.patchは、部分的な設定更新をマージします。config.applyは、完全な設定ペイロードを検証して置き換えます。config.schemaは、Control UIおよびCLIツールで使われるライブ設定スキーマペイロード を返します: スキーマ、uiHints、バージョン、生成メタデータ。これには、ランタイムで 読み込める場合のプラグイン + チャネルスキーマメタデータも含まれます。 スキーマには、UIで使われるものと同じラベルおよびヘルプテキストから導出された フィールドtitle/descriptionメタデータが含まれます。これには、ネストしたobject、 wildcard、array-item、および対応するフィールドドキュメントが存在する場合のanyOf/oneOf/allOf合成分岐も含まれます。config.schema.lookupは、1つの設定パス向けのパススコープ付きlookupペイロードを返します: 正規化されたパス、浅いスキーマノード、一致したhint +hintPath、および UI/CLIドリルダウン向けの直接の子サマリーです。- Lookupスキーマノードは、ユーザー向けドキュメントおよび一般的な検証フィールドを保持します:
title,description,type,enum,const,format,pattern, 数値/文字列/配列/objectの境界、およびadditionalProperties,deprecated,readOnly,writeOnlyのような真偽値フラグ。 - 子サマリーは
key、正規化されたpath、type、required、hasChildren、および一致したhint/hintPathを公開します。
- Lookupスキーマノードは、ユーザー向けドキュメントおよび一般的な検証フィールドを保持します:
update.runは、Gateway更新フローを実行し、更新自体が成功した場合にのみ再起動をスケジュールします。wizard.start、wizard.next、wizard.status、wizard.cancelは、 オンボーディングウィザードをWS RPC経由で公開します。
既存の主要ファミリー
agentとworkspaceヘルパー
agents.listは、設定済みagentエントリを返します。agents.create、agents.update、agents.deleteは、agentレコードと workspace配線を管理します。agents.files.list、agents.files.get、agents.files.setは、 agent向けに公開されたブートストラップworkspaceファイルを管理します。agent.identity.getは、agentまたはセッションの有効なassistant identityを返します。agent.waitは、実行完了を待ち、利用可能な場合は終端スナップショットを返します。
セッション制御
sessions.listは、現在のセッションインデックスを返します。sessions.subscribeとsessions.unsubscribeは、現在のWSクライアントの セッション変更イベント購読を切り替えます。sessions.messages.subscribeとsessions.messages.unsubscribeは、 1つのセッションのトランスクリプト/メッセージイベント購読を切り替えます。sessions.previewは、特定のセッションキー向けに制限付きトランスクリプトプレビューを返します。sessions.resolveは、セッションターゲットを解決または正規化します。sessions.createは、新しいセッションエントリを作成します。sessions.sendは、既存のセッションにメッセージを送信します。sessions.steerは、アクティブなセッション向けの中断して誘導するバリアントです。sessions.abortは、セッションのアクティブな作業を中止します。sessions.patchは、セッションメタデータ/上書きを更新します。sessions.reset、sessions.delete、sessions.compactは、セッション保守を実行します。sessions.getは、保存済みの完全なセッション行を返します。- chat実行では引き続き
chat.history、chat.send、chat.abort、chat.injectを使用します。 chat.historyは、UIクライアント向けに表示正規化されています: インラインディレクティブタグは 表示テキストから削除され、プレーンテキストのツール呼び出しXMLペイロード (<tool_call>...</tool_call>、<function_call>...</function_call>、<tool_calls>...</tool_calls>、<function_calls>...</function_calls>、 および切り詰められたツール呼び出しブロックを含む)と、 漏れ出したASCII/全角のモデル制御トークンは削除され、正確にNO_REPLY/no_replyである純粋なsilent-token assistant行は省略され、 過大な行はプレースホルダーに置き換えられる場合があります。
デバイスpairingとデバイストークン
device.pair.listは、保留中および承認済みのpair済みデバイスを返します。device.pair.approve、device.pair.reject、device.pair.removeは、 デバイスpairingレコードを管理します。device.token.rotateは、pairing済みデバイストークンを承認済みroleおよび scopeの範囲内でローテーションします。device.token.revokeは、pairing済みデバイストークンを失効させます。
node pairing、invoke、および保留中作業
node.pair.request、node.pair.list、node.pair.approve、node.pair.reject、node.pair.verifyは、node pairingとブートストラップ 検証を扱います。node.listとnode.describeは、既知/接続中のノード状態を返します。node.renameは、pairing済みノードラベルを更新します。node.invokeは、接続中ノードにコマンドを転送します。node.invoke.resultは、invokeリクエストの結果を返します。node.eventは、ノード起点イベントをGatewayへ戻します。node.canvas.capability.refreshは、スコープ付きcanvas-capabilityトークンを更新します。node.pending.pullとnode.pending.ackは、接続中ノードのキューAPIです。node.pending.enqueueとnode.pending.drainは、 オフライン/切断中ノード向けの永続保留作業を管理します。
承認ファミリー
exec.approval.request、exec.approval.get、exec.approval.list、exec.approval.resolveは、単発のexec承認リクエストと、 保留中承認の検索/再生を扱います。exec.approval.waitDecisionは、1件の保留中exec承認を待機し、 最終判断を返します(タイムアウト時はnull)。exec.approvals.getとexec.approvals.setは、Gateway exec承認 ポリシースナップショットを管理します。exec.approvals.node.getとexec.approvals.node.setは、 ノードリレーコマンド経由でnodeローカルのexec承認ポリシーを管理します。plugin.approval.request、plugin.approval.list、plugin.approval.waitDecision、plugin.approval.resolveは、 プラグイン定義の承認フローを扱います。
その他の主要ファミリー
- automation:
wakeは、即時または次のheartbeatでのwakeテキスト注入をスケジュールしますcron.list,cron.status,cron.add,cron.update,cron.remove,cron.run,cron.runs
- Skills/ツール:
skills.*,tools.catalog,tools.effective
一般的なイベントファミリー
chat:chat.injectなどの、UI chat更新やその他のトランスクリプト専用chatイベント。session.messageとsession.tool: 購読されたセッション向けの トランスクリプト/イベントストリーム更新。sessions.changed: セッションインデックスまたはメタデータが変更された。presence: systemプレゼンススナップショット更新。tick: 定期的なkeepalive / 生存確認イベント。health: Gatewayヘルススナップショット更新。heartbeat: heartbeatイベントストリーム更新。cron: cron実行/ジョブ変更イベント。shutdown: Gatewayシャットダウン通知。node.pair.requested/node.pair.resolved: node pairingライフサイクル。node.invoke.request: node invokeリクエストのブロードキャスト。device.pair.requested/device.pair.resolved: pair済みデバイスライフサイクル。voicewake.changed: ウェイクワードトリガー設定が変更された。exec.approval.requested/exec.approval.resolved: exec承認 ライフサイクル。plugin.approval.requested/plugin.approval.resolved: プラグイン承認 ライフサイクル。
nodeヘルパーメソッド
- ノードは、自動許可チェック向けの現在のskill実行ファイル一覧を取得するために
skills.binsを呼び出せます。
operatorヘルパーメソッド
- operatorは、agent向けのランタイムツールカタログを取得するために
tools.catalog(operator.read)を呼び出せます。レスポンスには、グループ化された ツールと由来メタデータが含まれます:source:coreまたはpluginpluginId:source="plugin"のときのプラグイン所有者optional: プラグインツールがオプションかどうか
- operatorは、セッションのランタイム有効ツール
インベントリを取得するために
tools.effective(operator.read)を呼び出せます。sessionKeyは必須です。- Gatewayは、呼び出し元が指定した認証や配信コンテキストを受け取る代わりに、 信頼できるランタイムコンテキストをサーバー側でセッションから導出します。
- レスポンスはセッションスコープであり、core、plugin、channelツールを含む、 現在アクティブな会話で今すぐ使えるものを反映します。
- operatorは、agent向けの表示可能なskillインベントリを取得するために
skills.status(operator.read)を呼び出せます。agentIdは任意です。省略するとデフォルトagent workspaceを読み取ります。- レスポンスには、rawシークレット値を公開することなく、 適格性、不足している要件、設定チェック、およびサニタイズ済みinstall optionsが含まれます。
- operatorは、ClawHub検出メタデータ向けに
skills.searchとskills.detail(operator.read)を呼び出せます。 - operatorは、2つのモードで
skills.install(operator.admin)を呼び出せます:- ClawHubモード:
{ source: "clawhub", slug, version?, force? }は、 デフォルトagent workspaceのskills/ディレクトリにskillフォルダーをインストールします。 - Gateway installerモード:
{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }は、Gatewayホスト上で宣言されたmetadata.openclaw.installアクションを実行します。
- ClawHubモード:
- operatorは、2つのモードで
skills.update(operator.admin)を呼び出せます:- ClawHubモードでは、1つの追跡対象slugまたはデフォルトagent workspace内の すべての追跡対象ClawHubインストールを更新します。
- Configモードでは、
enabled、apiKey、envなどのskills.entries.<skillKey>値をパッチします。
exec承認
- execリクエストに承認が必要な場合、Gatewayは
exec.approval.requestedをブロードキャストします。 - operatorクライアントは、
exec.approval.resolveを呼び出して解決します (operator.approvalsscopeが必要)。 host=nodeの場合、exec.approval.requestにはsystemRunPlan(正規のargv/cwd/rawCommand/sessionメタデータ)が含まれていなければなりません。systemRunPlanがないリクエストは拒否されます。- 承認後、転送された
node.invoke system.run呼び出しは、その正規のsystemRunPlanを権威あるコマンド/cwd/sessionコンテキストとして再利用します。 - 呼び出し元が prepare と最終的な承認済み
system.run転送の間でcommand、rawCommand、cwd、agentId、sessionKeyを変更した場合、 Gatewayは変更されたペイロードを信頼せず、実行を拒否します。
agent配信フォールバック
agentリクエストには、アウトバウンド配信を要求するためのdeliver=trueを含めることができます。bestEffortDeliver=falseは厳格な動作を維持します: 解決不能または内部専用の配信先はINVALID_REQUESTを返します。bestEffortDeliver=trueは、外部配信可能ルートを解決できない場合 (たとえば内部/webchatセッションや曖昧なマルチチャネル設定)に、 セッション専用実行へのフォールバックを許可します。
バージョニング
PROTOCOL_VERSIONはsrc/gateway/protocol/schema.tsにあります。- クライアントは
minProtocol+maxProtocolを送信し、サーバーは不一致を拒否します。 - スキーマ + モデルはTypeBox定義から生成されます:
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
認証
- 共有シークレットGateway認証では、設定された認証モードに応じて
connect.params.auth.tokenまたはconnect.params.auth.passwordを使用します。 - Tailscale Serve のようなIDを伴うモード
(
gateway.auth.allowTailscale: true)や、non-loopbackgateway.auth.mode: "trusted-proxy"では、connect.params.auth.*の代わりにリクエストヘッダーから接続認証チェックを満たします。 - private-ingress
gateway.auth.mode: "none"は、共有シークレット接続認証を 完全にスキップします。このモードを公開/信頼できないingressで公開しないでください。 - pairing後、Gatewayは接続のrole + scopeにスコープされたデバイストークンを発行します。
これは
hello-ok.auth.deviceTokenで返され、クライアントは将来の接続のために これを永続化する必要があります。 - クライアントは、接続成功後に主要な
hello-ok.auth.deviceTokenを永続化する必要があります。 - その保存済みデバイストークンで再接続する場合は、そのトークンに対して以前承認された scopeセットも再利用する必要があります。これにより、すでに許可された read/probe/statusアクセスが保持され、再接続時により狭い暗黙的な admin専用scopeへ静かに縮小されるのを防げます。
- 通常の接続認証の優先順位は、明示的な共有token/passwordが最優先で、次に
明示的な
deviceToken、次に保存済みのデバイスごとのトークン、 最後にブートストラップトークンです。 - 追加の
hello-ok.auth.deviceTokensエントリは、ブートストラップ引き継ぎトークンです。 それらは、wss://や loopback/local pairing のような信頼できる転送上で 接続がブートストラップ認証を使った場合にのみ永続化してください。 - クライアントが明示的な
deviceTokenまたは明示的なscopesを指定した場合、 その呼び出し元要求のscopeセットが権威を持ち続けます。キャッシュされたscopeが再利用されるのは、 クライアントが保存済みのデバイスごとのトークンを再利用している場合だけです。 - デバイストークンは
device.token.rotateとdevice.token.revokeでローテーション/失効できます (operator.pairingscopeが必要)。 - トークン発行/ローテーションは、そのデバイスのpairingエントリに記録された 承認済みroleセットの範囲内に制限されます。トークンのローテーションで、 pairing承認が一度も許可していないroleへデバイスを拡張することはできません。
- pair済みデバイストークンセッションでは、呼び出し元が
operator.adminも 持っていない限り、デバイス管理は自己スコープになります: non-admin呼び出し元は、自分自身のデバイスエントリのみを削除/失効/ローテーションできます。 device.token.rotateは、要求されたoperator scopeセットも 呼び出し元の現在のセッションscopeに対してチェックします。non-admin呼び出し元は、 現在自分が保持しているものより広いoperator scopeセットへトークンをローテーションできません。- 認証失敗には
error.details.codeと復旧ヒントが含まれます:error.details.canRetryWithDeviceToken(boolean)error.details.recommendedNextStep(retry_with_device_token,update_auth_configuration,update_auth_credentials,wait_then_retry,review_auth_configuration)
AUTH_TOKEN_MISMATCHに対するクライアント動作:- 信頼されたクライアントは、キャッシュされたデバイスごとのトークンで 1回だけ制限付き再試行を試みてもかまいません。
- その再試行も失敗した場合、クライアントは自動再接続ループを停止し、 operator向けの対処ガイダンスを表示する必要があります。
デバイスidentity + pairing
- ノードは、キーペアフィンガープリントから導出された安定したデバイスidentity(
device.id)を含める必要があります。 - Gatewayは、デバイス + roleごとにトークンを発行します。
- ローカル自動承認が有効でない限り、新しいデバイスIDにはpairing承認が必要です。
- pairing自動承認は、直接のlocal loopback接続を中心にしています。
- OpenClawには、信頼された共有シークレットヘルパーフロー向けの 狭いbackend/container-local self-connectパスもあります。
- 同一ホストのtailnetやLAN接続も、引き続きリモートとして扱われ、 pairing承認が必要です。
- すべてのWSクライアントは、
connect中にdeviceidentity を含める必要があります (operator + node)。 Control UIがこれを省略できるのは、次のモードだけです:- localhost専用の非安全HTTP互換性向け
gateway.controlUi.allowInsecureAuth=true gateway.auth.mode: "trusted-proxy"でのoperator Control UI認証成功時。gateway.controlUi.dangerouslyDisableDeviceAuth=true(緊急避難用、重大なセキュリティ低下)。
- localhost専用の非安全HTTP互換性向け
- すべての接続は、サーバー提供の
connect.challengenonce に署名しなければなりません。
デバイス認証移行診断
依然としてpre-challenge署名動作を使っているレガシークライアント向けに、connect は現在、安定した error.details.reason の下で
error.details.code に DEVICE_AUTH_* 詳細コードを返します。
一般的な移行失敗:
| メッセージ | details.code | details.reason | 意味 |
|---|---|---|---|
device nonce required | DEVICE_AUTH_NONCE_REQUIRED | device-nonce-missing | クライアントが device.nonce を省略した(または空を送信した)。 |
device nonce mismatch | DEVICE_AUTH_NONCE_MISMATCH | device-nonce-mismatch | クライアントが古い/誤ったnonceで署名した。 |
device signature invalid | DEVICE_AUTH_SIGNATURE_INVALID | device-signature | 署名ペイロードがv2ペイロードと一致しない。 |
device signature expired | DEVICE_AUTH_SIGNATURE_EXPIRED | device-signature-stale | 署名済みタイムスタンプが許容スキュー範囲外である。 |
device identity mismatch | DEVICE_AUTH_DEVICE_ID_MISMATCH | device-id-mismatch | device.id が公開鍵フィンガープリントと一致しない。 |
device public key invalid | DEVICE_AUTH_PUBLIC_KEY_INVALID | device-public-key | 公開鍵の形式/正規化に失敗した。 |
- 常に
connect.challengeを待つ。 - サーバーnonceを含むv2ペイロードに署名する。
- 同じnonceを
connect.params.device.nonceで送る。 - 推奨署名ペイロードは
v3で、device/client/role/scopes/token/nonce フィールドに加えてplatformとdeviceFamilyも結び付けます。 - レガシーな
v2署名も互換性のため引き続き受け入れられますが、 pair済みデバイスのメタデータ固定が、再接続時のコマンドポリシーを引き続き制御します。
TLS + ピン留め
- WS接続ではTLSがサポートされています。
- クライアントは、必要に応じてGateway証明書のフィンガープリントをピン留めできます
(
gateway.tls設定、およびgateway.remote.tlsFingerprintまたは CLI--tls-fingerprintを参照)。
スコープ
このプロトコルは、完全なGateway API(status、channels、models、chat、 agent、sessions、nodes、approvalsなど)を公開します。正確なサーフェスはsrc/gateway/protocol/schema.ts 内のTypeBoxスキーマで定義されます。