Перейти к основному содержанию
Control UI — это небольшое одностраничное приложение на Vite + Lit, обслуживаемое Gateway:
  • по умолчанию: http://<host>:18789/
  • необязательный префикс: задайте gateway.controlUi.basePath (например, /openclaw)
Оно взаимодействует напрямую с Gateway WebSocket на том же порту.

Быстрое открытие (локально)

Если Gateway запущен на том же компьютере, откройте: Если страница не загружается, сначала запустите Gateway: openclaw gateway. Аутентификация передается во время рукопожатия WebSocket через:
  • connect.params.auth.token
  • connect.params.auth.password
  • заголовки идентификации Tailscale Serve, когда gateway.auth.allowTailscale: true
  • заголовки идентификации доверенного прокси, когда gateway.auth.mode: "trusted-proxy"
Панель настроек дашборда хранит токен для текущей сессии вкладки браузера и выбранного URL Gateway; пароли не сохраняются. Onboarding обычно создает токен Gateway для аутентификации с общим секретом при первом подключении, но аутентификация по паролю тоже работает, когда gateway.auth.mode равен "password".

Сопряжение устройства (первое подключение)

Когда вы подключаетесь к Control UI из нового браузера или с нового устройства, Gateway обычно требует одноразового подтверждения сопряжения. Это мера безопасности для предотвращения несанкционированного доступа. Что вы увидите: “disconnected (1008): pairing required”
1

Выведите список ожидающих запросов

openclaw devices list
2

Подтвердите по ID запроса

openclaw devices approve <requestId>
Если браузер повторяет сопряжение с измененными данными аутентификации (роль/области доступа/публичный ключ), предыдущий ожидающий запрос заменяется и создается новый requestId. Перед подтверждением повторно выполните openclaw devices list. Если браузер уже сопряжен и вы меняете доступ с чтения на доступ записи/администратора, это считается повышением подтверждения, а не тихим переподключением. OpenClaw сохраняет старое подтверждение активным, блокирует переподключение с более широкими правами и просит явно подтвердить новый набор областей доступа. После подтверждения устройство запоминается и не потребует повторного подтверждения, пока вы не отзовете его командой openclaw devices revoke --device <id> --role <role>. См. CLI устройств для ротации и отзыва токенов. Агенты Paperclip, подключающиеся через адаптер openclaw_gateway, используют тот же процесс подтверждения при первом запуске. После первой попытки подключения выполните openclaw devices approve --latest, чтобы просмотреть ожидающий запрос, затем повторно выполните напечатанную команду openclaw devices approve <requestId>, чтобы подтвердить его. Для удаленного Gateway передайте явные значения --url и --token. Чтобы подтверждения оставались стабильными между перезапусками, настройте постоянный adapterConfig.devicePrivateKeyPem в Paperclip вместо того, чтобы позволять ему создавать новую временную идентичность устройства при каждом запуске.
  • Прямые подключения браузера через local loopback (127.0.0.1 / localhost) подтверждаются автоматически.
  • Tailscale Serve может пропустить цикл сопряжения для операторских сессий Control UI, когда gateway.auth.allowTailscale: true, идентичность Tailscale проверена, а браузер предоставляет свою идентичность устройства.
  • Прямые привязки Tailnet, подключения браузера по LAN и профили браузера без идентичности устройства по-прежнему требуют явного подтверждения.
  • Каждый профиль браузера создает уникальный ID устройства, поэтому смена браузера или очистка данных браузера потребует повторного сопряжения.

Личная идентичность (локально в браузере)

Control UI поддерживает личную идентичность для каждого браузера (отображаемое имя и аватар), прикрепляемую к исходящим сообщениям для указания авторства в общих сессиях. Она хранится в хранилище браузера, ограничена текущим профилем браузера и не синхронизируется с другими устройствами и не сохраняется на стороне сервера, кроме обычных метаданных авторства транскрипта для сообщений, которые вы действительно отправляете. Очистка данных сайта или смена браузера сбрасывает ее в пустое состояние. Тот же локальный для браузера шаблон применяется к переопределению аватара ассистента. Загруженные аватары ассистента накладываются на идентичность, разрешенную Gateway, только в локальном браузере и никогда не проходят туда и обратно через config.patch. Общее поле конфигурации ui.assistant.avatar по-прежнему доступно для клиентов не из UI, которые записывают это поле напрямую (например, скриптовых Gateway или пользовательских дашбордов).

Эндпоинт runtime-конфигурации

Control UI получает свои runtime-настройки из /control-ui-config.json, разрешаемого относительно базового пути Control UI в Gateway (например, /__openclaw__/control-ui-config.json, когда UI обслуживается по /__openclaw__/). Этот эндпоинт защищен той же аутентификацией Gateway, что и остальная HTTP-поверхность: неаутентифицированные браузеры не могут получить его, а успешное получение требует либо уже действительного токена/пароля Gateway, идентичности Tailscale Serve, либо идентичности доверенного прокси.

