Gateway
โปรโตคอล Gateway
โปรโตคอล Gateway WS คือ ระนาบควบคุมเดียว + ทรานสปอร์ตของ Node สำหรับ OpenClaw ไคลเอนต์ทั้งหมด (CLI, UI เว็บ, แอป macOS, Node iOS/Android, Node แบบ headless) เชื่อมต่อผ่าน WebSocket และประกาศ role + scope ของตน ในช่วง handshake
ทรานสปอร์ต
- WebSocket, text frames พร้อม payload JSON
- เฟรมแรก ต้อง เป็นคำขอ
connect - เฟรมก่อนเชื่อมต่อถูกจำกัดไว้ที่ 64 KiB หลังจาก handshake สำเร็จแล้ว ไคลเอนต์
ควรทำตามขีดจำกัด
hello-ok.policy.maxPayloadและhello-ok.policy.maxBufferedBytesเมื่อเปิดใช้ diagnostics, เฟรมขาเข้าที่มีขนาดใหญ่เกินไปและบัฟเฟอร์ขาออกที่ช้าจะส่งอีเวนต์payload.largeก่อนที่ gateway จะปิดหรือทิ้งเฟรมที่ได้รับผลกระทบ อีเวนต์เหล่านี้เก็บ ขนาด ขีดจำกัด พื้นผิว และรหัสเหตุผลที่ปลอดภัยไว้ แต่ไม่เก็บเนื้อหาข้อความ เนื้อหาไฟล์แนบ เนื้อหาเฟรมดิบ โทเค็น คุกกี้ หรือค่าลับ
Handshake (connect)
Gateway → Client (challenge ก่อนเชื่อมต่อ):
{ "type": "event", "event": "connect.challenge", "payload": { "nonce": "…", "ts": 1737264000000 }}Client → 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 → Client:
{ "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 ไคลเอนต์ควรลองส่งการตอบกลับนั้นใหม่
ภายในงบเวลาการเชื่อมต่อโดยรวม แทนที่จะแสดงเป็นความล้มเหลวของ handshake
แบบสิ้นสุด
server, features, snapshot และ policy ทั้งหมดเป็นค่าที่ schema กำหนดให้มี
(packages/gateway-protocol/src/schema/frames.ts) auth ก็จำเป็นเช่นกันและรายงาน
role/scopes ที่เจรจาได้ pluginSurfaceUrls เป็นตัวเลือกเสริมและแมปชื่อพื้นผิวของ plugin
เช่น canvas ไปยัง URL ที่โฮสต์แบบมี scope
URL พื้นผิวของ plugin ที่มี scope อาจหมดอายุได้ Node สามารถเรียก
node.pluginSurface.refresh พร้อม { "surface": "canvas" } เพื่อรับรายการใหม่
ใน pluginSurfaceUrls การรีแฟกเตอร์ Plugin Canvas แบบทดลองไม่รองรับเส้นทางความเข้ากันได้
canvasHostUrl, canvasCapability หรือ node.canvas.capability.refresh ที่เลิกใช้แล้ว;
ไคลเอนต์ native และ gateway ปัจจุบันต้องใช้พื้นผิวของ plugin
เมื่อไม่มีการออกโทเค็นอุปกรณ์ hello-ok.auth จะรายงานสิทธิ์ที่เจรจาได้
โดยไม่มีฟิลด์โทเค็น:
{ "auth": { "role": "operator", "scopes": ["operator.read", "operator.write"] }}ไคลเอนต์ backend ในโปรเซสเดียวกันที่เชื่อถือได้ (client.id: "gateway-client",
client.mode: "backend") อาจละเว้น device บนการเชื่อมต่อ loopback โดยตรงได้เมื่อ
ยืนยันตัวตนด้วยโทเค็น/รหัสผ่าน gateway ที่ใช้ร่วมกัน เส้นทางนี้สงวนไว้สำหรับ
RPC ระนาบควบคุมภายใน และป้องกันไม่ให้ baseline การจับคู่ CLI/อุปกรณ์ที่ค้างอยู่
ไปบล็อกงาน backend ภายใน เช่น การอัปเดตเซสชัน subagent ไคลเอนต์ระยะไกล,
ไคลเอนต์จาก browser-origin, ไคลเอนต์ Node และไคลเอนต์ที่ระบุ device-token/device-identity
ยังคงใช้การตรวจสอบการจับคู่และการยกระดับ scope ตามปกติ
เมื่อมีการออกโทเค็นอุปกรณ์ hello-ok จะรวมข้อมูลนี้ด้วย:
{ "auth": { "deviceToken": "…", "role": "operator", "scopes": ["operator.read", "operator.write"] }}การบูตสแตรปด้วย QR/setup-code ในตัวเป็นเส้นทางส่งต่อมือถือแบบใหม่ เมื่อ การเชื่อมต่อด้วย setup-code baseline สำเร็จ จะส่งคืนโทเค็น Node หลักพร้อม โทเค็น operator แบบมีขอบเขตหนึ่งรายการ:
{ "auth": { "deviceToken": "…", "role": "node", "scopes": [], "deviceTokens": [ { "deviceToken": "…", "role": "operator", "scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"] } ] }}การส่งต่อ operator ถูกจำกัดโดยตั้งใจ เพื่อให้การ onboarding ด้วย QR สามารถเริ่ม
ลูป operator บนมือถือและทำการตั้งค่า native ให้เสร็จ โดยไม่ให้ scope สำหรับ
การเปลี่ยนแปลงการจับคู่หรือ operator.admin โดยรวม operator.talk.secrets ไว้เพื่อให้
ไคลเอนต์ native อ่านการกำหนดค่า Talk ที่ต้องใช้หลัง bootstrap ได้ การเข้าถึง
การจับคู่และผู้ดูแลระบบที่กว้างกว่านี้ต้องใช้การจับคู่ operator หรือ flow โทเค็น
ที่ได้รับอนุมัติแยกต่างหาก ไคลเอนต์ควรคงค่า
hello-ok.auth.deviceTokens ไว้เฉพาะ
เมื่อการเชื่อมต่อใช้ bootstrap auth บนทรานสปอร์ตที่เชื่อถือได้ เช่น wss:// หรือ
การจับคู่ผ่าน loopback/local
ตัวอย่าง Node
{ "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": "…" } }}การจัดเฟรม
- Request:
{type:"req", id, method, params} - Response:
{type:"res", id, ok, payload|error} - Event:
{type:"event", event, payload, seq?, stateVersion?}
เมธอดที่มีผลข้างเคียงต้องใช้ idempotency keys (ดู schema)
Roles + scopes
สำหรับโมเดล scope ของ operator แบบเต็ม การตรวจสอบในช่วงอนุมัติ และ ความหมายของ shared-secret ดู Operator scopes
Roles
operator= ไคลเอนต์ระนาบควบคุม (CLI/UI/automation)node= โฮสต์ความสามารถ (camera/screen/canvas/system.run)
Scopes (operator)
scope ที่พบบ่อย:
operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
talk.config พร้อม includeSecrets: true ต้องใช้ operator.talk.secrets
(หรือ operator.admin)
เมื่อรวม secrets ไว้ ไคลเอนต์ควรอ่านข้อมูลประจำตัวของผู้ให้บริการ Talk ที่ใช้งานอยู่
จาก talk.resolved.config.apiKey; talk.providers.<id>.apiKey
ยังคงมีรูปทรงเหมือนแหล่งที่มา และอาจเป็นออบเจ็กต์ SecretRef หรือสตริงที่ถูกปกปิด
เมธอด Gateway RPC ที่ลงทะเบียนโดย plugin อาจขอ scope ของ operator ของตนเองได้ แต่
prefix ของ core admin ที่สงวนไว้ (config.*, exec.approvals.*, wizard.*,
update.*) จะแปลงเป็น operator.admin เสมอ
scope ของเมธอดเป็นเพียงด่านแรกเท่านั้น คำสั่ง slash บางรายการที่เข้าถึงผ่าน
chat.send จะใช้การตรวจสอบระดับคำสั่งที่เข้มงวดกว่าเพิ่มเติม ตัวอย่างเช่น การเขียนแบบคงอยู่
ด้วย /config set และ /config unset ต้องใช้ operator.admin
node.pair.approve ยังมีการตรวจสอบ scope เพิ่มเติมในช่วงอนุมัติ นอกเหนือจาก
scope ของเมธอดพื้นฐาน:
- คำขอที่ไม่มีคำสั่ง:
operator.pairing - คำขอที่มีคำสั่ง Node ที่ไม่ใช่ exec:
operator.pairing+operator.write - คำขอที่รวม
system.run,system.run.prepareหรือsystem.which:operator.pairing+operator.admin
Caps/commands/permissions (node)
Node ประกาศการอ้างสิทธิ์ความสามารถในช่วงเชื่อมต่อ:
caps: หมวดหมู่ความสามารถระดับสูง เช่นcamera,canvas,screen,location,voiceและtalkcommands: รายการคำสั่งที่อนุญาตสำหรับ invokepermissions: สวิตช์ย่อยแบบละเอียด (เช่นscreen.record,camera.capture)
Gateway ถือค่าสิ่งเหล่านี้เป็น claims และบังคับใช้ allowlist ฝั่งเซิร์ฟเวอร์
Presence
system-presenceส่งคืนรายการที่ key ด้วย identity ของอุปกรณ์- รายการ presence รวม
deviceId,rolesและscopesเพื่อให้ UI แสดงหนึ่งแถวต่ออุปกรณ์ได้ แม้เมื่อเชื่อมต่อเป็นทั้ง operator และ node node.listรวมฟิลด์ตัวเลือกเสริมlastSeenAtMsและlastSeenReasonNode ที่เชื่อมต่ออยู่รายงาน เวลาเชื่อมต่อปัจจุบันของตนเป็นlastSeenAtMsพร้อมเหตุผลconnect; Node ที่จับคู่แล้วอาจรายงาน background presence แบบคงทนได้ด้วย เมื่ออีเวนต์ Node ที่เชื่อถือได้อัปเดต metadata การจับคู่ของตน
อีเวนต์ alive เบื้องหลังของ Node
Node อาจเรียก node.event พร้อม event: "node.presence.alive" เพื่อบันทึกว่า Node ที่จับคู่แล้ว
ยัง alive ระหว่างการ wake ในเบื้องหลัง โดยไม่ทำเครื่องหมายว่าเชื่อมต่ออยู่
{ "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 เป็น enum แบบปิด: background, silent_push, bg_app_refresh,
significant_location, manual หรือ connect สตริง trigger ที่ไม่รู้จักจะถูก gateway ทำให้เป็น
background ก่อนคงค่าไว้ อีเวนต์นี้คงทนเฉพาะสำหรับเซสชันอุปกรณ์ Node ที่ยืนยันตัวตนแล้ว
เท่านั้น; เซสชันที่ไม่มีอุปกรณ์หรือยังไม่ได้จับคู่จะส่งคืน handled: false
Gateway ที่สำเร็จจะส่งคืนผลลัพธ์แบบมีโครงสร้าง:
{ "ok": true, "event": "node.presence.alive", "handled": true, "reason": "persisted"}Gateway รุ่นเก่าอาจยังส่งคืน { "ok": true } สำหรับ node.event; ไคลเอนต์ควรถือว่านั่นเป็น
RPC ที่ได้รับการยืนยันแล้ว ไม่ใช่การคงค่า presence แบบคงทน
การกำหนด scope ของอีเวนต์ broadcast
อีเวนต์ broadcast ของ WebSocket ที่เซิร์ฟเวอร์ push จะถูก gate ด้วย scope เพื่อไม่ให้เซสชันที่มี scope สำหรับการจับคู่หรือเฉพาะ Node รับเนื้อหาเซสชันแบบ passive
- เฟรม chat, agent และ tool-result (รวมถึงอีเวนต์
agentแบบ streamed และผลลัพธ์ tool call) ต้องมีอย่างน้อยoperator.readเซสชันที่ไม่มีoperator.readจะข้ามเฟรมเหล่านี้ทั้งหมด - broadcast
plugin.*ที่กำหนดโดย Plugin ถูก gate ไปยังoperator.writeหรือoperator.adminขึ้นอยู่กับวิธีที่ plugin ลงทะเบียนไว้ - อีเวนต์สถานะและทรานสปอร์ต (
heartbeat,presence,tick, lifecycle การเชื่อมต่อ/ตัดการเชื่อมต่อ ฯลฯ) ยังคงไม่ถูกจำกัด เพื่อให้ทุกเซสชันที่ยืนยันตัวตนแล้วสังเกตสุขภาพของทรานสปอร์ตได้ - ตระกูลอีเวนต์ broadcast ที่ไม่รู้จัก ถูก gate ด้วย scope ตามค่าเริ่มต้น (fail-closed) เว้นแต่ handler ที่ลงทะเบียนไว้จะผ่อนคลายข้อจำกัดอย่างชัดเจน
การเชื่อมต่อไคลเอนต์แต่ละรายการเก็บหมายเลขลำดับต่อไคลเอนต์ของตนเอง เพื่อให้ broadcast รักษาลำดับแบบ monotonic บน socket นั้น แม้เมื่อไคลเอนต์ต่างกันเห็น subset ของสตรีมอีเวนต์ที่ถูกกรองด้วย scope แตกต่างกัน
ตระกูลเมธอด RPC ที่พบบ่อย
พื้นผิว WS สาธารณะกว้างกว่าตัวอย่าง handshake/auth ด้านบน นี่
ไม่ใช่ dump ที่สร้างขึ้น — hello-ok.features.methods เป็นรายการ discovery
แบบอนุรักษ์นิยมที่สร้างจาก src/gateway/server-methods-list.ts รวมกับ export เมธอดของ
plugin/channel ที่โหลดแล้ว ให้ถือเป็น feature discovery ไม่ใช่รายการแจกแจงแบบเต็ม
ของ src/gateway/server-methods/*.ts
ระบบและตัวตน
healthส่งคืนสแนปช็อตสถานะสุขภาพของ Gateway ที่แคชไว้หรือเพิ่งโพรบใหม่diagnostics.stabilityส่งคืนตัวบันทึกเสถียรภาพการวินิจฉัยแบบมีขอบเขตล่าสุด โดยเก็บเมทาดาต้าด้านการปฏิบัติการ เช่น ชื่อเหตุการณ์ จำนวน ขนาดไบต์ ค่าการใช้หน่วยความจำ สถานะคิว/เซสชัน ชื่อช่องทาง/Plugin และรหัสเซสชัน แต่ไม่เก็บข้อความแชต เนื้อหา Webhook เอาต์พุตของเครื่องมือ เนื้อหาคำขอหรือคำตอบแบบดิบ โทเคน คุกกี้ หรือค่าลับ ต้องมีขอบเขตการอ่านของผู้ปฏิบัติการstatusส่งคืนสรุป Gateway รูปแบบ/status; ฟิลด์ที่ละเอียดอ่อนจะถูกรวมไว้เฉพาะสำหรับไคลเอนต์ผู้ปฏิบัติการที่มีขอบเขตผู้ดูแลระบบเท่านั้นgateway.identity.getส่งคืนตัวตนอุปกรณ์ของ Gateway ที่ใช้โดยโฟลว์รีเลย์และการจับคู่system-presenceส่งคืนสแนปช็อตการปรากฏตัวปัจจุบันสำหรับอุปกรณ์ผู้ปฏิบัติการ/Node ที่เชื่อมต่ออยู่system-eventเพิ่มเหตุการณ์ระบบและสามารถอัปเดต/กระจายบริบทการปรากฏตัวได้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ส่งคืนความพร้อมของหน่วยความจำเวกเตอร์ / embedding ที่แคชไว้สำหรับพื้นที่ทำงานของเอเจนต์เริ่มต้นที่ใช้งานอยู่ ส่ง{ "probe": true }หรือ{ "deep": true }เฉพาะเมื่อผู้เรียกต้องการ ping ผู้ให้บริการ embedding แบบสดอย่างชัดเจน ไคลเอนต์ที่รองรับ Dreaming อาจส่ง{ "agentId": "agent-id" }เพื่อจำกัดสถิติที่เก็บ Dreaming ไปยังพื้นที่ทำงานของเอเจนต์ที่เลือกได้ด้วย; หากละagentIdจะคง fallback ของเอเจนต์เริ่มต้นและรวมพื้นที่ทำงาน 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 harness แบบอ่านอย่างเดียวและมีขอบเขตสำหรับไคลเอนต์ control-plane ระยะไกล โดยอาจรวมพาธพื้นที่ทำงาน ส่วนย่อยหน่วยความจำ Markdown ที่ยึดหลักจริงซึ่งเรนเดอร์แล้ว และตัวเลือกการเลื่อนระดับเชิงลึก ดังนั้นผู้เรียกต้องมีoperator.readsessions.usageส่งคืนสรุปการใช้งานรายเซสชัน ส่งagentIdสำหรับหนึ่ง เอเจนต์ หรือagentScope: "all"เพื่อแสดงเอเจนต์ที่กำหนดค่าไว้ร่วมกันsessions.usage.timeseriesส่งคืนการใช้งานแบบอนุกรมเวลาสำหรับหนึ่งเซสชันsessions.usage.logsส่งคืนรายการบันทึกการใช้งานสำหรับหนึ่งเซสชัน
ช่องทางและตัวช่วยเข้าสู่ระบบ
channels.statusส่งคืนสรุปสถานะช่องทาง/Plugin ในตัวและที่บันเดิลมาchannels.logoutออกจากระบบช่องทาง/บัญชีที่ระบุเมื่อช่องทางรองรับการออกจากระบบweb.login.startเริ่มโฟลว์เข้าสู่ระบบ QR/เว็บสำหรับผู้ให้บริการช่องทางเว็บปัจจุบันที่รองรับ QRweb.login.waitรอให้โฟลว์เข้าสู่ระบบ QR/เว็บนั้นเสร็จสมบูรณ์และเริ่มช่องทางเมื่อสำเร็จpush.testส่ง APNs push ทดสอบไปยัง Node iOS ที่ลงทะเบียนไว้voicewake.getส่งคืนตัวกระตุ้นคำปลุกที่จัดเก็บไว้voicewake.setอัปเดตตัวกระตุ้นคำปลุกและกระจายการเปลี่ยนแปลง
การรับส่งข้อความและบันทึก
sendคือ RPC การส่งออกโดยตรงสำหรับการส่งที่กำหนดเป้าหมายตามช่องทาง/บัญชี/เธรดนอกตัวรันแชตlogs.tailส่งคืนส่วนท้ายบันทึกไฟล์ของ Gateway ที่กำหนดค่าไว้ พร้อมการควบคุมเคอร์เซอร์/ขีดจำกัดและจำนวนไบต์สูงสุด
Talk และ TTS
talk.catalogส่งคืนแคตตาล็อกผู้ให้บริการ Talk แบบอ่านอย่างเดียวสำหรับเสียงพูด การถอดเสียงแบบสตรีม และเสียงแบบเรียลไทม์ โดยรวมรหัสผู้ให้บริการแบบบัญญัติ นามแฝงในรีจิสทรี ป้ายกำกับ สถานะที่กำหนดค่าไว้ ผลลัพธ์readyระดับกลุ่มแบบไม่บังคับ รหัสโมเดล/เสียงที่เปิดเผย โหมดบัญญัติ ทรานสปอร์ต กลยุทธ์สมอง และแฟล็กเสียง/ความสามารถแบบเรียลไทม์ โดยไม่ส่งคืนความลับของผู้ให้บริการหรือเปลี่ยนแปลงการกำหนดค่าส่วนกลาง Gateway ปัจจุบันตั้งค่าreadyหลังจากใช้การเลือกผู้ให้บริการรันไทม์แล้ว; ไคลเอนต์ควรถือว่าการไม่มีค่านี้หมายถึงยังไม่ได้ตรวจสอบ เพื่อความเข้ากันได้กับ Gateway รุ่นเก่าtalk.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ด้วยเพื่อให้มองเห็นคีย์เซสชันตามขอบเขต; การสร้าง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ขับเคลื่อนวงจรชีวิตเทิร์นของ managed-room พร้อมการปฏิเสธเทิร์นเก่าก่อนล้างสถานะtalk.session.cancelOutputหยุดเอาต์พุตเสียงของผู้ช่วย โดยหลักใช้สำหรับการแทรกพูดที่ถูกควบคุมด้วย VAD ในเซสชันรีเลย์ของ Gatewaytalk.session.submitToolResultทำให้การเรียกเครื่องมือของผู้ให้บริการที่ปล่อยโดยเซสชันรีเลย์เรียลไทม์ที่ Gateway เป็นเจ้าของเสร็จสมบูรณ์ ส่งoptions: { willContinue: true }สำหรับเอาต์พุตเครื่องมือชั่วคราวเมื่อจะมีผลลัพธ์สุดท้ายตามมา หรือoptions: { suppressResponse: true }เมื่อผลลัพธ์เครื่องมือควรตอบสนองการเรียกของผู้ให้บริการโดยไม่เริ่มคำตอบผู้ช่วยเรียลไทม์อีกครั้งtalk.session.steerส่งการควบคุมเสียงของรันที่กำลังใช้งานเข้าสู่เซสชัน 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 เป็นเจ้าของการกำหนดค่า ข้อมูลประจำตัว คำสั่ง และนโยบายเครื่องมือtalk.client.toolCallให้ทรานสปอร์ตเรียลไทม์ที่ไคลเอนต์เป็นเจ้าของส่งต่อการเรียกเครื่องมือของผู้ให้บริการไปยังนโยบาย Gateway เครื่องมือแรกที่รองรับคือopenclaw_agent_consult; ไคลเอนต์จะได้รับรหัสรันและรอเหตุการณ์วงจรชีวิตแชตปกติก่อนส่งผลลัพธ์เครื่องมือเฉพาะผู้ให้บริการtalk.client.steerส่งการควบคุมเสียงของรันที่กำลังใช้งานสำหรับทรานสปอร์ตเรียลไทม์ที่ไคลเอนต์เป็นเจ้าของ Gateway จะแก้หารันแบบฝังที่ใช้งานอยู่จากsessionKeyและส่งคืนผลลัพธ์ยอมรับ/ปฏิเสธแบบมีโครงสร้างแทนการทิ้งการบังคับทิศทางอย่างเงียบ ๆtalk.eventคือช่องทางเหตุการณ์ Talk เดียวสำหรับอะแดปเตอร์เรียลไทม์ การถอดเสียง STT/TTS, managed-room, โทรศัพท์ และการประชุมtalk.speakสังเคราะห์เสียงพูดผ่านผู้ให้บริการเสียงพูด Talk ที่ใช้งานอยู่tts.statusส่งคืนสถานะเปิดใช้ TTS ผู้ให้บริการที่ใช้งานอยู่ ผู้ให้บริการ fallback และสถานะการกำหนดค่าผู้ให้บริการtts.providersส่งคืนคลังผู้ให้บริการ TTS ที่มองเห็นได้tts.enableและtts.disableสลับสถานะการตั้งค่า TTStts.setProviderอัปเดตผู้ให้บริการ TTS ที่ต้องการtts.convertเรียกใช้การแปลงข้อความเป็นเสียงพูดแบบครั้งเดียว
ความลับ การกำหนดค่า การอัปเดต และวิซาร์ด
secrets.reloadแก้หา SecretRefs ที่ใช้งานอยู่อีกครั้งและสลับสถานะความลับของรันไทม์เฉพาะเมื่อสำเร็จทั้งหมดเท่านั้นsecrets.resolveแก้หาการกำหนดความลับเป้าหมายคำสั่งสำหรับชุดคำสั่ง/เป้าหมายที่ระบุconfig.getส่งคืนสแนปช็อตการกำหนดค่าปัจจุบันและแฮชconfig.setเขียนเพย์โหลดการกำหนดค่าที่ผ่านการตรวจสอบแล้วconfig.patchผสานการอัปเดตการกำหนดค่าบางส่วน การแทนที่อาร์เรย์แบบทำลาย ต้องระบุพาธที่ได้รับผลกระทบในreplacePaths; อาร์เรย์ซ้อน ใต้รายการอาร์เรย์ใช้พาธ[]เช่นagents.list[].skillsconfig.applyตรวจสอบความถูกต้อง + แทนที่เพย์โหลดการกำหนดค่าทั้งหมดconfig.schemaส่งคืนเพย์โหลดสคีมาการกำหนดค่าแบบสดที่ใช้โดยเครื่องมือ Control UI และ CLI: สคีมา,uiHints, เวอร์ชัน และเมทาดาต้าการสร้าง รวมถึงเมทาดาต้าสคีมา Plugin + ช่องทางเมื่อรันไทม์โหลดได้ สคีมารวมเมทาดาต้าฟิลด์title/descriptionที่ได้มาจากป้ายกำกับและข้อความช่วยเหลือเดียวกับที่ UI ใช้ รวมถึงอ็อบเจ็กต์ซ้อน wildcard รายการอาร์เรย์ และแขนงการประกอบanyOf/oneOf/allOfเมื่อมีเอกสารฟิลด์ที่ตรงกันconfig.schema.lookupส่งคืนเพย์โหลดการค้นหาแบบจำกัดพาธสำหรับพาธการกำหนดค่าหนึ่งพาธ: พาธที่ทำให้เป็นมาตรฐานแล้ว โหนดสคีมาตื้น ๆ คำใบ้ที่ตรงกัน +hintPath,reloadKindแบบไม่บังคับ และสรุปลูกโดยตรงสำหรับการเจาะลึกใน UI/CLIreloadKindเป็นหนึ่งใน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เพื่อให้การเริ่มต้นกลับมาทำเทิร์นเอเจนต์ติดตามผลหนึ่งครั้งผ่านคิวความต่อเนื่องของการรีสตาร์ต การอัปเดตตัวจัดการแพ็กเกจและการอัปเดต git-checkout ที่มีการกำกับดูแลจาก control plane ใช้การส่งต่องาน managed-service แบบแยกออก แทนการแทนที่ผังแพ็กเกจหรือเปลี่ยนแปลงเอาต์พุต checkout/build ภายใน Gateway ที่กำลังทำงาน การส่งต่องานที่เริ่มแล้วส่งคืนok: trueพร้อมresult.reason: "managed-service-handoff-started"และhandoff.status: "started"; การส่งต่องานที่ไม่พร้อมใช้งานหรือล้มเหลวส่งคืนok: falseพร้อมmanaged-service-handoff-unavailableหรือmanaged-service-handoff-failedรวมถึงhandoff.commandเมื่อจำเป็นต้องอัปเดตด้วยเชลล์แบบแมนนวล การส่งต่องานที่ไม่พร้อมใช้งานหมายความว่า OpenClaw ไม่มีขอบเขตผู้กำกับดูแลที่ปลอดภัยหรือตัวตนบริการที่ทนทาน เช่นOPENCLAW_SYSTEMD_UNITสำหรับ systemd ระหว่างการส่งต่องานที่เริ่มแล้ว sentinel การรีสตาร์ตอาจรายงานstats.reason: "restart-health-pending"ชั่วครู่; ความต่อเนื่องจะถูกหน่วงจนกว่า CLI จะตรวจสอบ Gateway ที่รีสตาร์ตแล้วและเขียน sentinelokสุดท้ายupdate.statusรีเฟรชและส่งคืน sentinel การรีสตาร์ตการอัปเดตล่าสุด รวมถึงเวอร์ชันที่กำลังรันหลังรีสตาร์ตเมื่อมีwizard.start,wizard.next,wizard.status, และwizard.cancelเปิดเผยวิซาร์ดการเริ่มต้นใช้งานผ่าน 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ที่ระบุอย่างชัดเจน คิวรีรันและงานจะ resolve เซสชันเจ้าของทางฝั่งเซิร์ฟเวอร์ และส่งคืนเฉพาะสื่อทรานสคริปต์ที่มีแหล่งที่มาตรงกันเท่านั้น แหล่ง URL ที่ไม่ปลอดภัยหรือเป็น local จะส่งคืนการดาวน์โหลดที่ไม่รองรับแทนการดึงข้อมูลทางฝั่งเซิร์ฟเวอร์environments.listและenvironments.statusเปิดเผยการค้นพบสภาพแวดล้อมแบบอ่านอย่างเดียวของ Gateway-local และ Node สำหรับไคลเอนต์ SDKagent.identity.getส่งคืนตัวตนผู้ช่วยที่มีผลใช้งานสำหรับเอเจนต์หรือเซสชันagent.waitรอให้รันเสร็จสิ้นและส่งคืนสแนปช็อตสถานะสิ้นสุดเมื่อมีให้ใช้
การควบคุมเซสชัน
sessions.listส่งคืนดัชนีเซสชันปัจจุบัน รวมถึงเมทาดาทาagentRuntimeต่อแถวเมื่อมีการกำหนดค่าแบ็กเอนด์รันไทม์ของเอเจนต์sessions.subscribeและsessions.unsubscribeสลับการสมัครรับเหตุการณ์การเปลี่ยนแปลงเซสชันสำหรับไคลเอนต์ WS ปัจจุบันsessions.messages.subscribeและsessions.messages.unsubscribeสลับการสมัครรับเหตุการณ์ทรานสคริปต์/ข้อความสำหรับหนึ่งเซสชันsessions.previewส่งคืนตัวอย่างทรานสคริปต์แบบมีขอบเขตสำหรับคีย์เซสชันที่ระบุsessions.describeส่งคืนหนึ่งแถวเซสชันของ Gateway สำหรับคีย์เซสชันที่ตรงกันทุกประการsessions.resolveresolve หรือทำให้เป้าหมายเซสชันเป็นรูปแบบ canonicalsessions.createสร้างรายการเซสชันใหม่sessions.sendส่งข้อความเข้าไปในเซสชันที่มีอยู่sessions.steerเป็นรูปแบบ interrupt-and-steer สำหรับเซสชันที่ใช้งานอยู่sessions.abortยกเลิกงานที่ใช้งานอยู่สำหรับเซสชัน ผู้เรียกอาจส่งkeyพร้อมrunIdที่เป็นทางเลือก หรือส่งเฉพาะrunIdสำหรับรันที่ใช้งานอยู่ซึ่ง Gateway สามารถ resolve ไปยังเซสชันได้sessions.patchอัปเดตเมทาดาทา/การ override ของเซสชัน และรายงานโมเดล canonical ที่ resolve แล้วพร้อมagentRuntimeที่มีผลใช้งานsessions.reset,sessions.deleteและsessions.compactดำเนินการบำรุงรักษาเซสชันsessions.getส่งคืนแถวเซสชันที่จัดเก็บไว้แบบเต็ม- การเรียกใช้แชทยังคงใช้
chat.history,chat.send,chat.abortและchat.injectchat.historyถูกทำให้เป็นมาตรฐานสำหรับการแสดงผลแก่ไคลเอนต์ UI: แท็กคำสั่งแบบ inline จะถูกลบออกจากข้อความที่มองเห็นได้, payload XML ของ tool-call แบบข้อความล้วน (รวมถึง<tool_call>...</tool_call>,<function_call>...</function_call>,<tool_calls>...</tool_calls>,<function_calls>...</function_calls>และบล็อก tool-call ที่ถูกตัดทอน) และโทเคนควบคุมโมเดลแบบ ASCII/full-width ที่รั่วออกมาจะถูกลบออก, แถวผู้ช่วยที่เป็น silent-token ล้วน เช่นNO_REPLY/no_replyที่ตรงทุกประการจะถูกละเว้น และแถวที่มีขนาดใหญ่เกินไปอาจถูกแทนที่ด้วย placeholder chat.message.getเป็นตัวอ่าน full-message แบบมีขอบเขตที่เพิ่มเข้ามาสำหรับรายการทรานสคริปต์ที่มองเห็นได้รายการเดียว ไคลเอนต์ส่งsessionKey,agentIdที่เป็นทางเลือกเมื่อการเลือกเซสชันมีขอบเขตตามเอเจนต์ พร้อมmessageIdของทรานสคริปต์ที่เคยเปิดเผยผ่านchat.historyและ Gateway จะส่งคืน projection ที่ถูกทำให้เป็นมาตรฐานสำหรับการแสดงผลแบบเดียวกันโดยไม่มีเพดานการตัดทอนประวัติแบบเบา เมื่อรายการที่จัดเก็บไว้ยังมีอยู่และไม่ได้มีขนาดใหญ่เกินไปchat.sendรับfastMode: "auto"แบบหนึ่งเทิร์นเพื่อใช้โหมดเร็วกับการเรียกโมเดลที่เริ่มก่อนจุดตัด auto จากนั้นจึงเริ่มการเรียก retry, fallback, tool-result หรือ continuation ภายหลังโดยไม่ใช้โหมดเร็ว จุดตัดมีค่าเริ่มต้นที่ 60 วินาที และสามารถกำหนดค่าต่อโมเดลได้ด้วยagents.defaults.models["<provider>/<model>"].params.fastAutoOnSecondsผู้เรียกchat.sendสามารถส่งfastAutoOnSecondsแบบหนึ่งเทิร์นเพื่อ override จุดตัดสำหรับคำขอนั้น
การจับคู่อุปกรณ์และโทเคนอุปกรณ์
device.pair.listส่งคืนอุปกรณ์ที่จับคู่แล้วซึ่งรออนุมัติและได้รับอนุมัติแล้วdevice.pair.setupCodeสร้างโค้ดตั้งค่ามือถือ และโดยค่าเริ่มต้นจะสร้าง PNG QR data URL ด้วย ต้องใช้operator.adminและตั้งใจละเว้นจากการค้นพบที่ประกาศไว้ ผลลัพธ์มีsetupCode,qrDataUrlที่เป็นทางเลือก,gatewayUrl, ป้ายกำกับauthที่ไม่เป็นความลับ และurlSourcedevice.pair.approve,device.pair.rejectและdevice.pair.removeจัดการระเบียนการจับคู่อุปกรณ์device.token.rotateหมุนเวียนโทเคนอุปกรณ์ที่จับคู่แล้วภายในขอบเขตบทบาทที่อนุมัติและขอบเขตผู้เรียกdevice.token.revokeเพิกถอนโทเคนอุปกรณ์ที่จับคู่แล้วภายในขอบเขตบทบาทที่อนุมัติและขอบเขตผู้เรียก
โค้ดตั้งค่าฝังข้อมูลรับรองเริ่มต้นที่มีอายุสั้น ไคลเอนต์ต้องไม่ บันทึก log หรือคงข้อมูลนี้ไว้นอกเหนือจาก flow การจับคู่
การจับคู่ Node, การเรียกใช้ และงานที่รอดำเนินการ
node.pair.request,node.pair.list,node.pair.approve,node.pair.reject,node.pair.removeและnode.pair.verifyครอบคลุมการจับคู่ Node และการยืนยัน bootstrapnode.listและnode.describeส่งคืนสถานะ Node ที่รู้จัก/เชื่อมต่ออยู่node.renameอัปเดตป้ายกำกับ Node ที่จับคู่แล้วnode.invokeส่งต่อคำสั่งไปยัง Node ที่เชื่อมต่ออยู่node.invoke.resultส่งคืนผลลัพธ์สำหรับคำขอ invokenode.eventนำเหตุการณ์ที่มาจาก Node กลับเข้าสู่ Gatewaynode.pending.pullและnode.pending.ackเป็น API คิวของ Node ที่เชื่อมต่ออยู่node.pending.enqueueและnode.pending.drainจัดการงานที่รอดำเนินการแบบคงทนสำหรับ Node ที่ offline/ตัดการเชื่อมต่อ
ตระกูลการอนุมัติ
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 แบบ local ของ Node ผ่านคำสั่ง relay ของ Nodeplugin.approval.request,plugin.approval.list,plugin.approval.waitDecisionและplugin.approval.resolveครอบคลุม flow การอนุมัติที่ Plugin กำหนด
Automation, skills และเครื่องมือ
- Automation:
wakeจัดกำหนดการฉีดข้อความปลุกทันทีหรือใน Heartbeat ถัดไป;cron.get,cron.list,cron.status,cron.add,cron.update,cron.remove,cron.run,cron.runsจัดการงานที่กำหนดเวลาไว้ cron.runยังคงเป็น RPC แบบ enqueue สำหรับการรันด้วยตนเอง ไคลเอนต์ที่ต้องการ semantics ของการเสร็จสิ้นควรอ่านrunIdที่ส่งคืนและ pollcron.runscron.runsรับตัวกรองrunIdที่เป็นทางเลือกและไม่ว่าง เพื่อให้ไคลเอนต์ติดตามการรันด้วยตนเองหนึ่งรายการในคิวได้โดยไม่ชนกับรายการประวัติอื่นของงานเดียวกัน- Skills และเครื่องมือ:
commands.list,skills.*,tools.catalog,tools.effective,tools.invoke
ตระกูลเหตุการณ์ทั่วไป
chat: การอัปเดตแชท UI เช่นchat.injectและเหตุการณ์แชทอื่นที่เป็นเฉพาะทรานสคริปต์ ใน protocol v4 payload แบบ delta จะมีdeltaText;messageยังคงเป็น สแนปช็อตผู้ช่วยแบบสะสม การแทนที่ที่ไม่ใช่ prefix จะตั้งreplace=trueและใช้deltaTextเป็นข้อความแทนที่session.message,session.operationและsession.tool: ทรานสคริปต์, การดำเนินการเซสชันที่กำลังทำงาน และการอัปเดตสตรีมเหตุการณ์สำหรับเซสชัน ที่สมัครรับsessions.changed: ดัชนีเซสชันหรือเมทาดาทาเปลี่ยนแปลงpresence: การอัปเดตสแนปช็อต presence ของระบบtick: เหตุการณ์ keepalive / liveness เป็นระยะhealth: การอัปเดตสแนปช็อตสุขภาพของ Gatewayheartbeat: การอัปเดตสตรีมเหตุการณ์ Heartbeatcron: เหตุการณ์การเปลี่ยนแปลงรัน/งาน Cronshutdown: การแจ้งเตือนการปิด Gatewaynode.pair.requested/node.pair.resolved: วงจรชีวิตการจับคู่ Nodenode.invoke.request: การ broadcast คำขอ invoke ของ Nodedevice.pair.requested/device.pair.resolved: วงจรชีวิตอุปกรณ์ที่จับคู่voicewake.changed: การกำหนดค่า trigger wake-word เปลี่ยนแปลงexec.approval.requested/exec.approval.resolved: วงจรชีวิตการอนุมัติ execplugin.approval.requested/plugin.approval.resolved: วงจรชีวิตการอนุมัติ Plugin
เมธอดตัวช่วย Node
- Node อาจเรียก
skills.binsเพื่อดึงรายการ executable ของ skill ปัจจุบัน สำหรับการตรวจสอบ auto-allow
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 งานที่หายไปจะส่งคืนรูปแบบข้อผิดพลาด not-found ของ 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, timestamp, progress,
สรุปสถานะสิ้นสุด และข้อความข้อผิดพลาดที่ผ่านการล้างข้อมูลแล้ว 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 อนุมานบริบทรันไทม์ที่เชื่อถือได้จากเซสชันฝั่งเซิร์ฟเวอร์ แทนการยอมรับบริบทการยืนยันตัวตนหรือการส่งมอบที่ผู้เรียกส่งมา
- การตอบกลับเป็นการฉายภาพจากเซิร์ฟเวอร์ในขอบเขตเซสชันของคลังที่ใช้งานอยู่ รวมถึงเครื่องมือ core, Plugin, channel และเครื่องมือเซิร์ฟเวอร์ 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เอเจนต์ของเซสชันที่แก้ไขได้ต้องตรงกับagentId - แรปเปอร์ core สำหรับเจ้าของเท่านั้น เช่น
cron,gatewayและnodesต้องใช้อัตลักษณ์เจ้าของ/ผู้ดูแล (operator.admin) แม้ว่าเมธอดtools.invokeเองจะเป็นoperator.write - การตอบกลับเป็นเอนเวโลปสำหรับ SDK ที่มี
ok,toolName,outputที่ไม่บังคับ และฟิลด์errorแบบมีชนิด การปฏิเสธจากการอนุมัติหรือนโยบายจะส่งคืนok:falseในเพย์โหลด แทนการข้ามไปป์ไลน์นโยบายเครื่องมือของ Gateway
- ต้องระบุ
- ผู้ปฏิบัติการอาจเรียก
skills.status(operator.read) เพื่อดึงคลัง Skills ที่มองเห็นได้สำหรับเอเจนต์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ที่ระบุชัดเจน และจะ fallback ไปยังแค็ตตาล็อกเต็มเฉพาะเมื่อไม่มีแถวโมเดลที่กำหนดค่าไว้"all": แค็ตตาล็อก Gateway แบบเต็ม โดยข้ามagents.defaults.modelsใช้สิ่งนี้สำหรับการวินิจฉัยและ UI การค้นพบ ไม่ใช่ตัวเลือกโมเดลตามปกติ
การอนุมัติ Exec
- เมื่อคำขอ exec ต้องการการอนุมัติ Gateway จะบรอดแคสต์
exec.approval.requested - ไคลเอนต์ผู้ปฏิบัติการแก้ไขโดยเรียก
exec.approval.resolve(ต้องใช้สโคปoperator.approvals) - สำหรับ
host=nodeคำขอexec.approval.requestต้องมีsystemRunPlan(ข้อมูลมาตรฐานargv/cwd/rawCommand/เมทาดาทาเซสชัน) คำขอที่ไม่มีsystemRunPlanจะถูกปฏิเสธ - หลังการอนุมัติ การเรียก
node.invoke system.runที่ส่งต่อจะใช้systemRunPlanมาตรฐานนั้นซ้ำเป็นบริบทคำสั่ง/cwd/เซสชันที่มีอำนาจ - หากผู้เรียกแก้ไข
command,rawCommand,cwd,agentIdหรือsessionKeyระหว่างการเตรียมและการส่งต่อsystem.runที่ได้รับอนุมัติขั้นสุดท้าย Gateway จะปฏิเสธการรันแทนการเชื่อถือเพย์โหลดที่ถูกแก้ไข
Fallback การส่งมอบเอเจนต์
- คำขอ
agentสามารถมีdeliver=trueเพื่อขอการส่งมอบขาออก bestEffortDeliver=falseคงพฤติกรรมที่เข้มงวด: เป้าหมายการส่งมอบที่แก้ไขไม่ได้หรือเป็นภายในเท่านั้นจะส่งคืนINVALID_REQUESTbestEffortDeliver=trueอนุญาตให้ fallback ไปยังการดำเนินการเฉพาะเซสชันเมื่อไม่สามารถแก้ไขเส้นทางที่ส่งมอบภายนอกได้ (เช่น เซสชันภายใน/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) |
| การหนีบ fast-retry หลังปิด 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 จาก ส่วนหัวคำขอแทนconnect.params.auth.* - private-ingress
gateway.auth.mode: "none"จะข้ามการยืนยันตัวตน connect แบบ shared-secret ทั้งหมด อย่าเปิดเผยโหมดนั้นบน ingress สาธารณะ/ไม่น่าเชื่อถือ - หลังจากจับคู่แล้ว Gateway จะออก device token ที่จำกัดขอบเขตตาม role +
scopes ของการเชื่อมต่อ โดยส่งคืนใน
hello-ok.auth.deviceTokenและไคลเอนต์ควร เก็บไว้เพื่อใช้กับการเชื่อมต่อครั้งต่อไป - ไคลเอนต์ควรเก็บ
hello-ok.auth.deviceTokenหลักหลังจาก connect สำเร็จทุกครั้ง - การเชื่อมต่อใหม่ด้วย device token ที่ เก็บไว้ นั้นควรนำชุด scope ที่อนุมัติแล้ว ซึ่งเก็บไว้สำหรับ token นั้นกลับมาใช้ด้วย สิ่งนี้จะรักษาสิทธิ์เข้าถึง read/probe/status ที่ได้รับอนุญาตแล้ว และหลีกเลี่ยงการลดขอบเขตการเชื่อมต่อใหม่ อย่างเงียบ ๆ ให้เหลือเพียง scope admin-only โดยนัยที่แคบกว่า
- การประกอบการยืนยันตัวตน connect ฝั่งไคลเอนต์ (
selectConnectAuthในsrc/gateway/client.ts):auth.passwordแยกอิสระจากส่วนอื่นและจะถูกส่งต่อเสมอเมื่อตั้งค่าไว้auth.tokenจะถูกเติมตามลำดับความสำคัญ: shared token ที่ระบุชัดเจนก่อน จากนั้นdeviceTokenที่ระบุชัดเจน แล้วจึงเป็น token ต่ออุปกรณ์ที่เก็บไว้ (ผูกกับdeviceId+role)auth.bootstrapTokenจะถูกส่งเฉพาะเมื่อไม่มีรายการข้างต้นแก้เป็นauth.tokenได้ shared token หรือ device token ใด ๆ ที่แก้ได้จะระงับการส่งค่านี้- การเลื่อนระดับ token ของอุปกรณ์ที่เก็บไว้โดยอัตโนมัติในการลองซ้ำแบบครั้งเดียว
AUTH_TOKEN_MISMATCHถูกจำกัดไว้สำหรับ ปลายทางที่เชื่อถือได้เท่านั้น — loopback หรือwss://ที่มีtlsFingerprintแบบปักหมุดไว้wss://สาธารณะที่ไม่มีการปักหมุดจะไม่เข้าเงื่อนไข
- bootstrap ด้วย setup-code ในตัวจะส่งคืน
hello-ok.auth.deviceTokenของ node หลัก พร้อม token ของ operator ที่มีขอบเขตจำกัดในhello-ok.auth.deviceTokensสำหรับการส่งต่อให้มือถือที่เชื่อถือได้ token ของ operator มีoperator.talk.secretsสำหรับการอ่านค่ากำหนด native Talk แต่ไม่รวม scope สำหรับ การเปลี่ยนแปลงการจับคู่และoperator.admin - ระหว่างที่ bootstrap ด้วย setup-code ที่ไม่ใช่ baseline กำลังรอการอนุมัติ รายละเอียด
PAIRING_REQUIREDจะมีrecommendedNextStep: "wait_then_retry",retryable: true, และpauseReconnect: falseไคลเอนต์ควรเชื่อมต่อใหม่ต่อไปด้วย bootstrap token เดิม จนกว่าคำขอจะได้รับการอนุมัติหรือ token จะใช้งานไม่ได้ - เก็บ
hello-ok.auth.deviceTokensเฉพาะเมื่อ connect ใช้ bootstrap auth บน transport ที่เชื่อถือได้ เช่นwss://หรือการจับคู่แบบ loopback/local - หากไคลเอนต์ระบุ
deviceTokenอย่างชัดเจน หรือระบุscopesอย่างชัดเจน ชุด scope ที่ผู้เรียกขอยังคงเป็นแหล่งอ้างอิงหลัก scope ที่แคชไว้จะถูกนำกลับมาใช้ เฉพาะเมื่อไคลเอนต์กำลังนำ token ต่ออุปกรณ์ที่เก็บไว้กลับมาใช้ - Device tokens สามารถหมุนเวียน/เพิกถอนได้ผ่าน
device.token.rotateและdevice.token.revoke(ต้องใช้ scopeoperator.pairing) การหมุนเวียนหรือ เพิกถอน node หรือ role อื่นที่ไม่ใช่ operator ต้องใช้operator.adminด้วย device.token.rotateจะส่งคืน metadata การหมุนเวียน โดยจะสะท้อน bearer token ทดแทนเฉพาะสำหรับการเรียกจากอุปกรณ์เดียวกันที่ยืนยันตัวตนด้วย device token นั้นอยู่แล้ว เพื่อให้ไคลเอนต์ที่ใช้เฉพาะ token สามารถเก็บค่าทดแทนก่อนเชื่อมต่อใหม่ได้ การหมุนเวียนแบบ shared/admin จะไม่สะท้อน bearer token- การออก token การหมุนเวียน และการเพิกถอนจะถูกจำกัดไว้กับชุด role ที่อนุมัติแล้ว ซึ่งบันทึกอยู่ในรายการจับคู่ของอุปกรณ์นั้น การเปลี่ยนแปลง token ไม่สามารถขยายหรือ กำหนดเป้าหมาย role ของอุปกรณ์ที่การอนุมัติการจับคู่ไม่เคยให้ไว้
- สำหรับเซสชัน token ของอุปกรณ์ที่จับคู่แล้ว การจัดการอุปกรณ์จะจำกัดขอบเขตไว้กับตนเอง
เว้นแต่ผู้เรียกจะมี
operator.adminด้วย: ผู้เรียกที่ไม่ใช่ admin สามารถจัดการได้เฉพาะ token ของ operator สำหรับรายการอุปกรณ์ ของตนเอง เท่านั้น การจัดการ token ของ node และ token อื่นที่ไม่ใช่ operator เป็น admin-only แม้สำหรับอุปกรณ์ของผู้เรียกเอง device.token.rotateและdevice.token.revokeยังตรวจสอบชุด scope ของ token operator เป้าหมายเทียบกับ scope ของเซสชันปัจจุบันของผู้เรียกด้วย ผู้เรียกที่ไม่ใช่ admin ไม่สามารถหมุนเวียนหรือเพิกถอน token operator ที่มีขอบเขตกว้างกว่าที่ตนมีอยู่แล้ว- ความล้มเหลวของการยืนยันตัวตนจะมี
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:- ไคลเอนต์ที่เชื่อถือได้อาจลองซ้ำแบบมีขอบเขตหนึ่งครั้งด้วย token ต่ออุปกรณ์ที่แคชไว้
- หากการลองซ้ำนั้นล้มเหลว ไคลเอนต์ควรหยุดลูปเชื่อมต่อใหม่อัตโนมัติและแสดงคำแนะนำการดำเนินการสำหรับ operator
AUTH_SCOPE_MISMATCHหมายความว่า device token ได้รับการจดจำแล้วแต่ไม่ครอบคลุม role/scopes ที่ร้องขอ ไคลเอนต์ไม่ควรนำเสนอสิ่งนี้ว่าเป็น token ที่ไม่ถูกต้อง ให้แจ้ง operator เพื่อจับคู่ใหม่หรืออนุมัติสัญญา scope ที่แคบกว่า/กว้างกว่า
ข้อมูลระบุตัวตนอุปกรณ์ + การจับคู่
- Nodes ควรมีข้อมูลระบุตัวตนอุปกรณ์ที่เสถียร (
device.id) ซึ่งได้มาจาก fingerprint ของ keypair - Gateway ออก token ต่ออุปกรณ์ + role
- ต้องมีการอนุมัติการจับคู่สำหรับ ID อุปกรณ์ใหม่ เว้นแต่จะเปิดใช้การอนุมัติอัตโนมัติแบบ local
- การอนุมัติการจับคู่อัตโนมัติมีศูนย์กลางอยู่ที่การเชื่อมต่อ local loopback โดยตรง
- OpenClaw ยังมีเส้นทาง self-connect แบบ backend/container-local ที่แคบสำหรับ helper flows แบบ shared-secret ที่เชื่อถือได้
- การเชื่อมต่อ tailnet หรือ LAN บนโฮสต์เดียวกันยังคงถือเป็นระยะไกลสำหรับการจับคู่และ ต้องได้รับการอนุมัติ
- โดยปกติไคลเอนต์ WS จะรวมข้อมูลระบุตัวตน
deviceระหว่างconnect(operator + node) ข้อยกเว้น operator ที่ไม่มีอุปกรณ์มีเฉพาะเส้นทางความเชื่อถือที่ระบุชัดเจน:gateway.controlUi.allowInsecureAuth=trueสำหรับความเข้ากันได้กับ HTTP ที่ไม่ปลอดภัยแบบ localhost-only- การยืนยันตัวตน Control UI ของ operator ผ่าน
gateway.auth.mode: "trusted-proxy"ที่สำเร็จ gateway.controlUi.dangerouslyDisableDeviceAuth=true(break-glass, ลดระดับความปลอดภัยอย่างรุนแรง)- RPC backend ของ
gateway-clientแบบ direct-loopback บนเส้นทาง helper ภายในที่สงวนไว้
- การละเว้นข้อมูลระบุตัวตนอุปกรณ์มีผลต่อ scope เมื่ออนุญาตการเชื่อมต่อ operator
ที่ไม่มีอุปกรณ์ผ่านเส้นทางความเชื่อถือที่ระบุชัดเจน OpenClaw ยังคงล้าง scope
ที่ประกาศเองเป็นชุดว่าง เว้นแต่เส้นทางนั้นมีข้อยกเว้นการรักษา scope ที่มีชื่อกำกับ
จากนั้นเมธอดที่ถูกควบคุมด้วย scope จะล้มเหลวด้วย
missing scope gateway.controlUi.dangerouslyDisableDeviceAuth=trueเป็นเส้นทางรักษา scope แบบ break-glass ของ Control UI ไม่ได้ให้ scope แก่ไคลเอนต์ WebSocket แบบ backend หรือ CLI-shaped ที่กำหนดเองโดยพลการ- เส้นทาง helper backend ของ
gateway-clientแบบ direct-loopback ที่สงวนไว้จะรักษา scope เฉพาะสำหรับ RPC control-plane แบบ local ภายในเท่านั้น ID backend ที่กำหนดเอง จะไม่ได้รับข้อยกเว้นนี้ - การเชื่อมต่อทั้งหมดต้องลงนาม nonce
connect.challengeที่เซิร์ฟเวอร์ให้มา
การวินิจฉัยการย้ายการยืนยันตัวตนอุปกรณ์
สำหรับไคลเอนต์รุ่นเก่าที่ยังคงใช้พฤติกรรมการลงนามก่อน 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 - ลายเซ็น
v2รุ่นเก่ายังคงได้รับการยอมรับเพื่อความเข้ากันได้ แต่การปักหมุด metadata ของอุปกรณ์ที่จับคู่แล้วยังคงควบคุมนโยบายคำสั่งเมื่อเชื่อมต่อใหม่
TLS + การปักหมุด
- รองรับ TLS สำหรับการเชื่อมต่อ WS
- ไคลเอนต์อาจเลือกปักหมุด fingerprint ของใบรับรอง Gateway ได้ (ดู config
gateway.tlsพร้อมgateway.remote.tlsFingerprintหรือ CLI--tls-fingerprint)
Scope
โปรโตคอลนี้เปิดเผย Gateway API เต็มรูปแบบ (status, channels, models, chat,
agent, sessions, nodes, approvals เป็นต้น) พื้นผิวที่แน่นอนกำหนดโดย
TypeBox schemas ใน packages/gateway-protocol/src/schema.ts