> ## Documentation Index
> Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Протокол Gateway

Протокол Gateway WS — это **единая плоскость управления + транспорт узлов** для
OpenClaw. Все клиенты (CLI, веб-UI, приложение macOS, узлы iOS/Android,
безголовые узлы) подключаются через WebSocket и объявляют свою **роль** +
**область действия** во время рукопожатия.

## Транспорт

* WebSocket, текстовые фреймы с JSON-полезной нагрузкой.
* Первый фрейм **должен** быть запросом `connect`.
* Фреймы до подключения ограничены 64 КиБ. После успешного рукопожатия клиентам
  следует соблюдать ограничения `hello-ok.policy.maxPayload` и
  `hello-ok.policy.maxBufferedBytes`. Когда диагностика включена,
  слишком большие входящие фреймы и медленные исходящие буферы порождают события
  `payload.large` до того, как gateway закроет или отбросит затронутый фрейм.
  Эти события сохраняют размеры, лимиты, поверхности и безопасные коды причин.
  Они не сохраняют тело сообщения, содержимое вложений, необработанное тело фрейма,
  токены, cookie или секретные значения.

## Рукопожатие (connect)

Gateway → Клиент (предварительный вызов до подключения):

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "type": "event",
  "event": "connect.challenge",
  "payload": { "nonce": "…", "ts": 1737264000000 }
}
```

Клиент → Gateway:

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "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 → Клиент:

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "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 еще завершает запуск вспомогательных компонентов, запрос `connect`
может вернуть повторяемую ошибку `UNAVAILABLE` с `details.reason`, равным
`"startup-sidecars"`, и `retryAfterMs`. Клиентам следует повторить такой ответ
в пределах общего бюджета подключения, а не показывать его как окончательный
сбой рукопожатия.

`server`, `features`, `snapshot` и `policy` обязательны по схеме
(`packages/gateway-protocol/src/schema/frames.ts`). `auth` также обязателен и сообщает
согласованные роль/области действия. `pluginSurfaceUrls` необязателен и сопоставляет
имена поверхностей Plugin, например `canvas`, с URL размещенных поверхностей в рамках области действия.

URL поверхностей Plugin с областью действия могут истекать. Узлы могут вызвать
`node.pluginSurface.refresh` с `{ "surface": "canvas" }`, чтобы получить свежую
запись в `pluginSurfaceUrls`. Экспериментальный рефакторинг Plugin Canvas не
поддерживает устаревший путь совместимости `canvasHostUrl`, `canvasCapability` или
`node.canvas.capability.refresh`; текущие нативные клиенты и gateways должны
использовать поверхности Plugin.

Когда токен устройства не выдан, `hello-ok.auth` сообщает согласованные
разрешения без полей токена:

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "auth": {
    "role": "operator",
    "scopes": ["operator.read", "operator.write"]
  }
}
```

Доверенные backend-клиенты в том же процессе (`client.id: "gateway-client"`,
`client.mode: "backend"`) могут не указывать `device` при прямых loopback-подключениях,
когда они аутентифицируются с помощью общего токена/пароля gateway. Этот путь
зарезервирован для внутренних RPC плоскости управления и не дает устаревшим
базовым привязкам CLI/устройства блокировать локальную backend-работу, например
обновления сеансов субагентов. Удаленные клиенты, клиенты из браузерного origin,
клиенты узлов и явные клиенты с токеном устройства/идентичностью устройства
по-прежнему используют обычные проверки сопряжения и повышения области действия.

Когда токен устройства выдан, `hello-ok` также включает:

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "auth": {
    "deviceToken": "…",
    "role": "operator",
    "scopes": ["operator.read", "operator.write"]
  }
}
```

Встроенная инициализация через QR/код настройки — это новый путь передачи на мобильное устройство.
Успешное базовое подключение по коду настройки возвращает основной токен узла
и один ограниченный токен оператора:

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "auth": {
    "deviceToken": "…",
    "role": "node",
    "scopes": [],
    "deviceTokens": [
      {
        "deviceToken": "…",
        "role": "operator",
        "scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"]
      }
    ]
  }
}
```

Передача оператору намеренно ограничена, чтобы QR-онбординг мог запустить
мобильный операторский цикл без выдачи `operator.admin` или `operator.pairing`.
Она включает `operator.talk.secrets`, чтобы нативный клиент мог прочитать
конфигурацию Talk, которая нужна ему после инициализации. Более широкие области
администрирования и сопряжения требуют отдельного одобренного операторского
сопряжения или потока токенов. Клиентам следует сохранять
`hello-ok.auth.deviceTokens` только
когда подключение использовало bootstrap-аутентификацию по доверенному транспорту,
например `wss://`, или через loopback/локальное сопряжение.