Поддержка языков

Control UI может локализовать себя при первой загрузке на основе локали вашего браузера. Чтобы переопределить ее позже, откройте Обзор -> Доступ к Gateway -> Язык. Выбор локали находится в карточке «Доступ к Gateway», а не в разделе «Внешний вид».
  • Поддерживаемые локали: en, zh-CN, zh-TW, pt-BR, de, es, ja-JP, ko, fr, ar, it, tr, uk, id, pl, th, vi, nl, fa
  • Неанглийские переводы лениво загружаются в браузере.
  • Выбранная локаль сохраняется в хранилище браузера и повторно используется при будущих посещениях.
  • Отсутствующие ключи переводов возвращаются к английскому.
Переводы документации генерируются для того же набора неанглийских локалей, но встроенный в сайт документации выбор языка Mintlify ограничен кодами локалей, которые принимает Mintlify. Документация на тайском (th) и персидском (fa) все равно генерируется в publish-репозитории; она может не отображаться в этом выборе, пока Mintlify не начнет поддерживать эти коды.

Темы внешнего вида

Панель «Внешний вид» сохраняет встроенные темы Claw, Knot и Dash, а также один локальный для браузера слот импорта tweakcn. Чтобы импортировать тему, откройте редактор tweakcn, выберите или создайте тему, нажмите Поделиться и вставьте скопированную ссылку на тему в раздел «Внешний вид». Импортер также принимает URL реестра https://tweakcn.com/r/themes/<id>, URL редактора вида https://tweakcn.com/editor/theme?theme=amethyst-haze, относительные пути /themes/<id>, необработанные ID тем и имена тем по умолчанию, например amethyst-haze. Раздел «Внешний вид» также включает локальную для браузера настройку размера текста. Настройка хранится вместе с остальными предпочтениями Control UI, применяется к тексту чата, тексту компоновщика, карточкам инструментов и боковым панелям чата, а также сохраняет текстовые поля размером не менее 16px, чтобы мобильный Safari не выполнял автоматическое масштабирование при фокусе. Импортированные темы хранятся только в текущем профиле браузера. Они не записываются в конфигурацию Gateway и не синхронизируются между устройствами. Замена импортированной темы обновляет один локальный слот; ее очистка переключает активную тему обратно на Claw, если была выбрана импортированная тема.

