Автоматизация браузера

В Hermes Agent встроен полноценный набор инструментов для автоматизации браузера, и работать он может через несколько разных бэкендов:

  • Облачный режим Browserbase через Browserbase — управляемые облачные браузеры и инструменты обхода антибот-защиты
  • Облачный режим Browser Use через Browser Use — альтернативный облачный провайдер браузера
  • Облачный режим Firecrawl через Firecrawl — облачные браузеры со встроенным скрейпингом
  • Локальный режим Camofox через Camofox — локальный браузинг с защитой от детектирования (подмена отпечатка на базе Firefox)
  • Локальный Chromium-family по CDP — подключение браузерных инструментов к вашему экземпляру Chrome, Brave, Chromium или Edge командой /browser connect
  • Локальный режим браузера через CLI agent-browser и установленный локально Chromium

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

Обзор

Страницы представлены в виде деревьев доступности (текстовых снимков), и для LLM-агентов такой формат подходит идеально. Интерактивные элементы получают ref-идентификаторы (вроде @e1, @e2), по которым агент кликает и вводит текст.

Что умеет набор:

  • Облачное выполнение через несколько провайдеров — Browserbase, Browser Use или Firecrawl — без локального браузера
  • Интеграция с локальным Chromium-family — подключение к запущенному Chrome, Brave, Chromium или Edge по CDP для браузинга вживую
  • Встроенный стелс — случайные отпечатки, разгадывание CAPTCHA, резидентные прокси (Browserbase)
  • Изоляция сессий — у каждой задачи своя браузерная сессия
  • Автоматическая очистка — простаивающие сессии закрываются по таймауту
  • Анализ зрением — скриншот плюс разбор через ИИ для понимания визуальной части

Установка

совет
Подписчики Nous

Если у вас оплачена подписка Nous Portal, автоматизацию браузера можно запускать через Tool Gateway вообще без отдельных API-ключей. На свежей установке выполните hermes setup --portal, чтобы войти и сразу включить все инструменты шлюза; в уже настроенной установке выберите провайдером браузера Nous Subscription через hermes model или hermes tools.

Облачный режим Browserbase

Чтобы пользоваться управляемыми облачными браузерами Browserbase, добавьте:

# Add to ~/.hermes/.env
BROWSERBASE_API_KEY=***
BROWSERBASE_PROJECT_ID=your-project-id-here

Учётные данные возьмите на browserbase.com.

Облачный режим Browser Use

Чтобы выбрать Browser Use облачным провайдером браузера, добавьте:

# Add to ~/.hermes/.env
BROWSER_USE_API_KEY=***

API-ключ получите на browser-use.com. Browser Use отдаёт облачный браузер через свой REST API. Если заданы учётные данные и Browserbase, и Browser Use, приоритет за Browserbase.

Облачный режим Firecrawl

Чтобы выбрать Firecrawl облачным провайдером браузера, добавьте:

# Add to ~/.hermes/.env
FIRECRAWL_API_KEY=fc-***

API-ключ получите на firecrawl.dev. Затем выберите Firecrawl провайдером браузера:

hermes setup tools
# → Browser Automation → Firecrawl

Необязательные настройки:

# Self-hosted Firecrawl instance (default: https://api.firecrawl.dev)
FIRECRAWL_API_URL=http://localhost:3002

# Session TTL in seconds (default: 300)
FIRECRAWL_BROWSER_TTL=600

Гибридная маршрутизация: облако для публичных URL, локаль для LAN/localhost

Когда настроен облачный провайдер, Hermes автоматически поднимает локальный sidecar на Chromium для URL, которые резолвятся в приватный, loopback- или LAN-адрес (localhost, 127.0.0.1, 192.168.x.x, 10.x.x.x, 172.16-31.x.x, *.local, *.lan, *.internal, IPv6-loopback ::1, link-local 169.254.x.x). Публичные URL в той же беседе по-прежнему идут через облачного провайдера.

