---
read_when:
    - Реализация или обновление WS-клиентов Gateway
    - Отладка несоответствий протокола или ошибок подключения
    - Повторное создание схемы и моделей протокола
summary: 'Протокол WebSocket для Gateway: установление соединения, кадры, версионирование'
title: Протокол Gateway
x-i18n:
    generated_at: "2026-07-13T18:09:55Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 24
    provider: openai
    source_hash: 27070ffbc7ac9dffa381df2b9078f7f1c92a2e2949c9b689a32b02badf0a988e
    source_path: gateway/protocol.md
    workflow: 16
---

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

## Транспорт и кадрирование

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

Форматы кадров:

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

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

## Рукопожатие

Gateway отправляет вызов перед подключением:

```json
{
  "type": "event",
  "event": "connect.challenge",
  "payload": { "nonce": "…", "ts": 1737264000000 }
}
```

Клиент отвечает запросом `connect`:

```json
{
  "type": "req",
  "id": "…",
  "method": "connect",
  "params": {
    "minProtocol": 4,
    "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 отвечает сообщением `hello-ok`:

```json
{
  "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
    }
  }
}
```

`server`, `features`, `snapshot`, `policy` и `auth` обязательны для
`HelloOkSchema` (`packages/gateway-protocol/src/schema/frames.ts`). `auth`
сообщает согласованную роль и области доступа, даже когда токен устройства не выдаётся (формат
показан выше). `pluginSurfaceUrls` необязателен и сопоставляет имена поверхностей плагинов (например,
`canvas`) с размещёнными URL-адресами с ограниченной областью доступа; срок их действия может истечь, поэтому узлы вызывают
`node.pluginSurface.refresh` с `{ "surface": "canvas" }`, чтобы получить новую запись.
Устаревший путь `canvasHostUrl` / `canvasCapability` / `node.canvas.capability.refresh`
не поддерживается; используйте поверхности плагинов.

Пока Gateway завершает запуск вспомогательных процессов, `connect` может вернуть
ошибку `UNAVAILABLE`, допускающую повторную попытку, с `details.reason: "startup-sidecars"` и
`retryAfterMs`. Повторите попытку в пределах бюджета подключения, вместо того чтобы считать её
неустранимой ошибкой рукопожатия.

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

```json
{
  "auth": {
    "deviceToken": "…",
    "role": "operator",
    "scopes": ["operator.read", "operator.write"]
  }
}
```

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

```json
{
  "auth": {
    "deviceToken": "…",
    "role": "node",
    "scopes": [],
    "deviceTokens": [
      {
        "deviceToken": "…",
        "role": "operator",
        "scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"]
      }
    ]
  }
}
```

Эта передача управления оператору намеренно ограничена: её достаточно для запуска мобильного
цикла оператора и нативной настройки, включая `operator.talk.secrets` для чтения
конфигурации Talk, но без областей доступа для изменения сопряжения и без `operator.admin`. Для более широкого
доступа к сопряжению и администрированию требуется отдельный одобренный процесс сопряжения или выдачи токена. Сохраняйте
`hello-ok.auth.deviceTokens` только в том случае, если начальная аутентификация выполнялась через доверенный
транспорт (`wss://` или локальное сопряжение через loopback).

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

### Роль рабочего процесса и закрытый протокол

Облачные рабочие процессы используют выделенный локальный вход через принадлежащий Gateway
SSH-туннель с закреплённым ключом хоста. Он принимает только идентификационные данные рабочего процесса и никогда не направляет
общую аутентификацию, события узлов, RPC оператора или методы плагинов. Строгий `connect`
проверяет хранимую в виде хеша краткосрочную учётную информацию, привязанную к среде, хешу
пакета, эпохе владельца, версии набора RPC, сроку действия и одному допускающему значение null сеансу; он
отдельно проверяет текущую версию и набор возможностей. При успехе возвращается минимальный
`worker-hello-ok`; согласование возможностей не зависит от общей версии
протокола. Размер кадров остаётся меньше 64 КиБ, за исключением согласованного кадра `worker.inference.start`,
размер которого может достигать 25 МиБ. Закрытый список разрешений содержит `worker.heartbeat`,
`worker.transcript.commit`, `worker.live-event`, `worker.inference.start` и
`worker.inference.cancel`.

Фиксация транскриптов использует ограждение по эпохе владельца, принадлежащую Gateway привязку сеанса,
compare-and-swap базового листа и устойчивое повторное воспроизведение последовательности; Gateway создаёт
идентификаторы записей транскрипта и родительских записей через обычный модуль записи сеансов. Владение и
срок действия повторно проверяются при каждом RPC.

### Возможности клиента

Клиенты оператора могут объявлять необязательные возможности в `connect.params.caps`:

- `tool-events`: принимает структурированные события жизненного цикла инструментов.
- `inline-widgets`: может отображать результаты инструментов в размещённых встроенных виджетах.

Возможности клиента описывают подключённый клиент, а не авторизацию. Инструменты агента могут объявлять обязательные возможности; Gateway исключает такие инструменты, если в `caps` исходного клиента отсутствует хотя бы одно требование. У запусков, инициированных каналом, нет возможностей клиента Gateway, поэтому инструменты с ограничением по возможностям недоступны, даже если политика инструментов явно разрешает их.

### Пример подключения узла

```json
{
  "type": "req",
  "id": "…",
  "method": "connect",
  "params": {
    "minProtocol": 4,
    "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": "…"
    }
  }
}
```

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

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

Gateway рассматривает их как заявки и применяет списки разрешений на стороне сервера.

## Роли и области доступа

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

Роли:

- `operator`: клиент плоскости управления (CLI/интерфейс/автоматизация).
- `node`: узел предоставления возможностей (камера/экран/холст/system.run).
- `worker`: узел облачного выполнения в выделенном закрытом протоколе рабочих процессов.

Области доступа оператора (`src/gateway/operator-scopes.ts`), полный закрытый набор:

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

`talk.config` с `includeSecrets: true` требует `operator.talk.secrets` (или
`operator.admin`). Если включены секреты, читайте учётные данные активного провайдера Talk
из `talk.resolved.config.apiKey`; `talk.providers.<id>.apiKey`
сохраняет исходную форму и может быть объектом SecretRef или отредактированной строкой.

Зарегистрированные плагинами методы RPC Gateway могут запрашивать собственную область доступа оператора,
но следующие зарезервированные префиксы ядра всегда разрешаются в `operator.admin`
(`src/shared/gateway-method-policy.ts`): `config.*`, `exec.approvals.*`,
`wizard.*`, `update.*`.

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

Для `node.pair.approve` поверх базовой области доступа метода
(`operator.pairing`) выполняется дополнительная проверка области доступа во время одобрения на основе объявленного
`commands` ожидающего запроса (`src/infra/node-pairing-authz.ts`):

| Объявленные команды                                            | Требуемые области доступа               |
| -------------------------------------------------------------- | ------------------------------------- |
| нет                                                            | `operator.pairing`                    |
| команды, не связанные с выполнением                            | `operator.pairing` + `operator.write` |
| включает `system.run`, `system.run.prepare` или `system.which` | `operator.pairing` + `operator.admin` |

### Caps/commands/permissions (узел)

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

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