Что он может делать (сегодня)

  • Общайтесь с моделью через Gateway WS (chat.history, chat.send, chat.abort, chat.inject).
  • Обновления истории чата запрашивают ограниченное недавнее окно с лимитами текста для каждого сообщения, чтобы большие сессии не заставляли браузер отрисовывать полный payload транскрипта до того, как чат станет пригодным для использования.
  • Разговаривайте через realtime-сессии браузера. OpenAI использует прямой WebRTC, Google Live использует ограниченный одноразовый браузерный токен через WebSocket, а backend-only realtime-голосовые plugins используют relay-транспорт Gateway. Сессии провайдера, принадлежащие клиенту, начинаются с talk.client.create; relay-сессии Gateway начинаются с talk.session.create. Relay хранит учетные данные провайдера на Gateway, пока браузер транслирует PCM с микрофона через talk.session.appendAudio, пересылает вызовы инструментов провайдера openclaw_agent_consult через talk.client.toolCall для политики Gateway и более крупной настроенной модели OpenClaw, а также маршрутизирует голосовое управление активным запуском через talk.client.steer или talk.session.steer.
  • Потоково отображайте вызовы инструментов и live-карточки вывода инструментов в чате (события агента).
  • Вкладка активности с локальными для браузера, ориентированными на редактирование секретов сводками live-активности инструментов из существующей доставки session.tool / событий инструментов.
  • Каналы: статус встроенных, а также bundled/external plugin channels, QR-вход и конфигурация для каждого канала (channels.status, web.login.*, config.patch).
  • Обновления проверок каналов сохраняют предыдущий снимок видимым, пока завершаются медленные проверки провайдеров, а частичные снимки помечаются, когда проверка или аудит превышает свой UI-бюджет.
  • Инстансы: список присутствия + обновление (system-presence).
  • Сессии: по умолчанию выводят список сессий настроенного агента, возвращаются от устаревших ключей сессий ненастроенного агента и применяют переопределения модели/мышления/быстрого режима/подробного режима/трассировки/reasoning для каждой сессии (sessions.list, sessions.patch).
  • Dreams: статус Dreaming, переключатель включения/выключения и читатель дневника снов (doctor.memory.status, doctor.memory.dreamDiary, config.patch).
  • Задания Cron: список/добавление/редактирование/запуск/включение/отключение + история запусков (cron.*).
  • Skills: статус, включение/отключение, установка, обновления API-ключей (skills.*).
  • Узлы: список + возможности (node.list).
  • Подтверждения exec: редактируйте allowlist Gateway или узла + политику запросов для exec host=gateway/node (exec.approvals.*).
  • Просмотр/редактирование ~/.openclaw/openclaw.json (config.get, config.set).
  • MCP имеет отдельную страницу настроек для настроенных серверов, включения, сводок OAuth/фильтров/параллельности, распространенных операторских команд и scoped-редактора конфигурации mcp.
  • Применение + перезапуск с валидацией (config.apply) и пробуждение последней активной сессии.
  • Записи включают защиту base-hash, чтобы предотвратить перезапись параллельных изменений.
  • Записи (config.set/config.apply/config.patch) предварительно проверяют разрешение активных SecretRef для ссылок в отправленном payload конфигурации; неразрешенные активные отправленные ссылки отклоняются до записи.
  • Сохранения форм отбрасывают устаревшие отредактированные placeholders, которые нельзя восстановить из сохраненной конфигурации, при этом сохраняя отредактированные значения, которые все еще сопоставляются с сохраненными секретами.
  • Схема + рендеринг формы (config.schema / config.schema.lookup, включая поля title / description, совпавшие подсказки UI, сводки непосредственных дочерних элементов, метаданные документации на вложенных узлах object/wildcard/array/composition, а также схемы plugin + канала, когда доступны); редактор Raw JSON доступен только когда снимок имеет безопасный raw round-trip.
  • Если снимок не может безопасно пройти round-trip необработанного текста, Control UI принудительно включает режим формы и отключает режим Raw для этого снимка.
  • В редакторе Raw JSON действие «Сбросить к сохраненному» сохраняет форму, созданную в raw-редакторе (форматирование, комментарии, компоновку $include), вместо повторного рендеринга сглаженного снимка, поэтому внешние изменения переживают сброс, когда снимок может безопасно пройти round-trip.
  • Структурированные объектные значения SecretRef отображаются только для чтения в текстовых полях формы, чтобы предотвратить случайное повреждение объекта в строку.
  • Отладка: снимки статуса/здоровья/моделей + журнал событий + ручные RPC-вызовы (status, health, models.list).
  • Журнал событий включает тайминги обновлений/RPC Control UI, тайминги медленного рендеринга чата/конфигурации и записи отзывчивости браузера для длинных кадров анимации или долгих задач, когда браузер предоставляет эти типы записей PerformanceObserver.
  • Логи: live tail файловых логов Gateway с фильтрацией/экспортом (logs.tail).
  • Обновление: выполните обновление package/git + перезапуск (update.run) с отчетом о перезапуске, затем опрашивайте update.status после переподключения, чтобы проверить версию запущенного Gateway.
  • Для изолированных заданий доставка по умолчанию объявляет сводку. Можно переключить на none, если нужны только внутренние запуски.
  • Поля канала/цели появляются, когда выбрано объявление.
  • Режим Webhook использует delivery.mode = "webhook" с delivery.to, заданным как действительный HTTP(S) Webhook URL.
  • Для заданий основного сеанса доступны режимы доставки webhook и none.
  • Расширенные элементы управления редактированием включают удаление после запуска, сброс переопределения агента, точные/разнесенные параметры cron, переопределения модели/мышления агента и переключатели доставки по мере возможности.
  • Проверка формы выполняется встроенно с ошибками на уровне полей; недопустимые значения отключают кнопку сохранения до исправления.
  • Задайте cron.webhookToken, чтобы отправлять выделенный bearer-токен; если он не указан, Webhook отправляется без заголовка авторизации.
  • Устаревший резервный вариант: выполните openclaw doctor --fix, чтобы перенести сохраненные устаревшие задания с notify: true из cron.webhook в явный Webhook для каждого задания или доставку по завершении.

Страница MCP

Выделенная страница MCP — это операторское представление для MCP-серверов, управляемых OpenClaw, в mcp.servers. Она сама не запускает MCP-транспорты; используйте ее для просмотра и редактирования сохраненной конфигурации, а затем выполните openclaw mcp doctor --probe, когда нужно живое подтверждение работы сервера. Типичный рабочий процесс:
  1. Откройте MCP на боковой панели.
  2. Проверьте карточки сводки для общего количества серверов, а также количества включенных, OAuth- и отфильтрованных серверов.
  3. Просмотрите строку каждого сервера: транспорт, включение, аутентификацию, фильтры, тайм-ауты и подсказки команд.
  4. Переключайте включение, когда сервер должен оставаться настроенным, но не участвовать в обнаружении во время выполнения.
  5. Отредактируйте ограниченный раздел конфигурации mcp для определений серверов, заголовков, путей TLS/mTLS, метаданных OAuth, фильтров инструментов и метаданных проекции Codex.
  6. Используйте Сохранить для записи конфигурации или Сохранить и опубликовать, когда работающий Gateway должен применить измененную конфигурацию.
  7. Выполните openclaw mcp status --verbose, openclaw mcp doctor --probe или openclaw mcp reload из терминала, когда отредактированному процессу нужны статическая диагностика, живое подтверждение или сброс кэшированного рантайма.
