Gateway
Protokół Gateway
Protokół Gateway WS jest pojedynczą płaszczyzną sterowania + transportem węzłów dla OpenClaw. Wszyscy klienci (CLI, web UI, aplikacja macOS, węzły iOS/Android, węzły headless) łączą się przez WebSocket i deklarują swoją rolę + zakres podczas uzgadniania połączenia.
Transport
- WebSocket, ramki tekstowe z ładunkami JSON.
- Pierwsza ramka musi być żądaniem
connect. - Ramki przed połączeniem są ograniczone do 64 KiB. Po udanym uzgodnieniu połączenia klienci
powinni przestrzegać limitów
hello-ok.policy.maxPayloadihello-ok.policy.maxBufferedBytes. Przy włączonej diagnostyce zbyt duże ramki przychodzące i wolne bufory wychodzące emitują zdarzeniapayload.largezanim gateway zamknie lub odrzuci dotkniętą ramkę. Te zdarzenia zachowują rozmiary, limity, powierzchnie i bezpieczne kody przyczyn. Nie zachowują treści wiadomości, zawartości załączników, surowej treści ramki, tokenów, plików cookie ani wartości tajnych.
Uzgadnianie połączenia (connect)
Gateway → Klient (wyzwanie przed połączeniem):
{ "type": "event", "event": "connect.challenge", "payload": { "nonce": "…", "ts": 1737264000000 }}Klient → 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 → Klient:
{ "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 } }}Gdy Gateway nadal kończy uruchamianie procesów pomocniczych, żądanie connect może
zwrócić ponawialny błąd UNAVAILABLE z details.reason ustawionym na
"startup-sidecars" oraz retryAfterMs. Klienci powinni ponawiać taką odpowiedź
w ramach swojego ogólnego budżetu połączenia zamiast przedstawiać ją jako końcową
awarię uzgadniania połączenia.
server, features, snapshot i policy są wymagane przez schemat
(packages/gateway-protocol/src/schema/frames.ts). auth jest również wymagane i zgłasza
wynegocjowaną rolę/zakresy. pluginSurfaceUrls jest opcjonalne i mapuje nazwy powierzchni
pluginów, takie jak canvas, na zakresowe hostowane adresy URL.
Zakresowe adresy URL powierzchni pluginów mogą wygasać. Węzły mogą wywołać
node.pluginSurface.refresh z { "surface": "canvas" }, aby otrzymać świeży
wpis w pluginSurfaceUrls. Eksperymentalna przebudowa pluginu Canvas nie
obsługuje przestarzałej ścieżki zgodności canvasHostUrl, canvasCapability ani
node.canvas.capability.refresh; obecni klienci natywni i gatewaye muszą używać powierzchni pluginów.
Gdy token urządzenia nie zostanie wydany, hello-ok.auth zgłasza wynegocjowane
uprawnienia bez pól tokenu:
{ "auth": { "role": "operator", "scopes": ["operator.read", "operator.write"] }}Zaufani klienci backendu w tym samym procesie (client.id: "gateway-client",
client.mode: "backend") mogą pomijać device przy bezpośrednich połączeniach loopback,
gdy uwierzytelniają się współdzielonym tokenem/hasłem gatewaya. Ta ścieżka jest zarezerwowana
dla wewnętrznych RPC płaszczyzny sterowania i zapobiega blokowaniu lokalnej pracy backendu,
takiej jak aktualizacje sesji podagentów, przez nieaktualne bazowe parowania CLI/urządzeń. Klienci zdalni,
klienci pochodzący z przeglądarki, klienci węzłów oraz jawni klienci tokenu urządzenia/tożsamości urządzenia
nadal używają normalnych kontroli parowania i podnoszenia zakresu.
Gdy token urządzenia zostanie wydany, hello-ok zawiera również:
{ "auth": { "deviceToken": "…", "role": "operator", "scopes": ["operator.read", "operator.write"] }}Wbudowany bootstrap kodu QR/kodu konfiguracji jest świeżą ścieżką przekazania mobilnego. Udane bazowe połączenie kodem konfiguracji zwraca główny token węzła oraz jeden ograniczony token operatora:
{ "auth": { "deviceToken": "…", "role": "node", "scopes": [], "deviceTokens": [ { "deviceToken": "…", "role": "operator", "scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"] } ] }}Przekazanie operatora jest celowo ograniczone, aby onboarding przez QR mógł uruchomić
mobilną pętlę operatora i ukończyć natywną konfigurację bez przyznawania zakresów
modyfikacji parowania ani operator.admin. Obejmuje operator.talk.secrets, aby
klient natywny mógł odczytać konfigurację Talk potrzebną po bootstrapie. Szersze
parowanie i dostęp administracyjny wymagają osobnego zatwierdzonego parowania operatora lub przepływu
tokenu. Klienci powinni utrwalać
hello-ok.auth.deviceTokens tylko
wtedy, gdy połączenie użyło uwierzytelniania bootstrap na zaufanym transporcie, takim jak wss:// lub
loopback/parowanie lokalne.
Przykład węzła
{ "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": "…" } }}Ramkowanie
- Żądanie:
{type:"req", id, method, params} - Odpowiedź:
{type:"res", id, ok, payload|error} - Zdarzenie:
{type:"event", event, payload, seq?, stateVersion?}
Metody wywołujące skutki uboczne wymagają kluczy idempotencji (zobacz schemat).
Role + zakresy
Pełny model zakresów operatora, kontrole w czasie zatwierdzania i semantykę współdzielonych sekretów opisuje sekcja Zakresy operatora.
Role
operator= klient płaszczyzny sterowania (CLI/UI/automatyzacja).node= host możliwości (camera/screen/canvas/system.run).
Zakresy (operator)
Typowe zakresy:
operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
talk.config z includeSecrets: true wymaga operator.talk.secrets
(lub operator.admin).
Gdy sekrety są dołączone, klienci powinni odczytywać poświadczenie aktywnego dostawcy Talk
z talk.resolved.config.apiKey; talk.providers.<id>.apiKey
pozostaje w kształcie źródłowym i może być obiektem SecretRef albo zredagowanym ciągiem.
Metody RPC gatewaya zarejestrowane przez plugin mogą żądać własnego zakresu operatora, ale
zastrzeżone prefiksy administracyjne rdzenia (config.*, exec.approvals.*, wizard.*,
update.*) zawsze rozwiązują się do operator.admin.
Zakres metody jest tylko pierwszą bramką. Niektóre polecenia ukośnikowe osiągane przez
chat.send nakładają dodatkowo surowsze kontrole na poziomie polecenia. Na przykład trwałe
zapisy /config set i /config unset wymagają operator.admin.
node.pair.approve ma również dodatkową kontrolę zakresu w czasie zatwierdzania ponad
bazowym zakresem metody:
- żądania bez poleceń:
operator.pairing - żądania z poleceniami węzła innymi niż exec:
operator.pairing+operator.write - żądania obejmujące
system.run,system.run.preparelubsystem.which:operator.pairing+operator.admin
Możliwości/polecenia/uprawnienia (węzeł)
Węzły deklarują roszczenia dotyczące możliwości w czasie połączenia:
caps: kategorie możliwości wysokiego poziomu, takie jakcamera,canvas,screen,location,voiceitalk.commands: lista dozwolonych poleceń dla invoke.permissions: szczegółowe przełączniki (np.screen.record,camera.capture).
Gateway traktuje je jako roszczenia i egzekwuje listy dozwolone po stronie serwera.
Obecność
system-presencezwraca wpisy kluczowane tożsamością urządzenia.- Wpisy obecności obejmują
deviceId,rolesiscopes, aby UI mogły pokazywać jeden wiersz na urządzenie nawet wtedy, gdy łączy się ono zarówno jako operator, jak i node. node.listobejmuje opcjonalne polalastSeenAtMsilastSeenReason. Połączone węzły zgłaszają swój bieżący czas połączenia jakolastSeenAtMsz przyczynąconnect; sparowane węzły mogą też zgłaszać trwałą obecność w tle, gdy zaufane zdarzenie węzła aktualizuje ich metadane parowania.
Zdarzenie aktywności węzła w tle
Węzły mogą wywołać node.event z event: "node.presence.alive", aby zapisać, że sparowany węzeł był
aktywny podczas wybudzenia w tle bez oznaczania go jako połączonego.
{ "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 jest zamkniętym wyliczeniem: background, silent_push, bg_app_refresh,
significant_location, manual lub connect. Nieznane ciągi wyzwalacza są normalizowane do
background przez gateway przed utrwaleniem. Zdarzenie jest trwałe tylko dla uwierzytelnionych sesji
urządzeń węzłów; sesje bez urządzenia lub niesparowane zwracają handled: false.
Udane gatewaye zwracają ustrukturyzowany wynik:
{ "ok": true, "event": "node.presence.alive", "handled": true, "reason": "persisted"}Starsze gatewaye mogą nadal zwracać { "ok": true } dla node.event; klienci powinni traktować to jako
potwierdzone RPC, a nie jako trwałe utrwalenie obecności.
Zakresowanie zdarzeń rozgłoszeniowych
Zdarzenia rozgłoszeniowe WebSocket wypychane przez serwer są bramkowane zakresami, aby sesje zakresowane parowaniem lub tylko węzłowe nie odbierały biernie treści sesji.
- Ramki czatu, agenta i wyników narzędzi (w tym strumieniowane zdarzenia
agenti wyniki wywołań narzędzi) wymagają co najmniejoperator.read. Sesje bezoperator.readcałkowicie pomijają te ramki. - Rozgłoszenia
plugin.*zdefiniowane przez plugin są bramkowane dooperator.writeluboperator.admin, zależnie od tego, jak plugin je zarejestrował. - Zdarzenia statusu i transportu (
heartbeat,presence,tick, cykl życia connect/disconnect itd.) pozostają nieograniczone, aby stan transportu był obserwowalny dla każdej uwierzytelnionej sesji. - Nieznane rodziny zdarzeń rozgłoszeniowych są domyślnie bramkowane zakresami (fail-closed), chyba że zarejestrowany handler jawnie je poluzuje.
Każde połączenie klienta utrzymuje własny numer sekwencyjny per klient, więc rozgłoszenia zachowują monotoniczną kolejność na tym gnieździe nawet wtedy, gdy różni klienci widzą różne, filtrowane zakresami podzbiory strumienia zdarzeń.
Typowe rodziny metod RPC
Publiczna powierzchnia WS jest szersza niż powyższe przykłady uzgadniania połączenia/uwierzytelniania. To
nie jest wygenerowany zrzut — hello-ok.features.methods jest konserwatywną
listą wykrywania zbudowaną z src/gateway/server-methods-list.ts oraz załadowanych
eksportów metod pluginów/kanałów. Traktuj ją jako wykrywanie funkcji, a nie pełne
wyliczenie src/gateway/server-methods/*.ts.
System i tożsamość
healthzwraca buforowaną lub świeżo sprawdzoną migawkę kondycji Gateway.diagnostics.stabilityzwraca ostatni ograniczony rejestrator stabilności diagnostycznej. Przechowuje metadane operacyjne, takie jak nazwy zdarzeń, liczby, rozmiary w bajtach, odczyty pamięci, stan kolejki/sesji, nazwy kanałów/pluginów oraz identyfikatory sesji. Nie przechowuje tekstu czatu, treści webhooków, wyników narzędzi, surowych treści żądań lub odpowiedzi, tokenów, plików cookie ani wartości tajnych. Wymagany jest zakres odczytu operatora.statuszwraca podsumowanie Gateway w stylu/status; pola wrażliwe są uwzględniane tylko dla klientów operatora z zakresem administratora.gateway.identity.getzwraca tożsamość urządzenia Gateway używaną przez przepływy przekaźnika i parowania.system-presencezwraca bieżącą migawkę obecności dla połączonych urządzeń operatora/węzłów.system-eventdopisuje zdarzenie systemowe i może aktualizować/rozgłaszać kontekst obecności.last-heartbeatzwraca najnowsze utrwalone zdarzenie heartbeat.set-heartbeatsprzełącza przetwarzanie heartbeat w Gateway.
Modele i użycie
models.listzwraca katalog modeli dozwolonych przez środowisko uruchomieniowe. Przekaż{ "view": "configured" }dla skonfigurowanych modeli o rozmiarze odpowiednim dla selektora (agents.defaults.modelsnajpierw, potemmodels.providers.*.models) albo{ "view": "all" }dla pełnego katalogu.usage.statuszwraca podsumowania okien użycia dostawcy/pozostałego limitu.usage.costzwraca zagregowane podsumowania kosztów użycia dla zakresu dat. PrzekażagentIddla jednego agenta alboagentScope: "all", aby zagregować skonfigurowanych agentów.doctor.memory.statuszwraca gotowość pamięci wektorowej / buforowanych embeddingów dla aktywnego domyślnego obszaru roboczego agenta. Przekaż{ "probe": true }albo{ "deep": true }tylko wtedy, gdy wywołujący jawnie chce aktywnego pingu dostawcy embeddingów. Klienci obsługujący Dreaming mogą także przekazać{ "agentId": "agent-id" }, aby ograniczyć statystyki magazynu Dreaming do wybranego obszaru roboczego agenta; pominięcieagentIdzachowuje fallback do domyślnego agenta i agreguje skonfigurowane obszary robocze Dreaming.doctor.memory.dreamDiary,doctor.memory.backfillDreamDiary,doctor.memory.resetDreamDiary,doctor.memory.resetGroundedShortTerm,doctor.memory.repairDreamingArtifactsidoctor.memory.dedupeDreamDiaryprzyjmują opcjonalne parametry{ "agentId": "agent-id" }dla widoków/akcji Dreaming wybranego agenta. GdyagentIdzostanie pominięte, działają na skonfigurowanym domyślnym obszarze roboczym agenta.doctor.memory.remHarnesszwraca ograniczony, tylko do odczytu podgląd harness REM dla zdalnych klientów płaszczyzny sterowania. Może obejmować ścieżki obszaru roboczego, fragmenty pamięci, wyrenderowany ugruntowany Markdown i kandydatów do głębokiej promocji, więc wywołujący potrzebująoperator.read.sessions.usagezwraca podsumowania użycia według sesji. PrzekażagentIddla jednego agenta alboagentScope: "all", aby wyświetlić razem skonfigurowanych agentów.sessions.usage.timeserieszwraca użycie w szeregach czasowych dla jednej sesji.sessions.usage.logszwraca wpisy dziennika użycia dla jednej sesji.
Kanały i pomocniki logowania
channels.statuszwraca podsumowania stanu wbudowanych + dołączonych kanałów/pluginów.channels.logoutwylogowuje określony kanał/konto, gdy kanał obsługuje wylogowanie.web.login.starturuchamia przepływ logowania QR/web dla bieżącego dostawcy kanału web obsługującego QR.web.login.waitczeka na zakończenie tego przepływu logowania QR/web i po powodzeniu uruchamia kanał.push.testwysyła testowe powiadomienie APNs push do zarejestrowanego węzła iOS.voicewake.getzwraca zapisane wyzwalacze słowa wybudzającego.voicewake.setaktualizuje wyzwalacze słowa wybudzającego i rozgłasza zmianę.
Wiadomości i dzienniki
sendto bezpośrednie wychodzące RPC dostarczania dla wysyłek kierowanych do kanału/konta/wątku poza uruchamiaczem czatu.logs.tailzwraca skonfigurowany ogon pliku dziennika gateway z kontrolkami kursora/limitu i maksymalnej liczby bajtów.
Talk i TTS
talk.catalogzwraca tylko do odczytu katalog dostawców Talk dla mowy, transkrypcji strumieniowej i głosu w czasie rzeczywistym. Obejmuje kanoniczne identyfikatory dostawców, aliasy rejestru, etykiety, skonfigurowany stan, opcjonalny wynikreadyna poziomie grupy, ujawnione identyfikatory modeli/głosów, kanoniczne tryby, transporty, strategie mózgu oraz flagi dźwięku/możliwości czasu rzeczywistego bez zwracania sekretów dostawcy ani mutowania globalnej konfiguracji. Obecne Gateways ustawiająreadypo zastosowaniu wyboru dostawcy runtime; klienci powinni traktować jego brak jako niezweryfikowany, aby zachować zgodność ze starszymi Gateways.talk.configzwraca efektywny ładunek konfiguracji Talk;includeSecretswymagaoperator.talk.secrets(luboperator.admin).talk.session.createtworzy należącą do Gateway sesję Talk dlarealtime/gateway-relay,transcription/gateway-relayalbostt-tts/managed-room. W przypadkustt-tts/managed-roomwywołujący zoperator.write, którzy przekazująsessionKey, muszą także przekazaćspawnedBy, aby zapewnić zakresową widoczność klucza sesji; tworzeniesessionKeybez zakresu orazbrain: "direct-tools"wymagająoperator.admin.talk.session.joinwaliduje token sesji pokoju zarządzanego, emituje zdarzeniasession.readylubsession.replacedw razie potrzeby i zwraca metadane pokoju/sesji oraz ostatnie zdarzenia Talk bez tokenu w postaci jawnej ani zapisanego skrótu tokenu.talk.session.appendAudiodołącza wejściowy dźwięk PCM base64 do należących do Gateway sesji przekaźnika czasu rzeczywistego i transkrypcji.talk.session.startTurn,talk.session.endTurnitalk.session.cancelTurnsterują cyklem życia tury pokoju zarządzanego z odrzucaniem nieaktualnej tury przed wyczyszczeniem stanu.talk.session.cancelOutputzatrzymuje wyjściowy dźwięk asystenta, głównie dla wtrącenia sterowanego VAD w sesjach przekaźnika Gateway.talk.session.submitToolResultkończy wywołanie narzędzia dostawcy wyemitowane przez należącą do Gateway sesję przekaźnika czasu rzeczywistego. Przekażoptions: { willContinue: true }dla tymczasowego wyniku narzędzia, gdy wynik końcowy nadejdzie później, albooptions: { suppressResponse: true }, gdy wynik narzędzia ma zaspokoić wywołanie dostawcy bez uruchamiania kolejnej odpowiedzi asystenta w czasie rzeczywistym.talk.session.steerwysyła sterowanie głosem aktywnego przebiegu do należącej do Gateway sesji Talk wspieranej przez agenta. Akceptuje{ sessionId, text, mode? }, gdziemodetostatus,steer,cancelalbofollowup; pominięty tryb jest klasyfikowany na podstawie wypowiedzianego tekstu.talk.session.closezamyka należącą do Gateway sesję przekaźnika, transkrypcji lub pokoju zarządzanego i emituje końcowe zdarzenia Talk.talk.modeustawia/rozgłasza bieżący stan trybu Talk dla klientów WebChat/Control UI.talk.client.createtworzy należącą do klienta sesję dostawcy czasu rzeczywistego przy użyciuwebrtcalboprovider-websocket, podczas gdy Gateway posiada konfigurację, poświadczenia, instrukcje i politykę narzędzi.talk.client.toolCallpozwala należącym do klienta transportom czasu rzeczywistego przekazywać wywołania narzędzi dostawcy do polityki Gateway. Pierwszym obsługiwanym narzędziem jestopenclaw_agent_consult; klienci otrzymują identyfikator przebiegu i czekają na zwykłe zdarzenia cyklu życia czatu przed przesłaniem wyniku narzędzia specyficznego dla dostawcy.talk.client.steerwysyła sterowanie głosem aktywnego przebiegu dla należących do klienta transportów czasu rzeczywistego. Gateway rozwiązuje aktywny osadzony przebieg zsessionKeyi zwraca ustrukturyzowany wynik zaakceptowany/odrzucony zamiast po cichu porzucać sterowanie.talk.eventto pojedynczy kanał zdarzeń Talk dla adapterów czasu rzeczywistego, transkrypcji, STT/TTS, pokoju zarządzanego, telefonii i spotkań.talk.speaksyntetyzuje mowę przez aktywnego dostawcę mowy Talk.tts.statuszwraca stan włączenia TTS, aktywnego dostawcę, dostawców zapasowych i stan konfiguracji dostawcy.tts.providerszwraca widoczny spis dostawców TTS.tts.enableitts.disableprzełączają stan preferencji TTS.tts.setProvideraktualizuje preferowanego dostawcę TTS.tts.converturuchamia jednorazową konwersję tekstu na mowę.
Sekrety, konfiguracja, aktualizacja i kreator
secrets.reloadponownie rozwiązuje aktywne SecretRefs i podmienia stan sekretów runtime tylko przy pełnym powodzeniu.secrets.resolverozwiązuje przypisania sekretów celu polecenia dla określonego zestawu poleceń/celów.config.getzwraca bieżący zrzut konfiguracji i skrót.config.setzapisuje zwalidowany ładunek konfiguracji.config.patchscala częściową aktualizację konfiguracji. Destrukcyjne zastąpienie tablicy wymaga dotkniętej ścieżki wreplacePaths; zagnieżdżone tablice pod wpisami tablic używają ścieżek[], takich jakagents.list[].skills.config.applywaliduje i zastępuje pełny ładunek konfiguracji.config.schemazwraca bieżący ładunek schematu konfiguracji używany przez narzędzia Control UI i CLI: schemat,uiHints, wersję i metadane generowania, w tym metadane schematów pluginów i kanałów, gdy runtime może je załadować. Schemat zawiera metadane póltitle/descriptionwyprowadzone z tych samych etykiet i tekstu pomocy, których używa UI, w tym gałęzie zagnieżdżonych obiektów, symboli wieloznacznych, elementów tablic oraz kompozycjianyOf/oneOf/allOf, gdy istnieje pasująca dokumentacja pól.config.schema.lookupzwraca ładunek wyszukiwania w zakresie ścieżki dla jednej ścieżki konfiguracji: znormalizowaną ścieżkę, płytki węzeł schematu, dopasowaną wskazówkę ihintPath, opcjonalnereloadKindoraz bezpośrednie podsumowania dzieci dla przechodzenia w głąb w UI/CLI.reloadKindjest jednym zrestart,hotalbononei odzwierciedla planer ponownego ładowania konfiguracji Gateway dla żądanej ścieżki. Węzły schematu wyszukiwania zachowują dokumentację widoczną dla użytkownika i typowe pola walidacji (title,description,type,enum,const,format,pattern, ograniczenia liczb/ciągów/tablic/obiektów oraz flagi takie jakadditionalProperties,deprecated,readOnly,writeOnly). Podsumowania dzieci ujawniająkey, znormalizowanąpath,type,required,hasChildren, opcjonalnereloadKindoraz dopasowanehint/hintPath.update.runuruchamia przepływ aktualizacji gateway i planuje restart tylko wtedy, gdy sama aktualizacja się powiodła; wywołujący z sesją mogą dołączyćcontinuationMessage, aby uruchomienie wznowiło jedną następną turę agenta przez kolejkę kontynuacji restartu. Aktualizacje menedżera pakietów i nadzorowane aktualizacje git-checkout z płaszczyzny sterowania używają odłączonego przekazania usługi zarządzanej zamiast zastępowania drzewa pakietu albo mutowania wyjścia checkout/build wewnątrz działającego Gateway. Rozpoczęte przekazanie zwracaok: truezresult.reason: "managed-service-handoff-started"ihandoff.status: "started"; niedostępne lub nieudane przekazania zwracająok: falsezmanaged-service-handoff-unavailablealbomanaged-service-handoff-failed, plushandoff.command, gdy wymagana jest ręczna aktualizacja w powłoce. Niedostępne przekazanie oznacza, że OpenClaw nie ma bezpiecznej granicy nadzorcy ani trwałej tożsamości usługi, takiej jakOPENCLAW_SYSTEMD_UNITdla systemd. Podczas rozpoczętego przekazania znacznik restartu może krótko zgłaszaćstats.reason: "restart-health-pending"; kontynuacja jest opóźniana, dopóki CLI nie zweryfikuje zrestartowanego Gateway i nie zapisze końcowego znacznikaok.update.statusodświeża i zwraca najnowszy znacznik restartu aktualizacji, w tym wersję działającą po restarcie, gdy jest dostępna.wizard.start,wizard.next,wizard.statusiwizard.canceludostępniają kreator wdrażania przez WS RPC.
Pomocnicy agentów i przestrzeni roboczej
agents.listzwraca skonfigurowane wpisy agentów, w tym efektywny model i metadane środowiska wykonawczego.agents.create,agents.updateiagents.deletezarządzają rekordami agentów oraz powiązaniami przestrzeni roboczej.agents.files.list,agents.files.getiagents.files.setzarządzają plikami startowymi przestrzeni roboczej udostępnianymi agentowi.tasks.list,tasks.getitasks.canceludostępniają rejestr zadań Gateway klientom SDK i operatorom.artifacts.list,artifacts.getiartifacts.downloadudostępniają podsumowania artefaktów pochodzących z transkrypcji oraz pobrania dla jawnego zakresusessionKey,runIdlubtaskId. Zapytania o uruchomienia i zadania rozwiązują sesję właściciela po stronie serwera i zwracają tylko media transkrypcji z pasującym pochodzeniem; niebezpieczne lub lokalne źródła URL zwracają nieobsługiwane pobrania zamiast pobierania po stronie serwera.environments.listienvironments.statusudostępniają klientom SDK tylko do odczytu wykrywanie środowisk lokalnych Gateway oraz węzłów.agent.identity.getzwraca efektywną tożsamość asystenta dla agenta lub sesji.agent.waitczeka na zakończenie uruchomienia i zwraca końcową migawkę, gdy jest dostępna.
Kontrola sesji
sessions.listzwraca bieżący indeks sesji, w tym metadaneagentRuntimew każdym wierszu, gdy skonfigurowany jest backend środowiska wykonawczego agenta.sessions.subscribeisessions.unsubscribeprzełączają subskrypcje zdarzeń zmian sesji dla bieżącego klienta WS.sessions.messages.subscribeisessions.messages.unsubscribeprzełączają subskrypcje zdarzeń transkrypcji/wiadomości dla jednej sesji.sessions.previewzwraca ograniczone podglądy transkrypcji dla określonych kluczy sesji.sessions.describezwraca jeden wiersz sesji Gateway dla dokładnego klucza sesji.sessions.resolverozwiązuje lub kanonizuje cel sesji.sessions.createtworzy nowy wpis sesji.sessions.sendwysyła wiadomość do istniejącej sesji.sessions.steerto wariant przerwania i ukierunkowania dla aktywnej sesji.sessions.abortprzerywa aktywną pracę dla sesji. Wywołujący może przekazaćkeyoraz opcjonalnierunId, albo przekazać samorunIddla aktywnych uruchomień, które Gateway może rozwiązać do sesji.sessions.patchaktualizuje metadane/nadpisania sesji i raportuje rozwiązany model kanoniczny oraz efektywneagentRuntime.sessions.reset,sessions.deleteisessions.compactwykonują konserwację sesji.sessions.getzwraca pełny zapisany wiersz sesji.- Wykonywanie czatu nadal używa
chat.history,chat.send,chat.abortichat.inject.chat.historyjest normalizowane do wyświetlania dla klientów UI: znaczniki dyrektyw inline są usuwane z widocznego tekstu, tekstowe ładunki XML wywołań narzędzi (w tym<tool_call>...</tool_call>,<function_call>...</function_call>,<tool_calls>...</tool_calls>,<function_calls>...</function_calls>oraz ucięte bloki wywołań narzędzi) i ujawnione tokeny sterujące modelu ASCII/pełnej szerokości są usuwane, czysto ciche wiersze asystenta z tokenami, takie jak dokładneNO_REPLY/no_reply, są pomijane, a zbyt duże wiersze mogą być zastępowane symbolami zastępczymi. chat.message.getto addytywny, ograniczony czytnik pełnej wiadomości dla pojedynczego widocznego wpisu transkrypcji. Klienci przekazująsessionKey, opcjonalneagentId, gdy wybór sesji jest ograniczony do agenta, orazmessageIdtranskrypcji wcześniej udostępnione przezchat.history, a Gateway zwraca tę samą znormalizowaną do wyświetlania projekcję bez lekkiego limitu obcinania historii, gdy zapisany wpis jest nadal dostępny i nie jest zbyt duży.chat.sendakceptuje jednorazowefastMode: "auto", aby użyć trybu szybkiego dla wywołań modelu rozpoczętych przed automatycznym odcięciem, a następnie uruchamiać późniejsze ponowienia, fallbacki, wyniki narzędzi lub wywołania kontynuacji bez trybu szybkiego. Odcięcie domyślnie wynosi 60 sekund i można je skonfigurować dla każdego modelu przezagents.defaults.models["<provider>/<model>"].params.fastAutoOnSeconds. Wywołującychat.sendmoże przekazać jednorazowefastAutoOnSeconds, aby nadpisać odcięcie dla tego żądania.
Parowanie urządzeń i tokeny urządzeń
device.pair.listzwraca oczekujące i zatwierdzone sparowane urządzenia.device.pair.setupCodetworzy kod konfiguracji mobilnej oraz, domyślnie, adres URL danych QR PNG. Wymagaoperator.admini celowo jest pomijane w ogłaszanym wykrywaniu. Wynik obejmujesetupCode, opcjonalneqrDataUrl,gatewayUrl, nietajną etykietęauthiurlSource.device.pair.approve,device.pair.rejectidevice.pair.removezarządzają rekordami parowania urządzeń.device.token.rotaterotuje token sparowanego urządzenia w granicach jego zatwierdzonej roli i zakresu wywołującego.device.token.revokeunieważnia token sparowanego urządzenia w granicach jego zatwierdzonej roli i zakresu wywołującego.
Kod konfiguracji osadza krótkotrwałe poświadczenie startowe. Klienci nie mogą go logować ani utrwalać poza przepływem parowania.
Parowanie węzłów, wywoływanie i oczekująca praca
node.pair.request,node.pair.list,node.pair.approve,node.pair.reject,node.pair.removeinode.pair.verifyobejmują parowanie węzłów oraz weryfikację startową.node.listinode.describezwracają stan znanych/połączonych węzłów.node.renameaktualizuje etykietę sparowanego węzła.node.invokeprzekazuje polecenie do połączonego węzła.node.invoke.resultzwraca wynik żądania wywołania.node.eventprzenosi zdarzenia pochodzące z węzła z powrotem do Gateway.node.pending.pullinode.pending.ackto interfejsy API kolejki połączonych węzłów.node.pending.enqueueinode.pending.drainzarządzają trwałą oczekującą pracą dla węzłów offline/rozłączonych.
Rodziny zatwierdzeń
exec.approval.request,exec.approval.get,exec.approval.listiexec.approval.resolveobejmują jednorazowe żądania zatwierdzenia wykonania oraz wyszukiwanie/odtwarzanie oczekujących zatwierdzeń.exec.approval.waitDecisionczeka na jedno oczekujące zatwierdzenie wykonania i zwraca ostateczną decyzję (lubnullpo przekroczeniu limitu czasu).exec.approvals.getiexec.approvals.setzarządzają migawkami zasad zatwierdzania wykonania Gateway.exec.approvals.node.getiexec.approvals.node.setzarządzają lokalną dla węzła zasadą zatwierdzania wykonania przez polecenia przekaźnika węzła.plugin.approval.request,plugin.approval.list,plugin.approval.waitDecisioniplugin.approval.resolveobejmują przepływy zatwierdzania zdefiniowane przez Plugin.
Automatyzacja, Skills i narzędzia
- Automatyzacja:
wakeplanuje natychmiastowe lub przy następnym Heartbeat wstrzyknięcie tekstu wybudzenia;cron.get,cron.list,cron.status,cron.add,cron.update,cron.remove,cron.run,cron.runszarządzają zaplanowaną pracą. cron.runpozostaje RPC w stylu dodania do kolejki dla uruchomień ręcznych. Klienci, którzy potrzebują semantyki zakończenia, powinni odczytać zwróconerunIdi odpytywaćcron.runs.cron.runsakceptuje opcjonalny niepusty filtrrunId, aby klienci mogli śledzić jedno zakolejkowane uruchomienie ręczne bez wyścigu z innymi wpisami historii dla tego samego zadania.- Skills i narzędzia:
commands.list,skills.*,tools.catalog,tools.effective,tools.invoke.
Typowe rodziny zdarzeń
chat: aktualizacje czatu UI, takie jakchat.inject, oraz inne zdarzenia czatu wyłącznie transkrypcyjne. W protokole v4 ładunki delta przenosządeltaText;messagepozostaje skumulowaną migawką asystenta. Zastąpienia niebędące prefiksem ustawiająreplace=truei używajądeltaTextjako tekstu zastępczego.session.message,session.operationisession.tool: aktualizacje transkrypcji, operacji sesji w toku oraz strumienia zdarzeń dla subskrybowanej sesji.sessions.changed: indeks sesji lub metadane zostały zmienione.presence: aktualizacje migawek obecności systemu.tick: okresowe zdarzenie keepalive / żywotności.health: aktualizacja migawki stanu Gateway.heartbeat: aktualizacja strumienia zdarzeń Heartbeat.cron: zdarzenie zmiany uruchomienia/zadania Cron.shutdown: powiadomienie o zamknięciu Gateway.node.pair.requested/node.pair.resolved: cykl życia parowania węzła.node.invoke.request: rozgłoszenie żądania wywołania węzła.device.pair.requested/device.pair.resolved: cykl życia sparowanego urządzenia.voicewake.changed: zmieniono konfigurację wyzwalacza słowa wybudzającego.exec.approval.requested/exec.approval.resolved: cykl życia zatwierdzenia wykonania.plugin.approval.requested/plugin.approval.resolved: cykl życia zatwierdzenia Plugin.
Metody pomocnicze węzłów
- Węzły mogą wywoływać
skills.bins, aby pobrać bieżącą listę plików wykonywalnych umiejętności na potrzeby kontroli automatycznego zezwalania.
RPC rejestru zadań
Klienci operatorów mogą sprawdzać i anulować rekordy zadań w tle Gateway przez RPC rejestru zadań. Te metody zwracają oczyszczone podsumowania zadań, a nie surowy stan środowiska wykonawczego.
tasks.listwymagaoperator.read.- Parametry: opcjonalny
status("queued","running","completed","failed","cancelled"lub"timed_out") albo tablica tych statusów, opcjonalneagentId, opcjonalnesessionKey, opcjonalnylimitod1do500oraz opcjonalny ciągcursor. - Wynik:
{ "tasks": TaskSummary[], "nextCursor"?: string }.
- Parametry: opcjonalny
tasks.getwymagaoperator.read.- Parametry:
{ "taskId": string }. - Wynik:
{ "task": TaskSummary }. - Brakujące identyfikatory zadań zwracają kształt błędu Gateway nie znaleziono.
- Parametry:
tasks.cancelwymagaoperator.write.- Parametry:
{ "taskId": string, "reason"?: string }. - Wynik:
{ "found": boolean, "cancelled": boolean, "reason"?: string, "task"?: TaskSummary }. foundinformuje, czy rejestr zawierał pasujące zadanie.cancelledinformuje, czy środowisko wykonawcze zaakceptowało lub odnotowało anulowanie.
- Parametry:
TaskSummary zawiera id, status i opcjonalne metadane, takie jak kind,
runtime, title, agentId, sessionKey, childSessionKey, ownerKey,
runId, taskId, flowId, parentTaskId, sourceId, znaczniki czasu, postęp,
podsumowanie końcowe oraz oczyszczony tekst błędu. agentId identyfikuje agenta
wykonującego zadanie; sessionKey i ownerKey zachowują kontekst żądającego oraz kontroli.
Metody pomocnicze operatora
- Operatorzy mogą wywołać
commands.list(operator.read), aby pobrać inwentarz poleceń środowiska wykonawczego dla agenta.agentIdjest opcjonalne; pomiń je, aby odczytać domyślny obszar roboczy agenta.scopekontroluje, do której powierzchni odnosi się główna wartośćname:textzwraca główny token polecenia tekstowego bez początkowego/nativeoraz domyślna ścieżkabothzwracają nazwy natywne uwzględniające dostawcę, gdy są dostępne
textAliasesprzenosi dokładne aliasy z ukośnikiem, takie jak/modeli/m.nativeNameprzenosi nazwę polecenia natywnego uwzględniającą dostawcę, gdy taka istnieje.providerjest opcjonalne i wpływa tylko na nazewnictwo natywne oraz dostępność natywnych poleceń pluginu.includeArgs=falsepomija serializowane metadane argumentów w odpowiedzi.
- Operatorzy mogą wywołać
tools.catalog(operator.read), aby pobrać katalog narzędzi środowiska wykonawczego dla agenta. Odpowiedź zawiera pogrupowane narzędzia i metadane pochodzenia:source:corelubpluginpluginId: właściciel pluginu, gdysource="plugin"optional: czy narzędzie pluginu jest opcjonalne
- Operatorzy mogą wywołać
tools.effective(operator.read), aby pobrać efektywny w środowisku wykonawczym inwentarz narzędzi dla sesji.sessionKeyjest wymagane.- Gateway wyprowadza zaufany kontekst środowiska wykonawczego z sesji po stronie serwera, zamiast akceptować kontekst uwierzytelniania lub dostarczania dostarczony przez wywołującego.
- Odpowiedź jest ograniczoną do sesji, wyprowadzoną przez serwer projekcją aktywnego inwentarza, obejmującą narzędzia rdzenia, pluginów, kanałów oraz już wykrytych serwerów MCP.
tools.effectivejest tylko do odczytu dla MCP: może przepuścić rozgrzany katalog MCP sesji przez końcową politykę narzędzi, ale nie tworzy środowisk wykonawczych MCP, nie łączy transportów ani nie wydajetools/list. Jeśli nie istnieje pasujący rozgrzany katalog, odpowiedź może zawierać powiadomienie takie jakmcp-not-yet-connected,mcp-not-yet-listedlubmcp-stale-catalog.- Wpisy efektywnych narzędzi używają
source="core",source="plugin",source="channel"lubsource="mcp".
- Operatorzy mogą wywołać
tools.invoke(operator.write), aby uruchomić jedno dostępne narzędzie przez tę samą ścieżkę polityki Gateway co/tools/invoke.namejest wymagane.args,sessionKey,agentId,confirmiidempotencyKeysą opcjonalne.- Jeśli obecne są zarówno
sessionKey, jak iagentId, rozwiązany agent sesji musi pasować doagentId. - Ograniczone do właściciela wrappery rdzenia, takie jak
cron,gatewayinodes, wymagają tożsamości właściciela/administratora (operator.admin), mimo że sama metodatools.invokema uprawnienieoperator.write. - Odpowiedź jest kopertą skierowaną do SDK z polami
ok,toolName, opcjonalnymoutputi typowanymi polamierror. Odmowy zatwierdzenia lub polityki zwracająok:falsew ładunku, zamiast omijać potok polityki narzędzi Gateway.
- Operatorzy mogą wywołać
skills.status(operator.read), aby pobrać widoczny inwentarz Skills dla agenta.agentIdjest opcjonalne; pomiń je, aby odczytać domyślny obszar roboczy agenta.- Odpowiedź zawiera kwalifikowalność, brakujące wymagania, kontrole konfiguracji oraz oczyszczone opcje instalacji bez ujawniania surowych wartości sekretów.
- Operatorzy mogą wywołać
skills.searchiskills.detail(operator.read) dla metadanych odkrywania ClawHub. - Operatorzy mogą wywołać
skills.upload.begin,skills.upload.chunkiskills.upload.commit(operator.admin), aby przygotować prywatne archiwum Skills przed jego instalacją. Jest to osobna administracyjna ścieżka przesyłania dla zaufanych klientów, a nie zwykły przepływ instalacji Skills z ClawHub, i domyślnie jest wyłączona, chyba że włączonoskills.install.allowUploadedArchives.skills.upload.begin({ kind: "skill-archive", slug, sizeBytes, sha256?, force?, idempotencyKey? })tworzy przesyłanie powiązane z tym slugiem i wartością force.skills.upload.chunk({ uploadId, offset, dataBase64 })dopisuje bajty przy dokładnym zdekodowanym przesunięciu.skills.upload.commit({ uploadId, sha256? })weryfikuje końcowy rozmiar i SHA-256. Commit tylko finalizuje przesyłanie; nie instaluje Skills.- Przesłane archiwa Skills są archiwami zip zawierającymi główny plik
SKILL.md. Wewnętrzna nazwa katalogu archiwum nigdy nie wybiera celu instalacji.
- Operatorzy mogą wywołać
skills.install(operator.admin) w trzech trybach:- Tryb ClawHub:
{ source: "clawhub", slug, version?, force? }instaluje folder Skills w kataloguskills/domyślnego obszaru roboczego agenta. - Tryb przesyłania:
{ source: "upload", uploadId, slug, force?, sha256?, timeoutMs? }instaluje zatwierdzone przesyłanie w kataloguskills/<slug>domyślnego obszaru roboczego agenta. Slug i wartość force muszą odpowiadać pierwotnemu żądaniuskills.upload.begin. Ten tryb jest odrzucany, chyba że włączonoskills.install.allowUploadedArchives. Ustawienie nie wpływa na instalacje ClawHub. - Tryb instalatora Gateway:
{ name, installId, timeoutMs? }uruchamia zadeklarowaną akcjęmetadata.openclaw.installna hoście Gateway. Starsi klienci nadal mogą wysyłaćdangerouslyForceUnsafeInstall; to pole jest przestarzałe, akceptowane tylko ze względu na zgodność protokołu i ignorowane. Użyjsecurity.installPolicydo decyzji instalacyjnych należących do operatora.
- Tryb ClawHub:
- Operatorzy mogą wywołać
skills.update(operator.admin) w dwóch trybach:- Tryb ClawHub aktualizuje jeden śledzony slug albo wszystkie śledzone instalacje ClawHub w domyślnym obszarze roboczym agenta.
- Tryb konfiguracji łata wartości
skills.entries.<skillKey>, takie jakenabled,apiKeyienv.
Widoki models.list
models.list przyjmuje opcjonalny parametr view:
- Pominięte lub
"default": bieżące zachowanie środowiska wykonawczego. Jeśli skonfigurowanoagents.defaults.models, odpowiedź jest dozwolonym katalogiem, w tym dynamicznie wykrytymi modelami dla wpisówprovider/*. W przeciwnym razie odpowiedź jest pełnym katalogiem Gateway. "configured": zachowanie o rozmiarze selektora. Jeśli skonfigurowanoagents.defaults.models, nadal ma pierwszeństwo, w tym odkrywanie ograniczone do dostawcy dla wpisówprovider/*. Bez listy dozwolonych odpowiedź używa jawnych wpisówmodels.providers.*.models, przechodząc do pełnego katalogu tylko wtedy, gdy nie istnieją skonfigurowane wiersze modeli."all": pełny katalog Gateway, z pominięciemagents.defaults.models. Używaj tego do diagnostyki i interfejsów odkrywania, nie do zwykłych selektorów modeli.
Zatwierdzenia exec
- Gdy żądanie exec wymaga zatwierdzenia, Gateway rozgłasza
exec.approval.requested. - Klienci operatora rozwiązują je, wywołując
exec.approval.resolve(wymaga zakresuoperator.approvals). - Dla
host=nodeżądanieexec.approval.requestmusi zawieraćsystemRunPlan(kanoniczneargv/cwd/rawCommand/metadane sesji). Żądania bezsystemRunPlansą odrzucane. - Po zatwierdzeniu przekazywane wywołania
node.invoke system.runponownie używają tego kanonicznegosystemRunPlanjako autorytatywnego kontekstu polecenia/cwd/sesji. - Jeśli wywołujący zmieni
command,rawCommand,cwd,agentIdlubsessionKeymiędzy przygotowaniem a końcowym, zatwierdzonym przekazaniemsystem.run, Gateway odrzuci uruchomienie zamiast ufać zmienionemu ładunkowi.
Awaryjna ścieżka dostarczania agenta
- Żądania
agentmogą zawieraćdeliver=true, aby zażądać dostarczania wychodzącego. bestEffortDeliver=falsezachowuje ścisłe zachowanie: nierozwiązane lub wyłącznie wewnętrzne cele dostarczania zwracająINVALID_REQUEST.bestEffortDeliver=truepozwala na przejście do wykonania tylko w sesji, gdy nie można rozwiązać żadnej zewnętrznej trasy możliwej do dostarczenia (na przykład sesje wewnętrzne/webchat lub niejednoznaczne konfiguracje wielokanałowe).- Końcowe wyniki
agentmogą zawieraćresult.deliveryStatus, gdy zażądano dostarczania, używając tych samych statusówsent,suppressed,partial_failedifailed, które udokumentowano dlaopenclaw agent --json --deliver.
Wersjonowanie
PROTOCOL_VERSIONznajduje się wpackages/gateway-protocol/src/version.ts.- Klienci wysyłają
minProtocol+maxProtocol; serwer odrzuca zakresy, które nie obejmują jego bieżącego protokołu. Obecni klienci i serwery wymagają protokołu v4. - Schematy i modele są generowane z definicji TypeBox:
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
Stałe klienta
Klient referencyjny w src/gateway/client.ts używa tych wartości domyślnych. Wartości są stabilne w protokole v4 i stanowią oczekiwaną bazę dla klientów zewnętrznych.
| Stała | Wartość domyślna | Źródło |
|---|---|---|
PROTOCOL_VERSION |
4 |
packages/gateway-protocol/src/version.ts |
MIN_CLIENT_PROTOCOL_VERSION |
4 |
packages/gateway-protocol/src/version.ts |
| Limit czasu żądania (na RPC) | 30_000 ms |
src/gateway/client.ts (requestTimeoutMs) |
| Limit czasu preauth / connect-challenge | 15_000 ms |
src/gateway/handshake-timeouts.ts (config/env może zwiększyć sparowany budżet serwera/klienta) |
| Początkowy backoff ponownego połączenia | 1_000 ms |
src/gateway/client.ts (backoffMs) |
| Maksymalny backoff ponownego połączenia | 30_000 ms |
src/gateway/client.ts (scheduleReconnect) |
| Ograniczenie szybkiej ponownej próby po zamknięciu device-token | 250 ms |
src/gateway/client.ts |
Okres karencji force-stop przed terminate() |
250 ms |
FORCE_STOP_TERMINATE_GRACE_MS |
Domyślny limit czasu stopAndWait() |
1_000 ms |
STOP_AND_WAIT_TIMEOUT_MS |
Domyślny interwał tick (przed hello-ok) |
30_000 ms |
src/gateway/client.ts |
| Zamknięcie po limicie czasu tick | kod 4000, gdy cisza przekracza tickIntervalMs * 2 |
src/gateway/client.ts |
MAX_PAYLOAD_BYTES |
25 * 1024 * 1024 (25 MB) |
src/gateway/server-constants.ts |
Serwer ogłasza efektywne wartości policy.tickIntervalMs, policy.maxPayload i policy.maxBufferedBytes w hello-ok; klienci powinni respektować te wartości zamiast domyślnych sprzed uzgadniania.
Uwierzytelnianie
- Uwierzytelnianie Gateway za pomocą współdzielonego sekretu używa
connect.params.auth.tokenalboconnect.params.auth.password, zależnie od skonfigurowanego trybu uwierzytelniania. - Tryby przenoszące tożsamość, takie jak Tailscale Serve
(
gateway.auth.allowTailscale: true) albo tryb spoza local loopbackgateway.auth.mode: "trusted-proxy", spełniają kontrolę uwierzytelniania połączenia na podstawie nagłówków żądania zamiastconnect.params.auth.*. - Prywatny ingress
gateway.auth.mode: "none"całkowicie pomija uwierzytelnianie połączenia współdzielonym sekretem; nie wystawiaj tego trybu na publiczny/niezaufany ingress. - Po sparowaniu Gateway wydaje token urządzenia ograniczony do roli połączenia
- zakresów. Jest zwracany w
hello-ok.auth.deviceTokeni powinien być utrwalony przez klienta na potrzeby przyszłych połączeń.
- zakresów. Jest zwracany w
- Klienci powinni utrwalać podstawowy
hello-ok.auth.deviceTokenpo każdym udanym połączeniu. - Ponowne łączenie z tym zapisanym tokenem urządzenia powinno także ponownie używać zapisanego zatwierdzonego zestawu zakresów dla tego tokenu. Zachowuje to dostęp do odczytu/sondowania/statusu, który został już przyznany, i zapobiega cichemu zawężeniu ponownych połączeń do węższego, domyślnego zakresu tylko dla administratora.
- Składanie uwierzytelniania połączenia po stronie klienta (
selectConnectAuthwsrc/gateway/client.ts):auth.passwordjest niezależne i zawsze przekazywane dalej, gdy jest ustawione.auth.tokenjest wypełniane według priorytetu: najpierw jawny współdzielony token, potem jawnydeviceToken, a następnie zapisany token dla danego urządzenia (kluczowany przezdeviceId+role).auth.bootstrapTokenjest wysyłany tylko wtedy, gdy żaden z powyższych elementów nie rozwiązałauth.token. Współdzielony token lub dowolny rozwiązany token urządzenia go tłumi.- Automatyczne promowanie zapisanego tokenu urządzenia przy jednorazowej ponownej próbie
AUTH_TOKEN_MISMATCHjest ograniczone do zaufanych punktów końcowych — loopback albowss://z przypiętymtlsFingerprint. Publicznewss://bez przypięcia się nie kwalifikuje.
- Wbudowany bootstrap kodu konfiguracji zwraca podstawowy token węzła
hello-ok.auth.deviceTokenoraz ograniczony token operatora whello-ok.auth.deviceTokensna potrzeby zaufanego przekazania mobilnego. Token operatora obejmujeoperator.talk.secretsdo natywnych odczytów konfiguracji Talk, ale wyklucza zakresy mutacji parowania orazoperator.admin. - Gdy bootstrap kodu konfiguracji inny niż bazowy czeka na zatwierdzenie, szczegóły
PAIRING_REQUIREDobejmująrecommendedNextStep: "wait_then_retry",retryable: trueorazpauseReconnect: false. Klienci powinni kontynuować ponowne łączenie z tym samym tokenem bootstrapu, dopóki żądanie nie zostanie zatwierdzone albo token nie stanie się nieprawidłowy. - Utrwalaj
hello-ok.auth.deviceTokenstylko wtedy, gdy połączenie użyło uwierzytelniania bootstrapu przez zaufany transport, taki jakwss://albo parowanie przez loopback/lokalne. - Jeśli klient podaje jawny
deviceTokenalbo jawnescopes, ten zestaw zakresów zażądany przez wywołującego pozostaje rozstrzygający; zakresy z pamięci podręcznej są ponownie używane tylko wtedy, gdy klient ponownie używa zapisanego tokenu dla danego urządzenia. - Tokeny urządzeń można rotować/odwoływać przez
device.token.rotateidevice.token.revoke(wymaga zakresuoperator.pairing). Rotowanie lub odwoływanie tokenu węzła albo innej roli niebędącej operatorem wymaga takżeoperator.admin. device.token.rotatezwraca metadane rotacji. Zwraca zastępczy bearer token tylko dla wywołań z tego samego urządzenia, które są już uwierzytelnione tym tokenem urządzenia, aby klienci używający tylko tokenów mogli utrwalić zamiennik przed ponownym połączeniem. Rotacje współdzielone/administracyjne nie zwracają bearer tokenu.- Wydawanie, rotacja i odwoływanie tokenów pozostają ograniczone do zatwierdzonego zestawu ról zapisanego we wpisie parowania danego urządzenia; mutacja tokenu nie może rozszerzyć ani wskazać roli urządzenia, której zatwierdzenie parowania nigdy nie przyznało.
- W sesjach tokenów sparowanych urządzeń zarządzanie urządzeniami jest samoograniczone, chyba że
wywołujący ma także
operator.admin: wywołujący bez uprawnień administratora mogą zarządzać tylko tokenem operatora dla wpisu własnego urządzenia. Zarządzanie tokenami węzła i innymi tokenami niebędącymi operatorami jest dostępne tylko dla administratora, nawet dla własnego urządzenia wywołującego. device.token.rotateidevice.token.revokesprawdzają także docelowy zestaw zakresów tokenu operatora względem bieżących zakresów sesji wywołującego. Wywołujący bez uprawnień administratora nie mogą rotować ani odwoływać szerszego tokenu operatora niż ten, który już posiadają.- Niepowodzenia uwierzytelniania obejmują
error.details.codeoraz wskazówki odzyskiwania:error.details.canRetryWithDeviceToken(boolean)error.details.recommendedNextStep(retry_with_device_token,update_auth_configuration,update_auth_credentials,wait_then_retry,review_auth_configuration)
- Zachowanie klienta dla
AUTH_TOKEN_MISMATCH:- Zaufani klienci mogą podjąć jedną ograniczoną ponowną próbę z tokenem dla danego urządzenia z pamięci podręcznej.
- Jeśli ta ponowna próba się nie powiedzie, klienci powinni zatrzymać automatyczne pętle ponownego łączenia i pokazać operatorowi wskazówki dotyczące działania.
AUTH_SCOPE_MISMATCHoznacza, że token urządzenia został rozpoznany, ale nie obejmuje żądanej roli/zakresów. Klienci nie powinni przedstawiać tego jako złego tokenu; poproś operatora o ponowne sparowanie albo zatwierdzenie węższego/szerszego kontraktu zakresów.
Tożsamość urządzenia + parowanie
- Węzły powinny zawierać stabilną tożsamość urządzenia (
device.id) wyprowadzoną z odcisku palca pary kluczy. - Gateway wydaje tokeny dla urządzenia + roli.
- Zatwierdzenia parowania są wymagane dla nowych identyfikatorów urządzeń, chyba że włączono lokalne automatyczne zatwierdzanie.
- Automatyczne zatwierdzanie parowania koncentruje się na bezpośrednich połączeniach przez lokalny local loopback.
- OpenClaw ma także wąską ścieżkę samopołączenia lokalną dla backendu/kontenera dla zaufanych przepływów pomocniczych ze współdzielonym sekretem.
- Połączenia z tego samego hosta przez tailnet lub LAN nadal są traktowane jako zdalne na potrzeby parowania i wymagają zatwierdzenia.
- Klienci WS zwykle uwzględniają tożsamość
devicepodczasconnect(operator + węzeł). Jedynymi wyjątkami operatora bez urządzenia są jawne ścieżki zaufania:gateway.controlUi.allowInsecureAuth=truedla zgodności z niebezpiecznym HTTP tylko na localhost.- udane uwierzytelnienie operatora Control UI w
gateway.auth.mode: "trusted-proxy". gateway.controlUi.dangerouslyDisableDeviceAuth=true(tryb awaryjny, poważne obniżenie bezpieczeństwa).- bezpośrednie RPC backendu
gateway-clientprzez loopback na zarezerwowanej wewnętrznej ścieżce pomocniczej.
- Pominięcie tożsamości urządzenia ma konsekwencje dla zakresu. Gdy połączenie operatora bez urządzenia
jest dopuszczone przez jawną ścieżkę zaufania, OpenClaw nadal czyści
samodzielnie zadeklarowane zakresy do pustego zestawu, chyba że ta ścieżka ma nazwany
wyjątek zachowania zakresów. Metody ograniczone zakresem kończą się wtedy niepowodzeniem z
missing scope. gateway.controlUi.dangerouslyDisableDeviceAuth=trueto ścieżka awaryjnego zachowania zakresów Control UI. Nie przyznaje zakresów dowolnym niestandardowym klientom WebSocket w kształcie backendu lub CLI.- Zarezerwowana ścieżka pomocnicza backendu
gateway-clientprzez bezpośredni loopback zachowuje zakresy tylko dla wewnętrznych lokalnych RPC płaszczyzny sterowania; niestandardowe identyfikatory backendu nie otrzymują tego wyjątku. - Wszystkie połączenia muszą podpisać nonce
connect.challengedostarczony przez serwer.
Diagnostyka migracji uwierzytelniania urządzeń
Dla starszych klientów, którzy nadal używają zachowania podpisywania sprzed challenge, connect zwraca teraz
kody szczegółów DEVICE_AUTH_* w error.details.code ze stabilnym error.details.reason.
Typowe niepowodzenia migracji:
| Komunikat | details.code | details.reason | Znaczenie |
|---|---|---|---|
device nonce required |
DEVICE_AUTH_NONCE_REQUIRED |
device-nonce-missing |
Klient pominął device.nonce (albo wysłał pusty). |
device nonce mismatch |
DEVICE_AUTH_NONCE_MISMATCH |
device-nonce-mismatch |
Klient podpisał przy użyciu nieaktualnego/błędnego nonce. |
device signature invalid |
DEVICE_AUTH_SIGNATURE_INVALID |
device-signature |
Ładunek podpisu nie pasuje do ładunku v2. |
device signature expired |
DEVICE_AUTH_SIGNATURE_EXPIRED |
device-signature-stale |
Podpisany znacznik czasu jest poza dozwolonym odchyleniem. |
device identity mismatch |
DEVICE_AUTH_DEVICE_ID_MISMATCH |
device-id-mismatch |
device.id nie pasuje do odcisku palca klucza publicznego. |
device public key invalid |
DEVICE_AUTH_PUBLIC_KEY_INVALID |
device-public-key |
Format/kanonikalizacja klucza publicznego nie powiodła się. |
Cel migracji:
- Zawsze czekaj na
connect.challenge. - Podpisuj ładunek v2, który zawiera nonce serwera.
- Wyślij ten sam nonce w
connect.params.device.nonce. - Preferowany ładunek podpisu to
v3, który wiążeplatformideviceFamilyoprócz pól device/client/role/scopes/token/nonce. - Starsze podpisy
v2pozostają akceptowane ze względów zgodności, ale przypinanie metadanych sparowanego urządzenia nadal kontroluje politykę poleceń przy ponownym połączeniu.
TLS + przypinanie
- TLS jest obsługiwane dla połączeń WS.
- Klienci mogą opcjonalnie przypiąć odcisk palca certyfikatu Gateway (zobacz konfigurację
gateway.tlsorazgateway.remote.tlsFingerprintalbo CLI--tls-fingerprint).
Zakres
Ten protokół udostępnia pełne API Gateway (status, kanały, modele, czat,
agent, sesje, węzły, zatwierdzenia itd.). Dokładna powierzchnia jest zdefiniowana przez
schematy TypeBox w packages/gateway-protocol/src/schema.ts.