Так решается типичная ситуация «разрабатываю локально, но использую Browserbase»: агент снимет скриншот вашей панели на http://localhost:3000 И заскрейпит https://github.com, не заставляя вас переключать провайдеров или отключать SSRF-защиту. Приватный URL облачный провайдер вообще не видит.

Функция включена по умолчанию. Чтобы её отключить (тогда все URL уходят настроенному облачному провайдеру, как раньше):

# ~/.hermes/config.yaml
browser:
  cloud_provider: browserbase
  auto_local_for_private_urls: false

При отключённой автомаршрутизации приватные URL отклоняются с сообщением "Blocked: URL targets a private or internal address" — если только вы дополнительно не выставите browser.allow_private_urls: true (это разрешит облачному провайдеру попробовать их открыть, но обычно ничего не выйдет: тот же Browserbase до вашей LAN не дотянется).

Требования: локальный sidecar использует тот же CLI agent-browser, что и чисто локальный режим, поэтому его нужно установить (hermes setup tools → Browser Automation ставит его автоматически). Редиректы после перехода с публичного URL на приватный адрес всё равно блокируются — трюк «редирект на внутренний адрес», чтобы достать вашу LAN через публичный путь, не сработает.

Локальный режим Camofox

Camofox — это self-hosted сервер на Node.js, оборачивающий Camoufox (форк Firefox с подменой отпечатка на C++). Он даёт локальный браузинг с защитой от детектирования без зависимости от облака.

# Clone the Camofox browser server first
git clone https://github.com/jo-inc/camofox-browser
cd camofox-browser

# Build and start with Docker using the default container settings
# (auto-detects arch: aarch64 on M1/M2, x86_64 on Intel)
make up

# Stop and remove the default container
make down

# Force a clean rebuild (for example, after upgrading VERSION/RELEASE)
make reset

# Just download binaries without building
make fetch

# Override arch or version explicitly
make up ARCH=x86_64
make up VERSION=135.0.1 RELEASE=beta.24

make up сразу запускает контейнер по умолчанию. Если же вам нужны свои настройки рантайма — например, увеличенная куча Node, VNC или каталог с постоянным профилем — сначала соберите образ, а потом запустите его вручную:

# Build the image without starting the default container
make build

# Start with persistence, VNC live view, and a larger Node heap
mkdir -p ~/.camofox-docker
docker run -d \
  --name camofox-browser \
  --restart unless-stopped \
  -p 9377:9377 \
  -p 6080:6080 \
  -p 5901:5900 \
  -e CAMOFOX_PORT=9377 \
  -e ENABLE_VNC=1 \
  -e VNC_BIND=0.0.0.0 \
  -e VNC_RESOLUTION=1920x1080 \
  -e MAX_OLD_SPACE_SIZE=2048 \
  -v ~/.camofox-docker:/root/.camofox \
  camofox-browser:135.0.1-aarch64

С включённым VNC браузер запускается в headed-режиме, и за ним можно следить вживую в обычном браузере по адресу http://localhost:6080 (noVNC). Можно также подключить нативный VNC-клиент к localhost:5901.

Если вы уже запускали make up, остановите и удалите тот контейнер по умолчанию, прежде чем стартовать свой:

make down
# then run the custom docker run command above

Затем пропишите в ~/.hermes/.env:

CAMOFOX_URL=http://localhost:9377

Если Camofox крутится в Docker и вы хотите, чтобы он открывал веб-приложения с хост-машины, включите переписывание loopback-адресов. CAMOFOX_URL по-прежнему должен указывать на опубликованный на хосте control API, но URL страниц вроде http://127.0.0.1:3000 изнутри контейнера нужно открывать как http://host.docker.internal:3000:

# ~/.hermes/config.yaml
browser:
  camofox:
    rewrite_loopback_urls: true
    loopback_host_alias: host.docker.internal  # default; use a LAN IP if needed

Эквивалентные переменные окружения:

CAMOFOX_REWRITE_LOOPBACK_URLS=true
CAMOFOX_LOOPBACK_HOST_ALIAS=host.docker.internal