### Пример узла

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "type": "req",
  "id": "…",
  "method": "connect",
  "params": {
    "minProtocol": 3,
    "maxProtocol": 4,
    "client": {
      "id": "ios-node",
      "version": "1.2.3",
      "platform": "ios",
      "mode": "node"
    },
    "role": "node",
    "scopes": [],
    "caps": ["camera", "canvas", "screen", "location", "voice"],
    "commands": ["camera.snap", "canvas.navigate", "screen.record", "location.get"],
    "permissions": { "camera.capture": true, "screen.record": false },
    "auth": { "token": "…" },
    "locale": "en-US",
    "userAgent": "openclaw-ios/1.2.3",
    "device": {
      "id": "device_fingerprint",
      "publicKey": "…",
      "signature": "…",
      "signedAt": 1737264000000,
      "nonce": "…"
    }
  }
}
```

## Обрамление

* **Запрос**: `{type:"req", id, method, params}`
* **Ответ**: `{type:"res", id, ok, payload|error}`
* **Событие**: `{type:"event", event, payload, seq?, stateVersion?}`

Методы с побочными эффектами требуют **ключи идемпотентности** (см. схему).

## Роли + области действия

Полную модель областей действия оператора, проверки во время одобрения и
семантику общего секрета см. в разделе [Области действия оператора](/ru/gateway/operator-scopes).

### Роли

* `operator` = клиент плоскости управления (CLI/UI/автоматизация).
* `node` = хост возможностей (camera/screen/canvas/system.run).

### Области действия (оператор)

Распространенные области действия:

* `operator.read`
* `operator.write`
* `operator.admin`
* `operator.approvals`
* `operator.pairing`
* `operator.talk.secrets`

`talk.config` с `includeSecrets: true` требует `operator.talk.secrets`
(или `operator.admin`).

RPC-методы gateway, зарегистрированные Plugin, могут запрашивать собственную
область действия оператора, но зарезервированные префиксы администрирования ядра
(`config.*`, `exec.approvals.*`, `wizard.*`, `update.*`) всегда разрешаются в
`operator.admin`.

Область действия метода — только первый барьер. Некоторые slash-команды,
доступные через `chat.send`, применяют поверх него более строгие проверки
на уровне команды. Например, постоянные записи `/config set` и `/config unset`
требуют `operator.admin`.

`node.pair.approve` также имеет дополнительную проверку области действия во время
одобрения поверх базовой области действия метода:

* запросы без команд: `operator.pairing`
* запросы с node-командами не exec-типа: `operator.pairing` + `operator.write`
* запросы, включающие `system.run`, `system.run.prepare` или `system.which`:
  `operator.pairing` + `operator.admin`

### Возможности/команды/разрешения (узел)

Узлы объявляют заявки на возможности во время подключения:

* `caps`: высокоуровневые категории возможностей, такие как `camera`, `canvas`, `screen`,
  `location`, `voice` и `talk`.
* `commands`: allowlist команд для вызова.
* `permissions`: детальные переключатели (например, `screen.record`, `camera.capture`).

Gateway рассматривает их как **заявки** и применяет серверные allowlist.

## Присутствие

* `system-presence` возвращает записи, ключами которых являются идентичности устройств.
* Записи присутствия включают `deviceId`, `roles` и `scopes`, чтобы UI могли показывать одну строку на устройство
  даже когда оно подключается и как **operator**, и как **node**.
* `node.list` включает необязательные поля `lastSeenAtMs` и `lastSeenReason`. Подключенные узлы сообщают
  текущее время подключения как `lastSeenAtMs` с причиной `connect`; сопряженные узлы также могут сообщать
  устойчивое фоновое присутствие, когда доверенное событие узла обновляет их метаданные сопряжения.

### Фоновое событие активности узла

Узлы могут вызвать `node.event` с `event: "node.presence.alive"`, чтобы записать, что сопряженный узел был
активен во время фонового пробуждения, не помечая его как подключенный.

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "event": "node.presence.alive",
  "payloadJSON": "{\"trigger\":\"silent_push\",\"sentAtMs\":1737264000000,\"displayName\":\"Peter's iPhone\",\"version\":\"2026.4.28\",\"platform\":\"iOS 18.4.0\",\"deviceFamily\":\"iPhone\",\"modelIdentifier\":\"iPhone17,1\",\"pushTransport\":\"relay\"}"
}
```

`trigger` — закрытое перечисление: `background`, `silent_push`, `bg_app_refresh`,
`significant_location`, `manual` или `connect`. Неизвестные строки trigger нормализуются gateway до
`background` перед сохранением. Событие устойчиво только для аутентифицированных сеансов устройств
узлов; сеансы без устройства или без сопряжения возвращают `handled: false`.