Страница скрывает URL-подобные значения, содержащие учетные данные, перед отображением и заключает имена серверов в кавычки во фрагментах команд, чтобы скопированные команды продолжали работать с пробелами или метасимволами оболочки. Полный справочник CLI и конфигурации находится в MCP.

Вкладка активности

Вкладка активности — это временный локальный для браузера наблюдатель за живой активностью инструментов. Она формируется из того же потока событий Gateway session.tool / событий инструментов, который питает карточки инструментов в чате; она не добавляет другое семейство событий Gateway, конечную точку, долговременное хранилище активности, поток метрик или внешний поток наблюдателя. Записи активности хранят только очищенные сводки и отредактированные, усеченные превью вывода. Значения аргументов инструментов не сохраняются в состоянии активности; UI показывает, что аргументы скрыты, и записывает только количество полей аргументов. Список в памяти привязан к текущей вкладке браузера, сохраняется при навигации внутри Control UI и сбрасывается при перезагрузке страницы, переключении сеанса или нажатии Очистить.

Поведение чата

  • chat.send является неблокирующим: он сразу подтверждает получение с { runId, status: "started" }, а ответ передается потоком через события chat. Доверенные клиенты Control UI также могут получать необязательные метаданные времени ACK для локальной диагностики.
  • Загрузки в чат принимают изображения и не-видео файлы. Изображения сохраняют исходный путь изображения; остальные файлы сохраняются как управляемые медиа и отображаются в истории как ссылки на вложения.
  • Повторная отправка с тем же idempotencyKey возвращает { status: "in_flight" } во время выполнения и { status: "ok" } после завершения.
  • Ответы chat.history ограничены по размеру для безопасности UI. Когда записи транскрипта слишком велики, Gateway может усекать длинные текстовые поля, опускать тяжелые блоки метаданных и заменять чрезмерно большие сообщения заполнителем ([chat.history omitted: message too large]).
  • Когда видимое сообщение ассистента было усечено в chat.history, боковой читатель может по требованию получить полную нормализованную для отображения запись транскрипта через chat.message.get по sessionKey, активному agentId при необходимости и messageId транскрипта. Если Gateway все еще не может вернуть больше, читатель показывает явное состояние недоступности, а не молча повторяет усеченное превью.
  • Изображения ассистента/сгенерированные изображения сохраняются как управляемые ссылки на медиа и отдаются обратно через аутентифицированные медиа-URL Gateway, поэтому перезагрузки не зависят от того, остаются ли необработанные base64-полезные нагрузки изображений в ответе истории чата.
  • При отображении chat.history Control UI удаляет из видимого текста ассистента встроенные директивные теги только для отображения (например, [[reply_to_*]] и [[audio_as_voice]]), plain-text XML-полезные нагрузки вызовов инструментов (включая <tool_call>...</tool_call>, <function_call>...</function_call>, <tool_calls>...</tool_calls>, <function_calls>...</function_calls> и усеченные блоки вызовов инструментов), а также просочившиеся ASCII/полноширинные управляющие токены модели, и опускает записи ассистента, весь видимый текст которых состоит только из точного молчаливого токена NO_REPLY / no_reply или токена подтверждения Heartbeat HEARTBEAT_OK.
  • Во время активной отправки и финального обновления истории представление чата сохраняет видимыми локальные оптимистичные сообщения пользователя/ассистента, если chat.history кратко возвращает более старый снимок; канонический транскрипт заменяет эти локальные сообщения, когда история Gateway догоняет.
  • Живые события chat представляют состояние доставки, а chat.history перестраивается из долговременного транскрипта сеанса. После финальных событий инструментов Control UI перезагружает историю и объединяет только небольшой оптимистичный хвост; граница транскрипта описана в WebChat.
  • chat.inject добавляет заметку ассистента в транскрипт сеанса и транслирует событие chat для обновлений только UI (без запуска агента и без доставки в канал).
  • Заголовок чата показывает фильтр агента перед выбором сеанса, а выбор сеанса ограничен выбранным агентом. При переключении агентов показываются только сеансы, связанные с этим агентом, и выполняется откат к основному сеансу этого агента, если у него еще нет сохраненных сеансов панели.
  • На ширине desktop элементы управления чатом остаются в одной компактной строке и сворачиваются при прокрутке транскрипта вниз; прокрутка вверх, возврат к началу или достижение низа восстанавливают элементы управления.
  • Последовательные повторяющиеся текстовые сообщения отображаются как один пузырь с бейджем количества. Сообщения с изображениями, вложениями, выводом инструментов или превью canvas не сворачиваются.
  • Переключатели модели и мышления в заголовке чата немедленно патчат активный сеанс через sessions.patch; это постоянные переопределения сеанса, а не параметры отправки только для одного хода.
  • Если отправить сообщение, пока изменение переключателя модели для того же сеанса еще сохраняется, composer дожидается этого патча сеанса перед вызовом chat.send, чтобы отправка использовала выбранную модель.
  • Ввод /new в Control UI создает и переключает на тот же новый сеанс панели, что и Новый чат, кроме случая, когда настроено session.dmScope: "main" и текущий родитель — основной сеанс агента; тогда основной сеанс сбрасывается на месте. Ввод /reset сохраняет явный сброс Gateway на месте для текущего сеанса.
  • Переключатель модели чата запрашивает настроенное представление моделей Gateway. Если присутствует agents.defaults.models, этот allowlist управляет переключателем, включая записи provider/*, которые сохраняют каталоги в области провайдера динамическими. Иначе переключатель показывает явные записи models.providers.*.models плюс провайдеров с пригодной аутентификацией. Полный каталог остается доступен через отладочный RPC models.list с view: "all".
  • Когда свежие отчеты Gateway об использовании сеанса включают текущие токены контекста, область composer чата показывает компактный индикатор использования контекста. При высокой нагрузке на контекст он переключается на предупреждающий стиль, а на рекомендуемых уровнях Compaction показывает компактную кнопку, запускающую обычный путь Compaction сеанса. Устаревшие снимки токенов скрываются, пока Gateway снова не сообщит свежие данные использования.
Режим Talk использует зарегистрированного realtime-провайдера голоса. Настройте OpenAI с talk.realtime.provider: "openai" плюс профиль аутентификации API-ключа openai, talk.realtime.providers.openai.apiKey или OPENAI_API_KEY; OAuth-профили OpenAI не настраивают Realtime-голос. Настройте Google с talk.realtime.provider: "google" плюс talk.realtime.providers.google.apiKey. Браузер никогда не получает стандартный API-ключ провайдера. OpenAI получает временный Realtime client secret для WebRTC. Google Live получает одноразовый ограниченный токен аутентификации Live API для браузерного WebSocket-сеанса, при этом инструкции и объявления инструментов зафиксированы в токене Gateway. Провайдеры, которые предоставляют только backend realtime bridge, работают через relay-транспорт Gateway, поэтому учетные данные и сокеты поставщика остаются на сервере, а браузерное аудио проходит через аутентифицированные RPC Gateway. Подсказка Realtime-сеанса собирается Gateway; talk.client.create не принимает предоставленные вызывающим кодом переопределения инструкций.Composer чата включает кнопку параметров Talk рядом с кнопкой запуска/остановки Talk. Параметры применяются к следующему сеансу Talk и могут переопределять провайдера, транспорт, модель, голос, усилие рассуждения, порог VAD, длительность тишины и начальный padding. Когда параметр пустой, Gateway использует настроенные значения по умолчанию, если они доступны, или значение по умолчанию провайдера. Выбор Gateway relay принудительно включает путь backend relay; выбор WebRTC оставляет сеанс во владении клиента и приводит к ошибке вместо молчаливого отката к relay, если провайдер не может создать браузерный сеанс.В composer чата элемент управления Talk — это кнопка с волнами рядом с кнопкой диктовки через микрофон. Когда Talk запускается, строка состояния composer показывает Connecting Talk..., затем Talk live, пока аудио подключено, или Asking OpenClaw..., пока realtime-вызов инструмента консультируется с настроенной более крупной моделью через talk.client.toolCall.Живая smoke-проверка для сопровождающих: OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts проверяет backend WebSocket bridge OpenAI, WebRTC SDP-обмен OpenAI в браузере, настройку браузерного WebSocket с ограниченным токеном Google Live и браузерный адаптер Gateway relay с поддельным микрофонным медиа. Команда выводит только статус провайдера и не записывает секреты в лог.
  • Нажмите Остановить (вызывает chat.abort).
  • Пока запуск активен, обычные последующие сообщения ставятся в очередь. Нажмите Направить на сообщении в очереди, чтобы внедрить это последующее сообщение в выполняющийся ход.
  • Введите /stop (или отдельные фразы прерывания, такие как stop, stop action, stop run, stop openclaw, please stop), чтобы прервать вне основного потока.
  • chat.abort поддерживает { sessionKey } (без runId), чтобы прервать все активные запуски для этого сеанса.
  • Когда запуск прерван, частичный текст ассистента все равно может отображаться в UI.
  • Gateway сохраняет прерванный частичный текст ассистента в историю транскрипта, когда существует буферизованный вывод.
  • Сохраненные записи включают метаданные прерывания, чтобы потребители транскрипта могли отличать частичные результаты прерывания от обычного вывода завершения.

Установка PWA и web push

Control UI поставляется с manifest.webmanifest и service worker, поэтому современные браузеры могут устанавливать его как автономное PWA. Web Push позволяет Gateway пробуждать установленное PWA уведомлениями, даже когда вкладка или окно браузера не открыты. Если страница показывает Несоответствие протокола сразу после обновления OpenClaw, сначала заново откройте панель с помощью openclaw dashboard и выполните жесткое обновление страницы. Если сбой сохраняется, очистите данные сайта для origin панели или проверьте в приватном окне браузера; старая вкладка или кэш service worker браузера может продолжать запускать набор Control UI до обновления против более нового Gateway.
ПоверхностьЧто она делает
ui/public/manifest.webmanifestМанифест PWA. Браузеры предлагают «Установить приложение», когда он становится доступен.
ui/public/sw.jsService worker, который обрабатывает события push и клики по уведомлениям.
push/vapid-keys.json (в каталоге состояния OpenClaw)Автоматически созданная пара ключей VAPID, используемая для подписи полезных нагрузок Web Push.
push/web-push-subscriptions.jsonСохраненные конечные точки подписок браузера.
Переопределяйте пару ключей VAPID через переменные окружения процесса Gateway, когда нужно закрепить ключи (для развертываний на нескольких хостах, ротации секретов или тестов):
  • OPENCLAW_VAPID_PUBLIC_KEY
  • OPENCLAW_VAPID_PRIVATE_KEY
  • OPENCLAW_VAPID_SUBJECT (по умолчанию https://openclaw.ai)
Control UI использует эти методы Gateway, ограниченные областью доступа, для регистрации и тестирования браузерных подписок:
  • push.web.vapidPublicKey — получает активный публичный ключ VAPID.
  • push.web.subscribe — регистрирует endpoint плюс keys.p256dh/keys.auth.
  • push.web.unsubscribe — удаляет зарегистрированную конечную точку.
  • push.web.test — отправляет тестовое уведомление в подписку вызывающей стороны.
Web Push не зависит от пути ретрансляции iOS APNS (см. Конфигурация для push через ретранслятор) и существующего метода push.test, которые предназначены для нативного сопряжения с мобильными устройствами.

Встроенные размещенные элементы

Сообщения ассистента могут отображать размещенный веб-контент встроенно с помощью шорткода [embed ...]. Политика песочницы iframe управляется параметром gateway.controlUi.embedSandbox:
Отключает выполнение скриптов внутри размещенных встроенных элементов.
Пример:
{
  gateway: {
    controlUi: {
      embedSandbox: "scripts",
    },
  },
}
Используйте trusted только тогда, когда встроенному документу действительно нужно поведение same-origin. Для большинства игр и интерактивных canvas, созданных агентом, scripts — более безопасный выбор.
Абсолютные внешние URL встроенных элементов http(s) по умолчанию остаются заблокированными. Если вы намеренно хотите, чтобы [embed url="https://..."] загружал сторонние страницы, задайте gateway.controlUi.allowExternalEmbedUrls: true.

Ширина сообщений чата

Сгруппированные сообщения чата используют удобную для чтения максимальную ширину по умолчанию. Развертывания на широких мониторах могут переопределить ее без исправления встроенного CSS, задав gateway.controlUi.chatMessageMaxWidth:
{
  gateway: {
    controlUi: {
      chatMessageMaxWidth: "min(1280px, 82%)",
    },
  },
}
Значение проверяется до того, как попадет в браузер. Поддерживаемые значения включают обычные длины и проценты, такие как 960px или 82%, а также ограниченные выражения ширины min(...), max(...), clamp(...), calc(...) и fit-content(...).

Доступ через tailnet (рекомендуется)

Оставьте Gateway на loopback и позвольте Tailscale Serve проксировать его через HTTPS:
openclaw gateway --tailscale serve
Откройте:
  • https://<magicdns>/ (или ваш настроенный gateway.controlUi.basePath)
По умолчанию запросы Control UI/WebSocket Serve могут проходить аутентификацию через заголовки идентификации Tailscale (tailscale-user-login), когда gateway.auth.allowTailscale равно true. OpenClaw проверяет идентичность, разрешая адрес x-forwarded-for с помощью tailscale whois и сопоставляя его с заголовком, и принимает такие запросы только тогда, когда запрос приходит на loopback с заголовками Tailscale x-forwarded-*. Для операторских сессий Control UI с идентичностью браузерного устройства этот проверенный путь Serve также пропускает цикл сопряжения устройства; браузеры без устройства и подключения с ролью узла по-прежнему проходят обычные проверки устройства. Задайте gateway.auth.allowTailscale: false, если хотите требовать явные учетные данные общего секрета даже для трафика Serve. Затем используйте gateway.auth.mode: "token" или "password".Для этого асинхронного пути идентификации Serve неудачные попытки аутентификации для того же IP клиента и области аутентификации сериализуются перед записями ограничения скорости. Поэтому параллельные неудачные повторы из того же браузера могут показать retry later во втором запросе вместо двух обычных несовпадений, выполняющихся параллельно.
Аутентификация Serve без токена предполагает, что хост gateway является доверенным. Если на этом хосте может выполняться недоверенный локальный код, требуйте аутентификацию по токену/паролю.

Небезопасный HTTP

Если открыть панель управления через обычный HTTP (http://<lan-ip> или http://<tailscale-ip>), браузер работает в небезопасном контексте и блокирует WebCrypto. По умолчанию OpenClaw блокирует подключения Control UI без идентичности устройства. Задокументированные исключения:
  • совместимость небезопасного HTTP только для localhost с gateway.controlUi.allowInsecureAuth=true
  • успешная операторская аутентификация Control UI через gateway.auth.mode: "trusted-proxy"
  • аварийный параметр gateway.controlUi.dangerouslyDisableDeviceAuth=true
Рекомендуемое исправление: используйте HTTPS (Tailscale Serve) или откройте UI локально:
  • https://<magicdns>/ (Serve)
  • http://127.0.0.1:18789/ (на хосте gateway)
{
  gateway: {
    controlUi: { allowInsecureAuth: true },
    bind: "tailnet",
    auth: { mode: "token", token: "replace-me" },
  },
}
allowInsecureAuth — это только локальный переключатель совместимости:
  • Он позволяет сессиям Control UI на localhost продолжаться без идентичности устройства в небезопасных HTTP-контекстах.
  • Он не обходит проверки сопряжения.
  • Он не ослабляет требования к идентичности устройства для удаленных (не localhost) подключений.
{
  gateway: {
    controlUi: { dangerouslyDisableDeviceAuth: true },
    bind: "tailnet",
    auth: { mode: "token", token: "replace-me" },
  },
}
dangerouslyDisableDeviceAuth отключает проверки идентичности устройства Control UI и является серьезным снижением безопасности. Быстро отмените его после аварийного использования.
  • Успешная аутентификация trusted-proxy может допускать операторские сессии Control UI без идентичности устройства.
  • Это не распространяется на сессии Control UI с ролью узла.
  • Reverse proxy на loopback того же хоста все равно не удовлетворяют аутентификации trusted-proxy; см. Аутентификация trusted proxy.
См. Tailscale для рекомендаций по настройке HTTPS.

Политика безопасности контента

Control UI поставляется со строгой политикой img-src: разрешены только ресурсы same-origin, URL data: и локально созданные URL blob:. Удаленные URL изображений http(s) и URL изображений с относительным протоколом отклоняются браузером и не выполняют сетевые запросы. Что это означает на практике:
  • Аватары и изображения, отдаваемые по относительным путям (например, /avatars/<id>), по-прежнему отображаются, включая аутентифицированные маршруты аватаров, которые UI загружает и преобразует в локальные URL blob:.
  • Встроенные URL data:image/... по-прежнему отображаются (полезно для полезных нагрузок внутри протокола).
  • Локальные URL blob:, созданные Control UI, по-прежнему отображаются.
  • Удаленные URL аватаров, выдаваемые метаданными канала, удаляются помощниками аватаров Control UI и заменяются встроенным логотипом/бейджем, поэтому скомпрометированный или вредоносный канал не может принудительно вызвать произвольные удаленные загрузки изображений из браузера оператора.
Вам не нужно ничего менять, чтобы получить это поведение — оно всегда включено и не настраивается.

Аутентификация маршрута аватара

Когда аутентификация gateway настроена, конечная точка аватара Control UI требует тот же токен gateway, что и остальная часть API:
  • GET /avatar/<agentId> возвращает изображение аватара только аутентифицированным вызывающим сторонам. GET /avatar/<agentId>?meta=1 возвращает метаданные аватара по тому же правилу.
  • Неаутентифицированные запросы к любому из маршрутов отклоняются (как и у соседнего маршрута assistant-media). Это предотвращает утечку идентичности агента через маршрут аватара на хостах, которые в остальном защищены.
  • Сам Control UI пересылает токен gateway как bearer-заголовок при загрузке аватаров и использует аутентифицированные URL blob, чтобы изображение по-прежнему отображалось в панелях управления.
Если отключить аутентификацию gateway (не рекомендуется на общих хостах), маршрут аватара также становится неаутентифицированным, в соответствии с остальной частью gateway.

Аутентификация маршрута медиа ассистента

Когда аутентификация gateway настроена, локальные превью медиа ассистента используют двухэтапный маршрут:
  • GET /__openclaw__/assistant-media?meta=1&source=<path> требует обычную операторскую аутентификацию Control UI. Браузер отправляет токен gateway как bearer-заголовок при проверке доступности.
  • Успешные ответы с метаданными включают краткоживущий mediaTicket, ограниченный этим точным исходным путем.
  • URL изображений, аудио, видео и документов, отображаемые браузером, используют mediaTicket=<ticket> вместо активного токена или пароля gateway. Билет быстро истекает и не может авторизовать другой источник.
Это сохраняет совместимость обычного отображения медиа с нативными медиаэлементами браузера, не помещая повторно используемые учетные данные gateway в видимые URL медиа.

Сборка UI

Gateway отдает статические файлы из dist/control-ui. Соберите их с помощью:
pnpm ui:build
Необязательная абсолютная база (когда нужны фиксированные URL ресурсов):
OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
Для локальной разработки (отдельный dev-сервер):
pnpm ui:dev
Затем укажите UI на ваш URL Gateway WS (например, ws://127.0.0.1:18789).

Пустая страница Control UI

Если браузер загружает пустую панель управления, а DevTools не показывает полезной ошибки, расширение или ранний content script могли помешать выполнению JavaScript-модуля приложения. Статическая страница включает простую HTML-панель восстановления, которая появляется, когда <openclaw-app> не зарегистрирован после запуска. Используйте действие панели Повторить попытку после изменения окружения браузера или перезагрузите вручную после этих проверок:
  • Отключите расширения, которые внедряются во все страницы, особенно расширения с content scripts <all_urls>.
  • Попробуйте приватное окно, чистый профиль браузера или другой браузер.
  • Оставьте Gateway запущенным и проверьте тот же URL панели управления после изменения браузера.

Отладка/тестирование: dev-сервер + удаленный Gateway

Control UI — это статические файлы; целевой WebSocket настраивается и может отличаться от HTTP origin. Это удобно, когда нужен локальный Vite dev-сервер, а Gateway работает в другом месте.
1

Start the UI dev server

pnpm ui:dev
2

Open with gatewayUrl

http://localhost:5173/?gatewayUrl=ws%3A%2F%2F<gateway-host>%3A18789
Необязательная одноразовая аутентификация (если нужна):
http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>
  • gatewayUrl сохраняется в localStorage после загрузки и удаляется из URL.
  • Если вы передаете полный endpoint ws:// или wss:// через gatewayUrl, URL-кодируйте значение gatewayUrl, чтобы браузер правильно разобрал строку запроса.
  • token по возможности следует передавать через фрагмент URL (#token=...). Фрагменты не отправляются на сервер, что предотвращает утечки через журналы запросов и Referer. Устаревшие параметры запроса ?token= по-прежнему однократно импортируются для совместимости, но только как fallback, и сразу удаляются после bootstrap.
  • password хранится только в памяти.
  • Когда задан gatewayUrl, UI не выполняет fallback к учетным данным из конфигурации или окружения. Явно укажите token (или password). Отсутствие явно заданных учетных данных является ошибкой.
  • Используйте wss://, когда Gateway находится за TLS (Tailscale Serve, HTTPS-прокси и т. д.).
  • gatewayUrl принимается только в окне верхнего уровня (не во встроенном), чтобы предотвратить clickjacking.
  • Публичные развертывания Control UI вне loopback должны явно задавать gateway.controlUi.allowedOrigins (полные origins). Частные загрузки из той же origin в LAN/Tailnet с loopback, RFC1918/link-local, .local, .ts.net или хостов Tailscale CGNAT принимаются без включения fallback по заголовку Host.
  • При запуске Gateway может добавлять локальные origins, такие как http://localhost:<port> и http://127.0.0.1:<port>, на основе фактических bind и port времени выполнения, но origins удаленных браузеров все равно требуют явных записей.
  • Не используйте gateway.controlUi.allowedOrigins: ["*"], кроме строго контролируемого локального тестирования. Это означает разрешить любую browser origin, а не «соответствовать тому хосту, который я использую».
  • gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true включает режим fallback по origin из заголовка Host, но это опасный режим безопасности.
Пример:
{
  gateway: {
    controlUi: {
      allowedOrigins: ["http://localhost:5173"],
    },
  },
}
Подробности настройки удаленного доступа: Удаленный доступ.

См. также