Переписывание затрагивает только URL переходов с loopback-хостами (localhost, 127.0.0.1, ::1). На CAMOFOX_URL оно не влияет. Для не-Docker установок Camofox оставьте его выключенным: там браузер и так работает на хосте, а loopback-URL корректны.

Или настройте через hermes tools → Browser Automation → Camofox.

Когда задан CAMOFOX_URL, все браузерные инструменты автоматически идут через Camofox вместо Browserbase или agent-browser.

Постоянные браузерные сессии

По умолчанию каждая сессия Camofox получает случайную личность — куки и входы в аккаунты не переживают перезапуск агента. Чтобы включить постоянные браузерные сессии, добавьте в ~/.hermes/config.yaml следующее:

browser:
  camofox:
    managed_persistence: true

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

внимание
Важна вложенность пути

Hermes читает browser.camofox.managed_persistence, а не managed_persistence на верхнем уровне. Частая ошибка — написать так:

# ❌ Wrong — Hermes ignores this
managed_persistence: true

Если флаг оказался не на том пути, Hermes молча откатывается к случайному эфемерному userId, и состояние входа теряется при каждой сессии.

Что делает Hermes
  • Отправляет в Camofox детерминированный userId, привязанный к профилю, чтобы сервер мог переиспользовать один и тот же профиль Firefox между сессиями.
  • Пропускает уничтожение контекста на стороне сервера при очистке, так что куки и входы сохраняются между задачами агента.
  • Привязывает userId к активному профилю Hermes, поэтому разные профили Hermes получают разные браузерные профили (изоляция профилей).
Чего Hermes не делает
  • Не навязывает персистентность серверу Camofox. Hermes лишь отправляет стабильный userId; сервер обязан учесть его и сопоставить этому userId каталог постоянного профиля Firefox.
  • Если ваша сборка сервера Camofox считает каждый запрос эфемерным (например, всегда вызывает browser.newContext() без загрузки сохранённого профиля), сделать такие сессии постоянными Hermes не сможет. Убедитесь, что запущена сборка Camofox с персистентностью профилей по userId.
Проверка работоспособности
  1. Запустите Hermes и свой сервер Camofox.
  2. В задаче с браузером откройте Google (или любой сайт со входом) и авторизуйтесь вручную.
  3. Завершите браузерную задачу штатно.
  4. Запустите новую браузерную задачу.
  5. Откройте тот же сайт снова — вы должны остаться авторизованы.

Если на шаге 5 вас разлогинило, сервер Camofox не учитывает стабильный userId. Перепроверьте путь в конфиге, подтвердите, что после правки config.yaml вы полностью перезапустили Hermes, и проверьте, что версия сервера Camofox поддерживает постоянные профили по пользователям.

Где хранится состояние

Стабильный userId Hermes выводит из привязанного к профилю каталога ~/.hermes/browser_auth/camofox/ (или его аналога внутри $HERMES_HOME для нестандартных профилей). Сами данные браузерного профиля живут на стороне сервера Camofox, с ключом по этому userId. Чтобы полностью сбросить постоянный профиль, очистите его на сервере Camofox и удалите соответствующий каталог состояния профиля Hermes.

Управляемые извне сессии Camofox

Когда видимым браузером Camofox управляет другое приложение (десктопный ассистент, своя интеграция, другой агент), настройте Hermes так, чтобы он работал внутри той же личности, а не поднимал собственный изолированный профиль.

Поведением управляют три параметра:

ПараметрПеременная окруженияЭффект
browser.camofox.user_idCAMOFOX_USER_IDuserId Camofox, который Hermes использует при создании вкладок. Его установка переводит сессию в режим «управляется извне».
browser.camofox.session_keyCAMOFOX_SESSION_KEYsessionKey (он же listItemId), отправляемый при создании вкладки. Нужен для сопоставления с существующей вкладкой при адопции. Если не задан, по умолчанию берётся значение на каждую задачу.
browser.camofox.adopt_existing_tabCAMOFOX_ADOPT_EXISTING_TABКогда true, Hermes при первом использовании вызывает GET /tabs?userId=<user_id> и переиспользует существующую вкладку, прежде чем создавать новую.

