Gateway protocol
Gateway WS 協定是 OpenClaw 的單一控制平面 + 節點傳輸。所有客戶端(CLI、網頁 UI、macOS 應用程式、iOS/Android 節點、無頭節點)都透過 WebSocket 連線,並在握手時宣告其角色 + 範圍。
- WebSocket,具有 JSON 載荷的文字幀。
- 第一個幀必須是
connect請求。 - 連線前的幀大小上限為 64 KiB。成功交握後,客戶端應遵循
hello-ok.policy.maxPayload和hello-ok.policy.maxBufferedBytes限制。啟用診斷時,過大的入站幀和緩慢的出站緩衝區會在 Gateway 關閉或丟棄受影響的幀之前發出payload.large事件。這些事件包含大小、限制、介面和安全原因代碼。它們不包含訊息主體、附件內容、原始幀主體、令牌、Cookie 或秘密值。
握手 (連線)
Section titled “握手 (連線)”Gateway → 用戶端 (連線前挑戰):
{ "type": "event", "event": "connect.challenge", "payload": { "nonce": "…", "ts": 1737264000000 }}用戶端 → Gateway:
{ "type": "req", "id": "…", "method": "connect", "params": { "minProtocol": 3, "maxProtocol": 4, "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": 4, "server": { "version": "…", "connId": "…" }, "features": { "methods": ["…"], "events": ["…"] }, "snapshot": { "…": "…" }, "auth": { "role": "operator", "scopes": ["operator.read", "operator.write"] }, "policy": { "maxPayload": 26214400, "maxBufferedBytes": 52428800, "tickIntervalMs": 15000 } }}當 Gateway 尚在完成啟動 Sidecar 時,connect 請求可能會傳回一個可重試的 UNAVAILABLE 錯誤,並將 details.reason 設定為 "startup-sidecars" 和 retryAfterMs。客戶端應在其整體連線預算內重試該回應,而不是將其作為終端交握失敗呈現。
server、features、snapshot 和 policy 都是架構
(packages/gateway-protocol/src/schema/frames.ts) 所要求的。auth 也是必需的,並回報
協商的角色/範圍。pluginSurfaceUrls 是可選的,將外掛介面名稱,例如
canvas,對應到有範圍的託管 URL。
有範圍的插件介面 URL 可能會過期。節點可以呼叫 node.pluginSurface.refresh 並帶有 { "surface": "canvas" } 以在 pluginSurfaceUrls 中接收新條目。實驗性的 Canvas 插件重構不支援已棄用的 canvasHostUrl、canvasCapability 或 node.canvas.capability.refresh 相容路徑;目前的原生客戶端和 Gateway 必須使用插件介面。
當未發出裝置令牌時,hello-ok.auth 會回報不含令牌欄位的協商權限:
{ "auth": { "role": "operator", "scopes": ["operator.read", "operator.write"] }}受信任的同進程後端客戶端(client.id: "gateway-client"、
client.mode: "backend")在直接回送連線上使用共用 Gateway token/密碼進行驗證時,可以省略 device。此路徑保留給內部控制平面 RPC 使用,並防止過時的 CLI/裝置配對基準阻擋本機後端工作(例如子代理程式會話更新)。遠端客戶端、瀏覽器來源客戶端、節點客戶端以及明確的裝置 token/裝置身分客戶端仍使用正常的配對和權限升級檢查。
當發出裝置 token 時,hello-ok 也包含:
{ "auth": { "deviceToken": "…", "role": "operator", "scopes": ["operator.read", "operator.write"] }}內建的 QR/設定碼啟動是一個全新的移動裝置移交途徑。成功的基準設定碼連線會返回一個主要節點權杖加上一個受限的操作員權杖:
{ "auth": { "deviceToken": "…", "role": "node", "scopes": [], "deviceTokens": [ { "deviceToken": "…", "role": "operator", "scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"] } ] }}操作員移交是刻意設有界限的,以便 QR 入門可以在不授予 operator.admin 或 operator.pairing 的情況下啟動
行動操作員迴圈。它確實包含 operator.talk.secrets,以便原生客戶端可以在啟動後讀取其所需的 Talk
設定。更廣泛的管理員和配對範圍需要單獨的已批准操作員配對或權杖流程。僅當連線在受信任的傳輸(例如 wss://)
或迴路/本機配對上使用啟動驗證時,客戶端才應保存
hello-ok.auth.deviceTokens。
{ "type": "req", "id": "…", "method": "connect", "params": { "minProtocol": 3, "maxProtocol": 4, "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?}
具有副作用的方法需要 等冪鍵(請參閱架構)。
角色 + 權限
Section titled “角色 + 權限”如需完整的運算器範圍模型、批准時檢查以及共用密碼語意,請參閱 Operator scopes。
operator= 控制平面客戶端 (CLI/UI/自動化)。node= 功能主機 (camera/screen/canvas/system.run)。
權限(操作員)
Section titled “權限(操作員)”常見權限:
operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
帶有 includeSecrets: true 的 talk.config 需要 operator.talk.secrets
(或 operator.admin)。
外掛程式註冊的閘道 RPC 方法可以請求自己的操作員範圍,但保留的核心管理前綴(config.*、exec.approvals.*、wizard.*、
update.*)始終解析為 operator.admin。
方法範圍只是第一道關卡。透過 chat.send 到達的某些斜線指令會在其之上套用更嚴格的指令級別檢查。例如,持續性 /config set 和 /config unset 寫入需要 operator.admin。
node.pair.approve 除了基本方法範圍外,還有一個額外的批准時間範圍檢查:
- 無指令請求:
operator.pairing - 包含非執行節點指令的請求:
operator.pairing+operator.write - 包含
system.run、system.run.prepare或system.which的請求:operator.pairing+operator.admin
Caps/commands/permissions (node)
Section titled “Caps/commands/permissions (node)”節點會在連線時宣告能力聲明:
caps:高層級功能類別,例如camera、canvas、screen、location、voice和talk。commands:用於調用的指令允許清單。permissions:細粒度切換(例如screen.record、camera.capture)。
Gateway 將這些視為 聲明 並強制執行伺服器端允許清單。
Presence
Section titled “Presence”system-presence返回以裝置身分為鍵的項目。- Presence 項目包含
deviceId、roles和scopes,以便 UI 即使在裝置同時作為 operator 和 node 連線時,也能為每個裝置顯示單一行。 node.list包含可選的lastSeenAtMs和lastSeenReason欄位。已連線的節點將其當前連線時間報告為lastSeenAtMs並帶有原因connect;當受信任節點事件更新其配對元資料時,配對的節點也可以報告持久的背景存在狀態。
節點背景在線事件
Section titled “節點背景在線事件”節點可以呼叫 node.event 並使用 event: "node.presence.alive" 來記錄配對節點在背景喚醒期間處於存活狀態,而無需將其標記為已連線。
{ "event": "node.presence.alive", "payloadJSON": "{\"trigger\":\"silent_push\",\"sentAtMs\":1737264000000,\"displayName\":\"Peter's iPhone\",\"version\":\"2026.4.28\",\"platform\":\"iOS 18.4.0\",\"deviceFamily\":\"iPhone\",\"modelIdentifier\":\"iPhone17,1\",\"pushTransport\":\"relay\"}"}trigger 是一個封閉式枚舉:background、silent_push、bg_app_refresh、
significant_location、manual 或 connect。未知的觸發字串會在持久化之前由閘道正規化為
background。該事件僅對已驗證的節點裝置會話持久化;無裝置或未配對的會話會返回 handled: false。
成功的閘道會傳回結構化結果:
{ "ok": true, "event": "node.presence.alive", "handled": true, "reason": "persisted"}較舊的 Gateway 可能仍會針對 node.event 傳回 { "ok": true };客戶端應將其視為已確認的 RPC,而非持久的存在狀態儲存。
廣播事件範圍
Section titled “廣播事件範圍”伺服器推送的 WebSocket 廣播事件會受到範圍限制,因此僅限配對範圍或僅限節點的會話不會被動接收會話內容。
- 聊天、代理和工具結果幀(包括串流
agent事件和工具呼叫結果)至少需要operator.read。沒有operator.read的作業階段會完全略過這些幀。 - 外掛定義的
plugin.*廣播會限制為operator.write或operator.admin,具體取決於外掛如何註冊它們。 - 狀態和傳輸事件(
heartbeat、presence、tick、連線/中斷連線生命週期等)保持無限制,以便每個已驗證的作業階段都能觀察到傳輸的健康狀況。 - 未知的廣播事件系列 預設受範圍限制(預設拒絕),除非已註冊的處理程序明確放寬限制。
每個客戶端連接都會維護自己的每個客戶端序列號,因此即使不同的客戶端看到經過範圍過濾的事件流子集不同,廣播也能在該 socket 上保持單調排序。
常見的 RPC 方法系列
Section titled “常見的 RPC 方法系列”公開 WS 介面比上述握手/驗證範例更廣泛。這並非生成的傾印——hello-ok.features.methods 是一份保守的探索清單,建構自 src/gateway/server-methods-list.ts 加上已載入的外掛/通道方法匯出。請將其視為功能探索,而非 src/gateway/server-methods/*.ts 的完整列舉。
System and identity
health返回快取或新探測的閘道器健康快照。diagnostics.stability返回最近的有限診斷穩定性記錄器。它保留操作元數據,例如事件名稱、計數、位元組大小、內存讀數、佇列/會話狀態、通道/外掛名稱和會話 ID。它不保留聊天文字、Webhook 內文、工具輸出、原始請求或回應內文、Token、Cookie 或機密值。需要操作員讀取權限。status返回/status風格的閘道器摘要;敏感欄位僅包含在具有管理員範圍的操作員客戶端中。gateway.identity.get返回中繼和配對流程使用的閘道器裝置身分。system-presence返回已連線操作員/節點裝置的目前存在快照。system-event附加系統事件並可以更新/廣播存在上下文。last-heartbeat返回最新持久化的心跳事件。set-heartbeats切換閘道器上的心跳處理。
模型與使用
models.list返回執行時允許的模型目錄。傳入{ "view": "configured" }以獲取選擇器大小的已配置模型(優先agents.defaults.models,然後models.providers.*.models),或傳入{ "view": "all" }以獲取完整目錄。usage.status返回提供商使用視窗/剩餘配額摘要。usage.cost返回日期範圍內的彙總成本使用摘要。 傳入agentId指定單個代理,或傳入agentScope: "all"以彙總已配置的代理。doctor.memory.status返回活動預設代理工作區的向量記憶體/快取嵌入就緒狀態。僅當呼叫者明確需要即時嵌入提供商 Ping 時才傳遞{ "probe": true }或{ "deep": true }。支援 Dreaming 的客戶端也可以傳遞{ "agentId": "agent-id" }以將 Dreaming 存儲統計資訊範圍限定為選定的代理工作區;省略agentId將保留預設代理後備並彙總已配置的 Dreaming 工作區。doctor.memory.dreamDiary、doctor.memory.backfillDreamDiary、doctor.memory.resetDreamDiary、doctor.memory.resetGroundedShortTerm、doctor.memory.repairDreamingArtifacts和doctor.memory.dedupeDreamDiary接受可選的{ "agentId": "agent-id" }參數,用於選定代理的 Dreaming 檢視/操作。當省略agentId時,它們對已配置的預設代理工作區進行操作。doctor.memory.remHarness返回一個有限的、唯讀的 REM 掛接預覽,用於遠端控制平面客戶端。它可以包含工作區路徑、記憶體片段、呈現的落地 Markdown 和深度推廣候選項,因此呼叫者需要operator.read。sessions.usage返回每個會話的使用摘要。傳入agentId指定單個 代理,或傳入agentScope: "all"以列出已配置的代理。sessions.usage.timeseries返回單個會話的時間序列使用情況。sessions.usage.logs返回單個會話的使用日誌條目。
通道和登入協助程式
channels.status傳回內建 + 捆綁的通道/外掛狀態摘要。channels.logout登出支援登出的特定通道/帳戶。web.login.start為當前具備 QR 功能的 web 通道提供者啟動 QR/web 登入流程。web.login.wait等待該 QR/web 登入流程完成,並在成功時啟動通道。push.test發送測試 APNs 推播至已註冊的 iOS 節點。voicewake.get傳回已儲存的喚醒詞觸發器。voicewake.set更新喚醒詞觸發器並廣播變更。
訊息傳遞與日誌
send是用於聊天執行器之外,針對通道/帳戶/執行緒目標傳送的直接出站傳遞 RPC。logs.tail傳回已設定的閘道檔案日誌尾部,並包含遊標/限制與最大位元組控制。
Talk and TTS
talk.catalog傳回用於語音、串流轉錄即時語音的唯讀 Talk 提供者目錄。它包含提供者 ID、標籤、已設定狀態、公開的模型/語音 ID、標準模式、傳輸、Brain 策略以及即時音訊/能力標誌,而不會傳回提供者密鑰或修改全域設定。talk.config傳回有效的 Talk 設定負載;includeSecrets需要operator.talk.secrets(或operator.admin)。talk.session.create為realtime/gateway-relay、transcription/gateway-relay或stt-tts/managed-room建立 Gateway 擁有的 Talk 工作階段。對於stt-tts/managed-room,傳遞sessionKey的operator.write呼叫者也必須傳遞spawnedBy以取得有限範圍的工作階段金鑰可見性;未限定範圍的sessionKey建立和brain: "direct-tools"需要operator.admin。talk.session.join驗證受管理房間的工作階段權杖,根據需要發出session.ready或session.replaced事件,並傳回房間/工作階段中繼資料以及最近的 Talk 事件,而不包含明文權杖或儲存的權杖雜湊。talk.session.appendAudio將 base64 PCM 輸入音訊附加到 Gateway 擁有的即時轉送和轉錄工作階段。talk.session.startTurn、talk.session.endTurn和talk.session.cancelTurn驅動受管理房間的輪次生命週期,並在狀態清除前拒絕過期的輪次。talk.session.cancelOutput停止助理音訊輸出,主要用於 Gateway 轉送工作階段中的 VAD 閘控插話。talk.session.submitToolResult完成 Gateway 擁有的即時轉送工作階段所發出的提供者工具呼叫。當最終結果隨後而至時,請傳遞options: { willContinue: true }作為臨時工具輸出,或者當工具結果應滿足提供者呼叫而不啟動另一個即時助理回應時,請傳遞options: { suppressResponse: true }。talk.session.steer將執行中語音控制傳送到 Gateway 擁有的代理支援 Talk 工作階段。它接受{ sessionId, text, mode? },其中mode是status、steer、cancel或followup;省略的模式會從口語文字中分類。talk.session.close關閉 Gateway 擁有的轉送、轉錄或受管理房間工作階段,並發出終端 Talk 事件。talk.mode設定/廣播 WebChat/Control UI 用戶端的目前 Talk 模式狀態。talk.client.create使用webrtc或provider-websocket建立用戶端擁有的即時提供者工作階段,同時 Gateway 擁有設定、憑證、指示和工具原則。talk.client.toolCall允許用戶端擁有的即時傳輸將提供者工具呼叫轉發到 Gateway 原則。第一個支援的工具是openclaw_agent_consult;用戶端會收到一個執行 ID,並在提交提供者特定的工具結果之前等待正常的聊天生命週期事件。talk.client.steer為用戶端擁有的即時傳輸傳送執行中語音控制。Gateway 從sessionKey解析作用中的內嵌執行,並傳回結構化的已接受/已拒絕結果,而不是無聲地捨棄引導。talk.event是即時、轉錄、STT/TTS、受管理房間、電話和會議配接器的單一 Talk 事件通道。talk.speak透過作用中的 Talk 語音提供者合成語音。tts.status傳回 TTS 啟用狀態、作用中提供者、後援提供者和提供者設定狀態。tts.providers傳回可見的 TTS 提供者清單。tts.enable和tts.disable切換 TTS 偏好設定狀態。tts.setProvider更新偏好的 TTS 提供者。tts.convert執行一次性文字轉語音轉換。
Secrets, config, update, and wizard
secrets.reload重新解析有效的 SecretRef,並僅在完全成功時交換運行時密鑰狀態。secrets.resolve解析特定指令/目標集的指令目標密鑰分配。config.get返回當前配置快照和雜湊值。config.set寫入已驗證的配置負載。config.patch合併部分配置更新。config.apply驗證並替換完整的配置負載。config.schema返回由控制 UI 和 CLI 工具使用的即時配置架構負載:架構、uiHints、版本和生成元數據,包括運行時可以加載時的外掛程式 + 通道架構元數據。該架構包含從 UI 使用的相同標籤和幫助文本派生的欄位title/description元數據,包括巢狀物件、萬用字元、陣列項目,以及當存在匹配欄位文檔時的anyOf/oneOf/allOf組合分支。config.schema.lookup返回一個配置路徑的路徑範圍查找負載:標準化路徑、淺層架構節點、匹配的提示 +hintPath、可選的reloadKind,以及用於 UI/CLI 鑽取的直接子摘要。reloadKind是restart、hot或none之一,並反映所請求路徑的 Gateway 配置重新載入計劃器。查找架構節點保留面向用戶的文檔和常見驗證欄位(title、description、type、enum、const、format、pattern、數值/字串/陣列/物件邊界,以及諸如additionalProperties、deprecated、readOnly、writeOnly等標誌)。子摘要公開key、標準化的path、type、required、hasChildren、可選的reloadKind,加上匹配的hint/hintPath。update.run執行 Gateway 更新流程,並僅在更新本身成功時排程重新啟動;具有會話的調用者可以包含continuationMessage,以便啟動通過重新啟動繼續佇列恢復一個後續代理週期。來自控制平面的套件管理器更新使用分離的託管服務移交,而不是替換即時 Gateway 內部的套件樹。已啟動的移交返回帶有result.reason: "managed-service-handoff-started"和handoff.status: "started"的ok: true;不可用或失敗的移交返回帶有managed-service-handoff-unavailable或managed-service-handoff-failed的ok: false,加上需要手動 shell 更新時的handoff.command。在已啟動的移交期間,重新啟動哨兵可能會簡要報告stats.reason: "restart-health-pending";延續將延遲,直到 CLI 驗證重新啟動的 Gateway 並寫入最終的ok哨兵。update.status返回最新的快取更新重新啟動哨兵,包括可用時的重新啟動後運行版本。wizard.start、wizard.next、wizard.status和wizard.cancel通過 WS RPC 公開入門嚮導。
Agent and workspace helpers
agents.list傳回已設定的代理程式條目,包括有效的模型和執行時期中繼資料。agents.create、agents.update和agents.delete管理代理程式記錄和工作區連線。agents.files.list、agents.files.get和agents.files.set管理為代理程式公開的啟動工作區檔案。tasks.list、tasks.get和tasks.cancel向 SDK 和操作員客戶端公開 Gateway 任務分類帳。artifacts.list、artifacts.get和artifacts.download公開針對明確的sessionKey、runId或taskId範圍所衍生的文字記錄摘要與下載。執行和任務查詢會在伺服器端解析擁有的會話,並僅傳回具有相符來源的記錄媒體;不安全或本機 URL 來源會傳回不支援的下載,而不是在伺服器端擷取。environments.list和environments.status向 SDK 客戶端公開唯讀的 Gateway 本地和節點環境探索功能。agent.identity.get傳回代理程式或會話的有效助理身分。agent.wait等待執行完成,並在可用時傳回終端快照。
會話控制
sessions.list會傳回目前的會話索引,當設定代理程式執行時間後端時,還包含每列agentRuntime中繼資料。sessions.subscribe和sessions.unsubscribe切換目前 WS 用戶端的會話變更事件訂閱。sessions.messages.subscribe和sessions.messages.unsubscribe切換單一會話的文字紀錄/訊息事件訂閱。sessions.preview傳回特定會話金鑰的有限文字紀錄預覽。sessions.describe傳回指定會話金鑰的單一 Gateway 會話列。sessions.resolve解析或正規化會話目標。sessions.create建立新的會話項目。sessions.send將訊息傳送至現有會話。sessions.steer是作用中會話的中斷並導向變體。sessions.abort中止會話的作用中工作。呼叫者可以傳遞key加上選用的runId,或是僅傳遞runId,讓 Gateway 解析為會話的作用中執行。sessions.patch更新會話中繼資料/覆寫,並回報已解析的正規模型加上有效的agentRuntime。sessions.reset、sessions.delete和sessions.compact執行會話維護。sessions.get傳回完整的已儲存會話列。- 聊天執行仍使用
chat.history、chat.send、chat.abort和chat.inject。chat.history已針對 UI 用戶端進行顯示正規化:內聯指令標籤會從可見文字中移除,純文字工具呼叫 XML 載荷(包括 `
…
、
…
、
…
、
…
,以及截斷的工具呼叫區塊)和洩漏的 ASCII/全形模型控制權杖會被移除,純靜音權杖助手列(例如精確的 NO_REPLY/no_reply)會被省略,而過大的列可以由預留位置取代。 - chat.message.get是單一可見文字紀錄項目的累加有限完整訊息讀取器。用戶端傳遞sessionKey,當會話選擇為代理程式範圍時則加上選用的 agentId,以及先前透過 chat.history呈現的文字紀錄messageId`,而當儲存的項目仍存在且未過大時,Gateway 會傳回相同的顯示正規化投影,沒有輕量級歷史截斷上限。
裝置配對與裝置權杖
device.pair.list會傳回待處理與已核准的配對裝置。device.pair.approve、device.pair.reject和device.pair.remove用於管理裝置配對記錄。device.token.rotate會在其已核准的角色和呼叫者範圍界限內輪替配對裝置的權杖。device.token.revoke會在其已核准的角色和呼叫者範圍界限內撤銷配對裝置的權杖。
節點配對、調用與待處理工作
node.pair.request、node.pair.list、node.pair.approve、node.pair.reject、node.pair.remove和node.pair.verify涵蓋了節點配對與啟動驗證。node.list和node.describe會傳回已知/已連接的節點狀態。node.rename會更新配對節點的標籤。node.invoke會將指令轉發給已連接的節點。node.invoke.result會傳回調用請求的結果。node.event會將源自節點的事件帶回到閘道。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.approval.waitDecision等待一個待處理的執行審核並傳回最終決定(或在逾時時傳回null)。exec.approvals.get和exec.approvals.set管理閘道執行審核策略快照。exec.approvals.node.get和exec.approvals.node.set透過節點中繼指令管理節點本機執行審核策略。plugin.approval.request、plugin.approval.list、plugin.approval.waitDecision和plugin.approval.resolve涵蓋外掛程式定義的審核流程。
自動化、技能和工具
- 自動化:
wake排定立即或下次心跳喚醒的文字注入;cron.get、cron.list、cron.status、cron.add、cron.update、cron.remove、cron.run和cron.runs管理排定的工作。 cron.run仍是手動執行的佇列式 RPC。需要完成語意的客戶端應讀取傳回的runId並輪詢cron.runs。cron.runs接受可選的非空runId篩選器,因此客戶端可以追蹤一個佇列中的手動執行,而不會與同一工作的其他歷史記錄項目產生競爭。- 技能和工具:
commands.list、skills.*、tools.catalog、tools.effective、tools.invoke。
常見事件系列
Section titled “常見事件系列”chat: UI 聊天更新,例如chat.inject以及其他僅限逐字稿的聊天 事件。在協議 v4 中,增量承載攜帶deltaText;message保持 為累積的助理快照。非前綴替換會設定replace=true並使用deltaText作為替換文字。session.message、session.operation和session.tool:已訂閱 會話的逐字稿、進行中的會話操作和事件串流更新。sessions.changed:會話索引或中繼資料已變更。presence:系統在場快照更新。tick:週期性保活 / 活性事件。health:閘道健康狀態快照更新。heartbeat:心跳事件串流更新。cron: cron 執行/工作變更事件。shutdown:閘道關閉通知。node.pair.requested/node.pair.resolved:節點配對生命週期。node.invoke.request:節點調用請求廣播。device.pair.requested/device.pair.resolved:配對裝置生命週期。voicewake.changed:喚醒詞觸發配置已變更。exec.approval.requested/exec.approval.resolved:執行核准 生命週期。plugin.approval.requested/plugin.approval.resolved:外掛程式核准 生命週期。
節點輔助方法
Section titled “節點輔助方法”- 節點可以呼叫
skills.bins來取得當前的技能可執行檔列表 以進行自動允許檢查。
任務分類帳 RPC
Section titled “任務分類帳 RPC”操作員用戶端可以透過任務分類帳 RPC 檢查並取消閘道背景任務記錄。這些方法會回傳經過清理的任務摘要,而非原始 執行時狀態。
tasks.list需要operator.read。- 參數:可選
status("queued"、"running"、"completed"、"failed"、"cancelled"或"timed_out") 或這些狀態的陣列, 可選agentId、可選sessionKey、可選limit從1到500,以及可選字串cursor。 - 結果:
{ "tasks": TaskSummary[], "nextCursor"?: string }。
- 參數:可選
tasks.get需要operator.read。- 參數:
{ "taskId": string }。 - 結果:
{ "task": TaskSummary }。 - 遺失的任務 id 會回傳閘道找不到的錯誤格式。
- 參數:
tasks.cancel需要operator.write。- 參數:
{ "taskId": string, "reason"?: string }。 - 結果:
{ "found": boolean, "cancelled": boolean, "reason"?: string, "task"?: TaskSummary }。 found回報帳本是否有符合的任務。cancelled回報執行時是否接受或記錄取消。
- 參數:
TaskSummary 包含 id、status 和可選元數據,例如 kind、
runtime、title、agentId、sessionKey、childSessionKey、ownerKey、
runId、taskId、flowId、parentTaskId、sourceId、時間戳記、進度、
終端摘要和已清理的錯誤文本。
操作員輔助方法
Section titled “操作員輔助方法”- 操作員可以呼叫
commands.list(operator.read) 以取得代理程式的 執行時命令清單。agentId是可選的;省略它以讀取預設代理程式工作區。scope控制主要name的目標介面:text傳回主要文本命令 token,不含前導/native和預設的both路徑會在可用時返回供應商感知的原生名稱
textAliases攜帶精確的斜線別名,例如/model和/m。- 當存在供應商感知的原生命令名稱時,
nativeName會攜帶該名稱。 provider是可選的,且僅影響原生命名以及原生外掛程式命令的可用性。includeArgs=false會從回應中省略序列化的參數元資料。
- 操作員可以呼叫
tools.catalog(operator.read) 來擷取代理程式的執行階段工具目錄。回應包含分組的工具和來源元資料:source:core或pluginpluginId:當source="plugin"時為外掛程式擁有者optional:外掛程式工具是否為可選
- 操作員可以呼叫
tools.effective(operator.read) 來擷取工作階段的執行階段有效工具清單。sessionKey是必需的。- 閘道是從伺服器端的工作階段衍生受信任的執行時期內容,而不是接受呼叫者提供的驗證或傳遞內容。
- 回應是作用中清單的會話範圍伺服器衍生投影,包含核心、外掛、通道以及已探索的 MCP 伺服器工具。
tools.effective對於 MCP 是唯讀的:它可以透過最終工具策略投影暖工作階段 MCP 目錄,但不會建立 MCP 執行時、連接傳輸或發出tools/list。如果不存在匹配的暖目錄,回應可能包含通知,例如mcp-not-yet-connected、mcp-not-yet-listed或mcp-stale-catalog。- 有效的工具項目使用
source="core"、source="plugin"、source="channel"或source="mcp"。
- 操作員可以呼叫
tools.invoke(operator.write) 透過與/tools/invoke相同的閘道策略路徑來叫用一個可用工具。name是必填的。args、sessionKey、agentId、confirm和idempotencyKey是選填的。- 如果同時存在
sessionKey和agentId,解析出的 session agent 必須符合agentId。 - 回應是一個面向 SDK 的封包,包含
ok、toolName、選填的output以及具類型的error欄位。核准或策略拒絕會在 payload 中回傳ok:false,而不是 繞過 gateway tool policy pipeline。
- Operators 可以呼叫
skills.status(operator.read) 以取得 agent 的可見技能清單。agentId是選填的;省略它以讀取預設 agent 工作區。- 回應包括資格、缺失需求、配置檢查以及 經過清理的安裝選項,而不會暴露原始秘密值。
- Operators 可以呼叫
skills.search和skills.detail(operator.read) 以取得 ClawHub 探索中繼資料。 - Operators 可以呼叫
skills.upload.begin、skills.upload.chunk和skills.upload.commit(operator.admin) 以在安裝私人技能封存前進行暫存。這是一個供受信任用戶端使用的獨立管理員上傳路徑, 並非一般的 ClawHub 技能安裝流程,且預設為停用,除非skills.install.allowUploadedArchives已啟用。skills.upload.begin({ kind: "skill-archive", slug, sizeBytes, sha256?, force?, idempotencyKey? })會建立一個繫結至該 slug 與 force 值的上傳。skills.upload.chunk({ uploadId, offset, dataBase64 })會在 準確的解碼偏移位置附加位元組。skills.upload.commit({ uploadId, sha256? })會驗證最終大小與 SHA-256。Commit 僅會完成上傳;它不會安裝該技能。- 已上傳的技能封存是包含
SKILL.md根目錄的 zip 封存。 封存內部的目錄名稱從不決定安裝目標。
- Operators 可以三種模式呼叫
skills.install(operator.admin):- ClawHub 模式:
{ source: "clawhub", slug, version?, force? }會將 技能資料夾安裝至預設 agent 工作區的skills/目錄中。 - 上傳模式:
{ source: "upload", uploadId, slug, force?, sha256?, timeoutMs? }將已提交的上傳安裝至預設 agent workspaceskills/<slug>目錄。slug 和 force 值必須符合原始skills.upload.begin請求。除非啟用skills.install.allowUploadedArchives,否則會拒絕此模式。此設定不會 影響 ClawHub 安裝。 - Gateway 安裝程式模式:
{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }在 gateway 主機上執行宣告的metadata.openclaw.install動作。
- ClawHub 模式:
- 操作者可透過兩種模式呼叫
skills.update(operator.admin):- ClawHub 模式會更新預設代理工作區中的一個追蹤 slug 或所有已追蹤的 ClawHub 安裝。
- 設定模式會修補
skills.entries.<skillKey>值,例如enabled、apiKey和env。
models.list 檢視
Section titled “models.list 檢視”models.list 接受一個可選的 view 參數:
- 省略或
"default":目前的執行時行為。若已設定agents.defaults.models,回應為允許的目錄,包括針對provider/*項目動態探索的模型。否則回應為完整的 Gateway 目錄。 "configured":選擇器大小的行為。若已設定agents.defaults.models,它仍優先,包括針對provider/*項目的提供者範圍探索。若無允許清單,回應會使用明確的models.providers.*.models項目,僅在沒有已設定的模型資料列時才回退至完整目錄。"all":完整的 Gateway 目錄,繞過agents.defaults.models。將此用於診斷和探索 UI,而非一般的模型選擇器。
- 當 exec 請求需要批准時,gateway 會廣播
exec.approval.requested。 - 操作者客戶端透過呼叫
exec.approval.resolve來解決(需要operator.approvals範圍)。 - 對於
host=node,exec.approval.request必須包含systemRunPlan(規範argv/cwd/rawCommand/session 元資料)。缺少systemRunPlan的請求會被拒絕。 - 批准後,轉發的
node.invoke system.run呼叫會重複使用該規範systemRunPlan作為授權的 command/cwd/session 上下文。 - 如果呼叫者在 prepare 和最終批准的
system.run轉發之間變更了command、rawCommand、cwd、agentId或sessionKey,閘道會拒絕該次執行,而不是信任變更後的 payload。
Agent 傳送遞補
Section titled “Agent 傳送遞補”agent請求可以包含deliver=true以請求出站傳遞。bestEffortDeliver=false保持嚴格行為:未解析或僅限內部的傳遞目標會傳回INVALID_REQUEST。- 當無法解析外部可傳遞路由時(例如內部/webchat 會話或不明確的多通道配置),
bestEffortDeliver=true允許退回到僅限會話的執行。 - 最終的
agent結果在請求傳遞時可能包含result.deliveryStatus, 使用與openclaw agent --json --deliver中記錄的相同sent、suppressed、partial_failed和failed狀態。
PROTOCOL_VERSION位於packages/gateway-protocol/src/version.ts中。- 用戶端發送
minProtocol+maxProtocol;伺服器會拒絕不包含 其目前協定版本的範圍。目前的用戶端和伺服器需要協定 v4。 - Schema + 模型是從 TypeBox 定義生成的:
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
src/gateway/client.ts 中的參考客戶端使用這些預設值。這些值在 protocol v4 中保持穩定,並且是第三方客戶端的預期基準。
| 常數 | 預設值 | 來源 |
|---|---|---|
PROTOCOL_VERSION | 4 | packages/gateway-protocol/src/version.ts |
MIN_CLIENT_PROTOCOL_VERSION | 4 | packages/gateway-protocol/src/version.ts |
| 請求逾時 (每個 RPC) | 30_000 ms | src/gateway/client.ts (requestTimeoutMs) |
| 預先驗證 / 連線挑戰逾時 | 15_000 ms | src/gateway/handshake-timeouts.ts (config/env can raise the paired server/client budget) |
| 初始重新連線退避 | 1_000 ms | src/gateway/client.ts (backoffMs) |
| 最大重新連線退避 | 30_000 ms | src/gateway/client.ts (scheduleReconnect) |
| 裝置權杖關閉後的快速重試限制 | 250 ms | src/gateway/client.ts |
在 terminate() 之前的強制停止寬限期 | 250 ms | FORCE_STOP_TERMINATE_GRACE_MS |
stopAndWait() 預設逾時 | 1_000 ms | STOP_AND_WAIT_TIMEOUT_MS |
預設 tick 間隔 (pre hello-ok) | 30_000 ms | src/gateway/client.ts |
| Tick-逾時關閉 | 當靜默超過 tickIntervalMs * 2 時回傳 4000 | src/gateway/client.ts |
MAX_PAYLOAD_BYTES | 25 * 1024 * 1024 (25 MB) | src/gateway/server-constants.ts |
伺服器在 hello-ok 中通告有效的 policy.tickIntervalMs、policy.maxPayload 和 policy.maxBufferedBytes;客戶端應該遵守這些值,而不是交握前的預設值。
- 共用金鑰閘道驗證使用
connect.params.auth.token或connect.params.auth.password,具體取決於已配置的驗證模式。 - 承載身分的模式,例如 Tailscale Serve (
gateway.auth.allowTailscale: true) 或非本地迴路gateway.auth.mode: "trusted-proxy",會從請求標頭滿足連線驗證檢查,而不是使用connect.params.auth.*。 - Private-ingress
gateway.auth.mode: "none"會完全跳過 shared-secret 連線驗證;請勿在公開或不受信任的 ingress 上公開該模式。 - 配對後,Gateway 會發出一個範圍限定於連線 role + scopes 的 device token。它會在
hello-ok.auth.deviceToken中返回,客戶端應將其保存以供未來連線使用。 - 客戶端應在任何成功連線後保存主要的
hello-ok.auth.deviceToken。 - 使用該 已儲存 的裝置權杖重新連線時,也應重複使用為該權杖儲存 的已批准範圍集。這保留了已授予的讀取/探測/狀態存取權, 並避免將重新連線靜默收斂為 狹窄的隱含僅限管理員範圍。
- 客戶端連線驗證組裝(
selectConnectAuth於src/gateway/client.ts中):auth.password是正交的,且在設定時總是會被轉發。auth.token按優先順序填入:首先是明確的 shared token, 然後是明確的deviceToken,最後是儲存的每個裝置 token(以deviceId+role為鍵值)。- 僅當上述方法均未解析出
auth.token時,才會發送auth.bootstrapToken。如果有 shared token 或任何已解析的裝置 token,則會抑制發送。 - 在單次
AUTH_TOKEN_MISMATCH重試上自動提升儲存的裝置 token 僅限於 受信任的端點 — loopback,或具有固定tlsFingerprint的wss://。沒有固定的公開wss://不符合資格。
- 內建的 setup-code bootstrap 會在
hello-ok.auth.deviceTokens中傳回主要節點hello-ok.auth.deviceToken以及一個有限的 operator token,用於受信任的行動裝置移交。operator token 包含operator.talk.secrets用於原生 Talk 配置讀取,並排除operator.admin和operator.pairing。 - 當非基準的 setup-code bootstrap 等待核准時,
PAIRING_REQUIRED詳細資訊包括recommendedNextStep: "wait_then_retry"、retryable: true和pauseReconnect: false。客戶端應繼續使用相同的 bootstrap token 重新連線,直到請求被核准或 token 變得無效。 - 僅當連線在
wss://或 loopback/local 配對等受信任的傳輸上使用啟動授權 時,才持續儲存hello-ok.auth.deviceTokens。 - 如果用戶端提供明確的
deviceToken或明確的scopes,該呼叫者請求的範圍集將保持權威性;僅當用戶端重用儲存的每裝置權杖時,才會重用快取的範圍。 - 可以透過
device.token.rotate和device.token.revoke輪替/撤銷裝置權杖(需要operator.pairing範圍)。輪替或撤銷節點或其他非運算者角色也需要operator.admin。 device.token.rotate會傳回輪替中繼資料。它僅對已經使用該裝置權杖進行驗證的相同裝置呼叫回應替換的持有人權杖,因此僅使用權杖的用戶端可以在重新連線之前持續儲存其替換權杖。共用/管理員輪替不會回應持有人權杖。- 權杖的核發、輪替和撤銷僅限於記錄在該裝置配對條目中已核准的角色集合;權杖變更無法擴充或以配對核准從未授予的裝置角色為目標。
- 對於配對裝置權杖階段,裝置管理僅限自身範圍,除非呼叫者也具有
operator.admin:非管理員呼叫者只能管理其自己裝置條目的運算者權杖。節點和其他非運算者權杖管理僅限管理員,即使對於呼叫者自己的裝置也是如此。 device.token.rotate和device.token.revoke也會根據呼叫者的目前階段範圍檢查目標運算者權杖範圍集。非管理員呼叫者無法輪替或撤銷比其目前持有的範圍更廣的運算者權杖。- 授權失敗包括
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的用戶端行為:- 受信任的客戶端可以使用快取的每裝置權杖嘗試一次有界重試。
- 如果該重試失敗,客戶端應停止自動重新連線迴圈,並向操作員顯示操作指引。
AUTH_SCOPE_MISMATCH表示識別出裝置權杖,但其未涵蓋請求的角色/範圍。用戶端不應將此顯示為錯誤的權杖;應提示運算者重新配對或批准較窄/較廣的範圍合約。
裝置身分識別 + 配對
Section titled “裝置身分識別 + 配對”- 節點應包含穩定的裝置識別身份(
device.id),其衍生自金鑰對指紋。 - 閘道會發出每裝置 + 角色的權杖。
- 除非啟用了本機自動核准,否則新裝置 ID 需要配對核准。
- 配對自動核准是以直接本機回送連線為中心。
- OpenClaw 也針對受信任的共用金鑰輔助流程,提供了一個狹隘的後端/容器本機自連線路徑。
- 同主機 tailnet 或 LAN 連線在配對時仍被視為遠端連線,並需要核准。
- WS 客戶端通常在
connect期間包含device識別身份(操作員 + 節點)。唯一無裝置的操作員例外情況屬於明確信任路徑:gateway.controlUi.allowInsecureAuth=true用於僅限本地主機的不安全 HTTP 相容性。- 成功的
gateway.auth.mode: "trusted-proxy"操作員 Control UI 認證。 gateway.controlUi.dangerouslyDisableDeviceAuth=true(緊急破窗,嚴重的安全性降級)。- 使用共用的 gateway token/password 進行驗證的直接迴路
gateway-client後端 RPC。
- 省略裝置識別身份會對範圍產生後果。當 Control UI 連線缺少裝置識別身份時,
shouldClearUnboundScopesForMissingDeviceIdentity會將自行宣告的範圍清除為空集合,適用於 token、password 和 trusted-proxy 認證。此連線在明確信任路徑上是被允許的,但受範圍限制的方法會失敗。例外情況是具有allowInsecureAuth的本機 Control UI token/password 工作階段,這些會保留範圍。對於其他情況,僅將gateway.controlUi.dangerouslyDisableDeviceAuth=true設定為緊急破窗的範圍保留路徑。 - 所有連線都必須簽署伺服器提供的
connect.challengenonce。
裝置認證遷移診斷
Section titled “裝置認證遷移診斷”對於仍使用預先挑戰簽署行為的舊版客戶端,connect 現在會在 error.details.code 下傳回具有穩定 error.details.reason 的 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 載荷進行簽署。
- 在
connect.params.device.nonce中傳送相同的 nonce。 - 建議的簽署 Payload 是
v3,它會綁定platform和deviceFamily, 除此之外還包含 device/client/role/scopes/token/nonce 欄位。 - 為了相容性,舊版
v2簽署仍被接受,但在重新連線時,配對裝置的元數據固定(pinning)仍會控制指令政策。
TLS + 憑證固定
Section titled “TLS + 憑證固定”- WS 連線支援 TLS。
- 用戶端可以選擇性地固定(pin)閘道憑證指紋(請參閱
gateway.tls設定加上gateway.remote.tlsFingerprint或 CLI--tls-fingerprint)。
此協定公開了完整的閘道 API(狀態、頻道、模型、聊天、
代理、會話、節點、審批等)。確切的介面範圍由 packages/gateway-protocol/src/schema.ts 中的 TypeBox schemas 定義。