41 KiB
| read_when | summary | title | x-i18n | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Protokol WebSocket Gateway: jabat tangan, bingkai, pengelolaan versi | Protokol Gateway |
|
Gateway protocol WS adalah bidang kontrol tunggal + transport node untuk OpenClaw. Semua klien (CLI, UI web, aplikasi macOS, node iOS/Android, node headless) terhubung melalui WebSocket dan mendeklarasikan peran + cakupan mereka saat handshake.
Transport
- WebSocket, frame teks dengan payload JSON.
- Frame pertama harus berupa permintaan
connect. - Frame pra-koneksi dibatasi hingga 64 KiB. Setelah handshake berhasil, klien
harus mengikuti batas
hello-ok.policy.maxPayloaddanhello-ok.policy.maxBufferedBytes. Dengan diagnostik diaktifkan, frame masuk yang terlalu besar dan buffer keluar yang lambat memancarkan eventpayload.largesebelum gateway menutup atau membuang frame yang terdampak. Event ini menyimpan ukuran, batas, permukaan, dan kode alasan aman. Event ini tidak menyimpan isi pesan, konten lampiran, isi frame mentah, token, cookie, atau nilai rahasia.
Handshake (connect)
Gateway → Klien (tantangan pra-koneksi):
{
"type": "event",
"event": "connect.challenge",
"payload": { "nonce": "…", "ts": 1737264000000 }
}
Klien → Gateway:
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"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 → Klien:
{
"type": "res",
"id": "…",
"ok": true,
"payload": {
"type": "hello-ok",
"protocol": 3,
"server": { "version": "…", "connId": "…" },
"features": { "methods": ["…"], "events": ["…"] },
"snapshot": { "…": "…" },
"auth": {
"role": "operator",
"scopes": ["operator.read", "operator.write"]
},
"policy": {
"maxPayload": 26214400,
"maxBufferedBytes": 52428800,
"tickIntervalMs": 15000
}
}
}
Saat Gateway masih menyelesaikan sidecar startup, permintaan connect dapat
mengembalikan error UNAVAILABLE yang dapat dicoba ulang dengan details.reason
diatur ke "startup-sidecars" dan retryAfterMs. Klien harus mencoba ulang
respons tersebut dalam anggaran koneksi keseluruhan mereka, bukan menampilkannya
sebagai kegagalan handshake terminal.
server, features, snapshot, dan policy semuanya diwajibkan oleh skema
(src/gateway/protocol/schema/frames.ts). auth juga diwajibkan dan melaporkan
peran/cakupan yang dinegosiasikan. canvasHostUrl bersifat opsional.
Ketika tidak ada token perangkat yang diterbitkan, hello-ok.auth melaporkan
izin yang dinegosiasikan tanpa kolom token:
{
"auth": {
"role": "operator",
"scopes": ["operator.read", "operator.write"]
}
}
Klien backend tepercaya dalam proses yang sama (client.id: "gateway-client",
client.mode: "backend") dapat menghilangkan device pada koneksi loopback
langsung ketika mereka mengautentikasi dengan token/kata sandi gateway bersama.
Jalur ini disediakan untuk RPC bidang kontrol internal dan mencegah baseline
pasangan CLI/perangkat yang usang memblokir pekerjaan backend lokal seperti
pembaruan sesi subagen. Klien jarak jauh, klien asal browser, klien node, dan
klien token-perangkat/identitas-perangkat eksplisit tetap menggunakan pemeriksaan
pasangan dan peningkatan cakupan normal.
Ketika token perangkat diterbitkan, hello-ok juga menyertakan:
{
"auth": {
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.read", "operator.write"]
}
}
Selama handoff bootstrap tepercaya, hello-ok.auth juga dapat menyertakan entri
peran tambahan yang dibatasi dalam deviceTokens:
{
"auth": {
"deviceToken": "…",
"role": "node",
"scopes": [],
"deviceTokens": [
{
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"]
}
]
}
}
Untuk alur bootstrap node/operator bawaan, token node primer tetap
scopes: [] dan token operator yang diserahkan tetap dibatasi pada allowlist
operator bootstrap (operator.approvals, operator.read,
operator.talk.secrets, operator.write). Pemeriksaan cakupan bootstrap tetap
berprefiks peran: entri operator hanya memenuhi permintaan operator, dan peran
non-operator tetap memerlukan cakupan di bawah prefiks peran mereka sendiri.
Contoh node
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"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": "…"
}
}
}
Framing
- Permintaan:
{type:"req", id, method, params} - Respons:
{type:"res", id, ok, payload|error} - Event:
{type:"event", event, payload, seq?, stateVersion?}
Metode yang memiliki efek samping memerlukan kunci idempotensi (lihat skema).
Peran + cakupan
Untuk model cakupan operator lengkap, pemeriksaan pada waktu persetujuan, dan semantik rahasia bersama, lihat Cakupan operator.
Peran
operator= klien bidang kontrol (CLI/UI/otomasi).node= host kapabilitas (camera/screen/canvas/system.run).
Cakupan (operator)
Cakupan umum:
operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
talk.config dengan includeSecrets: true memerlukan operator.talk.secrets
(atau operator.admin).
Metode RPC gateway yang didaftarkan Plugin dapat meminta cakupan operatornya
sendiri, tetapi prefiks admin inti yang dicadangkan (config.*,
exec.approvals.*, wizard.*, update.*) selalu diselesaikan ke
operator.admin.
Cakupan metode hanya gerbang pertama. Beberapa perintah slash yang dicapai
melalui chat.send menerapkan pemeriksaan tingkat perintah yang lebih ketat di
atasnya. Misalnya, penulisan persisten /config set dan /config unset
memerlukan operator.admin.
node.pair.approve juga memiliki pemeriksaan cakupan tambahan pada waktu
persetujuan di atas cakupan metode dasar:
- permintaan tanpa perintah:
operator.pairing - permintaan dengan perintah node non-exec:
operator.pairing+operator.write - permintaan yang menyertakan
system.run,system.run.prepare, atausystem.which:operator.pairing+operator.admin
Kapabilitas/perintah/izin (node)
Node mendeklarasikan klaim kapabilitas saat connect:
caps: kategori kapabilitas tingkat tinggi.commands: allowlist perintah untuk invoke.permissions: sakelar granular (mis.screen.record,camera.capture).
Gateway memperlakukan ini sebagai klaim dan memberlakukan allowlist sisi server.
Presence
system-presencemengembalikan entri yang dikunci berdasarkan identitas perangkat.- Entri Presence mencakup
deviceId,roles, danscopessehingga UI dapat menampilkan satu baris per perangkat meskipun perangkat tersebut terhubung sebagai operator dan node. node.listmenyertakan kolom opsionallastSeenAtMsdanlastSeenReason. Node yang terhubung melaporkan waktu koneksi mereka saat ini sebagailastSeenAtMsdengan alasanconnect; node yang sudah dipasangkan juga dapat melaporkan Presence latar belakang yang tahan lama ketika event node tepercaya memperbarui metadata pasangan mereka.
Event node tetap hidup di latar belakang
Node dapat memanggil node.event dengan event: "node.presence.alive" untuk mencatat bahwa node yang dipasangkan
hidup selama wake latar belakang tanpa menandainya sebagai terhubung.
{
"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 adalah enum tertutup: background, silent_push, bg_app_refresh,
significant_location, manual, atau connect. String trigger yang tidak dikenal dinormalisasi menjadi
background oleh gateway sebelum persistensi. Event hanya tahan lama untuk sesi perangkat node yang diautentikasi;
sesi tanpa perangkat atau belum dipasangkan mengembalikan handled: false.
Gateway yang berhasil mengembalikan hasil terstruktur:
{
"ok": true,
"event": "node.presence.alive",
"handled": true,
"reason": "persisted"
}
Gateway lama mungkin masih mengembalikan { "ok": true } untuk node.event; klien harus memperlakukannya sebagai
RPC yang diakui, bukan sebagai persistensi Presence yang tahan lama.
Cakupan event siaran
Event siaran WebSocket yang didorong server dibatasi cakupan sehingga sesi yang dicakup pasangan atau hanya-node tidak menerima konten sesi secara pasif.
- Frame chat, agen, dan hasil alat (termasuk event
agentstreaming dan hasil panggilan alat) memerlukan setidaknyaoperator.read. Sesi tanpaoperator.readmelewati frame ini sepenuhnya. - Siaran
plugin.*yang ditentukan Plugin dibatasi keoperator.writeatauoperator.admin, tergantung bagaimana Plugin mendaftarkannya. - Event status dan transport (
heartbeat,presence,tick, siklus hidup connect/disconnect, dll.) tetap tidak dibatasi sehingga kesehatan transport tetap dapat diamati oleh setiap sesi yang diautentikasi. - Keluarga event siaran yang tidak dikenal secara default dibatasi cakupan (fail-closed) kecuali handler terdaftar secara eksplisit melonggarkannya.
Setiap koneksi klien mempertahankan nomor urut per-kliennya sendiri sehingga siaran mempertahankan urutan monoton pada soket tersebut meskipun klien yang berbeda melihat subset aliran event yang berbeda karena difilter cakupan.
Keluarga metode RPC umum
Permukaan WS publik lebih luas daripada contoh handshake/auth di atas. Ini
bukan dump yang dihasilkan — hello-ok.features.methods adalah daftar
discovery konservatif yang dibangun dari src/gateway/server-methods-list.ts
ditambah ekspor metode plugin/channel yang dimuat. Perlakukan ini sebagai
discovery fitur, bukan enumerasi lengkap dari src/gateway/server-methods/*.ts.
Keluarga event umum
chat: pembaruan chat UI sepertichat.injectdan event chat khusus transkrip lainnya.session.messagedansession.tool: pembaruan transkrip/event-stream untuk sesi yang dilanggani.sessions.changed: indeks sesi atau metadata berubah.presence: pembaruan snapshot presence sistem.tick: event keepalive / liveness berkala.health: pembaruan snapshot kesehatan gateway.heartbeat: pembaruan stream event Heartbeat.cron: event perubahan run/job Cron.shutdown: notifikasi shutdown gateway.node.pair.requested/node.pair.resolved: siklus hidup pairing Node.node.invoke.request: broadcast permintaan invoke Node.device.pair.requested/device.pair.resolved: siklus hidup perangkat yang dipasangkan.voicewake.changed: konfigurasi pemicu wake-word berubah.exec.approval.requested/exec.approval.resolved: siklus hidup persetujuan exec.plugin.approval.requested/plugin.approval.resolved: siklus hidup persetujuan plugin.
Metode pembantu Node
- Node dapat memanggil
skills.binsuntuk mengambil daftar eksekutabel skill saat ini untuk pemeriksaan auto-allow.
Metode pembantu operator
- Operator dapat memanggil
commands.list(operator.read) untuk mengambil inventaris perintah runtime untuk sebuah agen.agentIdbersifat opsional; hilangkan untuk membaca workspace agen default.scopemengontrol surface mana yang ditargetkan olehnameutama:textmengembalikan token perintah teks utama tanpa awalan/nativedan jalur defaultbothmengembalikan nama native yang sadar penyedia jika tersedia
textAliasesmembawa alias slash persis seperti/modeldan/m.nativeNamemembawa nama perintah native yang sadar penyedia jika ada.providerbersifat opsional dan hanya memengaruhi penamaan native serta ketersediaan perintah plugin native.includeArgs=falsemenghilangkan metadata argumen berseri dari respons.
- Operator dapat memanggil
tools.catalog(operator.read) untuk mengambil katalog tool runtime untuk sebuah agen. Respons menyertakan tool yang dikelompokkan dan metadata asal:source:coreataupluginpluginId: pemilik plugin saatsource="plugin"optional: apakah tool plugin bersifat opsional
- Operator dapat memanggil
tools.effective(operator.read) untuk mengambil inventaris tool yang efektif saat runtime untuk sebuah sesi.sessionKeywajib diisi.- Gateway memperoleh konteks runtime tepercaya dari sesi di sisi server, alih-alih menerima konteks autentikasi atau pengiriman yang diberikan pemanggil.
- Respons dicakup untuk sesi dan mencerminkan apa yang dapat digunakan percakapan aktif saat ini, termasuk tool inti, plugin, dan kanal.
- Operator dapat memanggil
tools.invoke(operator.write) untuk menjalankan satu tool yang tersedia melalui jalur kebijakan Gateway yang sama seperti/tools/invoke.namewajib diisi.args,sessionKey,agentId,confirm, danidempotencyKeybersifat opsional.- Jika
sessionKeydanagentIdsama-sama ada, agen sesi yang di-resolve harus cocok denganagentId. - Respons berupa envelope yang menghadap SDK dengan bidang
ok,toolName,outputopsional, danerrorbertipe. Penolakan persetujuan atau kebijakan mengembalikanok:falsedalam payload, bukan melewati pipeline kebijakan tool Gateway.
- Operator dapat memanggil
skills.status(operator.read) untuk mengambil inventaris keterampilan yang terlihat untuk sebuah agen.agentIdbersifat opsional; hilangkan untuk membaca workspace agen default.- Respons menyertakan kelayakan, kebutuhan yang belum terpenuhi, pemeriksaan konfigurasi, dan opsi instalasi yang disanitasi tanpa mengekspos nilai rahasia mentah.
- Operator dapat memanggil
skills.searchdanskills.detail(operator.read) untuk metadata penemuan ClawHub. - Operator dapat memanggil
skills.install(operator.admin) dalam dua mode:- Mode ClawHub:
{ source: "clawhub", slug, version?, force? }memasang folder keterampilan ke direktoriskills/workspace agen default. - Mode pemasang Gateway:
{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }menjalankan aksimetadata.openclaw.installyang dideklarasikan pada host Gateway.
- Mode ClawHub:
- Operator dapat memanggil
skills.update(operator.admin) dalam dua mode:- Mode ClawHub memperbarui satu slug yang dilacak atau semua instalasi ClawHub yang dilacak di workspace agen default.
- Mode konfigurasi mem-patch nilai
skills.entries.<skillKey>sepertienabled,apiKey, danenv.
Tampilan models.list
models.list menerima parameter view opsional:
- Dihilangkan atau
"default": perilaku runtime saat ini. Jikaagents.defaults.modelsdikonfigurasi, respons adalah katalog yang diizinkan; jika tidak, respons adalah katalog Gateway lengkap. "configured": perilaku seukuran pemilih. Jikaagents.defaults.modelsdikonfigurasi, itu tetap menang. Jika tidak, respons menggunakan entrimodels.providers.*.modelseksplisit, dengan fallback ke katalog lengkap hanya saat tidak ada baris model yang dikonfigurasi."all": katalog Gateway lengkap, melewatiagents.defaults.models. Gunakan ini untuk diagnostik dan UI penemuan, bukan pemilih model normal.
Persetujuan eksekusi
- Saat permintaan eksekusi membutuhkan persetujuan, Gateway menyiarkan
exec.approval.requested. - Klien operator menyelesaikannya dengan memanggil
exec.approval.resolve(memerlukan scopeoperator.approvals). - Untuk
host=node,exec.approval.requestharus menyertakansystemRunPlan(argv/cwd/rawCommand/metadata sesi kanonis). Permintaan tanpasystemRunPlanditolak. - Setelah disetujui, panggilan
node.invoke system.runyang diteruskan menggunakan kembalisystemRunPlankanonis tersebut sebagai konteks perintah/cwd/sesi otoritatif. - Jika pemanggil memutasi
command,rawCommand,cwd,agentId, atausessionKeyantara persiapan dan penerusansystem.runfinal yang disetujui, Gateway menolak run tersebut alih-alih memercayai payload yang dimutasi.
Fallback pengiriman agen
- Permintaan
agentdapat menyertakandeliver=trueuntuk meminta pengiriman keluar. bestEffortDeliver=falsemempertahankan perilaku ketat: target pengiriman yang tidak terselesaikan atau hanya internal mengembalikanINVALID_REQUEST.bestEffortDeliver=truememungkinkan fallback ke eksekusi hanya sesi saat tidak ada rute eksternal yang dapat dikirim yang bisa di-resolve (misalnya sesi internal/webchat atau konfigurasi multi-kanal yang ambigu).
Pembuatan versi
PROTOCOL_VERSIONberada disrc/gateway/protocol/schema/protocol-schemas.ts.- Klien mengirim
minProtocol+maxProtocol; server menolak ketidakcocokan. - Skema + model dibuat dari definisi TypeBox:
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
Konstanta klien
Klien referensi di src/gateway/client.ts menggunakan default berikut. Nilai stabil di seluruh protokol v3 dan merupakan baseline yang diharapkan untuk klien pihak ketiga.
| Konstanta | Default | Sumber |
|---|---|---|
PROTOCOL_VERSION |
3 |
src/gateway/protocol/schema/protocol-schemas.ts |
| Timeout permintaan (per RPC) | 30_000 ms |
src/gateway/client.ts (requestTimeoutMs) |
| Timeout preauth / connect-challenge | 15_000 ms |
src/gateway/handshake-timeouts.ts (config/env dapat menaikkan anggaran server/klien berpasangan) |
| Backoff koneksi ulang awal | 1_000 ms |
src/gateway/client.ts (backoffMs) |
| Backoff koneksi ulang maks | 30_000 ms |
src/gateway/client.ts (scheduleReconnect) |
| Clamp coba ulang cepat setelah device-token close | 250 ms |
src/gateway/client.ts |
Grace force-stop sebelum terminate() |
250 ms |
FORCE_STOP_TERMINATE_GRACE_MS |
Timeout default stopAndWait() |
1_000 ms |
STOP_AND_WAIT_TIMEOUT_MS |
Interval tick default (sebelum hello-ok) |
30_000 ms |
src/gateway/client.ts |
| Penutupan tick-timeout | kode 4000 saat senyap melebihi tickIntervalMs * 2 |
src/gateway/client.ts |
MAX_PAYLOAD_BYTES |
25 * 1024 * 1024 (25 MB) |
src/gateway/server-constants.ts |
Server mengiklankan policy.tickIntervalMs, policy.maxPayload, dan policy.maxBufferedBytes yang efektif dalam hello-ok; klien harus mematuhi nilai tersebut alih-alih default sebelum handshake.
Autentikasi
- Autentikasi Gateway berbasis rahasia bersama menggunakan
connect.params.auth.tokenatauconnect.params.auth.password, tergantung pada mode autentikasi yang dikonfigurasi. - Mode yang membawa identitas seperti Tailscale Serve
(
gateway.auth.allowTailscale: true) atau non-loopbackgateway.auth.mode: "trusted-proxy"memenuhi pemeriksaan autentikasi connect dari header permintaan, bukan dariconnect.params.auth.*. - Ingress privat
gateway.auth.mode: "none"melewati autentikasi connect berbasis rahasia bersama sepenuhnya; jangan mengekspos mode itu pada ingress publik/tidak tepercaya. - Setelah pairing, Gateway menerbitkan token perangkat yang dicakup ke peran
koneksi + cakupan. Token ini dikembalikan dalam
hello-ok.auth.deviceTokendan harus disimpan oleh klien untuk koneksi berikutnya. - Klien harus menyimpan
hello-ok.auth.deviceTokenutama setelah setiap connect yang berhasil. - Menghubungkan ulang dengan token perangkat yang tersimpan itu juga harus menggunakan kembali set cakupan yang disetujui dan tersimpan untuk token tersebut. Ini mempertahankan akses baca/probe/status yang sudah diberikan dan menghindari reconnect yang diam-diam menyempit menjadi cakupan implisit hanya-admin.
- Penyusunan autentikasi connect sisi klien (
selectConnectAuthdisrc/gateway/client.ts):auth.passwordbersifat ortogonal dan selalu diteruskan saat disetel.auth.tokendiisi berdasarkan urutan prioritas: token bersama eksplisit terlebih dahulu, laludeviceTokeneksplisit, lalu token per perangkat yang tersimpan (dikunci berdasarkandeviceId+role).auth.bootstrapTokendikirim hanya ketika tidak ada hal di atas yang menghasilkanauth.token. Token bersama atau token perangkat apa pun yang berhasil diselesaikan akan menekannya.- Promosi otomatis token perangkat yang tersimpan pada percobaan ulang sekali jalan
AUTH_TOKEN_MISMATCHdibatasi hanya untuk endpoint tepercaya — loopback, atauwss://dengantlsFingerprintyang dipin.wss://publik tanpa pinning tidak memenuhi syarat.
- Entri tambahan
hello-ok.auth.deviceTokensadalah token serah-terima bootstrap. Simpan hanya ketika connect menggunakan autentikasi bootstrap pada transport tepercaya sepertiwss://atau pairing loopback/lokal. - Jika klien menyediakan
deviceTokeneksplisit atauscopeseksplisit, set cakupan yang diminta pemanggil itu tetap otoritatif; cakupan cache hanya digunakan kembali ketika klien menggunakan kembali token per perangkat yang tersimpan. - Token perangkat dapat dirotasi/dicabut melalui
device.token.rotatedandevice.token.revoke(memerlukan cakupanoperator.pairing). device.token.rotatemengembalikan metadata rotasi. Ia menggemakan token bearer pengganti hanya untuk panggilan perangkat yang sama yang sudah diautentikasi dengan token perangkat tersebut, sehingga klien hanya-token dapat menyimpan penggantinya sebelum menghubungkan ulang. Rotasi bersama/admin tidak menggemakan token bearer.- Penerbitan, rotasi, dan pencabutan token tetap dibatasi pada set peran yang disetujui yang tercatat dalam entri pairing perangkat tersebut; mutasi token tidak dapat memperluas atau menargetkan peran perangkat yang tidak pernah diberikan oleh persetujuan pairing.
- Untuk sesi token perangkat yang sudah dipairing, manajemen perangkat bersifat tercakup sendiri kecuali
pemanggil juga memiliki
operator.admin: pemanggil non-admin dapat menghapus/mencabut/merotasi hanya entri perangkat miliknya sendiri. device.token.rotatedandevice.token.revokejuga memeriksa set cakupan token operator target terhadap cakupan sesi pemanggil saat ini. Pemanggil non-admin tidak dapat merotasi atau mencabut token operator yang lebih luas daripada yang sudah mereka miliki.- Kegagalan autentikasi menyertakan
error.details.codeplus petunjuk pemulihan:error.details.canRetryWithDeviceToken(boolean)error.details.recommendedNextStep(retry_with_device_token,update_auth_configuration,update_auth_credentials,wait_then_retry,review_auth_configuration)
- Perilaku klien untuk
AUTH_TOKEN_MISMATCH:- Klien tepercaya dapat mencoba satu percobaan ulang terbatas dengan token per perangkat yang di-cache.
- Jika percobaan ulang itu gagal, klien harus menghentikan loop reconnect otomatis dan menampilkan panduan tindakan operator.
Identitas perangkat + pairing
- Node harus menyertakan identitas perangkat yang stabil (
device.id) yang diturunkan dari fingerprint keypair. - Gateway menerbitkan token per perangkat + peran.
- Persetujuan pairing diperlukan untuk ID perangkat baru kecuali persetujuan otomatis lokal diaktifkan.
- Persetujuan otomatis pairing berpusat pada connect local loopback langsung.
- OpenClaw juga memiliki jalur self-connect backend/container-lokal yang sempit untuk alur pembantu rahasia bersama tepercaya.
- Connect tailnet atau LAN pada host yang sama tetap diperlakukan sebagai remote untuk pairing dan memerlukan persetujuan.
- Klien WS biasanya menyertakan identitas
deviceselamaconnect(operator + node). Satu-satunya pengecualian operator tanpa perangkat adalah jalur kepercayaan eksplisit:gateway.controlUi.allowInsecureAuth=trueuntuk kompatibilitas HTTP tidak aman khusus localhost.- autentikasi Control UI operator
gateway.auth.mode: "trusted-proxy"yang berhasil. gateway.controlUi.dangerouslyDisableDeviceAuth=true(break-glass, penurunan keamanan berat).- RPC backend
gateway-clientdirect-loopback yang diautentikasi dengan token/kata sandi gateway bersama.
- Semua koneksi harus menandatangani nonce
connect.challengeyang disediakan server.
Diagnostik migrasi autentikasi perangkat
Untuk klien lama yang masih menggunakan perilaku penandatanganan pra-challenge, connect kini mengembalikan
kode detail DEVICE_AUTH_* di bawah error.details.code dengan error.details.reason yang stabil.
Kegagalan migrasi umum:
| Pesan | details.code | details.reason | Arti |
|---|---|---|---|
device nonce required |
DEVICE_AUTH_NONCE_REQUIRED |
device-nonce-missing |
Klien menghilangkan device.nonce (atau mengirim kosong). |
device nonce mismatch |
DEVICE_AUTH_NONCE_MISMATCH |
device-nonce-mismatch |
Klien menandatangani dengan nonce yang usang/salah. |
device signature invalid |
DEVICE_AUTH_SIGNATURE_INVALID |
device-signature |
Payload tanda tangan tidak cocok dengan payload v2. |
device signature expired |
DEVICE_AUTH_SIGNATURE_EXPIRED |
device-signature-stale |
Timestamp yang ditandatangani berada di luar skew yang diizinkan. |
device identity mismatch |
DEVICE_AUTH_DEVICE_ID_MISMATCH |
device-id-mismatch |
device.id tidak cocok dengan fingerprint kunci publik. |
device public key invalid |
DEVICE_AUTH_PUBLIC_KEY_INVALID |
device-public-key |
Format/kanonisasi kunci publik gagal. |
Target migrasi:
- Selalu tunggu
connect.challenge. - Tanda tangani payload v2 yang menyertakan nonce server.
- Kirim nonce yang sama dalam
connect.params.device.nonce. - Payload tanda tangan yang disarankan adalah
v3, yang mengikatplatformdandeviceFamilyselain bidang perangkat/klien/peran/cakupan/token/nonce. - Tanda tangan
v2lama tetap diterima untuk kompatibilitas, tetapi pinning metadata perangkat yang sudah dipairing tetap mengontrol kebijakan perintah saat reconnect.
TLS + pinning
- TLS didukung untuk koneksi WS.
- Klien dapat secara opsional melakukan pin pada fingerprint sertifikat gateway (lihat konfigurasi
gateway.tlsplusgateway.remote.tlsFingerprintatau CLI--tls-fingerprint).
Cakupan
Protokol ini mengekspos API gateway lengkap (status, channel, model, chat,
agen, sesi, node, persetujuan, dll.). Permukaan persisnya ditentukan oleh
skema TypeBox di src/gateway/protocol/schema.ts.