Переменные окружения имеют приоритет над config.yaml. Подходит любая из форм:

browser:
  camofox:
    user_id: shared-camofox
    session_key: visible-tab
    adopt_existing_tab: true
CAMOFOX_USER_ID=shared-camofox
CAMOFOX_SESSION_KEY=visible-tab
CAMOFOX_ADOPT_EXISTING_TAB=true

Что меняется при заданном user_id:

  • Hermes пропускает разрушающую очистку в конце задачи (так же, как при managed_persistence: true). Вкладка, куки и профиль другого приложения остаются целыми.
  • Hermes не вызывает DELETE /sessions/<user_id> — этот эндпоинт стирает все пользовательские данные, так что он снёс бы сессию внешнего приложения, если бы сработал.

Как работает адопция вкладок (при adopt_existing_tab: true):

  1. На первом вызове браузерного инструмента после старта процесса Hermes делает запрос GET /tabs?userId=<user_id> (таймаут 5 секунд).
  2. Если в ответе есть вкладка с listItemId == session_key, Hermes адоптирует самую свежесозданную в этой группе.
  3. Иначе Hermes адоптирует самую свежесозданную вкладку пользователя (с любым listItemId).
  4. Если вкладок нет или запрос провалился, Hermes на следующей операции откатывается к созданию новой вкладки.

Адопция срабатывает только до тех пор, пока для сессии не заполнен tab_id. Если внешнее приложение закроет адоптированную вкладку посреди работы, следующий вызов браузерного инструмента выдаст ошибку Camofox — заново опрашивать свежую вкладку на каждом вызове Hermes не станет.

Как выбрать session_key: если хотите, чтобы Hermes надёжно цеплялся к конкретной существующей вкладке, выставьте session_key равным тому listItemId, который внешнее приложение использовало при её создании. Если оставить session_key пустым и задать только user_id, Hermes сгенерирует session_key на каждую задачу (task_<id>): куки и профиль он разделит с внешним приложением, но откроет рядом собственную вкладку, а не переиспользует существующую.

О параллелизме: внешнее приложение и Hermes могут одновременно управлять одним userId Camofox, но фокус по вкладкам между клиентами Camofox не координирует. Согласуйте владение на уровне приложения (например, внешнее приложение приостанавливается на время работы Hermes).

Просмотр вживую по VNC

Когда Camofox работает в headed-режиме (с видимым окном браузера), он публикует VNC-порт в ответе health-check. Hermes сам это обнаруживает и добавляет VNC-URL в ответы на навигацию, так что агент может поделиться ссылкой, по которой вы будете смотреть за браузером вживую.

Локальный браузер семейства Chromium по CDP (/browser connect)

Вместо облачного провайдера браузерные инструменты Hermes можно подключить к вашему запущенному Chrome, Brave, Chromium или Edge через Chrome DevTools Protocol (CDP). Пригодится, когда хочется в реальном времени видеть, что делает агент, работать со страницами, требующими ваших собственных куки и сессий, или не платить за облачный браузер.

заметка

/browser connect — это слэш-команда интерактивного CLI, шлюз её не диспетчеризует. Если попробовать запустить её внутри WebUI, Telegram, Discord или другого чата через шлюз, сообщение уйдёт агенту обычным текстом, и команда не выполнится. Запустите Hermes из терминала (hermes или hermes chat) и выполните /browser connect там.

В CLI используйте:

/browser connect                 # Auto-launch/connect to a local Chromium-family browser at http://127.0.0.1:9222
/browser connect ws://host:port  # Connect to a specific CDP endpoint
/browser status                  # Check current connection
/browser disconnect              # Detach and return to cloud/local mode