Успешные gateways возвращают структурированный результат:

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "ok": true,
  "event": "node.presence.alive",
  "handled": true,
  "reason": "persisted"
}
```

Более старые gateways все еще могут возвращать `{ "ok": true }` для `node.event`; клиентам следует считать это
подтвержденным RPC, а не устойчивым сохранением присутствия.

## Определение областей действия широковещательных событий

Широковещательные события WebSocket, отправляемые сервером, ограничиваются областями действия, чтобы сеансы
с областью сопряжения или только для узла не получали пассивно содержимое сеанса.

* **Фреймы чата, агента и результатов инструментов** (включая потоковые события `agent` и результаты вызовов инструментов) требуют как минимум `operator.read`. Сеансы без `operator.read` полностью пропускают эти фреймы.
* **Широковещательные `plugin.*`, определенные Plugin**, ограничиваются `operator.write` или `operator.admin` в зависимости от того, как Plugin их зарегистрировал.
* **События статуса и транспорта** (`heartbeat`, `presence`, `tick`, жизненный цикл connect/disconnect и т. д.) остаются без ограничений, чтобы состояние транспорта было наблюдаемым для каждого аутентифицированного сеанса.
* **Неизвестные семейства широковещательных событий** по умолчанию ограничиваются областями действия (fail-closed), если зарегистрированный обработчик явно не ослабляет эти ограничения.

Каждое клиентское подключение хранит собственный порядковый номер для клиента, поэтому широковещательные события сохраняют монотонный порядок на этом сокете, даже когда разные клиенты видят разные отфильтрованные по областям действия подмножества потока событий.

## Общие семейства RPC-методов

Публичная поверхность WS шире, чем приведенные выше примеры рукопожатия/аутентификации. Это
не сгенерированный дамп — `hello-ok.features.methods` является консервативным
списком обнаружения, построенным из `src/gateway/server-methods-list.ts` плюс загруженных
экспортов методов Plugin/каналов. Рассматривайте его как обнаружение возможностей, а не как полное
перечисление `src/gateway/server-methods/*.ts`.

<AccordionGroup>
  <Accordion title="System and identity">
    * `health` возвращает кэшированный или заново проверенный снимок состояния Gateway.
    * `diagnostics.stability` возвращает недавний ограниченный регистратор диагностической стабильности. Он хранит операционные метаданные, такие как имена событий, счетчики, размеры в байтах, показания памяти, состояние очереди/сеанса, имена каналов/Plugin и идентификаторы сеансов. Он не хранит текст чатов, тела Webhook, выводы инструментов, сырые тела запросов или ответов, токены, cookie или секретные значения. Требуется область чтения оператора.
    * `status` возвращает сводку Gateway в стиле `/status`; чувствительные поля включаются только для операторских клиентов с областью администратора.
    * `gateway.identity.get` возвращает идентификатор устройства Gateway, используемый потоками ретрансляции и сопряжения.
    * `system-presence` возвращает текущий снимок присутствия для подключенных операторских/узловых устройств.
    * `system-event` добавляет системное событие и может обновлять/транслировать контекст присутствия.
    * `last-heartbeat` возвращает последнее сохраненное событие Heartbeat.
    * `set-heartbeats` включает или отключает обработку Heartbeat на Gateway.
  </Accordion>

  <Accordion title="Models and usage">
    * `models.list` возвращает каталог моделей, разрешенных средой выполнения. Передайте `{ "view": "configured" }` для настроенных моделей размером под средство выбора (`agents.defaults.models` сначала, затем `models.providers.*.models`) или `{ "view": "all" }` для полного каталога.
    * `usage.status` возвращает сводки окон использования провайдеров и оставшейся квоты.
    * `usage.cost` возвращает агрегированные сводки расходов за диапазон дат.
      Передайте `agentId` для одного агента или `agentScope: "all"`, чтобы агрегировать настроенных агентов.
    * `doctor.memory.status` возвращает готовность векторной памяти / кэшированных эмбеддингов для активной рабочей области агента по умолчанию. Передавайте `{ "probe": true }` или `{ "deep": true }` только когда вызывающей стороне явно нужен живой ping провайдера эмбеддингов. Клиенты, учитывающие 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 для удаленных клиентов плоскости управления. Он может включать пути рабочих областей, фрагменты памяти, отрендеренный заземленный Markdown и кандидатов для глубокого продвижения, поэтому вызывающим сторонам нужен `operator.read`.
    * `sessions.usage` возвращает сводки использования по сеансам. Передайте `agentId` для одного
      агента или `agentScope: "all"`, чтобы вывести настроенных агентов вместе.
    * `sessions.usage.timeseries` возвращает временной ряд использования для одного сеанса.
    * `sessions.usage.logs` возвращает записи журнала использования для одного сеанса.
  </Accordion>

  <Accordion title="Channels and login helpers">
    * `channels.status` возвращает сводки состояния встроенных + поставляемых каналов/Plugin.
    * `channels.logout` выполняет выход из конкретного канала/учетной записи, если канал поддерживает выход.
    * `web.login.start` запускает поток входа через QR/веб для текущего провайдера веб-канала с поддержкой QR.
    * `web.login.wait` ожидает завершения этого потока входа через QR/веб и при успехе запускает канал.
    * `push.test` отправляет тестовый push APNs на зарегистрированный узел iOS.
    * `voicewake.get` возвращает сохраненные триггеры фразы пробуждения.
    * `voicewake.set` обновляет триггеры фразы пробуждения и транслирует изменение.
  </Accordion>

  <Accordion title="Messaging and logs">
    * `send` — это прямой RPC исходящей доставки для отправок, нацеленных на канал/учетную запись/поток, вне раннера чата.
    * `logs.tail` возвращает настроенный хвост файлового журнала Gateway с управлением курсором/лимитом и максимальным числом байтов.
  </Accordion>

  <Accordion title="Talk and TTS">
    * `talk.catalog` возвращает доступный только для чтения каталог провайдеров Talk для речи, потоковой транскрипции и голоса в реальном времени. Он включает идентификаторы провайдеров, метки, состояние настройки, раскрытые идентификаторы моделей/голосов, канонические режимы, транспорты, стратегии brain и флаги аудио/возможностей реального времени, не возвращая секреты провайдеров и не изменяя глобальную конфигурацию.
    * `talk.config` возвращает эффективную полезную нагрузку конфигурации Talk; `includeSecrets` требует `operator.talk.secrets` (или `operator.admin`).
    * `talk.session.create` создает принадлежащий Gateway сеанс Talk для `realtime/gateway-relay`, `transcription/gateway-relay` или `stt-tts/managed-room`. Для `stt-tts/managed-room` вызывающие стороны с `operator.write`, передающие `sessionKey`, также должны передать `spawnedBy` для видимости ключа сеанса в заданной области; создание `sessionKey` без области и `brain: "direct-tools"` требуют `operator.admin`.
    * `talk.session.join` проверяет токен сеанса управляемой комнаты, при необходимости испускает события `session.ready` или `session.replaced` и возвращает метаданные комнаты/сеанса плюс недавние события Talk без токена в открытом виде или сохраненного хэша токена.
    * `talk.session.appendAudio` добавляет входное аудио PCM в base64 к принадлежащим Gateway сеансам ретрансляции реального времени и транскрипции.
    * `talk.session.startTurn`, `talk.session.endTurn` и `talk.session.cancelTurn` управляют жизненным циклом хода в управляемой комнате с отклонением устаревшего хода до очистки состояния.
    * `talk.session.cancelOutput` останавливает аудиовывод ассистента, главным образом для прерывания по VAD в сеансах ретрансляции Gateway.
    * `talk.session.submitToolResult` завершает вызов инструмента провайдера, испущенный принадлежащим Gateway сеансом ретрансляции реального времени. Передайте `options: { willContinue: true }` для промежуточного вывода инструмента, когда затем будет финальный результат, или `options: { suppressResponse: true }`, когда результат инструмента должен удовлетворить вызов провайдера без запуска еще одного ответа ассистента в реальном времени.
    * `talk.session.steer` отправляет голосовое управление активным запуском в принадлежащий Gateway сеанс Talk с агентной поддержкой. Он принимает `{ sessionId, text, mode? }`, где `mode` — `status`, `steer`, `cancel` или `followup`; опущенный режим классифицируется по произнесенному тексту.
    * `talk.session.close` закрывает принадлежащий Gateway сеанс ретрансляции, транскрипции или управляемой комнаты и испускает терминальные события Talk.
    * `talk.mode` задает/транслирует текущее состояние режима Talk для клиентов WebChat/Control UI.
    * `talk.client.create` создает принадлежащий клиенту сеанс провайдера реального времени с использованием `webrtc` или `provider-websocket`, при этом Gateway владеет конфигурацией, учетными данными, инструкциями и политикой инструментов.
    * `talk.client.toolCall` позволяет принадлежащим клиенту транспортам реального времени пересылать вызовы инструментов провайдера в политику Gateway. Первый поддерживаемый инструмент — `openclaw_agent_consult`; клиенты получают идентификатор запуска и ожидают обычных событий жизненного цикла чата перед отправкой результата инструмента, специфичного для провайдера.
    * `talk.client.steer` отправляет голосовое управление активным запуском для принадлежащих клиенту транспортов реального времени. Gateway разрешает активный встроенный запуск из `sessionKey` и возвращает структурированный результат принятия/отклонения вместо молчаливого отбрасывания управления.
    * `talk.event` — единый канал событий Talk для адаптеров реального времени, транскрипции, STT/TTS, управляемых комнат, телефонии и встреч.
    * `talk.speak` синтезирует речь через активного речевого провайдера Talk.
    * `tts.status` возвращает состояние включения TTS, активного провайдера, fallback-провайдеров и состояние конфигурации провайдеров.
    * `tts.providers` возвращает видимый инвентарь провайдеров TTS.
    * `tts.enable` и `tts.disable` переключают состояние настроек TTS.
    * `tts.setProvider` обновляет предпочтительного провайдера TTS.
    * `tts.convert` выполняет одноразовое преобразование текста в речь.
  </Accordion>

  <Accordion title="Secrets, config, update, and wizard">
    * `secrets.reload` заново разрешает активные SecretRefs и заменяет состояние секретов среды выполнения только при полном успехе.
    * `secrets.resolve` разрешает назначения секретов, нацеленные на команду, для конкретного набора команд/целей.
    * `config.get` возвращает текущий снимок конфигурации и хэш.
    * `config.set` записывает проверенную полезную нагрузку конфигурации.
    * `config.patch` объединяет частичное обновление конфигурации. Разрушительная замена
      массива требует указать затронутый путь в `replacePaths`; вложенные массивы
      под элементами массива используют пути `[]`, такие как `agents.list[].skills`.
    * `config.apply` проверяет и заменяет полную полезную нагрузку конфигурации.
    * `config.schema` возвращает живую полезную нагрузку схемы конфигурации, используемую Control UI и инструментами CLI: схему, `uiHints`, версию и метаданные генерации, включая метаданные схем Plugin + каналов, когда среда выполнения может их загрузить. Схема включает метаданные полей `title` / `description`, выведенные из тех же меток и справочного текста, которые использует UI, включая ветки компоновки вложенных объектов, wildcard, элементов массива и `anyOf` / `oneOf` / `allOf`, когда существует соответствующая документация поля.
    * `config.schema.lookup` возвращает полезную нагрузку поиска в области пути для одного пути конфигурации: нормализованный путь, поверхностный узел схемы, совпавшую подсказку + `hintPath`, необязательный `reloadKind` и непосредственные сводки дочерних элементов для детализации UI/CLI. `reloadKind` — одно из `restart`, `hot` или `none` и отражает планировщик перезагрузки конфигурации Gateway для запрошенного пути. Узлы схемы поиска сохраняют пользовательскую документацию и общие поля проверки (`title`, `description`, `type`, `enum`, `const`, `format`, `pattern`, ограничения чисел/строк/массивов/объектов и флаги вроде `additionalProperties`, `deprecated`, `readOnly`, `writeOnly`). Сводки дочерних элементов раскрывают `key`, нормализованный `path`, `type`, `required`, `hasChildren`, необязательный `reloadKind`, а также совпавшие `hint` / `hintPath`.
    * `update.run` запускает поток обновления Gateway и планирует перезапуск только когда само обновление успешно; вызывающие стороны с сеансом могут включить `continuationMessage`, чтобы при запуске возобновить один последующий ход агента через очередь продолжения после перезапуска. Обновления через менеджер пакетов и контролируемые обновления git-checkout из плоскости управления используют отделенную передачу управляемому сервису вместо замены дерева пакетов или изменения вывода 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`, когда требуется ручное обновление через shell. Недоступная передача означает, что OpenClaw не хватает безопасной границы супервизора или устойчивого идентификатора сервиса, например `OPENCLAW_SYSTEMD_UNIT` для systemd. Во время запущенной передачи sentinel перезапуска может кратко сообщать `stats.reason: "restart-health-pending"`; продолжение откладывается, пока CLI не проверит перезапущенный Gateway и не запишет финальный sentinel `ok`.
    * `update.status` обновляет и возвращает последний sentinel перезапуска обновления, включая версию, запущенную после перезапуска, если она доступна.
    * `wizard.start`, `wizard.next`, `wizard.status` и `wizard.cancel` предоставляют мастер онбординга через WS RPC.
  </Accordion>

  <Accordion title="Вспомогательные методы агента и рабочей области">
    * `agents.list` возвращает настроенные записи агентов, включая действующую модель и метаданные среды выполнения.
    * `agents.create`, `agents.update` и `agents.delete` управляют записями агентов и привязкой рабочей области.
    * `agents.files.list`, `agents.files.get` и `agents.files.set` управляют начальными файлами рабочей области, доступными агенту.
    * `tasks.list`, `tasks.get` и `tasks.cancel` предоставляют реестр задач Gateway клиентам SDK и операторам.
    * `artifacts.list`, `artifacts.get` и `artifacts.download` предоставляют сводки артефактов, полученных из транскрипта, и загрузки для явной области `sessionKey`, `runId` или `taskId`. Запросы запусков и задач определяют владеющую сессию на стороне сервера и возвращают только медиа из транскрипта с совпадающим происхождением; небезопасные или локальные URL-источники возвращают неподдерживаемые загрузки вместо получения на стороне сервера.
    * `environments.list` и `environments.status` предоставляют клиентам SDK доступное только для чтения обнаружение локальных для Gateway и узловых окружений.
    * `agent.identity.get` возвращает действующую идентичность ассистента для агента или сессии.
    * `agent.wait` ожидает завершения запуска и возвращает конечный снимок, когда он доступен.
  </Accordion>

  <Accordion title="Управление сессиями">
    * `sessions.list` возвращает текущий индекс сессий, включая построчные метаданные `agentRuntime`, когда настроен backend среды выполнения агента.
    * `sessions.subscribe` и `sessions.unsubscribe` переключают подписки на события изменения сессий для текущего WS-клиента.
    * `sessions.messages.subscribe` и `sessions.messages.unsubscribe` переключают подписки на события транскрипта/сообщений для одной сессии.
    * `sessions.preview` возвращает ограниченные предварительные просмотры транскрипта для конкретных ключей сессий.
    * `sessions.describe` возвращает одну строку сессии Gateway для точного ключа сессии.
    * `sessions.resolve` разрешает или канонизирует целевую сессию.
    * `sessions.create` создает новую запись сессии.
    * `sessions.send` отправляет сообщение в существующую сессию.
    * `sessions.steer` — вариант прерывания и перенаправления для активной сессии.
    * `sessions.abort` прерывает активную работу для сессии. Вызывающий может передать `key` плюс необязательный `runId` или передать только `runId` для активных запусков, которые Gateway может сопоставить с сессией.
    * `sessions.patch` обновляет метаданные/переопределения сессии и сообщает разрешенную каноническую модель плюс действующий `agentRuntime`.
    * `sessions.reset`, `sessions.delete` и `sessions.compact` выполняют обслуживание сессии.
    * `sessions.get` возвращает полную сохраненную строку сессии.
    * Выполнение чата по-прежнему использует `chat.history`, `chat.send`, `chat.abort` и `chat.inject`. `chat.history` нормализуется для отображения в UI-клиентах: встроенные теги директив удаляются из видимого текста, XML-полезные нагрузки вызовов инструментов в обычном тексте (включая `<tool_call>...</tool_call>`, `<function_call>...</function_call>`, `<tool_calls>...</tool_calls>`, `<function_calls>...</function_calls>` и усеченные блоки вызовов инструментов), а также утекшие ASCII/полноширинные управляющие токены модели удаляются, строки ассистента, состоящие только из тихих токенов, такие как точные `NO_REPLY` / `no_reply`, опускаются, а слишком большие строки могут заменяться заполнителями.
    * `chat.message.get` — аддитивный ограниченный считыватель полного сообщения для одной видимой записи транскрипта. Клиенты передают `sessionKey`, необязательный `agentId`, когда выбор сессии ограничен агентом, плюс `messageId` транскрипта, ранее предоставленный через `chat.history`, а Gateway возвращает ту же нормализованную для отображения проекцию без облегченного ограничения усечения истории, если сохраненная запись все еще доступна и не является слишком большой.
    * `chat.send` принимает для одного хода `fastMode: "auto"`, чтобы использовать быстрый режим для вызовов модели, начатых до автоматического порога, а затем запускать последующие повторные попытки, fallback, результаты инструментов или вызовы продолжения без быстрого режима. По умолчанию порог равен 60 секундам и может настраиваться для каждой модели через `agents.defaults.models["<provider>/<model>"].params.fastAutoOnSeconds`. Вызывающий `chat.send` может передать для одного хода `fastAutoOnSeconds`, чтобы переопределить порог для этого запроса.
  </Accordion>

  <Accordion title="Сопряжение устройств и токены устройств">
    * `device.pair.list` возвращает ожидающие и одобренные сопряженные устройства.
    * `device.pair.approve`, `device.pair.reject` и `device.pair.remove` управляют записями сопряжения устройств.
    * `device.token.rotate` ротирует токен сопряженного устройства в пределах его одобренной роли и границ области вызывающего.
    * `device.token.revoke` отзывает токен сопряженного устройства в пределах его одобренной роли и границ области вызывающего.
  </Accordion>

  <Accordion title="Сопряжение Node, вызов и ожидающая работа">
    * `node.pair.request`, `node.pair.list`, `node.pair.approve`, `node.pair.reject`, `node.pair.remove` и `node.pair.verify` охватывают сопряжение Node и проверку начальной настройки.
    * `node.list` и `node.describe` возвращают состояние известных/подключенных Node.
    * `node.rename` обновляет метку сопряженного Node.
    * `node.invoke` пересылает команду подключенному Node.
    * `node.invoke.result` возвращает результат для запроса вызова.
    * `node.event` передает события, исходящие от Node, обратно в Gateway.
    * `node.pending.pull` и `node.pending.ack` — API очереди подключенного Node.
    * `node.pending.enqueue` и `node.pending.drain` управляют долговечной ожидающей работой для автономных/отключенных Node.
  </Accordion>

  <Accordion title="Семейства утверждений">
    * `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 Gateway.
    * `exec.approvals.node.get` и `exec.approvals.node.set` управляют локальной для Node политикой утверждений exec через команды ретрансляции Node.
    * `plugin.approval.request`, `plugin.approval.list`, `plugin.approval.waitDecision` и `plugin.approval.resolve` охватывают потоки утверждения, определяемые Plugin.
  </Accordion>

  <Accordion title="Автоматизация, Skills и инструменты">
    * Автоматизация: `wake` планирует немедленную или следующую по Heartbeat вставку текста пробуждения; `cron.get`, `cron.list`, `cron.status`, `cron.add`, `cron.update`, `cron.remove`, `cron.run`, `cron.runs` управляют запланированной работой.
    * `cron.run` остается RPC в стиле постановки в очередь для ручных запусков. Клиенты, которым нужна семантика завершения, должны читать возвращенный `runId` и опрашивать `cron.runs`.
    * `cron.runs` принимает необязательный непустой фильтр `runId`, чтобы клиенты могли отслеживать один поставленный в очередь ручной запуск без гонки с другими записями истории для той же задачи.
    * Skills и инструменты: `commands.list`, `skills.*`, `tools.catalog`, `tools.effective`, `tools.invoke`.
  </Accordion>
</AccordionGroup>

### Общие семейства событий

* `chat`: обновления UI-чата, такие как `chat.inject`, и другие события чата
  только для транскрипта. В протоколе v4 delta-полезные нагрузки несут
  `deltaText`; `message` остается накопленным снимком ассистента. Замены
  не по префиксу устанавливают `replace=true` и используют `deltaText` как
  текст замены.
* `session.message`, `session.operation` и `session.tool`: обновления
  транскрипта, выполняющейся операции сессии и потока событий для подписанной
  сессии.
* `sessions.changed`: изменился индекс сессий или метаданные.
* `presence`: обновления снимка присутствия системы.
* `tick`: периодическое событие keepalive / liveness.
* `health`: обновление снимка состояния Gateway.
* `heartbeat`: обновление потока событий Heartbeat.
* `cron`: событие изменения запуска/задания Cron.
* `shutdown`: уведомление о завершении работы Gateway.
* `node.pair.requested` / `node.pair.resolved`: жизненный цикл сопряжения Node.
* `node.invoke.request`: широковещательный запрос вызова Node.
* `device.pair.requested` / `device.pair.resolved`: жизненный цикл сопряженного устройства.
* `voicewake.changed`: изменилась конфигурация триггера по слову пробуждения.
* `exec.approval.requested` / `exec.approval.resolved`: жизненный цикл
  утверждения exec.
* `plugin.approval.requested` / `plugin.approval.resolved`: жизненный цикл
  утверждения Plugin.

### Вспомогательные методы Node

* Node могут вызывать `skills.bins`, чтобы получить текущий список исполняемых файлов Skills
  для проверок автоматического разрешения.

### RPC реестра задач

Клиенты операторов могут просматривать и отменять записи фоновых задач Gateway через
RPC реестра задач. Эти методы возвращают очищенные сводки задач, а не сырое
состояние среды выполнения.

* `tasks.list` требует `operator.read`.
  * Параметры: необязательный `status` (`"queued"`, `"running"`, `"completed"`,
    `"failed"`, `"cancelled"` или `"timed_out"`) или массив этих статусов,
    необязательный `agentId`, необязательный `sessionKey`, необязательный `limit` от `1` до
    `500` и необязательная строка `cursor`.
  * Результат: `{ "tasks": TaskSummary[], "nextCursor"?: string }`.
* `tasks.get` требует `operator.read`.
  * Параметры: `{ "taskId": string }`.
  * Результат: `{ "task": TaskSummary }`.
  * Отсутствующие идентификаторы задач возвращают форму ошибки Gateway not-found.
* `tasks.cancel` требует `operator.write`.
  * Параметры: `{ "taskId": string, "reason"?: string }`.
  * Результат:
    `{ "found": boolean, "cancelled": boolean, "reason"?: string, "task"?: TaskSummary }`.
  * `found` сообщает, была ли в реестре совпадающая задача. `cancelled`
    сообщает, приняла ли среда выполнения отмену или записала ее.

`TaskSummary` включает `id`, `status` и необязательные метаданные, такие как `kind`,
`runtime`, `title`, `agentId`, `sessionKey`, `childSessionKey`, `ownerKey`,
`runId`, `taskId`, `flowId`, `parentTaskId`, `sourceId`, метки времени, прогресс,
конечную сводку и очищенный текст ошибки. `agentId` идентифицирует агента,
выполняющего задачу; `sessionKey` и `ownerKey` сохраняют контекст запрашивающего
и управления.

### Вспомогательные методы оператора

* Операторы могут вызывать `commands.list` (`operator.read`), чтобы получить инвентарь команд времени выполнения для агента.
  * `agentId` необязателен; опустите его, чтобы читать рабочее пространство агента по умолчанию.
  * `scope` управляет тем, на какую поверхность нацелено основное `name`:
    * `text` возвращает основной текстовый токен команды без начального `/`
    * `native` и путь по умолчанию `both` возвращают нативные имена с учетом провайдера, когда они доступны
  * `textAliases` содержит точные slash-псевдонимы, такие как `/model` и `/m`.
  * `nativeName` содержит нативное имя команды с учетом провайдера, когда оно существует.
  * `provider` необязателен и влияет только на нативное именование и доступность нативных команд Plugin.
  * `includeArgs=false` исключает сериализованные метаданные аргументов из ответа.
* Операторы могут вызывать `tools.catalog` (`operator.read`), чтобы получить каталог инструментов времени выполнения для агента. Ответ включает сгруппированные инструменты и метаданные происхождения:
  * `source`: `core` или `plugin`
  * `pluginId`: владелец Plugin, когда `source="plugin"`
  * `optional`: является ли инструмент Plugin необязательным
* Операторы могут вызывать `tools.effective` (`operator.read`), чтобы получить фактически действующий во время выполнения инвентарь инструментов для сессии.
  * `sessionKey` обязателен.
  * Gateway выводит доверенный контекст времени выполнения из сессии на стороне сервера, вместо того чтобы принимать предоставленный вызывающим кодом контекст аутентификации или доставки.
  * Ответ представляет собой серверную проекцию активного инвентаря в области сессии, включая core, Plugin, канал и уже обнаруженные инструменты MCP-сервера.
  * `tools.effective` доступен только для чтения для MCP: он может пропустить прогретый каталог MCP сессии через итоговую политику инструментов, но не создает среды выполнения MCP, не подключает транспорты и не выполняет `tools/list`. Если подходящего прогретого каталога нет, ответ может включать уведомление, например `mcp-not-yet-connected`, `mcp-not-yet-listed` или `mcp-stale-catalog`.
  * Записи эффективных инструментов используют `source="core"`, `source="plugin"`, `source="channel"` или `source="mcp"`.
* Операторы могут вызывать `tools.invoke` (`operator.write`), чтобы вызвать один доступный инструмент через тот же путь политики Gateway, что и `/tools/invoke`.
  * `name` обязателен. `args`, `sessionKey`, `agentId`, `confirm` и `idempotencyKey` необязательны.
  * Если присутствуют и `sessionKey`, и `agentId`, разрешенный агент сессии должен совпадать с `agentId`.
  * Core-обертки только для владельца, такие как `cron`, `gateway` и `nodes`, требуют идентичность владельца/администратора (`operator.admin`), хотя сам метод `tools.invoke` имеет `operator.write`.
  * Ответ представляет собой конверт для SDK с `ok`, `toolName`, необязательным `output` и типизированными полями `error`. Отказы из-за подтверждения или политики возвращают `ok:false` в полезной нагрузке, а не обходят конвейер политики инструментов Gateway.
* Операторы могут вызывать `skills.status` (`operator.read`), чтобы получить видимый инвентарь навыков для агента.
  * `agentId` необязателен; опустите его, чтобы читать рабочее пространство агента по умолчанию.
  * Ответ включает пригодность, отсутствующие требования, проверки конфигурации и очищенные параметры установки без раскрытия необработанных секретных значений.
* Операторы могут вызывать `skills.search` и `skills.detail` (`operator.read`) для метаданных обнаружения ClawHub.
* Операторы могут вызывать `skills.upload.begin`, `skills.upload.chunk` и `skills.upload.commit` (`operator.admin`), чтобы подготовить приватный архив навыка перед установкой. Это отдельный административный путь загрузки для доверенных клиентов, а не обычный поток установки навыка ClawHub, и он по умолчанию отключен, если не включен `skills.install.allowUploadedArchives`.
  * `skills.upload.begin({ kind: "skill-archive", slug, sizeBytes, sha256?, force?, idempotencyKey? })`
    создает загрузку, привязанную к этому slug и значению force.
  * `skills.upload.chunk({ uploadId, offset, dataBase64 })` добавляет байты по точному декодированному смещению.
  * `skills.upload.commit({ uploadId, sha256? })` проверяет итоговый размер и SHA-256. Commit только завершает загрузку; он не устанавливает навык.
  * Загруженные архивы навыков являются zip-архивами, содержащими корневой `SKILL.md`. Внутреннее имя каталога архива никогда не выбирает целевое место установки.
* Операторы могут вызывать `skills.install` (`operator.admin`) в трех режимах:
  * Режим ClawHub: `{ source: "clawhub", slug, version?, force? }` устанавливает папку навыка в каталог `skills/` рабочего пространства агента по умолчанию.
  * Режим загрузки: `{ source: "upload", uploadId, slug, force?, sha256?, timeoutMs? }`
    устанавливает завершенную загрузку в каталог `skills/<slug>` рабочего пространства агента по умолчанию. Slug и значение force должны совпадать с исходным запросом `skills.upload.begin`. Этот режим отклоняется, если не включен `skills.install.allowUploadedArchives`. Настройка не влияет на установки ClawHub.
  * Режим установщика Gateway: `{ name, installId, timeoutMs? }`
    выполняет объявленное действие `metadata.openclaw.install` на хосте Gateway.
    Старые клиенты все еще могут отправлять `dangerouslyForceUnsafeInstall`; это поле устарело, принимается только для совместимости протокола и игнорируется. Используйте `security.installPolicy` для решений по установке, которыми владеет оператор.
* Операторы могут вызывать `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"`: поведение размера picker. Если настроено `agents.defaults.models`, оно по-прежнему имеет приоритет, включая обнаружение в области провайдера для записей `provider/*`. Без списка разрешений ответ использует явные записи `models.providers.*.models`, откатываясь к полному каталогу только тогда, когда настроенных строк моделей нет.
* `"all"`: полный каталог Gateway, с обходом `agents.defaults.models`. Используйте это для диагностики и UI обнаружения, а не для обычных picker моделей.

## Подтверждения 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 отклоняет запуск вместо доверия измененной полезной нагрузке.

## Резервный вариант доставки агента

* Запросы `agent` могут включать `deliver=true`, чтобы запросить исходящую доставку.
* `bestEffortDeliver=false` сохраняет строгое поведение: неразрешенные или только внутренние цели доставки возвращают `INVALID_REQUEST`.
* `bestEffortDeliver=true` разрешает откат к выполнению только в сессии, когда не удается разрешить внешний доставляемый маршрут (например, внутренние/webchat-сессии или неоднозначные многоканальные конфигурации).
* Итоговые результаты `agent` могут включать `result.deliveryStatus`, когда доставка была запрошена, используя те же статусы `sent`, `suppressed`, `partial_failed` и `failed`, которые задокументированы для [`openclaw agent --json --deliver`](/ru/cli/agent#json-delivery-status).

## Версионирование

* `PROTOCOL_VERSION` находится в `packages/gateway-protocol/src/version.ts`.
* Клиенты отправляют `minProtocol` + `maxProtocol`; сервер отклоняет диапазоны, которые не включают его текущий протокол. Текущие клиенты и серверы требуют протокол v4.
* Схемы + модели генерируются из определений TypeBox:
  * `pnpm protocol:gen`
  * `pnpm protocol:gen:swift`
  * `pnpm protocol:check`

### Константы клиента

Эталонный клиент в `src/gateway/client.ts` использует эти значения по умолчанию. Значения стабильны в рамках протокола v4 и являются ожидаемой базовой линией для сторонних клиентов.

| Константа                                                    | Значение по умолчанию                                     | Источник                                                                                       |
| ------------------------------------------------------------ | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `PROTOCOL_VERSION`                                           | `4`                                                       | `packages/gateway-protocol/src/version.ts`                                                     |
| `MIN_CLIENT_PROTOCOL_VERSION`                                | `4`                                                       | `packages/gateway-protocol/src/version.ts`                                                     |
| Тайм-аут запроса (на RPC)                                    | `30_000` мс                                               | `src/gateway/client.ts` (`requestTimeoutMs`)                                                   |
| Тайм-аут Preauth / connect-challenge                         | `15_000` мс                                               | `src/gateway/handshake-timeouts.ts` (config/env могут увеличить парный бюджет сервера/клиента) |
| Начальная задержка повторного подключения                    | `1_000` мс                                                | `src/gateway/client.ts` (`backoffMs`)                                                          |
| Максимальная задержка повторного подключения                 | `30_000` мс                                               | `src/gateway/client.ts` (`scheduleReconnect`)                                                  |
| Ограничение быстрого повтора после закрытия device-token     | `250` мс                                                  | `src/gateway/client.ts`                                                                        |
| Льготный период принудительной остановки перед `terminate()` | `250` мс                                                  | `FORCE_STOP_TERMINATE_GRACE_MS`                                                                |
| Тайм-аут по умолчанию `stopAndWait()`                        | `1_000` мс                                                | `STOP_AND_WAIT_TIMEOUT_MS`                                                                     |
| Интервал tick по умолчанию (до `hello-ok`)                   | `30_000` мс                                               | `src/gateway/client.ts`                                                                        |
| Закрытие по тайм-ауту tick                                   | код `4000`, когда молчание превышает `tickIntervalMs * 2` | `src/gateway/client.ts`                                                                        |
| `MAX_PAYLOAD_BYTES`                                          | `25 * 1024 * 1024` (25 МБ)                                | `src/gateway/server-constants.ts`                                                              |

Сервер объявляет эффективные `policy.tickIntervalMs`, `policy.maxPayload` и `policy.maxBufferedBytes` в `hello-ok`; клиенты должны соблюдать эти значения, а не значения по умолчанию до handshake.

## Аутентификация

* Аутентификация Gateway по общему секрету использует `connect.params.auth.token` или
  `connect.params.auth.password`, в зависимости от настроенного режима аутентификации.
* Режимы с передачей идентичности, такие как Tailscale Serve
  (`gateway.auth.allowTailscale: true`) или не-loopback
  `gateway.auth.mode: "trusted-proxy"`, проходят проверку аутентификации connect по
  заголовкам запроса вместо `connect.params.auth.*`.
* `gateway.auth.mode: "none"` для приватного входящего трафика полностью пропускает
  аутентификацию connect по общему секрету; не открывайте этот режим на публичном
  или недоверенном входящем трафике.
* После сопряжения Gateway выдает **токен устройства**, ограниченный ролью соединения
  и областями доступа. Он возвращается в `hello-ok.auth.deviceToken`, и клиенту
  следует сохранять его для будущих подключений.
* Клиентам следует сохранять основной `hello-ok.auth.deviceToken` после любого
  успешного подключения.
* Повторное подключение с этим **сохраненным** токеном устройства также должно
  повторно использовать сохраненный утвержденный набор областей доступа для этого
  токена. Это сохраняет уже выданный доступ на чтение, пробу и статус и не дает
  повторным подключениям незаметно сжиматься до более узкой неявной области только
  для администратора.
* Сборка аутентификации connect на стороне клиента (`selectConnectAuth` в
  `src/gateway/client.ts`):
  * `auth.password` ортогонален и всегда передается, когда задан.
  * `auth.token` заполняется в порядке приоритета: сначала явный общий токен,
    затем явный `deviceToken`, затем сохраненный токен отдельного устройства
    (по ключу `deviceId` + `role`).
  * `auth.bootstrapToken` отправляется только когда ни один из вариантов выше не
    дал `auth.token`. Общий токен или любой найденный токен устройства подавляет его.
  * Автопродвижение сохраненного токена устройства при однократной повторной
    попытке `AUTH_TOKEN_MISMATCH` разрешено **только для доверенных конечных точек**:
    loopback или `wss://` с закрепленным `tlsFingerprint`. Публичный `wss://`
    без закрепления не подходит.
* Встроенная начальная загрузка по коду настройки возвращает основной
  `hello-ok.auth.deviceToken` Node плюс ограниченный токен оператора в
  `hello-ok.auth.deviceTokens` для доверенной передачи на мобильное устройство.
  Токен оператора включает `operator.talk.secrets` для чтения нативной конфигурации
  Talk и исключает `operator.admin` и `operator.pairing`.
* Пока небазовая начальная загрузка по коду настройки ожидает утверждения, сведения
  `PAIRING_REQUIRED` включают `recommendedNextStep: "wait_then_retry"`,
  `retryable: true` и `pauseReconnect: false`. Клиентам следует продолжать
  переподключаться с тем же токеном начальной загрузки, пока запрос не будет
  утвержден или токен не станет недействительным.
* Сохраняйте `hello-ok.auth.deviceTokens` только когда подключение использовало
  аутентификацию начальной загрузки на доверенном транспорте, таком как `wss://`,
  или при локальном сопряжении через loopback/local.
* Если клиент передает **явный** `deviceToken` или явные `scopes`, запрошенный
  вызывающей стороной набор областей доступа остается авторитетным; кэшированные
  области доступа повторно используются только когда клиент повторно использует
  сохраненный токен отдельного устройства.
* Токены устройств можно ротировать и отзывать через `device.token.rotate` и
  `device.token.revoke` (требуется область доступа `operator.pairing`). Ротация
  или отзыв токена Node либо другой неоператорской роли также требует
  `operator.admin`.
* `device.token.rotate` возвращает метаданные ротации. Он отражает замещающий
  bearer-токен только для вызовов с того же устройства, которые уже
  аутентифицированы этим токеном устройства, чтобы клиенты только с токеном могли
  сохранить замену до переподключения. Ротации по общему или административному
  токену не отражают bearer-токен.
* Выдача, ротация и отзыв токенов остаются ограничены утвержденным набором ролей,
  записанным в записи сопряжения этого устройства; изменение токенов не может
  расширить роль устройства или выбрать целевую роль устройства, которую утверждение
  сопряжения никогда не предоставляло.
* Для сеансов токенов сопряженных устройств управление устройствами ограничено
  самим устройством, если у вызывающей стороны нет `operator.admin`: вызывающие
  стороны без прав администратора могут управлять только токеном оператора для
  записи **своего** устройства. Управление токенами Node и других неоператорских
  ролей доступно только администратору, даже для собственного устройства вызывающей
  стороны.
* `device.token.rotate` и `device.token.revoke` также проверяют целевой набор
  областей доступа токена оператора относительно текущих областей доступа сеанса
  вызывающей стороны. Вызывающие стороны без прав администратора не могут ротировать
  или отзывать токен оператора с более широкими правами, чем уже имеют сами.
* Ошибки аутентификации включают `error.details.code` и подсказки для восстановления:
  * `error.details.canRetryWithDeviceToken` (boolean)
  * `error.details.recommendedNextStep` (`retry_with_device_token`, `update_auth_configuration`, `update_auth_credentials`, `wait_then_retry`, `review_auth_configuration`)
* Поведение клиента для `AUTH_TOKEN_MISMATCH`:
  * Доверенные клиенты могут выполнить одну ограниченную повторную попытку с
    кэшированным токеном отдельного устройства.
  * Если эта повторная попытка завершается ошибкой, клиентам следует остановить
    автоматические циклы переподключения и показать оператору руководство к действию.
* `AUTH_SCOPE_MISMATCH` означает, что токен устройства был распознан, но не покрывает
  запрошенную роль или области доступа. Клиентам не следует представлять это как
  неверный токен; предложите оператору повторно выполнить сопряжение или утвердить
  более узкий либо более широкий контракт областей доступа.

## Идентичность устройства + сопряжение

* Node должны включать стабильную идентичность устройства (`device.id`), полученную
  из отпечатка пары ключей.
* Gateway выдают токены для каждой пары устройство + роль.
* Для новых идентификаторов устройств требуются утверждения сопряжения, если не
  включено локальное автоутверждение.
* Автоутверждение сопряжения сосредоточено на прямых подключениях через local loopback.
* OpenClaw также имеет узкий путь самоподключения, локальный для backend/контейнера,
  для доверенных вспомогательных потоков с общим секретом.
* Подключения в tailnet или LAN с того же хоста все равно считаются удаленными для
  сопряжения и требуют утверждения.
* Клиенты WS обычно включают идентичность `device` во время `connect` (оператор +
  Node). Единственные исключения оператора без устройства — явные доверенные пути:
  * `gateway.controlUi.allowInsecureAuth=true` для совместимости небезопасного HTTP только на localhost.
  * успешная аутентификация оператора Control UI через `gateway.auth.mode: "trusted-proxy"`.
  * `gateway.controlUi.dangerouslyDisableDeviceAuth=true` (аварийный режим, серьезное снижение безопасности).
  * прямые loopback backend-RPC `gateway-client` на зарезервированном внутреннем
    вспомогательном пути.
* Пропуск идентичности устройства имеет последствия для областей доступа. Когда
  подключение оператора без устройства разрешено через явный доверенный путь,
  OpenClaw все равно очищает самостоятельно объявленные области доступа до пустого
  набора, если у этого пути нет именованного исключения для сохранения областей
  доступа. Методы, ограниченные областями доступа, затем завершаются ошибкой
  `missing scope`.
* `gateway.controlUi.dangerouslyDisableDeviceAuth=true` — это аварийный путь
  Control UI с сохранением областей доступа. Он не выдает области доступа
  произвольным пользовательским backend- или CLI-подобным WebSocket-клиентам.
* Зарезервированный прямой loopback вспомогательный backend-путь `gateway-client`
  сохраняет области доступа только для внутренних локальных RPC плоскости
  управления; пользовательские идентификаторы 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`       | Полезная нагрузка подписи не соответствует полезной нагрузке v2. |
| `device signature expired`  | `DEVICE_AUTH_SIGNATURE_EXPIRED`  | `device-signature-stale` | Подписанная временная метка вне допустимого отклонения.          |
| `device identity mismatch`  | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch`     | `device.id` не соответствует отпечатку публичного ключа.         |
| `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key`      | Формат или каноникализация публичного ключа не прошли проверку.  |

Цель миграции:

* Всегда ждать `connect.challenge`.
* Подписывать полезную нагрузку v2, которая включает nonce сервера.
* Отправлять тот же nonce в `connect.params.device.nonce`.
* Предпочтительная полезная нагрузка подписи — `v3`, которая связывает `platform` и `deviceFamily`
  в дополнение к полям device/client/role/scopes/token/nonce.
* Устаревшие подписи `v2` по-прежнему принимаются для совместимости, но закрепление
  метаданных сопряженного устройства все равно управляет политикой команд при
  переподключении.

## TLS + закрепление

* TLS поддерживается для соединений WS.
* Клиенты могут при необходимости закрепить отпечаток сертификата Gateway (см.
  конфигурацию `gateway.tls` плюс `gateway.remote.tlsFingerprint` или CLI
  `--tls-fingerprint`).

## Область доступа

Этот протокол открывает **полный API Gateway** (статус, каналы, модели, чат,
агент, сеансы, узлы, утверждения и т. д.). Точная поверхность определяется
схемами TypeBox в `packages/gateway-protocol/src/schema.ts`.

## Связанное

* [Протокол моста](/ru/gateway/bridge-protocol)
* [Runbook Gateway](/ru/gateway)