Gateway рассматривает их как **заявки** и применяет списки разрешений на стороне сервера.
Подключённые узлы могут публиковать необязательные видимые агенту дескрипторы инструментов плагинов или MCP
с помощью `node.pluginTools.update` после успешного подключения или
повторного подключения. Хосты безголовых узлов перезапускаются для применения изменений декларативного инвентаря MCP.
Этот метод обновления — единственный путь публикации; дескрипторы инструментов плагинов не принимаются в
параметрах `connect`. Каждый дескриптор должен использовать безопасный для провайдера `name` инструмента и указывать
`command` из текущего списка разрешённых команд узла. Gateway доверяет метаданным
дескрипторов от сопряжённого узла, отфильтровывает дескрипторы за пределами одобренной поверхности команд,
удаляет их при отключении узла и отклоняет попытки оператора
изменить каталог другого узла. Установите `gateway.nodes.pluginTools.enabled: false`,
чтобы игнорировать опубликованные узлами дескрипторы.

Подключённые хосты узлов публикуют полный каталог замещающих навыков через
`node.skills.update`. Этот метод роли узла — единственный способ публикации навыков
узла; навыки не принимаются в параметрах `connect`. Каждый дескриптор содержит
безопасное имя, описание и содержимое `SKILL.md` ограниченного размера. Gateway анализирует это
содержимое с помощью стандартного загрузчика навыков, включает его в снимки навыков агента,
пока узел подключён, и удаляет при отключении. Установите
`gateway.nodes.skills.enabled: false`, чтобы игнорировать навыки, опубликованные узлами.

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

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

Нативные узлы macOS также могут отправлять аутентифицированные события `node.presence.activity`
с ограниченным временем бездействия ввода. Gateway вычисляет временные метки активности по
собственным часам, предоставляет самый недавно активный подключённый Mac через `node.list` и
`node.describe` и транслирует обновления `node.presence` клиентам с областью доступа на чтение.
Сведения о выборе, конфиденциальности, контексте модели и маршрутизации
уведомлений см. в разделе [Присутствие активного компьютера](/nodes/presence).

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

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

```json
{
  "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`. Неизвестные значения нормализуются в
`background` (`src/shared/node-presence.ts`). Событие сохраняется только для
аутентифицированных сеансов устройств-узлов; сеансы без устройства или без сопряжения возвращают
`handled: false`.

При успешном выполнении Gateway возвращает структурированный результат:

```json
{
  "ok": true,
  "event": "node.presence.alive",
  "handled": true,
  "reason": "persisted"
}
```

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

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

Широковещательные события, отправляемые сервером, ограничиваются областями доступа, чтобы сеансы
только для сопряжения или узлов не получали пассивно содержимое сеансов
(`src/gateway/server-broadcast.ts`):

- Кадры чата, агента и результатов инструментов (потоковые события `agent`, события
  результатов инструментов) требуют как минимум `operator.read`. Сеансы без этой области доступа полностью
  пропускают такие кадры.
- Широковещательные события `plugin.*`, определённые плагинами, по умолчанию ограничиваются
  `operator.write` или `operator.admin`; явные записи, такие как
  `plugin.approval.requested` / `plugin.approval.resolved`, вместо этого используют
  `operator.approvals`.
- События состояния и транспорта (`heartbeat`, `presence`, `tick`, жизненный цикл
  подключения и отключения) остаются неограниченными, чтобы состояние транспорта было доступно
  каждому аутентифицированному сеансу.
- Неизвестные семейства широковещательных событий по умолчанию ограничиваются областями доступа
  (отказ по умолчанию), если зарегистрированный обработчик явно не ослабляет ограничения.

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

## Семейства методов RPC