Если браузер ещё не запущен с удалённой отладкой, Hermes попытается сам поднять поддерживаемый Chromium-family браузер с флагом --remote-debugging-port=9222. Детектируются Brave, Google Chrome, Chromium и Microsoft Edge, включая типичные пути установки в Linux вроде /opt/brave-bin/brave и /snap/bin/brave.

совет

Чтобы запустить Chromium-family браузер вручную с включённым CDP, используйте отдельный user-data-dir — тогда отладочный порт действительно поднимется, даже если браузер уже запущен с вашим обычным профилем:

# Linux — Brave
brave-browser \
  --remote-debugging-port=9222 \
  --user-data-dir=$HOME/.hermes/chrome-debug \
  --no-first-run \
  --no-default-browser-check &

# Linux — Google Chrome
google-chrome \
  --remote-debugging-port=9222 \
  --user-data-dir=$HOME/.hermes/chrome-debug \
  --no-first-run \
  --no-default-browser-check &

# macOS — Brave
"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" \
  --remote-debugging-port=9222 \
  --user-data-dir="$HOME/.hermes/chrome-debug" \
  --no-first-run \
  --no-default-browser-check &

# macOS — Google Chrome
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --remote-debugging-port=9222 \
  --user-data-dir="$HOME/.hermes/chrome-debug" \
  --no-first-run \
  --no-default-browser-check &

Затем запустите CLI Hermes и выполните /browser connect.

Зачем нужен --user-data-dir? Без него запуск Chromium-family браузера при уже работающем обычном экземпляре обычно открывает новое окно в существующем процессе — а тот процесс стартовал без --remote-debugging-port, так что порт 9222 не откроется. Отдельный user-data-dir заставляет создать свежий процесс браузера, где отладочный порт реально слушает. Флаги --no-first-run --no-default-browser-check пропускают мастер первого запуска для нового профиля.

При подключении по CDP все браузерные инструменты (browser_navigate, browser_click и т. д.) работают с вашим живым экземпляром браузера, а не поднимают облачную сессию.

WSL2 + Chrome на Windows: лучше MCP, чем /browser connect

Если Hermes работает внутри WSL2, а окно Chrome, которым вы хотите управлять, запущено на хосте Windows, /browser connect часто оказывается не лучшим путём.

Почему:

  • /browser connect рассчитывает, что Hermes сам доберётся до пригодного CDP-эндпоинта
  • современные live-debugging сессии Chrome часто публикуют host-local эндпоинт, к которому из WSL не дотянуться так же напрямую, как до классического порта 9222
  • даже когда Chrome на Windows доступен для отладки, чище всего отдать дело browser MCP-серверу на стороне Windows: пусть он подключится к Chrome, а Hermes общается с этим MCP-сервером

Для такой схемы предпочтительнее chrome-devtools-mcp через поддержку MCP в Hermes.

Практическую настройку смотрите в руководстве по MCP:

Локальный режим браузера

Если вы не задаёте никаких облачных учётных данных и не используете /browser connect, Hermes всё равно может работать с браузерными инструментами через локально установленный Chromium под управлением agent-browser.

Необязательные переменные окружения

# Residential proxies for better CAPTCHA solving (default: "true")
BROWSERBASE_PROXIES=true

# Advanced stealth with custom Chromium — requires Scale Plan (default: "false")
BROWSERBASE_ADVANCED_STEALTH=false

# Session reconnection after disconnects — requires paid plan (default: "true")
BROWSERBASE_KEEP_ALIVE=true

# Custom session timeout in seconds (max 21600 = 6 hours) (default: project default)
# Examples: 600 (10min), 1800 (30min), 21600 (6h max)
BROWSERBASE_SESSION_TIMEOUT=1800

# Inactivity timeout before auto-cleanup in seconds (default: 120)
BROWSER_INACTIVITY_TIMEOUT=120

# Extra Chromium launch flags (comma- or newline-separated). Hermes auto-injects
# `--no-sandbox,--disable-dev-shm-usage` when it detects root or AppArmor-restricted
# unprivileged user namespaces (Ubuntu 23.10+, DGX Spark, many container images),
# so most users don't need to set this. Set it manually only if you need a flag
# Hermes doesn't add automatically; setting it disables the auto-injection.
AGENT_BROWSER_ARGS=--no-sandbox

