Gateway
Gateway protocol
โปรโตคอล Gateway WS คือ control plane + การส่งข้อมูลของโหนดแบบเดียว สำหรับ OpenClaw ไคลเอนต์ทั้งหมด (CLI, UI บนเว็บ, แอป macOS, โหนด iOS/Android, โหนดแบบ headless) เชื่อมต่อผ่าน WebSocket และประกาศ บทบาท + ขอบเขต ของตนในช่วง handshake
การส่งข้อมูล
- WebSocket, text frames ที่มี JSON payload
- frame แรก ต้อง เป็นคำขอ
connect - frame ก่อน connect จำกัดไว้ที่ 64 KiB หลัง handshake สำเร็จ ไคลเอนต์
ควรทำตามขีดจำกัด
hello-ok.policy.maxPayloadและhello-ok.policy.maxBufferedBytesเมื่อเปิด diagnostics ไว้ frame ขาเข้าที่ใหญ่เกินและบัฟเฟอร์ขาออกที่ช้าจะปล่อยเหตุการณ์payload.largeก่อนที่ gateway จะปิดหรือทิ้ง frame ที่ได้รับผลกระทบ เหตุการณ์เหล่านี้เก็บ ขนาด ขีดจำกัด พื้นผิว และรหัสเหตุผลที่ปลอดภัย แต่ไม่เก็บเนื้อหาข้อความ เนื้อหาสิ่งแนบ เนื้อหา frame ดิบ token, cookie หรือค่าลับ
Handshake (connect)
Gateway → ไคลเอนต์ (pre-connect challenge):
{ "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 ช่วง startup ไม่เสร็จ คำขอ connect อาจ
ส่งคืนข้อผิดพลาด UNAVAILABLE ที่ลองใหม่ได้ โดยมี details.reason ตั้งเป็น
"startup-sidecars" และมี retryAfterMs ไคลเอนต์ควรลองส่ง response นั้นใหม่
ภายในงบเวลาการเชื่อมต่อโดยรวม แทนที่จะแสดงเป็นความล้มเหลวของ handshake ขั้นสุดท้าย
server, features, snapshot และ policy ทั้งหมดเป็นค่าที่ schema
(packages/gateway-protocol/src/schema/frames.ts) กำหนดว่าต้องมี auth ก็ต้องมีเช่นกัน
และรายงานบทบาท/ขอบเขตที่ negotiate แล้ว pluginSurfaceUrls เป็นค่าไม่บังคับ
และ map ชื่อพื้นผิวของ plugin เช่น canvas ไปยัง URL ที่ host ไว้แบบมีขอบเขต
URL พื้นผิว plugin แบบมีขอบเขตอาจหมดอายุได้ โหนดสามารถเรียก
node.pluginSurface.refresh พร้อม { "surface": "canvas" } เพื่อรับรายการใหม่
ใน pluginSurfaceUrls การ refactor Canvas plugin แบบทดลองไม่รองรับเส้นทางความเข้ากันได้
ที่เลิกใช้แล้วอย่าง canvasHostUrl, canvasCapability หรือ
node.canvas.capability.refresh; ไคลเอนต์ native และ gateway ปัจจุบันต้องใช้พื้นผิว plugin
เมื่อไม่ได้ออก device token, hello-ok.auth จะรายงาน permissions ที่ negotiate แล้ว
โดยไม่มีฟิลด์ token:
{ "auth": { "role": "operator", "scopes": ["operator.read", "operator.write"] }}ไคลเอนต์ backend แบบ same-process ที่เชื่อถือได้ (client.id: "gateway-client",
client.mode: "backend") อาจละ device ได้บนการเชื่อมต่อ loopback โดยตรง
เมื่อยืนยันตัวตนด้วย gateway token/password ที่ใช้ร่วมกัน เส้นทางนี้สงวนไว้สำหรับ
RPC ของ control plane ภายใน และป้องกันไม่ให้ baseline การจับคู่ CLI/device ที่ค้างอยู่
ขวางงาน backend ในเครื่อง เช่น การอัปเดตเซสชัน subagent ไคลเอนต์ระยะไกล
ไคลเอนต์จาก browser-origin, ไคลเอนต์โหนด และไคลเอนต์ device-token/device-identity
แบบชัดเจนยังคงใช้การจับคู่และการตรวจ scope-upgrade ปกติ
เมื่อมีการออก device token, hello-ok จะรวมสิ่งต่อไปนี้ด้วย:
{ "auth": { "deviceToken": "…", "role": "operator", "scopes": ["operator.read", "operator.write"] }}bootstrap ด้วย QR/setup-code ในตัวเป็นเส้นทาง handoff มือถือแบบใหม่ การ connect ด้วย baseline setup-code ที่สำเร็จจะส่งคืน token โหนดหลักพร้อม operator token ที่มีขอบเขตจำกัดหนึ่งรายการ:
{ "auth": { "deviceToken": "…", "role": "node", "scopes": [], "deviceTokens": [ { "deviceToken": "…", "role": "operator", "scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"] } ] }}operator handoff ถูกจำกัดโดยตั้งใจ เพื่อให้การ onboarding ผ่าน QR เริ่ม loop ของ
mobile operator ได้โดยไม่มอบ operator.admin หรือ operator.pairing
ทั้งนี้รวม operator.talk.secrets เพื่อให้ไคลเอนต์ native อ่านการกำหนดค่า Talk
ที่ต้องใช้หลัง bootstrap ได้ ขอบเขต admin และ pairing ที่กว้างขึ้นต้องใช้
การจับคู่ operator หรือ token flow ที่อนุมัติแยกต่างหาก ไคลเอนต์ควรคงค่า
hello-ok.auth.deviceTokens ไว้เฉพาะเมื่อการ connect ใช้ bootstrap auth
บน transport ที่เชื่อถือได้ เช่น wss:// หรือการจับคู่ loopback/local
ตัวอย่างโหนด
{ "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": "…" } }}การจัด frame
- คำขอ:
{type:"req", id, method, params} - Response:
{type:"res", id, ok, payload|error} - เหตุการณ์:
{type:"event", event, payload, seq?, stateVersion?}
method ที่มี side effect ต้องใช้ idempotency keys (ดู schema)
บทบาท + ขอบเขต
สำหรับโมเดลขอบเขต operator ฉบับเต็ม การตรวจช่วงอนุมัติ และความหมายของ shared-secret ดู ขอบเขต operator
บทบาท
operator= ไคลเอนต์ control plane (CLI/UI/automation)node= host ความสามารถ (camera/screen/canvas/system.run)
ขอบเขต (operator)
ขอบเขตที่พบบ่อย:
operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
talk.config พร้อม includeSecrets: true ต้องใช้ operator.talk.secrets
(หรือ operator.admin)
method RPC ของ gateway ที่ plugin ลงทะเบียนอาจขอขอบเขต operator ของตนเองได้ แต่
prefix admin หลักที่สงวนไว้ (config.*, exec.approvals.*, wizard.*,
update.*) จะ resolve เป็น operator.admin เสมอ
ขอบเขตของ method เป็นเพียงด่านแรกเท่านั้น slash command บางรายการที่เข้าถึงผ่าน
chat.send จะใช้การตรวจระดับ command ที่เข้มงวดกว่าเพิ่มเติม เช่น การเขียนถาวร
/config set และ /config unset ต้องใช้ operator.admin
node.pair.approve ยังมีการตรวจขอบเขตช่วงอนุมัติเพิ่มเติม นอกเหนือจากขอบเขต method พื้นฐาน:
- คำขอที่ไม่มี command:
operator.pairing - คำขอที่มี command โหนดที่ไม่ใช่ exec:
operator.pairing+operator.write - คำขอที่รวม
system.run,system.run.prepareหรือsystem.which:operator.pairing+operator.admin
Caps/commands/permissions (โหนด)
โหนดประกาศ capability claims ตอน connect:
caps: หมวดหมู่ความสามารถระดับสูง เช่นcamera,canvas,screen,location,voiceและtalkcommands: allowlist ของ command สำหรับ invokepermissions: toggle แบบละเอียด (เช่นscreen.record,camera.capture)
Gateway ถือค่าสิ่งเหล่านี้เป็น claims และบังคับใช้ allowlist ฝั่ง server
Presence
system-presenceส่งคืนรายการที่ key ด้วย identity ของอุปกรณ์- รายการ Presence รวม
deviceId,rolesและscopesเพื่อให้ UI แสดงหนึ่งแถวต่ออุปกรณ์ได้ แม้อุปกรณ์นั้นจะเชื่อมต่อเป็นทั้ง operator และ node node.listรวมฟิลด์ไม่บังคับlastSeenAtMsและlastSeenReasonโหนดที่เชื่อมต่ออยู่รายงาน เวลาการเชื่อมต่อปัจจุบันเป็นlastSeenAtMsพร้อมเหตุผลconnect; โหนดที่จับคู่แล้วอาจรายงาน presence เบื้องหลังแบบ durable ได้เช่นกัน เมื่อเหตุการณ์โหนดที่เชื่อถือได้อัปเดต metadata การจับคู่ของตน
เหตุการณ์โหนดยังทำงานอยู่เบื้องหลัง
โหนดอาจเรียก 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 เป็น closed enum: background, silent_push, bg_app_refresh,
significant_location, manual หรือ connect string trigger ที่ไม่รู้จักจะถูก normalize เป็น
background โดย gateway ก่อน persistence เหตุการณ์นี้ durable เฉพาะสำหรับเซสชันอุปกรณ์โหนด
ที่ยืนยันตัวตนแล้วเท่านั้น; เซสชันที่ไม่มีอุปกรณ์หรือไม่ได้จับคู่จะส่งคืน handled: false
gateway ที่สำเร็จจะส่งคืนผลลัพธ์แบบมีโครงสร้าง:
{ "ok": true, "event": "node.presence.alive", "handled": true, "reason": "persisted"}gateway รุ่นเก่าอาจยังส่งคืน { "ok": true } สำหรับ node.event; ไคลเอนต์ควรมองว่านั่นเป็น
RPC ที่ได้รับการยืนยันแล้ว ไม่ใช่การ persist presence แบบ durable
การกำหนดขอบเขตเหตุการณ์ broadcast
เหตุการณ์ broadcast ผ่าน WebSocket ที่ server push จะถูก gate ด้วยขอบเขต เพื่อไม่ให้เซสชันที่มีขอบเขตเฉพาะ pairing หรือเฉพาะโหนดรับเนื้อหาเซสชันแบบ passive
- frame ของ chat, agent และ tool-result (รวมถึงเหตุการณ์
agentแบบ streamed และผลลัพธ์ tool call) ต้องมีอย่างน้อยoperator.readเซสชันที่ไม่มีoperator.readจะข้าม frame เหล่านี้ทั้งหมด - broadcast
plugin.*ที่ plugin กำหนด จะถูก gate เป็นoperator.writeหรือoperator.adminขึ้นกับวิธีที่ plugin ลงทะเบียนไว้ - เหตุการณ์สถานะและ transport (
heartbeat,presence,tick, lifecycle connect/disconnect ฯลฯ) ยังคงไม่ถูกจำกัด เพื่อให้ทุกเซสชันที่ยืนยันตัวตนแล้วสังเกตสุขภาพของ transport ได้ - ตระกูลเหตุการณ์ broadcast ที่ไม่รู้จัก จะถูก gate ด้วยขอบเขตโดยค่าเริ่มต้น (fail-closed) เว้นแต่ handler ที่ลงทะเบียนไว้จะผ่อนคลายอย่างชัดเจน
การเชื่อมต่อไคลเอนต์แต่ละรายการเก็บ sequence number ต่อไคลเอนต์ของตนเอง เพื่อให้ broadcast รักษาลำดับ monotonic บน socket นั้น แม้ไคลเอนต์แต่ละรายจะเห็น subset ของ event stream ที่ถูกกรองตามขอบเขตต่างกัน
ตระกูล method RPC ที่พบบ่อย
พื้นผิว WS สาธารณะกว้างกว่าตัวอย่าง handshake/auth ด้านบน นี่ไม่ใช่ dump ที่สร้างขึ้น —
hello-ok.features.methods เป็นรายการ discovery แบบอนุรักษนิยมที่สร้างจาก
src/gateway/server-methods-list.ts บวกกับ export method ของ plugin/channel ที่โหลดแล้ว
ให้ถือว่าเป็น feature discovery ไม่ใช่การแจกแจงครบถ้วนของ src/gateway/server-methods/*.ts
ระบบและตัวตน
healthส่งคืนสแนปช็อตสุขภาพของ Gateway ที่แคชไว้หรือเพิ่งตรวจสอบใหม่diagnostics.stabilityส่งคืนตัวบันทึกเสถียรภาพการวินิจฉัยล่าสุดแบบมีขอบเขต โดยเก็บเมทาดาทาการดำเนินงาน เช่น ชื่อเหตุการณ์ จำนวน ขนาดไบต์ ค่าการอ่านหน่วยความจำ สถานะคิว/เซสชัน ชื่อช่องทาง/Plugin และรหัสเซสชัน ไม่เก็บข้อความแชต เนื้อหา Webhook เอาต์พุตเครื่องมือ เนื้อหาคำขอหรือคำตอบดิบ โทเค็น คุกกี้ หรือค่าลับ ต้องมีขอบเขตการอ่านของผู้ปฏิบัติงานstatusส่งคืนสรุป Gateway แบบ/status; ฟิลด์ที่ละเอียดอ่อนจะรวมเฉพาะสำหรับไคลเอนต์ผู้ปฏิบัติงานที่มีขอบเขตผู้ดูแลระบบgateway.identity.getส่งคืนตัวตนอุปกรณ์ Gateway ที่ใช้โดยโฟลว์รีเลย์และการจับคู่system-presenceส่งคืนสแนปช็อต presence ปัจจุบันสำหรับอุปกรณ์ผู้ปฏิบัติงาน/Node ที่เชื่อมต่ออยู่system-eventเพิ่มเหตุการณ์ระบบและสามารถอัปเดต/บรอดแคสต์บริบท presence ได้last-heartbeatส่งคืนเหตุการณ์ Heartbeat ล่าสุดที่บันทึกถาวรไว้set-heartbeatsสลับการประมวลผล Heartbeat บน Gateway
โมเดลและการใช้งาน
models.listส่งคืนแค็ตตาล็อกโมเดลที่รันไทม์อนุญาต ส่ง{ "view": "configured" }สำหรับโมเดลที่กำหนดค่าแล้วขนาดเหมาะกับตัวเลือก (agents.defaults.modelsก่อน แล้วตามด้วยmodels.providers.*.models) หรือ{ "view": "all" }สำหรับแค็ตตาล็อกทั้งหมดusage.statusส่งคืนสรุปหน้าต่างการใช้งาน/โควตาคงเหลือของผู้ให้บริการusage.costส่งคืนสรุปค่าใช้จ่ายการใช้งานแบบรวมสำหรับช่วงวันที่ ส่งagentIdสำหรับเอเจนต์หนึ่งตัว หรือagentScope: "all"เพื่อรวมเอเจนต์ที่กำหนดค่าไว้doctor.memory.statusส่งคืนความพร้อมของ vector-memory / embedding ที่แคชไว้สำหรับ workspace เอเจนต์เริ่มต้นที่ใช้งานอยู่ ส่ง{ "probe": true }หรือ{ "deep": true }เฉพาะเมื่อผู้เรียกต้องการ ping ผู้ให้บริการ embedding แบบสดอย่างชัดเจน ไคลเอนต์ที่รองรับ Dreaming อาจส่ง{ "agentId": "agent-id" }เพื่อจำกัดสถิติที่เก็บ Dreaming ไปยัง workspace เอเจนต์ที่เลือกได้ด้วย; การละเว้นagentIdจะคง fallback ไปยังเอเจนต์เริ่มต้นและรวม workspace Dreaming ที่กำหนดค่าไว้doctor.memory.dreamDiary,doctor.memory.backfillDreamDiary,doctor.memory.resetDreamDiary,doctor.memory.resetGroundedShortTerm,doctor.memory.repairDreamingArtifacts, และdoctor.memory.dedupeDreamDiaryรับพารามิเตอร์{ "agentId": "agent-id" }แบบไม่บังคับสำหรับมุมมอง/การกระทำ Dreaming ของเอเจนต์ที่เลือก เมื่อละเว้นagentIdจะทำงานกับ workspace เอเจนต์เริ่มต้นที่กำหนดค่าไว้doctor.memory.remHarnessส่งคืนตัวอย่าง REM harness แบบอ่านอย่างเดียวและมีขอบเขตสำหรับไคลเอนต์ control-plane ระยะไกล อาจรวมพาธ workspace, snippet หน่วยความจำ, markdown grounded ที่เรนเดอร์แล้ว และตัวเลือกการโปรโมตเชิงลึก ดังนั้นผู้เรียกต้องมีoperator.readsessions.usageส่งคืนสรุปการใช้งานรายเซสชัน ส่งagentIdสำหรับ เอเจนต์หนึ่งตัว หรือagentScope: "all"เพื่อแสดงเอเจนต์ที่กำหนดค่าไว้ร่วมกันsessions.usage.timeseriesส่งคืนการใช้งานแบบ timeseries สำหรับหนึ่งเซสชันsessions.usage.logsส่งคืนรายการบันทึกการใช้งานสำหรับหนึ่งเซสชัน
ช่องทางและตัวช่วยเข้าสู่ระบบ
channels.statusส่งคืนสรุปสถานะช่องทาง/Plugin แบบ built-in + bundledchannels.logoutออกจากระบบช่องทาง/บัญชีที่ระบุเมื่อช่องทางรองรับการออกจากระบบweb.login.startเริ่มโฟลว์เข้าสู่ระบบ QR/เว็บสำหรับผู้ให้บริการช่องทางเว็บปัจจุบันที่รองรับ QRweb.login.waitรอให้โฟลว์เข้าสู่ระบบ QR/เว็บนั้นเสร็จสมบูรณ์และเริ่มช่องทางเมื่อสำเร็จpush.testส่ง APNs push ทดสอบไปยัง Node iOS ที่ลงทะเบียนไว้voicewake.getส่งคืนทริกเกอร์ wake-word ที่จัดเก็บไว้voicewake.setอัปเดตทริกเกอร์ wake-word และบรอดแคสต์การเปลี่ยนแปลง
การส่งข้อความและบันทึก
sendคือ RPC การส่งออกโดยตรงสำหรับการส่งที่ระบุช่องทาง/บัญชี/thread นอก chat runnerlogs.tailส่งคืนส่วนท้ายบันทึกไฟล์ Gateway ที่กำหนดค่าไว้ พร้อมการควบคุม cursor/limit และ max-byte
Talk และ TTS
talk.catalogส่งคืนแค็ตตาล็อกผู้ให้บริการ Talk แบบอ่านอย่างเดียวสำหรับเสียงพูด การถอดเสียงแบบสตรีม และเสียงแบบเรียลไทม์ โดยรวมรหัสผู้ให้บริการ ป้ายกำกับ สถานะที่กำหนดค่า รหัสโมเดล/เสียงที่เปิดเผย โหมด canonical การขนส่ง กลยุทธ์สมอง และแฟล็กเสียง/ความสามารถแบบเรียลไทม์ โดยไม่ส่งคืนความลับของผู้ให้บริการหรือแก้ไข config ส่วนกลางtalk.configส่งคืน payload config Talk ที่มีผล;includeSecretsต้องใช้operator.talk.secrets(หรือoperator.admin)talk.session.createสร้างเซสชัน Talk ที่ Gateway เป็นเจ้าของสำหรับrealtime/gateway-relay,transcription/gateway-relay, หรือstt-tts/managed-roomสำหรับstt-tts/managed-roomผู้เรียกoperator.writeที่ส่งsessionKeyต้องส่งspawnedByด้วยเพื่อการมองเห็น session-key แบบมีขอบเขต; การสร้างsessionKeyแบบไม่มีขอบเขตและbrain: "direct-tools"ต้องใช้operator.admintalk.session.joinตรวจสอบโทเค็นเซสชัน managed-room, ปล่อยเหตุการณ์session.readyหรือsession.replacedตามจำเป็น และส่งคืนเมทาดาทาห้อง/เซสชันพร้อมเหตุการณ์ Talk ล่าสุด โดยไม่มีโทเค็นข้อความล้วนหรือแฮชโทเค็นที่จัดเก็บไว้talk.session.appendAudioเพิ่มเสียงอินพุต PCM แบบ base64 ไปยังเซสชันรีเลย์เรียลไทม์และถอดเสียงที่ Gateway เป็นเจ้าของtalk.session.startTurn,talk.session.endTurn, และtalk.session.cancelTurnขับเคลื่อน lifecycle ของ turn ใน managed-room พร้อมปฏิเสธ stale-turn ก่อนล้างสถานะtalk.session.cancelOutputหยุดเอาต์พุตเสียงของผู้ช่วย โดยหลักสำหรับการแทรกพูดที่ gated ด้วย VAD ในเซสชันรีเลย์ Gatewaytalk.session.submitToolResultทำให้การเรียกเครื่องมือของผู้ให้บริการที่ปล่อยโดยเซสชันรีเลย์เรียลไทม์ที่ Gateway เป็นเจ้าของเสร็จสมบูรณ์ ส่งoptions: { willContinue: true }สำหรับเอาต์พุตเครื่องมือชั่วคราวเมื่อจะมีผลลัพธ์สุดท้ายตามมา หรือoptions: { suppressResponse: true }เมื่อผลลัพธ์เครื่องมือควรทำให้การเรียกผู้ให้บริการสำเร็จโดยไม่เริ่มคำตอบผู้ช่วยเรียลไทม์อีกครั้งtalk.session.steerส่งการควบคุมเสียงของ active-run เข้าไปยังเซสชัน Talk ที่มีเอเจนต์รองรับและ Gateway เป็นเจ้าของ โดยรับ{ sessionId, text, mode? }ซึ่งmodeคือstatus,steer,cancel, หรือfollowup; โหมดที่ละเว้นจะถูกจัดประเภทจากข้อความพูดtalk.session.closeปิดเซสชันรีเลย์ ถอดเสียง หรือ managed-room ที่ Gateway เป็นเจ้าของ และปล่อยเหตุการณ์ Talk ปลายทางtalk.modeตั้งค่า/บรอดแคสต์สถานะโหมด Talk ปัจจุบันสำหรับไคลเอนต์ WebChat/Control UItalk.client.createสร้างเซสชันผู้ให้บริการเรียลไทม์ที่ไคลเอนต์เป็นเจ้าของโดยใช้webrtcหรือprovider-websocketขณะที่ Gateway เป็นเจ้าของ config, ข้อมูลประจำตัว, คำสั่ง และนโยบายเครื่องมือtalk.client.toolCallให้การขนส่งเรียลไทม์ที่ไคลเอนต์เป็นเจ้าของส่งต่อการเรียกเครื่องมือของผู้ให้บริการไปยังนโยบาย Gateway เครื่องมือที่รองรับตัวแรกคือopenclaw_agent_consult; ไคลเอนต์ได้รับรหัส run และรอเหตุการณ์ lifecycle แชตปกติก่อนส่งผลลัพธ์เครื่องมือเฉพาะผู้ให้บริการtalk.client.steerส่งการควบคุมเสียงของ active-run สำหรับการขนส่งเรียลไทม์ที่ไคลเอนต์เป็นเจ้าของ Gateway จะแก้ active embedded run จากsessionKeyและส่งคืนผลลัพธ์ accepted/rejected แบบมีโครงสร้างแทนการทิ้ง steering อย่างเงียบ ๆtalk.eventคือช่องทางเหตุการณ์ Talk เดียวสำหรับอะแดปเตอร์เรียลไทม์ การถอดเสียง STT/TTS, managed-room, โทรศัพท์ และการประชุมtalk.speakสังเคราะห์เสียงพูดผ่านผู้ให้บริการเสียงพูด Talk ที่ใช้งานอยู่tts.statusส่งคืนสถานะเปิดใช้งาน TTS ผู้ให้บริการที่ใช้งานอยู่ ผู้ให้บริการ fallback และสถานะ config ผู้ให้บริการtts.providersส่งคืน inventory ผู้ให้บริการ TTS ที่มองเห็นได้tts.enableและtts.disableสลับสถานะ prefs ของ TTStts.setProviderอัปเดตผู้ให้บริการ TTS ที่ต้องการtts.convertรันการแปลงข้อความเป็นเสียงแบบครั้งเดียว
ความลับ config การอัปเดต และ wizard
secrets.reloadresolveSecretRefsที่ใช้งานอยู่อีกครั้งและสลับสถานะความลับของรันไทม์เฉพาะเมื่อสำเร็จทั้งหมดsecrets.resolveresolve การกำหนดความลับเป้าหมายคำสั่งสำหรับชุดคำสั่ง/เป้าหมายที่ระบุconfig.getส่งคืนสแนปช็อต config ปัจจุบันและแฮชconfig.setเขียน payload config ที่ตรวจสอบแล้วconfig.patchรวมการอัปเดต config บางส่วน การแทนที่อาร์เรย์แบบทำลาย ต้องมีพาธที่ได้รับผลกระทบในreplacePaths; อาร์เรย์ซ้อน ภายใต้รายการอาร์เรย์ใช้พาธ[]เช่นagents.list[].skillsconfig.applyตรวจสอบ + แทนที่ payload config ทั้งหมดconfig.schemaส่งคืน payload schema config สดที่ใช้โดย Control UI และเครื่องมือ CLI: schema,uiHints, เวอร์ชัน และเมทาดาทาการสร้าง รวมถึงเมทาดาทา schema ของ Plugin + ช่องทางเมื่อรันไทม์โหลดได้ schema รวมเมทาดาทาฟิลด์title/descriptionที่ได้จากป้ายกำกับและข้อความช่วยเหลือเดียวกับที่ UI ใช้ รวมถึง object ซ้อน, wildcard, array-item และ branch การประกอบanyOf/oneOf/allOfเมื่อมีเอกสารฟิลด์ที่ตรงกันconfig.schema.lookupส่งคืน payload lookup ที่จำกัดด้วยพาธสำหรับหนึ่งพาธ config: พาธที่ normalize แล้ว, node schema แบบตื้น, hint ที่ตรงกัน +hintPath,reloadKindแบบไม่บังคับ และสรุปลูกทันทีสำหรับการเจาะลึก UI/CLIreloadKindเป็นหนึ่งในrestart,hot, หรือnoneและสะท้อน planner การ reload config ของ Gateway สำหรับพาธที่ร้องขอ node schema ของ lookup จะคงเอกสารที่ผู้ใช้เห็นและฟิลด์ตรวจสอบทั่วไป (title,description,type,enum,const,format,pattern, ขอบเขต numeric/string/array/object และแฟล็กเช่นadditionalProperties,deprecated,readOnly,writeOnly) สรุปลูกเปิดเผยkey,pathที่ normalize แล้ว,type,required,hasChildren,reloadKindแบบไม่บังคับ รวมถึงhint/hintPathที่ตรงกันupdate.runรันโฟลว์อัปเดต Gateway และจัดกำหนดการรีสตาร์ทเฉพาะเมื่อการอัปเดตเองสำเร็จ; ผู้เรียกที่มีเซสชันสามารถรวมcontinuationMessageเพื่อให้ startup กลับมาทำ agent turn ติดตามผลหนึ่งครั้งผ่านคิว restart continuation การอัปเดตผ่าน package-manager และการอัปเดต git-checkout ที่มีการควบคุมจาก control plane ใช้การส่งต่อไปยัง managed-service แบบ detached แทนการแทนที่ package tree หรือแก้ไขเอาต์พุต checkout/build ภายใน Gateway ที่กำลังทำงาน handoff ที่เริ่มแล้วส่งคืนok: trueพร้อมresult.reason: "managed-service-handoff-started"และhandoff.status: "started"; handoff ที่ไม่พร้อมใช้งานหรือล้มเหลวส่งคืนok: falseพร้อมmanaged-service-handoff-unavailableหรือmanaged-service-handoff-failedรวมถึงhandoff.commandเมื่อจำเป็นต้องอัปเดต shell ด้วยตนเอง handoff ที่ไม่พร้อมใช้งานหมายความว่า OpenClaw ไม่มีขอบเขต supervisor ที่ปลอดภัยหรือตัวตนบริการที่ทนทาน เช่นOPENCLAW_SYSTEMD_UNITสำหรับ systemd ระหว่าง handoff ที่เริ่มแล้ว restart sentinel อาจรายงานstats.reason: "restart-health-pending"ชั่วครู่; continuation จะถูกหน่วงจนกว่า CLI จะตรวจสอบ Gateway ที่รีสตาร์ทแล้วและเขียน sentinelokสุดท้ายupdate.statusรีเฟรชและส่งคืน restart sentinel การอัปเดตล่าสุด รวมถึงเวอร์ชันที่ทำงานอยู่หลังรีสตาร์ทเมื่อมีwizard.start,wizard.next,wizard.status, และwizard.cancelเปิดเผย onboarding wizard ผ่าน WS RPC
ตัวช่วยเอเจนต์และเวิร์กสเปซ
agents.listส่งคืนรายการเอเจนต์ที่กำหนดค่าไว้ รวมถึงโมเดลที่มีผลใช้งานและเมทาดาทารันไทม์agents.create,agents.updateและagents.deleteจัดการระเบียนเอเจนต์และการเชื่อมโยงเวิร์กสเปซagents.files.list,agents.files.getและagents.files.setจัดการไฟล์เวิร์กสเปซเริ่มต้นที่เปิดเผยให้เอเจนต์ใช้งานtasks.list,tasks.getและtasks.cancelเปิดเผยบัญชีแยกประเภทธุรกรรมงานของ Gateway ให้ไคลเอนต์ SDK และผู้ปฏิบัติงานใช้งานartifacts.list,artifacts.getและartifacts.downloadเปิดเผยสรุปอาร์ติแฟกต์ที่ได้จากทรานสคริปต์และการดาวน์โหลดสำหรับขอบเขตsessionKey,runIdหรือtaskIdที่ระบุชัดเจน การสืบค้นรันและงานจะแก้ไขเซสชันเจ้าของที่ฝั่งเซิร์ฟเวอร์ และส่งคืนเฉพาะสื่อทรานสคริปต์ที่มีแหล่งที่มาตรงกันเท่านั้น แหล่ง URL ที่ไม่ปลอดภัยหรือเป็นโลคัลจะส่งคืนการดาวน์โหลดที่ไม่รองรับแทนการดึงข้อมูลฝั่งเซิร์ฟเวอร์environments.listและenvironments.statusเปิดเผยการค้นหาสภาพแวดล้อมแบบอ่านอย่างเดียวของ Gateway โลคัลและ Node ให้ไคลเอนต์ SDK ใช้งาน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.injectchat.historyถูกปรับให้อยู่ในรูปแบบการแสดงผลสำหรับไคลเอนต์ UI: แท็กคำสั่งแบบอินไลน์จะถูกตัดออกจากข้อความที่มองเห็นได้, เพย์โหลด XML ของการเรียกเครื่องมือแบบข้อความธรรมดา (รวมถึง<tool_call>...</tool_call>,<function_call>...</function_call>,<tool_calls>...</tool_calls>,<function_calls>...</function_calls>และบล็อกการเรียกเครื่องมือที่ถูกตัดทอน) และโทเค็นควบคุมโมเดล ASCII/เต็มความกว้างที่รั่วออกมาจะถูกตัดออก, แถวผู้ช่วยที่เป็นโทเค็นเงียบล้วน เช่นNO_REPLY/no_replyแบบตรงตัวจะถูกละไว้ และแถวที่ใหญ่เกินไปอาจถูกแทนที่ด้วยตัวยึดตำแหน่ง chat.message.getเป็นตัวอ่านข้อความเต็มแบบจำกัดขอบเขตที่เพิ่มเข้ามาสำหรับรายการทรานสคริปต์ที่มองเห็นได้รายการเดียว ไคลเอนต์ส่งsessionKey,agentIdที่ไม่บังคับเมื่อการเลือกเซสชันถูกกำหนดขอบเขตตามเอเจนต์ พร้อมmessageIdของทรานสคริปต์ที่เคยแสดงผ่านchat.historyและ Gateway จะส่งคืนโปรเจกชันที่ปรับให้อยู่ในรูปแบบการแสดงผลเดียวกันโดยไม่มีเพดานการตัดทอนประวัติแบบเบา เมื่อรายการที่จัดเก็บไว้ยังมีอยู่และไม่ใหญ่เกินไปchat.sendรับfastMode: "auto"แบบหนึ่งเทิร์นเพื่อใช้โหมดเร็วสำหรับการเรียกโมเดลที่เริ่มก่อนจุดตัดอัตโนมัติ จากนั้นจึงเริ่มการเรียกลองใหม่ภายหลัง, สำรอง, ผลลัพธ์เครื่องมือ หรือการเรียกต่อเนื่องโดยไม่ใช้โหมดเร็ว จุดตัดมีค่าเริ่มต้นเป็น 60 วินาที และสามารถกำหนดค่าต่อโมเดลได้ด้วยagents.defaults.models["<provider>/<model>"].params.fastAutoOnSecondsผู้เรียกchat.sendสามารถส่งfastAutoOnSecondsแบบหนึ่งเทิร์นเพื่อแทนที่จุดตัดสำหรับคำขอนั้น
การจับคู่อุปกรณ์และโทเค็นอุปกรณ์
device.pair.listส่งคืนอุปกรณ์ที่จับคู่แล้วซึ่งรอดำเนินการและได้รับอนุมัติdevice.pair.approve,device.pair.rejectและdevice.pair.removeจัดการระเบียนการจับคู่อุปกรณ์device.token.rotateหมุนเวียนโทเค็นอุปกรณ์ที่จับคู่แล้วภายในขอบเขตบทบาทที่ได้รับอนุมัติและขอบเขตผู้เรียกdevice.token.revokeเพิกถอนโทเค็นอุปกรณ์ที่จับคู่แล้วภายในขอบเขตบทบาทที่ได้รับอนุมัติและขอบเขตผู้เรียก
การจับคู่ Node, การเรียกใช้ และงานที่รอดำเนินการ
node.pair.request,node.pair.list,node.pair.approve,node.pair.reject,node.pair.removeและnode.pair.verifyครอบคลุมการจับคู่ Node และการตรวจสอบการเริ่มต้นnode.listและnode.describeส่งคืนสถานะ Node ที่รู้จัก/เชื่อมต่ออยู่node.renameอัปเดตป้ายกำกับ Node ที่จับคู่แล้วnode.invokeส่งต่อคำสั่งไปยัง Node ที่เชื่อมต่ออยู่node.invoke.resultส่งคืนผลลัพธ์สำหรับคำขอเรียกใช้node.eventนำเหตุการณ์ที่มีต้นทางจาก Node กลับเข้าสู่ Gatewaynode.pending.pullและnode.pending.ackเป็น API คิวของ Node ที่เชื่อมต่ออยู่node.pending.enqueueและnode.pending.drainจัดการงานที่รอดำเนินการแบบคงทนสำหรับ Node ที่ออฟไลน์/ตัดการเชื่อมต่อ
กลุ่มการอนุมัติ
exec.approval.request,exec.approval.get,exec.approval.listและexec.approval.resolveครอบคลุมคำขออนุมัติการ exec แบบครั้งเดียว พร้อมการค้นหา/เล่นซ้ำการอนุมัติที่รอดำเนินการexec.approval.waitDecisionรอการอนุมัติการ exec ที่รอดำเนินการหนึ่งรายการและส่งคืนการตัดสินใจสุดท้าย (หรือnullเมื่อหมดเวลา)exec.approvals.getและexec.approvals.setจัดการสแนปช็อตนโยบายการอนุมัติการ exec ของ Gatewayexec.approvals.node.getและexec.approvals.node.setจัดการนโยบายการอนุมัติการ exec แบบโลคัลของ Node ผ่านคำสั่งรีเลย์ Nodeplugin.approval.request,plugin.approval.list,plugin.approval.waitDecisionและplugin.approval.resolveครอบคลุมโฟลว์การอนุมัติที่กำหนดโดย Plugin
ระบบอัตโนมัติ, Skills และเครื่องมือ
- ระบบอัตโนมัติ:
wakeกำหนดเวลาการแทรกข้อความปลุกแบบทันทีหรือใน Heartbeat ถัดไป;cron.get,cron.list,cron.status,cron.add,cron.update,cron.remove,cron.run,cron.runsจัดการงานที่กำหนดเวลาไว้ cron.runยังคงเป็น RPC แบบเข้าคิวสำหรับการรันด้วยตนเอง ไคลเอนต์ที่ต้องการความหมายของการเสร็จสมบูรณ์ควรอ่านrunIdที่ส่งคืนและโพลcron.runscron.runsรับตัวกรองrunIdที่ไม่บังคับและไม่ว่าง เพื่อให้ไคลเอนต์ติดตามการรันด้วยตนเองที่อยู่ในคิวหนึ่งรายการได้โดยไม่แข่งกับรายการประวัติอื่นของงานเดียวกัน- Skills และเครื่องมือ:
commands.list,skills.*,tools.catalog,tools.effective,tools.invoke.
กลุ่มเหตุการณ์ทั่วไป
chat: การอัปเดตแชท UI เช่นchat.injectและเหตุการณ์แชทอื่นที่เป็นทรานสคริปต์เท่านั้น ในโปรโตคอล v4 เพย์โหลดเดลตาจะมีdeltaText;messageยังคงเป็น สแนปช็อตผู้ช่วยแบบสะสม การแทนที่ที่ไม่ใช่คำนำหน้าจะตั้งreplace=trueและใช้deltaTextเป็นข้อความแทนที่session.message,session.operationและsession.tool: การอัปเดตทรานสคริปต์, การดำเนินการเซสชันที่กำลังทำงาน และสตรีมเหตุการณ์สำหรับเซสชัน ที่สมัครรับไว้sessions.changed: ดัชนีเซสชันหรือเมทาดาทาเปลี่ยนแปลงpresence: การอัปเดตสแนปช็อตสถานะระบบtick: เหตุการณ์ keepalive / liveness เป็นระยะhealth: การอัปเดตสแนปช็อตสุขภาพของ Gatewayheartbeat: การอัปเดตสตรีมเหตุการณ์ Heartbeatcron: เหตุการณ์เปลี่ยนแปลงรัน/งาน Cronshutdown: การแจ้งเตือนการปิด Gatewaynode.pair.requested/node.pair.resolved: วงจรชีวิตการจับคู่ Nodenode.invoke.request: การบรอดแคสต์คำขอเรียกใช้ Nodedevice.pair.requested/device.pair.resolved: วงจรชีวิตของอุปกรณ์ที่จับคู่แล้วvoicewake.changed: การกำหนดค่าทริกเกอร์คำปลุกเปลี่ยนแปลงexec.approval.requested/exec.approval.resolved: วงจรชีวิตการอนุมัติการ execplugin.approval.requested/plugin.approval.resolved: วงจรชีวิตการอนุมัติ Plugin
เมธอดตัวช่วย Node
- Node อาจเรียก
skills.binsเพื่อดึงรายการปัจจุบันของไฟล์ปฏิบัติการ Skills สำหรับการตรวจสอบอนุญาตอัตโนมัติ
RPC บัญชีแยกประเภทธุรกรรมงาน
ไคลเอนต์ผู้ปฏิบัติงานอาจตรวจสอบและยกเลิกระเบียนงานเบื้องหลังของ Gateway ผ่าน 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 งานที่ขาดหายจะส่งคืนรูปแบบข้อผิดพลาดไม่พบของ Gateway
- พารามิเตอร์:
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, ไทม์สแตมป์, ความคืบหน้า,
สรุปปลายทาง และข้อความข้อผิดพลาดที่ผ่านการล้างข้อมูลแล้ว agentId ระบุเอเจนต์
ที่ดำเนินงาน; sessionKey และ ownerKey รักษาบริบทผู้ร้องขอและการควบคุมไว้
เมธอดตัวช่วยผู้ปฏิบัติงาน
- ผู้ปฏิบัติงานสามารถเรียก
commands.list(operator.read) เพื่อดึงรายการคำสั่งรันไทม์สำหรับเอเจนต์ได้agentIdเป็นค่าที่ไม่บังคับ; ละไว้เพื่ออ่านเวิร์กสเปซเอเจนต์เริ่มต้นscopeควบคุมว่าพื้นผิวใดที่nameหลักจะกำหนดเป้าหมาย:textส่งคืนโทเค็นคำสั่งข้อความหลักโดยไม่มี/นำหน้าnativeและพาธเริ่มต้นbothจะส่งคืนชื่อแบบเนทีฟที่รับรู้ผู้ให้บริการเมื่อมี
textAliasesมีนามแฝงแบบสแลชที่ตรงตัว เช่น/modelและ/mnativeNameมีชื่อคำสั่งแบบเนทีฟที่รับรู้ผู้ให้บริการเมื่อมีอยู่providerเป็นค่าที่ไม่บังคับ และมีผลเฉพาะกับการตั้งชื่อแบบเนทีฟรวมถึงความพร้อมใช้งานของคำสั่ง Plugin แบบเนทีฟincludeArgs=falseละเว้นเมทาดาทาอาร์กิวเมนต์แบบทำให้เป็นอนุกรมจากการตอบกลับ
- ผู้ปฏิบัติงานสามารถเรียก
tools.catalog(operator.read) เพื่อดึงแค็ตตาล็อกเครื่องมือรันไทม์สำหรับเอเจนต์ได้ การตอบกลับรวมเครื่องมือที่จัดกลุ่มและเมทาดาทาแหล่งที่มา:source:coreหรือpluginpluginId: เจ้าของ Plugin เมื่อsource="plugin"optional: ระบุว่าเครื่องมือ Plugin เป็นแบบไม่บังคับหรือไม่
- ผู้ปฏิบัติงานสามารถเรียก
tools.effective(operator.read) เพื่อดึงรายการเครื่องมือที่มีผลในรันไทม์สำหรับเซสชันได้- ต้องระบุ
sessionKey - Gateway อนุมานบริบทรันไทม์ที่เชื่อถือได้จากเซสชันฝั่งเซิร์ฟเวอร์ แทนการยอมรับบริบทการยืนยันตัวตนหรือการส่งมอบที่ผู้เรียกส่งมา
- การตอบกลับเป็นการฉายภาพที่อนุมานจากเซิร์ฟเวอร์ตามขอบเขตเซสชันของรายการที่ใช้งานอยู่ รวมถึงเครื่องมือของคอร์, Plugin, ช่องทาง และเครื่องมือเซิร์ฟเวอร์ 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) เพื่อเรียกใช้เครื่องมือที่พร้อมใช้งานหนึ่งรายการผ่านพาธนโยบาย Gateway เดียวกับ/tools/invoke- ต้องระบุ
nameส่วนargs,sessionKey,agentId,confirmและidempotencyKeyเป็นค่าที่ไม่บังคับ - หากมีทั้ง
sessionKeyและagentIdเอเจนต์ของเซสชันที่ resolve แล้วต้องตรงกับagentId - ตัวครอบคอร์เฉพาะเจ้าของ เช่น
cron,gatewayและnodesต้องมีตัวตนเจ้าของ/ผู้ดูแลระบบ (operator.admin) แม้ว่าเมธอดtools.invokeเองจะเป็นoperator.write - การตอบกลับเป็น envelope สำหรับ SDK ที่มี
ok,toolName,outputที่ไม่บังคับ และฟิลด์errorแบบมีชนิด การอนุมัติหรือการปฏิเสธตามนโยบายจะส่งคืนok:falseในเพย์โหลด แทนที่จะข้ามไปป์ไลน์นโยบายเครื่องมือของ Gateway
- ต้องระบุ
- ผู้ปฏิบัติงานสามารถเรียก
skills.status(operator.read) เพื่อดึงรายการ skill ที่มองเห็นได้สำหรับเอเจนต์agentIdเป็นค่าที่ไม่บังคับ; ละไว้เพื่ออ่านเวิร์กสเปซเอเจนต์เริ่มต้น- การตอบกลับรวมคุณสมบัติที่เข้าเกณฑ์, ข้อกำหนดที่ขาดหาย, การตรวจสอบค่ากำหนด และตัวเลือกการติดตั้งที่ผ่านการทำให้ปลอดภัยโดยไม่เปิดเผยค่าความลับดิบ
- ผู้ปฏิบัติงานสามารถเรียก
skills.searchและskills.detail(operator.read) สำหรับเมทาดาทาการค้นพบของ ClawHub - ผู้ปฏิบัติงานสามารถเรียก
skills.upload.begin,skills.upload.chunkและskills.upload.commit(operator.admin) เพื่อจัดเตรียมไฟล์เก็บถาวร skill ส่วนตัวก่อนติดตั้งได้ นี่เป็นพาธอัปโหลดสำหรับผู้ดูแลระบบแยกต่างหากสำหรับไคลเอนต์ที่เชื่อถือได้ ไม่ใช่โฟลว์การติดตั้ง skill ของ ClawHub ตามปกติ และถูกปิดใช้งานเป็นค่าเริ่มต้น เว้นแต่จะเปิดใช้skills.install.allowUploadedArchivesskills.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- ไฟล์เก็บถาวร skill ที่อัปโหลดเป็นไฟล์ zip ที่มีราก
SKILL.mdชื่อไดเรกทอรีภายในไฟล์เก็บถาวรจะไม่เลือกเป้าหมายการติดตั้ง
- ผู้ปฏิบัติงานสามารถเรียก
skills.install(operator.admin) ได้ในสามโหมด:- โหมด ClawHub:
{ source: "clawhub", slug, version?, force? }ติดตั้งโฟลเดอร์ skill ลงในไดเรกทอรีskills/ของเวิร์กสเปซเอเจนต์เริ่มต้น - โหมดอัปโหลด:
{ source: "upload", uploadId, slug, force?, sha256?, timeoutMs? }ติดตั้งการอัปโหลดที่ commit แล้วลงในไดเรกทอรีskills/<slug>ของเวิร์กสเปซเอเจนต์เริ่มต้น ค่า slug และ force ต้องตรงกับคำขอskills.upload.beginเดิม โหมดนี้จะถูกปฏิเสธเว้นแต่เปิดใช้skills.install.allowUploadedArchivesการตั้งค่านี้ไม่มีผลต่อการติดตั้ง ClawHub - โหมดตัวติดตั้ง Gateway:
{ name, installId, timeoutMs? }เรียกใช้แอ็กชันmetadata.openclaw.installที่ประกาศไว้บนโฮสต์ gateway ไคลเอนต์รุ่นเก่าอาจยังส่งdangerouslyForceUnsafeInstall; ฟิลด์นี้เลิกใช้แล้ว ยอมรับเฉพาะเพื่อความเข้ากันได้ของโปรโตคอล และถูกละเว้น ใช้security.installPolicyสำหรับการตัดสินใจติดตั้งที่ผู้ปฏิบัติงานเป็นเจ้าของ
- โหมด ClawHub:
- ผู้ปฏิบัติงานสามารถเรียก
skills.update(operator.admin) ได้ในสองโหมด:- โหมด ClawHub อัปเดต slug ที่ติดตามหนึ่งรายการหรือการติดตั้ง ClawHub ที่ติดตามทั้งหมดในเวิร์กสเปซเอเจนต์เริ่มต้น
- โหมดค่ากำหนดแพตช์ค่า
skills.entries.<skillKey>เช่นenabled,apiKeyและenv
มุมมอง models.list
models.list ยอมรับพารามิเตอร์ view ที่ไม่บังคับ:
- ละไว้หรือ
"default": พฤติกรรมรันไทม์ปัจจุบัน หากกำหนดค่าagents.defaults.modelsไว้ การตอบกลับคือแค็ตตาล็อกที่อนุญาต รวมถึงโมเดลที่ค้นพบแบบไดนามิกสำหรับรายการprovider/*มิฉะนั้นการตอบกลับคือแค็ตตาล็อก Gateway แบบเต็ม "configured": พฤติกรรมขนาดพอดีกับตัวเลือก หากกำหนดค่าagents.defaults.modelsไว้ ค่านั้นยังคงมีผลเหนือกว่า รวมถึงการค้นพบตามขอบเขตผู้ให้บริการสำหรับรายการprovider/*หากไม่มี allowlist การตอบกลับจะใช้รายการmodels.providers.*.modelsที่ระบุชัดเจน โดยถอยกลับไปใช้แค็ตตาล็อกเต็มเฉพาะเมื่อไม่มีแถวโมเดลที่กำหนดค่าไว้"all": แค็ตตาล็อก Gateway แบบเต็ม โดยข้ามagents.defaults.modelsใช้สิ่งนี้สำหรับการวินิจฉัยและ UI การค้นพบ ไม่ใช่ตัวเลือกโมเดลตามปกติ
การอนุมัติ Exec
- เมื่อคำขอ exec ต้องการการอนุมัติ gateway จะกระจาย
exec.approval.requested - ไคลเอนต์ผู้ปฏิบัติงาน resolve โดยเรียก
exec.approval.resolve(ต้องมีขอบเขตoperator.approvals) - สำหรับ
host=nodeต้องมีsystemRunPlanในexec.approval.request(argv/cwd/rawCommand/เมทาดาทาเซสชันแบบ canonical) คำขอที่ไม่มีsystemRunPlanจะถูกปฏิเสธ - หลังการอนุมัติ การเรียก
node.invoke system.runที่ส่งต่อจะใช้systemRunPlanแบบ canonical นั้นซ้ำเป็นบริบทคำสั่ง/cwd/เซสชันที่มีอำนาจ - หากผู้เรียกแก้ไข
command,rawCommand,cwd,agentIdหรือsessionKeyระหว่างการเตรียมและการส่งต่อsystem.runที่ได้รับอนุมัติขั้นสุดท้าย gateway จะปฏิเสธการรันแทนการเชื่อถือเพย์โหลดที่ถูกแก้ไข
ทางเลือกสำรองการส่งมอบของเอเจนต์
- คำขอ
agentสามารถรวมdeliver=trueเพื่อขอการส่งมอบออกภายนอกได้ bestEffortDeliver=falseคงพฤติกรรมแบบเข้มงวด: เป้าหมายการส่งมอบที่ resolve ไม่ได้หรือเป็นภายในเท่านั้นจะส่งคืนINVALID_REQUESTbestEffortDeliver=trueอนุญาตให้ถอยกลับไปดำเนินการเฉพาะเซสชันเมื่อไม่สามารถ resolve เส้นทางที่ส่งมอบภายนอกได้ (เช่น เซสชันภายใน/webchat หรือค่ากำหนดหลายช่องทางที่กำกวม)- ผลลัพธ์
agentขั้นสุดท้ายอาจรวมresult.deliveryStatusเมื่อมีการร้องขอการส่งมอบ โดยใช้สถานะsent,suppressed,partial_failedและfailedเดียวกับที่จัดทำเอกสารไว้สำหรับopenclaw agent --json --deliver
การกำหนดเวอร์ชัน
PROTOCOL_VERSIONอยู่ในpackages/gateway-protocol/src/version.ts- ไคลเอนต์ส่ง
minProtocol+maxProtocol; เซิร์ฟเวอร์ปฏิเสธช่วงที่ไม่รวมโปรโตคอลปัจจุบันของตน ไคลเอนต์และเซิร์ฟเวอร์ปัจจุบันต้องใช้โปรโตคอล v4 - Schemas + models สร้างจากนิยาม TypeBox:
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
ค่าคงที่ของไคลเอนต์
ไคลเอนต์อ้างอิงใน src/gateway/client.ts ใช้ค่าเริ่มต้นเหล่านี้ ค่ามีเสถียรภาพตลอดโปรโตคอล v4 และเป็น baseline ที่คาดหวังสำหรับไคลเอนต์บุคคลที่สาม
| ค่าคงที่ | ค่าเริ่มต้น | แหล่งที่มา |
|---|---|---|
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) |
| หมดเวลา Preauth / connect-challenge | 15_000 ms |
src/gateway/handshake-timeouts.ts (config/env สามารถเพิ่มงบประมาณเซิร์ฟเวอร์/ไคลเอนต์แบบจับคู่ได้) |
| backoff การเชื่อมต่อใหม่เริ่มต้น | 1_000 ms |
src/gateway/client.ts (backoffMs) |
| backoff การเชื่อมต่อใหม่สูงสุด | 30_000 ms |
src/gateway/client.ts (scheduleReconnect) |
| clamp การลองซ้ำเร็วหลังปิด device-token | 250 ms |
src/gateway/client.ts |
ระยะผ่อนผัน force-stop ก่อน terminate() |
250 ms |
FORCE_STOP_TERMINATE_GRACE_MS |
หมดเวลาเริ่มต้นของ stopAndWait() |
1_000 ms |
STOP_AND_WAIT_TIMEOUT_MS |
ช่วง tick เริ่มต้น (ก่อน hello-ok) |
30_000 ms |
src/gateway/client.ts |
| ปิดเมื่อ tick-timeout | code 4000 เมื่อความเงียบเกิน tickIntervalMs * 2 |
src/gateway/client.ts |
MAX_PAYLOAD_BYTES |
25 * 1024 * 1024 (25 MB) |
src/gateway/server-constants.ts |
เซิร์ฟเวอร์ประกาศค่า policy.tickIntervalMs, policy.maxPayload และ policy.maxBufferedBytes ที่มีผลใน hello-ok; ไคลเอนต์ควรเคารพค่าเหล่านั้นแทนค่าเริ่มต้นก่อน handshake
Auth
- การยืนยันตัวตน Gateway แบบ shared-secret ใช้
connect.params.auth.tokenหรือconnect.params.auth.passwordขึ้นอยู่กับโหมดการยืนยันตัวตนที่กำหนดค่าไว้ - โหมดที่มีข้อมูลระบุตัวตน เช่น Tailscale Serve
(
gateway.auth.allowTailscale: true) หรือ non-loopbackgateway.auth.mode: "trusted-proxy"จะผ่านการตรวจสอบการยืนยันตัวตนขณะเชื่อมต่อจาก ส่วนหัวคำขอแทนconnect.params.auth.* gateway.auth.mode: "none"สำหรับ private-ingress จะข้ามการยืนยันตัวตนขณะเชื่อมต่อแบบ shared-secret ทั้งหมด อย่าเปิดใช้โหมดนั้นบน ingress สาธารณะ/ไม่น่าเชื่อถือ- หลังจากจับคู่แล้ว Gateway จะออก device token ที่จำกัดตามบทบาทการเชื่อมต่อ
- ขอบเขต โทเค็นนี้จะถูกส่งกลับใน
hello-ok.auth.deviceTokenและไคลเอนต์ควร คงไว้ใช้สำหรับการเชื่อมต่อในอนาคต
- ขอบเขต โทเค็นนี้จะถูกส่งกลับใน
- ไคลเอนต์ควรคง
hello-ok.auth.deviceTokenหลักไว้หลังจากเชื่อมต่อสำเร็จทุกครั้ง - การเชื่อมต่อใหม่ด้วย device token ที่ จัดเก็บไว้ ควรนำชุดขอบเขตที่อนุมัติแล้วและจัดเก็บไว้ สำหรับโทเค็นนั้นกลับมาใช้ด้วย วิธีนี้จะรักษาสิทธิ์อ่าน/probe/status ที่ได้รับอนุญาตแล้ว และหลีกเลี่ยงการยุบการเชื่อมต่อใหม่อย่างเงียบๆ ไปเป็น ขอบเขต implicit แบบ admin-only ที่แคบกว่า
- การประกอบการยืนยันตัวตนขณะเชื่อมต่อฝั่งไคลเอนต์ (
selectConnectAuthในsrc/gateway/client.ts):auth.passwordเป็นอิสระจากส่วนอื่น และจะถูกส่งต่อเสมอเมื่อตั้งค่าไว้auth.tokenจะถูกเติมตามลำดับความสำคัญ: shared token แบบชัดเจนก่อน จากนั้นdeviceTokenแบบชัดเจน แล้วจึงเป็นโทเค็นต่ออุปกรณ์ที่จัดเก็บไว้ (อ้างอิงด้วยdeviceId+role)auth.bootstrapTokenจะถูกส่งเฉพาะเมื่อไม่มีรายการข้างต้นใด resolve เป็นauth.tokenshared token หรือ device token ใดๆ ที่ resolve ได้จะระงับการส่งค่านี้- การเลื่อนใช้ device token ที่จัดเก็บไว้โดยอัตโนมัติในการลองใหม่แบบครั้งเดียว
เมื่อเจอ
AUTH_TOKEN_MISMATCHถูกจำกัดไว้เฉพาะ ปลายทางที่เชื่อถือได้เท่านั้น — loopback หรือwss://ที่มีtlsFingerprintแบบ pinnedwss://สาธารณะ ที่ไม่มี pinning จะไม่เข้าเกณฑ์
- bootstrap ด้วย setup-code ในตัวจะส่งคืน Node หลัก
hello-ok.auth.deviceTokenพร้อมโทเค็นผู้ปฏิบัติการแบบมีขอบเขตจำกัดในhello-ok.auth.deviceTokensสำหรับการส่งต่อไปยังมือถือที่เชื่อถือได้ โทเค็นผู้ปฏิบัติการ มีoperator.talk.secretsสำหรับอ่านการกำหนดค่า Talk แบบ native และ ไม่รวมoperator.adminกับoperator.pairing - ขณะที่ bootstrap ด้วย setup-code ที่ไม่ใช่ baseline กำลังรอการอนุมัติ รายละเอียด
PAIRING_REQUIREDจะมีrecommendedNextStep: "wait_then_retry",retryable: true, และpauseReconnect: falseไคลเอนต์ควรเชื่อมต่อใหม่ต่อไปด้วย bootstrap token เดิมจนกว่าคำขอจะได้รับอนุมัติหรือโทเค็นจะใช้ไม่ได้ - คง
hello-ok.auth.deviceTokensไว้เฉพาะเมื่อการเชื่อมต่อใช้ bootstrap auth บน transport ที่เชื่อถือได้ เช่นwss://หรือการจับคู่ผ่าน loopback/local - หากไคลเอนต์ระบุ
deviceTokenหรือscopesแบบ ชัดเจน ชุดขอบเขตที่ ผู้เรียกขอจะยังคงเป็นแหล่งอ้างอิงหลัก ขอบเขตที่แคชไว้จะถูกนำกลับมาใช้ เฉพาะเมื่อไคลเอนต์กำลังนำโทเค็นต่ออุปกรณ์ที่จัดเก็บไว้กลับมาใช้ - สามารถหมุนเวียน/เพิกถอน device token ได้ผ่าน
device.token.rotateและdevice.token.revoke(ต้องมีขอบเขตoperator.pairing) การหมุนเวียนหรือ เพิกถอน Node หรือบทบาทอื่นที่ไม่ใช่ผู้ปฏิบัติการต้องมีoperator.adminด้วย device.token.rotateส่งคืนเมทาดาทาการหมุนเวียน โดยจะ echo bearer token ตัวแทน เฉพาะสำหรับการเรียกจากอุปกรณ์เดียวกันที่ยืนยันตัวตนด้วย device token นั้นอยู่แล้ว เพื่อให้ไคลเอนต์แบบ token-only สามารถคงตัวแทนไว้ก่อนเชื่อมต่อใหม่ได้ การหมุนเวียนแบบ shared/admin จะไม่ echo bearer token- การออกโทเค็น การหมุนเวียน และการเพิกถอนจะยังคงจำกัดอยู่ภายในชุดบทบาทที่อนุมัติแล้ว ซึ่งบันทึกในรายการจับคู่ของอุปกรณ์นั้น การเปลี่ยนโทเค็นไม่สามารถขยายหรือ กำหนดเป้าหมายบทบาทอุปกรณ์ที่การอนุมัติการจับคู่ไม่เคยให้ไว้
- สำหรับเซสชันโทเค็นของอุปกรณ์ที่จับคู่แล้ว การจัดการอุปกรณ์จะจำกัดอยู่กับตนเอง เว้นแต่
ผู้เรียกจะมี
operator.adminด้วย: ผู้เรียกที่ไม่ใช่ admin สามารถจัดการได้เฉพาะ โทเค็นผู้ปฏิบัติการสำหรับรายการอุปกรณ์ของ ตนเอง เท่านั้น การจัดการโทเค็นของ Node และโทเค็นอื่นที่ไม่ใช่ผู้ปฏิบัติการเป็น admin-only แม้จะเป็นอุปกรณ์ของผู้เรียกเองก็ตาม device.token.rotateและdevice.token.revokeยังตรวจสอบชุดขอบเขตของโทเค็นผู้ปฏิบัติการ เป้าหมายเทียบกับขอบเขตเซสชันปัจจุบันของผู้เรียกด้วย ผู้เรียกที่ไม่ใช่ admin ไม่สามารถหมุนเวียนหรือเพิกถอนโทเค็นผู้ปฏิบัติการที่กว้างกว่าที่ตนมีอยู่แล้ว- ความล้มเหลวในการยืนยันตัวตนมี
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:- ไคลเอนต์ที่เชื่อถือได้อาจลองใหม่แบบมีขอบเขตหนึ่งครั้งด้วยโทเค็นต่ออุปกรณ์ที่แคชไว้
- หากการลองใหม่นั้นล้มเหลว ไคลเอนต์ควรหยุดลูปการเชื่อมต่อใหม่อัตโนมัติและแสดงคำแนะนำการดำเนินการสำหรับผู้ปฏิบัติการ
AUTH_SCOPE_MISMATCHหมายความว่า device token ถูกจดจำได้แต่ไม่ครอบคลุม บทบาท/ขอบเขตที่ร้องขอ ไคลเอนต์ไม่ควรแสดงสิ่งนี้ว่าเป็นโทเค็นไม่ถูกต้อง ให้แจ้งผู้ปฏิบัติการให้จับคู่ใหม่ หรืออนุมัติสัญญาขอบเขตที่แคบกว่า/กว้างกว่า
ข้อมูลระบุตัวตนอุปกรณ์ + การจับคู่
- Node ควรมีข้อมูลระบุตัวตนอุปกรณ์ที่เสถียร (
device.id) ซึ่งได้มาจาก fingerprint ของ keypair - Gateway ออกโทเค็นต่ออุปกรณ์ + บทบาท
- ต้องมีการอนุมัติการจับคู่สำหรับ ID อุปกรณ์ใหม่ เว้นแต่จะเปิดใช้การอนุมัติอัตโนมัติแบบ local
- การอนุมัติอัตโนมัติสำหรับการจับคู่มีศูนย์กลางอยู่ที่การเชื่อมต่อ local loopback โดยตรง
- OpenClaw ยังมีเส้นทาง self-connect แบบ backend/container-local ที่แคบสำหรับ โฟลว์ตัวช่วย shared-secret ที่เชื่อถือได้
- การเชื่อมต่อ same-host tailnet หรือ LAN ยังคงถือว่าเป็น remote สำหรับการจับคู่และ ต้องได้รับการอนุมัติ
- โดยปกติไคลเอนต์ WS จะรวมข้อมูลระบุตัวตน
deviceระหว่างconnect(ผู้ปฏิบัติการ + Node) ข้อยกเว้นผู้ปฏิบัติการที่ไม่มีอุปกรณ์มีเฉพาะเส้นทางความเชื่อถือแบบชัดเจน:gateway.controlUi.allowInsecureAuth=trueสำหรับความเข้ากันได้กับ HTTP ที่ไม่ปลอดภัยแบบ localhost-only- การยืนยันตัวตน Control UI ของผู้ปฏิบัติการด้วย
gateway.auth.mode: "trusted-proxy"ที่สำเร็จ gateway.controlUi.dangerouslyDisableDeviceAuth=true(break-glass, ลดระดับความปลอดภัยอย่างรุนแรง)- RPC backend
gateway-clientแบบ direct-loopback บนเส้นทางตัวช่วยภายในที่สงวนไว้
- การละเว้นข้อมูลระบุตัวตนอุปกรณ์มีผลต่อขอบเขต เมื่อการเชื่อมต่อผู้ปฏิบัติการแบบไม่มีอุปกรณ์
ได้รับอนุญาตผ่านเส้นทางความเชื่อถือแบบชัดเจน OpenClaw จะยังคงล้าง
ขอบเขตที่ประกาศเองเป็นชุดว่าง เว้นแต่เส้นทางนั้นจะมีข้อยกเว้นการคงขอบเขต
ที่มีชื่อกำกับ จากนั้นเมธอดที่ถูกควบคุมด้วยขอบเขตจะล้มเหลวด้วย
missing scope gateway.controlUi.dangerouslyDisableDeviceAuth=trueเป็นเส้นทาง break-glass สำหรับคงขอบเขตของ Control UI ไม่ได้ให้ขอบเขตแก่ไคลเอนต์ WebSocket แบบ backend ที่กำหนดเองหรือรูปแบบ CLI โดยพลการ- เส้นทางตัวช่วย backend
gateway-clientแบบ direct-loopback ที่สงวนไว้จะคง ขอบเขตเฉพาะสำหรับ RPC control-plane แบบ local ภายในเท่านั้น ID backend ที่กำหนดเองจะไม่ได้รับ ข้อยกเว้นนี้ - การเชื่อมต่อทั้งหมดต้องลงนาม nonce
connect.challengeที่เซิร์ฟเวอร์ให้มา
การวินิจฉัยการย้ายข้อมูล device auth
สำหรับไคลเอนต์ legacy ที่ยังใช้พฤติกรรมการลงนามก่อนมี challenge ตอนนี้ connect จะส่งคืน
รหัสรายละเอียด DEVICE_AUTH_* ใต้ error.details.code พร้อม error.details.reason ที่เสถียร
ความล้มเหลวทั่วไปในการย้ายข้อมูล:
| ข้อความ | 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 |
payload ลายเซ็นไม่ตรงกับ payload v2 |
device signature expired |
DEVICE_AUTH_SIGNATURE_EXPIRED |
device-signature-stale |
timestamp ที่ลงนามอยู่นอก skew ที่อนุญาต |
device identity mismatch |
DEVICE_AUTH_DEVICE_ID_MISMATCH |
device-id-mismatch |
device.id ไม่ตรงกับ fingerprint ของ public key |
device public key invalid |
DEVICE_AUTH_PUBLIC_KEY_INVALID |
device-public-key |
รูปแบบ/canonicalization ของ public key ล้มเหลว |
เป้าหมายการย้ายข้อมูล:
- รอ
connect.challengeเสมอ - ลงนาม payload v2 ที่มี nonce ของเซิร์ฟเวอร์
- ส่ง nonce เดียวกันใน
connect.params.device.nonce - payload ลายเซ็นที่แนะนำคือ
v3ซึ่งผูกplatformและdeviceFamilyเพิ่มเติมจากฟิลด์ device/client/role/scopes/token/nonce - ลายเซ็น legacy
v2ยังคงยอมรับเพื่อความเข้ากันได้ แต่การ pin เมทาดาทา paired-device ยังคงควบคุมนโยบายคำสั่งเมื่อเชื่อมต่อใหม่
TLS + pinning
- รองรับ TLS สำหรับการเชื่อมต่อ WS
- ไคลเอนต์อาจเลือก pin fingerprint ของใบรับรอง Gateway ได้ (ดูการกำหนดค่า
gateway.tlsพร้อมgateway.remote.tlsFingerprintหรือ CLI--tls-fingerprint)
ขอบเขต
โปรโตคอลนี้เปิดเผย Gateway API แบบเต็ม (status, channels, models, chat,
agent, sessions, nodes, approvals ฯลฯ) พื้นผิวที่แน่นอนกำหนดโดย
สคีมา TypeBox ใน packages/gateway-protocol/src/schema.ts