`hello-ok.features.methods` — консервативный список обнаружения, сформированный из
`src/gateway/server-methods-list.ts` и экспортируемых методов загруженных плагинов и каналов,
а не автоматически созданный перечень всех методов; некоторые методы (например,
`push.test`, `web.login.start`, `web.login.wait`, `sessions.usage`)
намеренно исключены из обнаружения, хотя являются реальными доступными для вызова
методами. Используйте этот список для обнаружения возможностей, а не как полный перечень
`src/gateway/server-methods/*.ts`.

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

  </Accordion>

  <Accordion title="Модели и использование">
    - `models.list` возвращает каталог моделей, разрешённых во время выполнения. См. «Представления `models.list`» ниже.
    - `usage.status` возвращает сводки окон использования и оставшейся квоты провайдеров.
    - `usage.cost` возвращает агрегированные сводки расходов за диапазон дат. Передайте `agentId` для одного агента или `agentScope: "all"`, чтобы агрегировать настроенных агентов.
    - `doctor.memory.status` возвращает готовность векторной памяти и кэшированных вложений для активной рабочей области агента по умолчанию. Передавайте `{ "probe": true }` или `{ "deep": true }` только для явной оперативной проверки связи с провайдером вложений. Передайте `{ "agentId": "agent-id" }`, чтобы ограничить статистику хранилища Dreaming одной рабочей областью агента; если параметр не указан, агрегируются настроенные рабочие области Dreaming.
    - `doctor.memory.dreamDiary`, `doctor.memory.backfillDreamDiary`, `doctor.memory.resetDreamDiary`, `doctor.memory.resetGroundedShortTerm`, `doctor.memory.repairDreamingArtifacts` и `doctor.memory.dedupeDreamDiary` принимают необязательный `{ "agentId": "agent-id" }`; если он не указан, они работают с настроенной рабочей областью агента по умолчанию.
    - `doctor.memory.remHarness` возвращает ограниченный предварительный просмотр REM, доступный только для чтения, для удалённых клиентов плоскости управления, включая пути рабочих областей, фрагменты памяти, отрисованный обоснованный Markdown и кандидатов на глубокое продвижение. Требует `operator.read`.
    - `sessions.usage` возвращает сводки использования по сеансам. Передайте `agentId` для одного агента или `agentScope: "all"`, чтобы получить совместный список настроенных агентов.
      Оба метода использования принимают `mode: "specific"` с часовым поясом IANA `timeZone` для границ и интервалов календарных дней с учётом перехода на летнее время. `utcOffset` по-прежнему поддерживается для старых клиентов и как резервный вариант, когда среда выполнения Gateway не распознаёт запрошенный часовой пояс.
    - `sessions.usage.timeseries` возвращает временной ряд использования для одного сеанса.
    - `sessions.usage.logs` возвращает записи журнала использования для одного сеанса.

  </Accordion>

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

  </Accordion>

  <Accordion title="Управление плагинами">
    - `plugins.list` (`operator.read`) возвращает перечень установленных плагинов, а также локально отобранные официальные варианты, диагностику и сведения о том, допускает ли текущий режим установки изменения.
    - `plugins.search` (`operator.read`) выполняет поиск доступных для установки семейств плагинов кода и плагинов-пакетов ClawHub. Передайте непустой `query` и необязательный `limit` от 1 до 100.
    - `plugins.install` (`operator.admin`) устанавливает либо официальную запись каталога с `{ source: "official", pluginId }`, либо пакет ClawHub с `{ source: "clawhub", packageName, version?, acknowledgeClawHubRisk? }`. При установке из ClawHub сохраняются проверки доверия Gateway, целостности и политики установки. После успешной установки требуется перезапуск Gateway.
    - `plugins.setEnabled` (`operator.admin`) изменяет политику включения одного установленного плагина с помощью `{ pluginId, enabled }`. Ответ включает обновлённую запись каталога, метаданные перезапуска и предупреждения о выборе слота.
    - `plugins.uninstall` (`operator.admin`) удаляет один внешний установленный плагин с помощью `{ pluginId }`: ссылки в конфигурации, запись установки и управляемые файлы. Поставляемые в комплекте плагины нельзя удалить — их можно только отключить. В ответе перечисляются действия удаления, и всегда требуется перезапуск Gateway.

  </Accordion>

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

  </Accordion>

  <Accordion title="Терминал оператора">
    - `terminal.open` запускает PTY хоста для явно указанного `agentId` или агента по умолчанию и возвращает разрешённого агента, рабочий каталог, оболочку и состояние изоляции.
    - `terminal.input`, `terminal.resize` и `terminal.close` работают только с сеансами, принадлежащими вызывающему подключению.
    - События `terminal.data` и `terminal.exit` передаются только подключению, которому принадлежит сеанс.
    - Сеансы, подключение которых прервано, отсоединяются, но не завершаются: они остаются доступными для повторного подключения в течение `gateway.terminal.detachedSessionTimeoutSeconds` (по умолчанию 300; `0` восстанавливает завершение при отключении), а недавний вывод накапливается в серверном буфере ограниченного размера.
    - `terminal.list` возвращает доступные для подключения сеансы; `terminal.attach` перепривязывает активный или отсоединённый сеанс к вызывающему подключению и возвращает буфер воспроизведения (перехват в стиле tmux — предыдущий активный владелец получает `terminal.exit` с причиной `detached`); `terminal.text` считывает буфер как обычный текст без подключения.
    - Каждый метод терминала требует `operator.admin`; `gateway.terminal.enabled` должен быть явно установлен в true. Полностью изолированным агентам доступ запрещён, а изменение политики агента закрывает существующие и запускаемые PTY, включая отсоединённые.

  </Accordion>

  <Accordion title="Разговор и TTS">
    - `talk.catalog` возвращает доступный только для чтения каталог провайдеров Talk для синтеза речи, потоковой транскрипции и голосового взаимодействия в реальном времени: канонические идентификаторы провайдеров, псевдонимы реестра, метки, состояние конфигурации, необязательный результат `ready` уровня группы, доступные идентификаторы моделей и голосов, канонические режимы, транспорты, стратегии мозга, а также флаги аудио и возможностей реального времени — без возврата секретов провайдеров и изменения глобальной конфигурации. Текущие Gateway устанавливают `ready` после применения выбора провайдера среды выполнения; на более старых Gateway отсутствие этого значения следует считать признаком отсутствия проверки.
    - `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, активного провайдера, резервных провайдеров и состояние конфигурации провайдеров.
    - `tts.providers` возвращает доступный список провайдеров TTS.
    - `tts.enable` и `tts.disable` переключают состояние настроек TTS.
    - `tts.setProvider` обновляет предпочтительного провайдера TTS.
    - `tts.convert` выполняет однократное преобразование текста в речь.
    - `tts.speak` (`operator.write`) озвучивает непустое значение `text` с помощью настроенной общей цепочки провайдеров TTS и возвращает один целый аудиоклип непосредственно в виде `audioBase64`, а также метаданные `provider` и необязательные `outputFormat`, `mimeType` и `fileExtension`. В отличие от `tts.convert`, этот метод не возвращает локальный путь Gateway; в отличие от `talk.speak`, он не требует провайдера Talk. Для текста, превышающего `messages.tts.maxTextLength`, возвращается `INVALID_REQUEST`; при ошибках синтеза возвращается `UNAVAILABLE`.

  </Accordion>

  <Accordion title="Секреты, конфигурация, обновление и мастер настройки">
    - `secrets.reload` повторно разрешает активные SecretRef и заменяет состояние секретов среды выполнения только при полном успехе.
    - `secrets.resolve` разрешает назначения секретов целевым объектам команд для заданного набора команд и целей.
    - `config.get` возвращает текущий снимок конфигурации и его хеш.
    - `config.set` записывает проверенную конфигурацию.
    - `config.patch` объединяет частичное обновление конфигурации. Для замены массива с удалением существующих элементов необходимо указать затронутый путь в `replacePaths`; вложенные массивы внутри элементов массива используют пути `[]`, например `agents.list[].skills`.
    - `config.apply` проверяет и заменяет полную конфигурацию.
    - `config.schema` возвращает актуальные данные схемы конфигурации, используемые инструментами Control UI и CLI: схему, `uiHints`, версию, метаданные генерации, а также метаданные схем плагинов и каналов, если их можно загрузить. Данные включают метаданные `title` / `description` из тех же меток и справочных текстов, что и в пользовательском интерфейсе, включая ветви композиции вложенных объектов, подстановочных знаков, элементов массивов и `anyOf` / `oneOf` / `allOf`, если существует соответствующая документация полей.
    - `config.schema.lookup` возвращает данные поиска в области одного пути конфигурации: нормализованный путь, поверхностный узел схемы, соответствующую подсказку и `hintPath`, необязательный `reloadKind`, а также сводки непосредственных дочерних элементов для детализации в UI/CLI. `reloadKind` имеет одно из значений `restart`, `hot` или `none` (`src/config/schema.ts`) и соответствует планировщику перезагрузки конфигурации 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 из плоскости управления используют передачу управления отдельной управляемой службе вместо замены дерева пакетов или изменения рабочей копии и результатов сборки внутри работающего Gateway. Запущенная передача управления возвращает `ok: true` с `result.reason: "managed-service-handoff-started"` и `handoff.status: "started"`; недоступная или неудачная передача возвращает `ok: false` с `managed-service-handoff-unavailable` или `managed-service-handoff-failed`, а также `handoff.command`, если требуется ручное обновление через оболочку. Недоступность означает, что у OpenClaw отсутствует безопасная граница супервизора или постоянный идентификатор службы, например `OPENCLAW_SYSTEMD_UNIT` для systemd. Во время запущенной передачи управления индикатор перезапуска может кратковременно сообщать `stats.reason: "restart-health-pending"`; продолжение откладывается, пока CLI не проверит перезапущенный Gateway и не запишет окончательный индикатор `ok`.
    - `update.status` обновляет и возвращает последний индикатор перезапуска после обновления, включая версию, работающую после перезапуска, если она доступна.
    - `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` управляют файлами начальной настройки рабочего пространства, доступными агенту.
    - `audit.activity.list` возвращает версионированный журнал активности, содержащий только метаданные; `audit.list` остаётся совместимым RPC для запусков и инструментов.
    - `agents.workspace.list` и `agents.workspace.get` (`operator.read`) предоставляют доступное только для чтения постраничное содержимое каталога рабочего пространства агента клиентам из доверенной операторской области, описанной в разделе [Области операторов](/ru/gateway/operator-scopes). Запросы принимают только пути относительно рабочего пространства; чтение ограничено корнем рабочего пространства после разрешения реального пути (выходы через символические и жёсткие ссылки отклоняются), имеет ограничение размера и поддерживает только текст UTF-8 и распространённые типы изображений (base64). Ответы не раскрывают путь к рабочему пространству на хосте. В этом пространстве имён отсутствуют операции записи.
    - `tasks.list`, `tasks.get` и `tasks.cancel` предоставляют журнал задач Gateway клиентам SDK и оператора. См. раздел [RPC журнала задач](#task-ledger-rpcs) ниже.
    - `artifacts.list`, `artifacts.get` и `artifacts.download` предоставляют сводки и загрузки артефактов, полученных из расшифровок, для явно заданной области `sessionKey`, `runId` или `taskId`. Для запросов запусков и задач сервер определяет владеющий ими сеанс и возвращает только мультимедиа из расшифровок с соответствующим происхождением; для небезопасных или локальных URL-источников возвращается сообщение о неподдерживаемой загрузке вместо получения данных на стороне сервера.
    - `environments.list` и `environments.status` сохраняют обнаружение локальной среды Gateway и среды Node. Настроенные облачные рабочие процессы и постоянные записи, оставленные предыдущими профилями, добавляют метаданные `worker` с `providerId`, необязательным `leaseId`, `state`, `ageMs`, необязательным `idleMs` и `attachedSessionIds`. Состояния жизненного цикла рабочего процесса: `requested`, `provisioning`, `bootstrapping`, `ready`, `attached`, `idle`, `draining`, `destroying`, `destroyed`, `failed` и `orphaned`.
    - `environments.create` (`{ profileId, idempotencyKey }`) создаёт рабочую среду из настроенного профиля провайдера плагина; повторные попытки с тем же ключом используют существующую постоянную операцию. `environments.destroy` (`{ environmentId }`) запрашивает идемпотентное удаление постоянной рабочей среды. Оба метода требуют `operator.admin`, выполняют запись в плоскости управления и возвращают сводку среды в том же формате, что и ответы о состоянии.
    - `agent.identity.get` возвращает эффективную идентичность ассистента для агента или сеанса.
    - `agent.wait` ожидает завершения запуска и возвращает итоговый снимок состояния, если он доступен.

  </Accordion>

  <Accordion title="Управление сеансами">
    - `sessions.list` возвращает текущий индекс сеансов, включая метаданные `agentRuntime` для каждой строки, если настроен бэкенд среды выполнения агента. Когда включено размещение на облачных воркерах или существует устойчивое состояние восстановления, строки сеансов также содержат закрытое состояние `placement` (`local`, `requested`, `provisioning`, `syncing`, `starting`, `active`, `draining`, `reconciling`, `reclaimed` или `failed`), а также зависящие от состояния поля окружения, эпохи владельца, рабочей области, пакета, курсора ACK или восстановления.
    - `sessions.subscribe` и `sessions.unsubscribe` включают и отключают подписки текущего клиента WS на события изменения сеансов.
    - `sessions.messages.subscribe` и `sessions.messages.unsubscribe` включают и отключают подписки на события расшифровки и сообщений для одного сеанса. Передайте `includeApprovals: true`, чтобы также получать санитизированные события жизненного цикла `session.approval` для подтверждений, сохранённая аудитория которых включает именно этот сеанс, а привязка проверяющего авторизует подписывающегося клиента. В таком случае ответ на подписку включает ограниченный список ожидающих элементов `approvalReplay`; он является авторитетным, когда `truncated` имеет значение false. Согласие действует для каждого отдельного вызова подписки и не сохраняется: повторная подписка на тот же сеанс без `includeApprovals: true` удаляет существующую подписку на подтверждения. Помимо обычных полномочий на чтение сеанса, для этого согласия требуется `operator.admin` или `operator.approvals` на сопряжённом устройстве.
    - `sessions.preview` возвращает ограниченные предварительные представления расшифровок для указанных ключей сеансов.
    - `sessions.describe` возвращает одну строку сеанса Gateway для точного ключа сеанса.
    - `sessions.resolve` разрешает или канонизирует целевой сеанс.
    - `sessions.create` создаёт новую запись сеанса. `worktree: true` подготавливает управляемое рабочее дерево; необязательные `worktreeBaseRef`/`worktreeName` выбирают базовую ссылку и имя ветки, а `execNode` (`operator.admin`) привязывает выполнение команд сеанса к хосту Node. Созданное рабочее дерево возвращается в результате и сохраняется в строке сеанса (`worktree: { id, branch, repoRoot }`). Если запись создана, но вложенный исходный `chat.send` отклонён, успешный результат включает `runStarted: false` и `runError`; клиенты могут сохранить запрос и повторить попытку с возвращённым ключом сеанса.
    - `sessions.dispatch` (`operator.admin`) перемещает существующий локальный сеанс OpenClaw с принадлежащим сеансу управляемым рабочим деревом в настроенный профиль облачного воркера. Передайте `{ key, profileId, agentId? }`. Метод отсутствует, если профиль воркера не настроен, закрывает локальный допуск новых ходов перед завершением активной работы и возвращает результат только после того, как размещение достигнет владения воркером `active`. Отправка является односторонней; возврат с воркера в локальную среду не входит в этот RPC.
    - `sessions.groups.list`, `sessions.groups.put`, `sessions.groups.rename` и `sessions.groups.delete` управляют принадлежащим Gateway каталогом пользовательских групп сеансов (имена и порядок отображения). Принадлежность к группе хранится в поле `category` каждого сеанса; при переименовании и удалении сервер обновляет входящие в группу сеансы.
    - `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` нормализуется для отображения в клиентах пользовательского интерфейса: встроенные теги директив удаляются из видимого текста, текстовые 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.toolTitles` возвращает краткие заголовки назначения для вызовов инструментов, отображаемых в Control UI (пакетно, не более 24 элементов с ограниченным объёмом входных данных). Функция включается явно через `gateway.controlUi.toolTitles` (по умолчанию отключена); отключённые Gateway отвечают `{ titles: {}, disabled: true }` без вызова модели, чтобы клиенты перестали отправлять запросы. Когда функция включена, для заголовков применяется стандартная маршрутизация вспомогательной модели: явно настроенный `utilityModel` (решение оператора, которое, как и для всех вспомогательных задач, может отправлять ограниченное содержимое задачи выбранному поставщику) либо объявленная поставщиком сеанса малая модель по умолчанию, чтобы неявно не появлялось новое направление исходящего трафика; пустой `utilityModel` полностью отключает заголовки. Для заголовков никогда не используется основная модель в качестве резервной. Результаты кэшируются в базе данных состояния каждого агента по ключу из имени инструмента и входных данных, поэтому повторные просмотры никогда не приводят к повторному выставлению счёта за те же вызовы.
    - `chat.send` принимает действующий в течение одного хода параметр `fastMode: "auto"`, чтобы использовать быстрый режим для вызовов модели, начатых до автоматического порога, а последующие повторные попытки, резервные вызовы, результаты инструментов или продолжения запускать без быстрого режима. По умолчанию порог составляет 60 секунд (`DEFAULT_FAST_MODE_AUTO_ON_SECONDS`) и может настраиваться для каждой модели с помощью `agents.defaults.models["<provider>/<model>"].params.fastAutoOnSeconds`. Вызывающий `chat.send` может передать действующий в течение одного хода параметр `fastAutoOnSeconds`, чтобы переопределить порог для этого запроса.

  </Accordion>

  <Accordion title="Сопряжение устройств и токены устройств">
    - `device.pair.list` возвращает ожидающие и одобренные сопряжённые устройства.
    - `device.pair.setupCode` создаёт код настройки мобильного устройства и по умолчанию URL данных PNG с QR-кодом. Для него требуется `operator.admin`, и он намеренно исключён из объявляемого обнаружения. Результат включает `setupCode`, необязательный `qrDataUrl`, `gatewayUrl`, несекретную метку `auth` и `urlSource`.
    - `device.pair.approve`, `device.pair.reject` и `device.pair.remove` управляют записями сопряжения устройств.
    - `device.pair.rename` назначает операторскую метку (`{ deviceId, label }`), которая имеет приоритет над отображаемым именем, сообщённым клиентом, и сохраняется после восстановления или повторного одобрения устройства.
    - `device.token.rotate` обновляет токен сопряжённого устройства в пределах его одобренной роли и области полномочий вызывающей стороны.
    - `device.token.revoke` отзывает токен сопряжённого устройства в пределах его одобренной роли и области полномочий вызывающей стороны.

    Код настройки содержит краткосрочные начальные учётные данные. Клиенты не должны
    регистрировать или сохранять их после завершения процесса сопряжения.

  </Accordion>

  <Accordion title="Сопряжение Node, вызовы и ожидающая работа">
    - `node.pair.list`, `node.pair.approve`, `node.pair.reject` и `node.pair.remove` охватывают подтверждения возможностей Node. `node.pair.request` и `node.pair.verify` были удалены в версии 2026.7 вместе с отдельным хранилищем сопряжений Node; ожидающие запросы создаются Gateway при подключении Node.
    - `node.list` и `node.describe` возвращают состояние известных и подключённых Node.
    - `node.rename` обновляет метку сопряжённого Node.
    - `node.invoke` перенаправляет команду подключённому Node.
    - `node.invoke.result` возвращает результат запроса вызова.
    - `mcp.tools.call.v1` — команда безголового хоста Node для вызова настроенного локального для Node инструмента MCP. Она передаётся через `node.invoke`, требует, чтобы Node объявил эту команду, и по-прежнему зависит от одобрения сопряжения и `gateway.nodes.denyCommands`.
    - `node.event` передаёт исходящие от Node события обратно в Gateway.
    - `node.pluginTools.update` — единственный путь публикации для замены видимых агенту дескрипторов плагинов и инструментов MCP подключённого Node; параметры `connect` их не передают.
    - `node.pending.pull` и `node.pending.ack` — API очереди подключённого Node.
    - `node.pending.enqueue` и `node.pending.drain` управляют устойчивой ожидающей работой для автономных или отключённых Node.

  </Accordion>

  <Accordion title="Семейства подтверждений">
    - `approval.get` и `approval.resolve` — устойчивые методы подтверждения, не зависящие от вида (область `operator.approvals`). `approval.get` возвращает санитизированную ожидающую или сохранённую конечную проекцию со стабильным `urlPath`; `approval.resolve` принимает канонический идентификатор подтверждения, явно заданный `kind` и решение, применяет разрешение по принципу «первый ответ имеет приоритет» и всегда возвращает записанный канонический результат.
    - `exec.approval.request`, `exec.approval.get`, `exec.approval.list` и `exec.approval.resolve` охватывают одноразовые запросы подтверждения выполнения, а также поиск и повторное воспроизведение ожидающих подтверждений. Они являются адаптерами на границе протокола над тем же устойчивым реестром подтверждений.
    - `exec.approval.waitDecision` ожидает одно подтверждение выполнения и возвращает окончательное решение (или `null` при истечении времени ожидания).
    - `exec.approvals.get` и `exec.approvals.set` управляют снимками политики подтверждения выполнения Gateway.
    - `exec.approvals.node.get` и `exec.approvals.node.set` управляют локальной для Node политикой подтверждения выполнения через ретранслируемые команды Node.
    - `plugin.approval.request`, `plugin.approval.list`, `plugin.approval.waitDecision` и `plugin.approval.resolve` охватывают определяемые плагинами процессы подтверждения.

  </Accordion>

  <Accordion title="Автоматизация, навыки и инструменты">
    - Автоматизация: `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`, чтобы клиенты могли отслеживать один поставленный в очередь ручной запуск без состояния гонки с другими записями истории для того же задания.
    - Навыки и инструменты: `commands.list`, `skills.*`, `tools.catalog`, `tools.effective`, `tools.invoke`. См. раздел [Вспомогательные методы оператора](#operator-helper-methods) ниже.

  </Accordion>
</AccordionGroup>

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

- `chat`: обновления чата в UI, такие как `chat.inject`, и другие события чата,
  относящиеся только к расшифровке. В протоколе v4 полезная нагрузка дельт содержит `deltaText`; `message`
  остаётся накопительным снимком ответа ассистента. Замены, не являющиеся префиксными,
  устанавливают `replace=true` и используют `deltaText` как текст замены.
- `session.message`, `session.operation`, `session.tool`: обновления расшифровки, выполняемой
  операции сеанса и потока событий для сеанса, на который оформлена подписка.
- `session.approval`: очищенное достоверное состояние ожидающих и завершённых согласований для
  подписчика точного сеанса, явно включившего эту возможность. Дочерние согласования используют
  сохранённую аудиторию предка; события никогда не изменяют расшифровки и не пробуждают агентов.
- `sessions.changed`: изменён индекс или метаданные сеанса.
- `presence`: обновления снимка присутствия системы.
- `tick`: периодическое событие поддержания соединения и проверки работоспособности.
- `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`: жизненный цикл
  согласования выполнения.
- `plugin.approval.requested` / `plugin.approval.resolved`: жизненный цикл
  согласования плагина.

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

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

## RPC журнала аудита

`audit.activity.list` предоставляет операторским клиентам стабильное представление метаданных жизненного цикла
запусков агентов, действий инструментов и сообщений с явным включением, упорядоченное от новых к старым. Для него требуется
`operator.read`. Запросы исключают записи старше 30 дней, а общий
журнал SQLite ограничен 100,000 записями. Просроченные строки удаляются при
запуске Gateway, во время ежечасного обслуживания и при последующих операциях записи. Модель данных
и семантику конфиденциальности см. в разделе [История аудита](/ru/gateway/audit).

- Параметры: необязательные точные `agentId`, `sessionKey` или `runId`; необязательный `kind`
  (`"agent_run"`, `"tool_action"` или `"message"`); необязательный `status`
  (`"started"`, `"succeeded"`, `"failed"`, `"cancelled"`, `"timed_out"`,
  `"blocked"` или `"unknown"`); необязательный `direction` сообщения (`"inbound"` или
  `"outbound"`) и точный `channel`; необязательные включительные границы `after` / `before`
  в миллисекундах Unix; необязательный `limit` от `1` до `500`; и необязательная
  строка `cursor` с предыдущей страницы.
- Результат: `{ "events": AuditActivityEventV1[], "nextCursor"?: string }`.

Именованное объединение результатов V1 содержит отдельные схемы запуска агента, действия инструмента,
входящего сообщения и исходящего сообщения. Дискриминатор `eventType` соответственно имеет значение
`agent_run`, `tool_action`, `inbound_message` или `outbound_message`; `kind` и
`direction` сообщения остаются доступными для фильтрации и отображения. Каждое событие содержит
целочисленный `schemaVersion: 1`. Ссылки на идентификаторы сообщений используют точный
формат `hmac-sha256:v1:<32 hex key id>:<64 hex digest>`; идентификатор субъекта-отправителя канала
использует тот же формат.

Для всех вариантов обязательны `eventType`, `schemaVersion`, `eventId`, `sequence`,
`sourceSequence`, `occurredAt`, `kind`, `action`, `status`, `actor` и
`redaction`. Поля вариантов:

| `eventType`        | Обязательные поля                                                  | Необязательные поля                                                                                                             |
| ------------------ | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `agent_run`        | `agentId`, `runId`; `kind: "agent_run"`                           | `sessionKey`, `sessionId`, `errorCode`                                                                                          |
| `tool_action`      | `agentId`, `runId`; `kind: "tool_action"`                         | `sessionKey`, `sessionId`, `toolCallId`, `toolName`, `errorCode`                                                                |
| `inbound_message`  | `direction: "inbound"`, `channel`, `conversationKind`, `outcome`  | `agentId`, `runId`, `durationMs`, `resultCount`, ссылки на идентификаторы, `reasonCode`, `errorCode`                     |
| `outbound_message` | `direction: "outbound"`, `channel`, `conversationKind`, `outcome` | `agentId`, `runId`, `durationMs`, `resultCount`, ссылки на идентификаторы, `reasonCode`, `deliveryKind`, `failureStage`, `errorCode` |

Закрытые перечисления сообщений:

- `conversationKind`: `direct`, `group`, `channel` или `unknown`.
- Входящий `outcome`: `completed`, `skipped` или `failed`; необязательный
  `reasonCode`: `duplicate`, `reply_operation_active`,
  `reply_operation_aborted`, `fast_abort`, `plugin_bound_handled`,
  `plugin_bound_unavailable`, `plugin_bound_declined`, `plugin_bound_error`,
  `before_dispatch_handled`, `acp_dispatch_completed`, `acp_dispatch_failed`,
  `acp_dispatch_empty` или `acp_dispatch_aborted`.
- Исходящий `outcome`: `sent`, `suppressed`, `failed` или `unknown`; необязательный
  `reasonCode`: `cancelled_by_message_sending_hook`,
  `cancelled_by_reply_payload_sending_hook`,
  `empty_after_message_sending_hook`, `empty_after_reply_payload_sending_hook`
  или `no_visible_payload`. Адаптер, не возвращающий идентификатор платформы, имеет значение
  `unknown`, поскольку внешнее побочное действие невозможно опровергнуть.
- `deliveryKind`: `text`, `media` или `other`; `failureStage`:
  `platform_send`, `queue` или `unknown`.

Терминальные поля взаимосвязаны, а не являются независимо необязательными:

| Вариант          | Сопоставление терминального состояния                                                                                                                             |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Запуск агента    | `started` не имеет `errorCode`; для каждого завершённого состояния, отличного от успешного, требуется соответствующий код `run_*`.       |
| Действие инструмента | `started` и успешное состояние не имеют `errorCode`; для каждого другого завершённого состояния требуется соответствующий код `tool_*`. |
| Входящее сообщение  | успешное = `completed`; заблокированное = `skipped`; неудачное = `failed` плюс `message_processing_failed`. `reasonCode`, если присутствует, должен относиться к этому семейству терминальных состояний. |
| Исходящее сообщение | успешное = `sent`; заблокированное = `suppressed` плюс `reasonCode`; неудачное = `failed` плюс `errorCode` и `failureStage`; неизвестное = `unknown` плюс `failureStage`. |

Каждое событие активности содержит стабильный идентификатор события, монотонную последовательность журнала,
последовательность исходного события, метку времени, субъекта, действие, состояние, целочисленный
`schemaVersion: 1` и `redaction: "metadata_only"`. Для записей запусков и инструментов
обязательны сведения о происхождении агента и запуска; также они могут содержать сведения о происхождении сеанса. Записи
сообщений могут содержать идентификаторы агента и запуска, но намеренно никогда не содержат
`sessionKey` или `sessionId`; поэтому фильтр запроса `sessionKey` применяется
только к строкам запусков и инструментов. События инструментов могут содержать идентификатор вызова и имя инструмента.

Записи сообщений используют `message.inbound.processed` или
`message.outbound.finished` и добавляют направление, канал, вид беседы,
нормализованный результат и необязательные вид доставки, этап сбоя, длительность,
количество результатов, код причины, а также псевдонимы учётной записи, беседы, сообщения и цели,
локально хешированные для установки с ключом. Эти псевдонимы помогают
сопоставлению, но не обеспечивают анонимизацию: база данных состояния содержит их ключ,
а экспорт через RPC и CLI — нет. Журнал не хранит запросы к модели, содержимое сообщений,
аргументы и результаты инструментов, вывод команд или необработанный текст ошибок.
Значения `sessionKey` запусков и инструментов остаются необработанными метаданными сопоставления и могут содержать
идентификаторы учётных записей или собеседников на платформе; записи сообщений не содержат ключей сеансов.

Для входящих строк `durationMs` измеряет время от диспетчеризации в ядре до терминального состояния, а
`resultCount` подсчитывает окончательно сформированные полезные нагрузки поставленных в очередь инструментов, блокировок и ответов. Для
исходящих строк `durationMs` охватывает период от принятия доставки во владение до подтверждения,
перемещения в очередь необрабатываемых сообщений или сверки (включая время ожидания в очереди), а `resultCount`
подсчитывает идентифицированные физические отправки на платформу. `deliveryKind`, если присутствует,
описывает фактическую полезную нагрузку после хуков и отрисовки; в подавленных или
неоднозначных из-за сбоя строках это поле отсутствует.

Текущий охват сообщений включает принятые входящие сообщения, дошедшие до
диспетчеризации в ядре, включая результаты обработки дубликатов и терминальные результаты ядра. Для исходящего потока записывается
одна терминальная строка на каждую исходную логическую полезную нагрузку ответа, дошедшую до общей устойчивой
доставки; разбиение на части и разветвление адаптера агрегируются в `resultCount`. Поставленные в очередь
повторяемые или неоднозначные отправки записываются только после подтверждения, перемещения
в очередь необрабатываемых сообщений или сверки. Локальные для плагина пути и пути прямой отправки, обходящие эти
общие границы, пока не охвачены. Ограниченная очередь обработчика работает по принципу максимальных усилий
и может терять записи при сбое или насыщении, поэтому эта поверхность не является
полным архивом для соблюдения нормативных требований.

Запись включена по умолчанию и управляется параметром
[`audit.enabled`](/ru/gateway/configuration-reference#audit). Запись сообщений
управляется отдельно параметром `audit.messages`, значение по умолчанию — `"off"`. Когда
запись отключена, `audit.activity.list` продолжает возвращать ранее записанные данные,
пока не истечёт срок их хранения.

Поставляемые схемы запроса, результата и `AuditEvent` для `audit.list`
остаются неизменными и возвращают только записи запусков агентов и действий инструментов. Новым операторским
клиентам следует вызывать `audit.activity.list`, когда Gateway объявляет его поддержку. Старые
версии Gateway могут вернуть запросу с областью чтения либо `unknown method: audit.activity.list`, либо, поскольку
в поставляемых версиях авторизация предшествовала поиску метода, `missing scope:
operator.admin`. Считайте последнее отсутствием метода
только в том случае, если метод не был объявлен. После этого клиент может повторить запрос через `audit.list`
только тогда, когда его фильтрам не требуется поддержка вида сообщения, направления или канала.

Используйте [`openclaw audit`](/ru/cli/audit) для текстовых запросов и ограниченного экспорта JSON.

## RPC журнала задач

Операторские клиенты просматривают и отменяют фоновые задачи Gateway через
RPC журнала задач (`packages/gateway-protocol/src/schema/tasks.ts`). Они
возвращают очищенные сводки задач, а не необработанное состояние среды выполнения.

- `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 «не найдено».
- `tasks.cancel` требует `operator.write`.
  - Параметры: `{ "taskId": string, "reason"?: string }`.
  - Результат: `{ "found": boolean, "cancelled": boolean, "reason"?: string, "task"?: TaskSummary }`.
  - `found` сообщает, содержал ли реестр соответствующую задачу. `cancelled`
    сообщает, приняла или зарегистрировала ли среда выполнения отмену.

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

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

- `commands.list` (`operator.read`) получает список команд среды выполнения для
  агента.
  - `agentId` необязателен; не указывайте его, чтобы прочитать рабочую область агента по умолчанию.
  - `scope` определяет, для какой поверхности предназначен основной `name`: `text` возвращает
    основной текстовый токен команды без начального `/`; `native` и
    путь по умолчанию `both` возвращают нативные имена с учётом провайдера, если они доступны.
  - `textAliases` содержит точные псевдонимы со слешем, например `/model` и `/m`.
  - `nativeName` содержит нативное имя команды с учётом провайдера, если оно
    существует.
  - `provider` необязателен и влияет только на нативное именование и доступность нативных команд
    плагина.
  - `includeArgs=false` исключает из ответа сериализованные метаданные аргументов.
- `tools.catalog` (`operator.read`) получает каталог инструментов среды выполнения для
  агента. Ответ включает сгруппированные инструменты и метаданные происхождения:
  - `source`: `core` или `plugin`
  - `pluginId`: плагин-владелец, когда `source="plugin"`
  - `optional`: является ли инструмент плагина необязательным
- `tools.effective` (`operator.read`) получает фактический список инструментов среды
  выполнения для сеанса.
  - `sessionKey` обязателен.
  - Gateway получает доверенный контекст среды выполнения из сеанса на стороне сервера,
    а не принимает предоставленный вызывающей стороной контекст аутентификации или доставки.
  - Ответ представляет собой сформированную сервером проекцию активного
    списка в рамках сеанса, включая основные инструменты, инструменты плагинов и каналов, а также уже обнаруженные инструменты
    серверов 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`.
  - Доступные только владельцу основные обёртки, такие как `cron`, `gateway` и `nodes`, требуют
    идентификацию владельца или администратора (`operator.admin`), хотя сам `tools.invoke`
    является `operator.write`.
  - Ответ представляет собой предназначенный для SDK конверт с полями `ok`, `toolName`, необязательным
    `output` и типизированными полями `error`. Отказы в одобрении или по политике возвращают
    `ok:false` в полезной нагрузке, не обходя конвейер политики инструментов
    Gateway.
- `skills.status` (`operator.read`) получает список видимых Skills для
  агента.
  - `agentId` необязателен; не указывайте его, чтобы прочитать рабочую область агента по умолчанию.
  - Ответ включает сведения о соответствии требованиям, недостающих требованиях, проверках конфигурации
    и очищенных вариантах установки без раскрытия исходных значений секретов.
- `skills.search` и `skills.detail` (`operator.read`) возвращают метаданные
  обнаружения ClawHub.
- `skills.upload.begin`, `skills.upload.chunk` и `skills.upload.commit`
  (`operator.admin`) подготавливают частный архив Skills перед его установкой. Это
  отдельный административный путь загрузки для доверенных клиентов, а не обычный процесс
  установки Skills из ClawHub; по умолчанию он отключён, если только
  не включён `skills.install.allowUploadedArchives`.
  - `skills.upload.begin({ kind: "skill-archive", slug, sizeBytes, sha256?, force?, idempotencyKey? })`
    создаёт загрузку, привязанную к этому идентификатору и значению принудительной установки.
  - `skills.upload.chunk({ uploadId, offset, dataBase64 })` добавляет байты с
    точного декодированного смещения.
  - `skills.upload.commit({ uploadId, sha256? })` проверяет итоговый размер и
    SHA-256. Фиксация лишь завершает загрузку; она не устанавливает Skills.
  - Загружаемые архивы Skills представляют собой ZIP-архивы с корнем `SKILL.md`. Имя внутреннего
    каталога архива никогда не определяет цель установки.
- `skills.install` (`operator.admin`) имеет три режима:
  - Режим ClawHub: `{ source: "clawhub", slug, version?, force? }` устанавливает
    папку Skills в каталог `skills/` рабочей области агента по умолчанию.
  - Режим загрузки: `{ source: "upload", uploadId, slug, force?, sha256?, timeoutMs? }`
    устанавливает зафиксированную загрузку в каталог
    `skills/<slug>` рабочей области агента по умолчанию. Идентификатор и значение принудительной установки должны совпадать с
    исходным запросом `skills.upload.begin`. Запрос отклоняется, если
    не включён `skills.install.allowUploadedArchives`; эта настройка не
    влияет на установки из ClawHub.
  - Режим установщика Gateway: `{ name, installId, timeoutMs? }` выполняет объявленное
    действие `metadata.openclaw.install` на хосте Gateway. Старые клиенты всё ещё могут
    отправлять `dangerouslyForceUnsafeInstall`; это поле устарело,
    принимается только для совместимости протокола и игнорируется. Используйте
    `security.installPolicy` для решений об установке, принимаемых оператором.
- `skills.update` (`operator.admin`) имеет два режима:
  - Режим ClawHub обновляет один отслеживаемый идентификатор или все отслеживаемые установки ClawHub в
    рабочей области агента по умолчанию.
  - Режим конфигурации изменяет значения `skills.entries.<skillKey>`, такие как `enabled`,
    `apiKey` и `env`.

### Представления `models.list`

`models.list` принимает необязательный параметр `view`
(`src/agents/model-catalog-visibility.ts`):

- Не указан или `"default"`: если настроен `agents.defaults.models`,
  ответ представляет разрешённый каталог, включая динамически обнаруженные модели
  для записей `provider/*`. В противном случае ответ представляет полный каталог
  Gateway.
- `"configured"`: поведение с объёмом данных, подходящим для средства выбора. Если настроен `agents.defaults.models`,
  он по-прежнему имеет приоритет, включая обнаружение в рамках провайдера для
  записей `provider/*`. При отсутствии списка разрешений ответ использует явные
  записи `models.providers.<provider>.models`, переходя к полному
  каталогу, только если настроенные строки моделей отсутствуют.
- `"provider-config"`: сформированный источником список `models.providers.*.models`,
  не зависящий от списков разрешений средства выбора. Строки включают общедоступные возможности моделей и
  доступность с учётом маршрута, но не содержат конечные точки провайдеров, данные аутентификации и
  конфигурацию запросов среды выполнения.
- `"all"`: полный каталог Gateway в обход `agents.defaults.models`. Используйте для
  интерфейсов диагностики и обнаружения, а не для обычных средств выбора моделей.

## Одобрения выполнения

- Когда запрос выполнения требует одобрения, Gateway рассылает
  `exec.approval.requested`.
- Клиенты оператора разрешают запрос, вызывая `exec.approval.resolve` (требуется
  `operator.approvals`).
- Для `host=node` объект `exec.approval.request` должен включать `systemRunPlan`
  (канонические метаданные `argv`/`cwd`/`rawCommand`/сеанса). Запросы без
  `systemRunPlan` отклоняются.
- После одобрения перенаправленные вызовы `node.invoke system.run` повторно используют этот
  канонический `systemRunPlan` как авторитетный контекст команды, текущего рабочего каталога и сеанса.
- Если вызывающая сторона изменяет `command`, `rawCommand`, `cwd`, `agentId` или
  `sessionKey` между подготовкой и окончательным перенаправлением одобренного `system.run`,
  Gateway отклоняет выполнение, а не доверяет изменённой полезной нагрузке.

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

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

## Управление версиями

- `PROTOCOL_VERSION`, `MIN_CLIENT_PROTOCOL_VERSION`,
  `MIN_NODE_PROTOCOL_VERSION` и `MIN_PROBE_PROTOCOL_VERSION` находятся в
  `packages/gateway-protocol/src/version.ts`.
- Клиенты отправляют `minProtocol` + `maxProtocol`. Клиенты оператора и интерфейса должны
  включать текущий протокол в этот диапазон; текущие клиенты и серверы используют
  протокол v4.
- Аутентифицированные клиенты, имеющие и `role: "node"`, и `client.mode: "node"`,
  могут использовать протокол Node версии N-1 (сейчас v3). Упрощённые проверки перезапуска используют
  то же окно N-1. Это окно совместимости не изменяет аутентификацию устройств, сопряжение, области действия, политику команд и одобрения
  выполнения. Возможности и команды Node, принадлежащие плагинам,
  остаются недоступными, пока Node не обновится до текущего
  протокола, поскольку размещаемые ими поверхности не входят в контракт N-1.
- Схемы и модели генерируются из определений TypeBox:
  - `pnpm protocol:gen`
  - `pnpm protocol:gen:swift`
  - `pnpm protocol:check`

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

Эталонная реализация клиента находится в `packages/gateway-client/src/`
(OpenClaw оборачивает её тонким фасадом `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`                                                                                |
| `MIN_NODE_PROTOCOL_VERSION`               | `3`                                                   | `packages/gateway-protocol/src/version.ts`                                                                                |
| `MIN_PROBE_PROTOCOL_VERSION`              | `3`                                                   | `packages/gateway-protocol/src/version.ts`                                                                                |
| Тайм-аут запроса (для каждого RPC)                 | `30_000` мс                                           | `packages/gateway-client/src/client.ts` (`requestTimeoutMs`)                                                              |
| Тайм-аут предварительной аутентификации / запроса подключения       | `15_000` мс                                           | `packages/gateway-client/src/timeouts.ts` (переменная окружения `OPENCLAW_HANDSHAKE_TIMEOUT_MS` может увеличить общий бюджет сервера и клиента) |
| Начальная задержка перед повторным подключением                 | `1_000` мс                                            | `packages/gateway-client/src/client.ts` (`GATEWAY_RECONNECT_POLICY`)                                                      |
| Максимальная задержка перед повторным подключением                     | `30_000` мс                                           | `packages/gateway-client/src/client.ts` (`GATEWAY_RECONNECT_POLICY`)                                                      |
| Ограничение задержки быстрой повторной попытки после закрытия из-за токена устройства | `250` мс                                              | `packages/gateway-client/src/client.ts`                                                                                   |
| Период ожидания перед принудительной остановкой `terminate()`     | `250` мс                                              | `FORCE_STOP_TERMINATE_GRACE_MS`                                                                                           |
| Тайм-аут `stopAndWait()` по умолчанию           | `1_000` мс                                            | `STOP_AND_WAIT_TIMEOUT_MS`                                                                                                |
| Интервал тактов по умолчанию (до `hello-ok`)    | `30_000` мс                                           | `packages/gateway-client/src/client.ts`                                                                                   |
| Закрытие по тайм-ауту такта                        | код `4000`, если период отсутствия активности превышает `tickIntervalMs * 2` | `packages/gateway-client/src/client.ts`                                                                                   |
| `MAX_PAYLOAD_BYTES`                       | `25 * 1024 * 1024` (25 МБ)                            | `src/gateway/server-constants.ts`                                                                                         |

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

Эталонный клиент позволяет конечным запросам использовать настроенный для них крайний срок, когда
он задан для каждого ожидающего запроса. Запрос `expectFinal` без конечного
`timeoutMs`, любой запрос с `timeoutMs: null` или сочетание конечных и
неограниченных запросов оставляет сторожевой таймер тактов активным. Если входящие события и
ответы отсутствуют дольше порогового значения тайм-аута такта, клиент закрывает
сокет с кодом `4000`, отклоняет все ожидающие запросы и повторно подключается. После
повторного подключения он не воспроизводит отклонённые запросы.

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

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

## Идентификация и сопряжение устройств

- Узлы должны включать стабильный идентификатор устройства (`device.id`), полученный из
  отпечатка пары ключей.
- Gateway выпускают токены для каждой комбинации устройства и роли.
- Для новых идентификаторов устройств требуется утверждение сопряжения, если не включено локальное
  автоматическое утверждение.
- Автоматическое утверждение сопряжения предназначено прежде всего для прямых локальных подключений через loopback.
- В OpenClaw также имеется узкоспециализированный путь самоподключения внутри серверной части или контейнера для
  доверенных вспомогательных потоков с общим секретом.
- Подключения с того же хоста через tailnet или LAN по-прежнему считаются удалёнными для целей сопряжения
  и требуют утверждения.
- Клиенты WS обычно включают идентификационные данные `device` во время `connect` (оператор +
  Node). Единственными исключениями для оператора без устройства являются явно доверенные пути:
  - `gateway.controlUi.allowInsecureAuth=true` для небезопасной совместимости по HTTP,
    доступной только с localhost.
  - успешная аутентификация оператора Control UI через `gateway.auth.mode: "trusted-proxy"`.
  - `gateway.controlUi.dangerouslyDisableDeviceAuth=true` (аварийный режим, значительное
    снижение уровня безопасности).
  - RPC серверной части через прямой loopback с `gateway-client` по зарезервированному внутреннему
    вспомогательному пути.
- Отсутствие идентификатора устройства влияет на области действия. Когда подключение
  оператора без устройства разрешено через явно доверенный путь, OpenClaw
  всё равно очищает самостоятельно объявленные области действия до пустого набора, если для этого пути не предусмотрено
  именованное исключение, сохраняющее области действия. Методы с проверкой областей действия затем завершаются ошибкой
  `missing scope`.
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true` — это аварийный путь Control UI
  с сохранением областей действия. Он не предоставляет области действия произвольным
  пользовательским клиентам серверной части или WebSocket-клиентам, построенным по образцу CLI.
- Зарезервированный вспомогательный путь серверной части `gateway-client` через прямой loopback сохраняет
  области действия только для внутренних локальных RPC плоскости управления; пользовательские идентификаторы серверной части
  не получают этого исключения.
- Все подключения должны подписывать предоставленный сервером одноразовый параметр `connect.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`  | Клиент создал подпись с устаревшим/неверным одноразовым значением.            |
| `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, содержащую одноразовое значение сервера.
- Отправляйте то же одноразовое значение в `connect.params.device.nonce`.
- Предпочтительная полезная нагрузка подписи — `v3`
  (`buildDeviceAuthPayloadV3` в `packages/gateway-client/src/device-auth.ts`),
  которая дополнительно связывает `platform` и `deviceFamily`
  с полями устройства/клиента/роли/областей доступа/токена/одноразового значения.
- Устаревшие подписи `v2` по-прежнему принимаются для совместимости, однако закрепление
  метаданных сопряжённого устройства всё равно определяет политику команд при повторном подключении.

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

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

## Область действия

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

## См. также

- [Протокол моста](/ru/gateway/bridge-protocol)
- [Руководство по эксплуатации Gateway](/ru/gateway)