Установка CLI agent-browser

npm install -g agent-browser
# Or install locally in the repo:
npm install
инфо

Набор инструментов browser должен быть в списке toolsets вашего конфига или включён через hermes config set toolsets '["hermes-cli", "browser"]'.

Доступные инструменты

browser_navigate

Переход по URL. Вызывается раньше любого другого браузерного инструмента. Инициализирует сессию Browserbase.

Navigate to https://github.com/NousResearch
совет

Для простого получения информации лучше брать web_search или web_extract — они быстрее и дешевле. Браузерные инструменты нужны там, где надо взаимодействовать со страницей (нажимать кнопки, заполнять формы, обрабатывать динамический контент).

browser_snapshot

Получить текстовый снимок дерева доступности текущей страницы. Возвращает интерактивные элементы с ref-идентификаторами вроде @e1, @e2 — их используют browser_click и browser_type.

  • full=false (по умолчанию): компактный вид, только интерактивные элементы
  • full=true: полное содержимое страницы

Снимки длиннее 8000 символов LLM автоматически сжимает в сводку.

browser_click

Кликнуть по элементу, заданному его ref-идентификатором из снимка.

Click @e5 to press the "Sign In" button

browser_type

Ввести текст в поле ввода. Сначала очищает поле, затем печатает новый текст.

Type "hermes agent" into the search field @e3

browser_scroll

Прокрутить страницу вверх или вниз, чтобы показать больше содержимого.

Scroll down to see more results

browser_press

Нажать клавишу. Полезно для отправки форм и навигации.

Press Enter to submit the form

Поддерживаемые клавиши: Enter, Tab, Escape, ArrowDown, ArrowUp и другие.

browser_back

Вернуться на предыдущую страницу в истории браузера.

browser_get_images

Перечислить все изображения текущей страницы с их URL и alt-текстом. Удобно, чтобы найти изображения для анализа.

browser_vision

Сделать скриншот и проанализировать его с помощью vision-ИИ. Применяйте, когда текстовый снимок не передаёт важную визуальную информацию — особенно для CAPTCHA, сложной вёрстки или визуальных проверок.

Скриншот сохраняется на диск, и путь к файлу возвращается вместе с разбором от ИИ. На мессенджер-платформах (Telegram, Discord, Slack, WhatsApp) можно попросить агента поделиться скриншотом — он отправится нативным фото-вложением через механизм MEDIA:.

What does the chart on this page show?

Скриншоты лежат в ~/.hermes/cache/screenshots/ и автоматически вычищаются через 24 часа.

browser_console

Получить вывод консоли браузера (сообщения log/warn/error) и неперехваченные исключения JavaScript с текущей страницы. Незаменимо для отлова тихих JS-ошибок, которых нет в дереве доступности.

Check the browser console for any JavaScript errors

Передайте clear=True, чтобы очистить консоль после чтения — тогда следующие вызовы покажут только новые сообщения.

browser_console также выполняет JavaScript, если вызвать его с аргументом expression — так же, как консоль DevTools. Результат приходит уже разобранным (JSON-сериализуемые объекты превращаются в dict, примитивные значения остаются примитивными).

browser_console(expression="document.querySelector('h1').textContent")
browser_console(expression="JSON.stringify(performance.timing)")

Когда для текущей сессии активен CDP-супервизор (обычно так у любой сессии, где browser_navigate отработал против бэкенда с поддержкой CDP), вычисление идёт по постоянному WebSocket супервизора — без затрат на запуск подпроцесса. В остальных случаях используется обычный путь через CLI agent-browser. Поведение в обоих случаях одинаковое, различается только задержка.

browser_cdp

Прямой проброс Chrome DevTools Protocol — запасной ход для браузерных операций, не покрытых другими инструментами. Используйте для работы с нативными диалогами, вычислений в области iframe, управления куки и сетью или любого CDP-метода, который понадобится агенту.

Доступен только когда CDP-эндпоинт достижим на старте сессии — то есть когда /browser connect подключился к запущенному Chrome, Brave, Chromium или Edge, либо когда в config.yaml задан browser.cdp_url. Локальный режим agent-browser по умолчанию, Camofox и облачные провайдеры (Browserbase, Browser Use, Firecrawl) пока не выставляют CDP этому инструменту — у облачных провайдеров есть CDP-URL на каждую сессию, но маршрутизация по живой сессии запланирована на потом.

Справочник методов CDP: https://chromedevtools.github.io/devtools-protocol/ — агент может через web_extract открыть страницу конкретного метода и посмотреть его параметры и форму ответа.

Типичные паттерны:

# List tabs (browser-level, no target_id)
browser_cdp(method="Target.getTargets")

# Handle a native JS dialog on a tab
browser_cdp(method="Page.handleJavaScriptDialog",
            params={"accept": true, "promptText": ""},
            target_id="<tabId>")

# Evaluate JS in a specific tab
browser_cdp(method="Runtime.evaluate",
            params={"expression": "document.title", "returnByValue": true},
            target_id="<tabId>")

# Get all cookies
browser_cdp(method="Network.getAllCookies")

Методы уровня браузера (Target.*, Browser.*, Storage.*) обходятся без target_id. Методам уровня страницы (Page.*, Runtime.*, DOM.*, Emulation.*) нужен target_id из Target.getTargets. Каждый вызов без состояния независим — сессии между вызовами не сохраняются.

Кросс-доменные iframe: передайте frame_id (из browser_snapshot.frame_tree.children[], где is_oopif=true), чтобы направить CDP-вызов через живую сессию супервизора для этого iframe. Именно так Runtime.evaluate внутри кросс-доменного iframe работает в Browserbase, где stateless-подключения CDP упёрлись бы в истечение подписанного URL. Пример:

browser_cdp(
  method="Runtime.evaluate",
  params={"expression": "document.title", "returnByValue": True},
  frame_id="<frame_id from browser_snapshot>",
)

Для iframe того же домена frame_id не нужен — используйте document.querySelector('iframe').contentDocument из Runtime.evaluate верхнего уровня.

browser_dialog

Отвечает на нативный JS-диалог (alert / confirm / prompt / beforeunload). До появления этого инструмента диалоги молча блокировали JS-поток страницы, и последующие вызовы browser_* зависали или падали; теперь агент видит ожидающие диалоги в выводе browser_snapshot и отвечает на них явно.

Порядок действий:

  1. Вызовите browser_snapshot. Если диалог блокирует страницу, он показывается как pending_dialogs: [{"id": "d-1", "type": "alert", "message": "..."}].
  2. Вызовите browser_dialog(action="accept") или browser_dialog(action="dismiss"). Для диалогов prompt() передайте prompt_text="...", чтобы задать ответ.
  3. Снимите снимок повторно — pending_dialogs пуст, JS-поток страницы возобновился.

Обнаружение происходит автоматически через постоянный CDP-супервизор — один WebSocket на задачу, подписанный на события Page/Runtime/Target. Супервизор ещё и наполняет в снимке поле frame_tree, чтобы агент видел структуру iframe текущей страницы, включая кросс-доменные (OOPIF) iframe.

Матрица доступности:

БэкендОбнаружение через pending_dialogsОтвет (инструмент browser_dialog)
Локальный Chrome через /browser connect или browser.cdp_url✓ полный сценарий
Browserbase✓ полный сценарий (через внедрённый XHR-мост)
Camofox / локальный agent-browser по умолчанию✗ (нет CDP-эндпоинта)

Как это работает в Browserbase. CDP-прокси Browserbase автоматически закрывает настоящие нативные диалоги на стороне сервера примерно за 10 мс, поэтому Page.handleJavaScriptDialog нам не подходит. Супервизор через Page.addScriptToEvaluateOnNewDocument внедряет небольшой скрипт, который подменяет window.alert/confirm/prompt синхронным XHR. Эти XHR мы перехватываем через Fetch.enable — JS-поток страницы остаётся заблокирован на XHR, пока мы не вызовем Fetch.fulfillRequest с ответом агента. Возвращаемые значения prompt() без изменений уходят обратно в JS страницы.

Политика диалогов настраивается в config.yaml в секции browser.dialog_policy:

ПолитикаПоведение
must_respond (по умолчанию)Перехватить, показать в снимке, дождаться явного вызова browser_dialog(). Защитное автозакрытие через browser.dialog_timeout_s (по умолчанию 300 с), чтобы забагованный агент не завис навсегда.
auto_dismissПерехватить, тут же закрыть. Диалог агент всё равно видит в истории browser_state, но реагировать не обязан.
auto_acceptПерехватить, тут же принять. Удобно при навигации по страницам с назойливыми запросами beforeunload.

Дерево фреймов внутри browser_snapshot.frame_tree ограничено 30 фреймами и глубиной OOPIF 2, чтобы payload не разрастался на страницах, забитых рекламой. При достижении лимитов всплывает флаг truncated: true; если агенту нужно полное дерево, он может вызвать browser_cdp с Page.getFrameTree.

Практические примеры

Заполнение веб-формы

User: Sign up for an account on example.com with my email john@example.com

Agent workflow:
1. browser_navigate("https://example.com/signup")
2. browser_snapshot()  → sees form fields with refs
3. browser_type(ref="@e3", text="john@example.com")
4. browser_type(ref="@e5", text="SecurePass123")
5. browser_click(ref="@e8")  → clicks "Create Account"
6. browser_snapshot()  → confirms success

Изучение динамического контента

User: What are the top trending repos on GitHub right now?

Agent workflow:
1. browser_navigate("https://github.com/trending")
2. browser_snapshot(full=true)  → reads trending repo list
3. Returns formatted results

Запись сессий

Браузерные сессии можно автоматически записывать в видеофайлы WebM:

browser:
  record_sessions: true  # default: false

При включении запись стартует автоматически на первом browser_navigate и сохраняется в ~/.hermes/browser_recordings/, когда сессия закрывается. Работает и в локальном, и в облачном (Browserbase) режиме. Записи старше 72 часов вычищаются автоматически.

Стелс-возможности

Browserbase даёт автоматический стелс:

ВозможностьПо умолчаниюПримечания
Базовый стелсВсегда включёнСлучайные отпечатки, рандомизация viewport, разгадывание CAPTCHA
Резидентные проксиВключеныМаршрутизация через резидентные IP для лучшего доступа
Продвинутый стелсВыключенСвоя сборка Chromium, требуется Scale Plan
Keep AliveВключёнПереподключение сессии после сетевых сбоев
заметка

Если платные функции на вашем тарифе недоступны, Hermes автоматически откатывается — сначала отключает keepAlive, затем прокси — так что браузинг работает и на бесплатных тарифах.

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

  • Каждая задача получает изолированную браузерную сессию через Browserbase
  • Сессии автоматически вычищаются после простоя (по умолчанию 2 минуты)
  • Фоновый поток проверяет устаревшие сессии каждые 30 секунд
  • При выходе процесса запускается аварийная очистка, чтобы не оставлять осиротевшие сессии
  • Сессии освобождаются через API Browserbase (статус REQUEST_RELEASE)

Ограничения

  • Текстовое взаимодействие — опора на дерево доступности, а не на пиксельные координаты
  • Размер снимка — большие страницы могут обрезаться или сжиматься LLM на отметке 8000 символов
  • Таймаут сессии — облачные сессии истекают по настройкам тарифа вашего провайдера
  • Стоимость — облачные сессии расходуют кредиты провайдера; сессии автоматически вычищаются при завершении беседы или после простоя. Для бесплатного локального браузинга используйте /browser connect.
  • Нет скачивания файлов — скачивать файлы из браузера нельзя
ESC