Главная / Статьи / Скриншоты как доказательство для ИИ-агентов: полная страница, регионы и диффы

Скриншоты как доказательство для ИИ-агентов: полная страница, регионы и диффы

Почему агентам мало скриншота из Playwright: полный захват страницы, нарезка на регионы, хранение по хешу, диффы без шума, мониторы и лимит расходов в MCP.

1335 слов

Чтобы агент поставил Playwright и сохранил PNG, хватит пары строк. С этим давно никто не мучается. Проблемы начинаются, когда такие картинки попадают в рабочий процесс в продакшене и кому-то приходится на них полагаться.

Тут агенту уже нужно доказать, что длинная страница снята до самого низа. Нужно порезать результат на куски, которые модель зрения реально сможет прочитать, хранить доказательства так, чтобы они потом не менялись, сравнивать два релиза без ложных тревог из-за сдвигов вёрстки, запускать проверки по расписанию и не выходить за бюджет, когда за процессом никто не следит.

Один из способов собрать всё это вместе — управляемый API для скриншотов с удалённым MCP-сервером, для публичных страниц или страниц, к которым у вызывающей стороны есть доступ. Заменять обычный Playwright там, где хватает одноразового снимка, он не должен. Его задача — быть слоем доказательств для повторяющихся процессов.

Съёмка страницы в заданном состоянии

Один URL не определяет, что окажется на скриншоте. Ширина экрана на десктопе, планшете и телефоне разная, светлая и тёмная темы выглядят по-разному, а страница после клика — уже другая страница. Поэтому сервису съёмки нужны настройки: именованные устройства и свои размеры окна, предпочтение темы, стратегия ожидания, очистка, скрытие селекторов, заголовки, cookies и сценарии взаимодействия. С ними процесс сам говорит, какую версию страницы сохранить, а не довольствуется тем, что успело загрузиться после перехода.

У съёмки всей страницы своя ловушка. Высота может меняться, пока подгружается ленивый контент, веб-шрифты и картинки, и браузер вполне способен вернуть изображение с пустым низом. Лечится это порядком действий: прокручивать по шагам, ждать, пока высота документа перестанет меняться, вернуться наверх, сделать снимок и сверить ширину и высоту готового PNG или JPEG с документом. Если страница так и не успокоилась или продолжает расти, вызов возвращает типизированную ошибку. Видимый сбой лучше неполного доказательства, которое выдают за полное.

Нарезка длинных страниц на читаемые регионы

Если втиснуть скриншот высотой 12 000 пикселей в небольшой вход модели зрения, текст превратится в кашу. Сервис решает это флагом regions в запросе.

curl --request POST https://api.scrinly.com/render/screenshot \
  --header "Authorization: Bearer $SCRINLY_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "url": "https://example.com",
    "device": "macbook-pro-14",
    "theme": "dark",
    "fullPage": true,
    "regions": true,
    "format": "jpg",
    "quality": 80
  }'

В ответе приходит весь скриншот и упорядоченные фрагменты: панель навигации, hero-блок, основной контент, призывы к действию, футер и другие найденные области. В манифесте для каждого региона указаны границы, порядок, уверенность, покрытие, размеры и хеш. Каждый фрагмент вырезается из итогового отданного скриншота, а не из повторной съёмки, которая могла бы отличаться.

Флаг design добавляет детерминированные данные о цветах, типографике, отступах, вёрстке и анимациях, очищенные и ограниченные по размеру. Никакая ИИ-модель в их получении не участвует.

Если обработка регионов упала, а сам скриншот получился, вызывающая сторона всё равно его получает, а возвращается только доплата за регионы.

Доказательства, которые нельзя перезаписать

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

{storagePrefix}/{screenshotSha256}.jpg

Разные байты дают разные ключи, а одинаковые снимки спокойно делят один. Результаты ссылаются прямо на хранилище, а не на прокси для картинок. По умолчанию файлы лежат в Backblaze B2, а клиенты REST API могут направить их в свои бакеты B2, S3 или R2. Кеширование включается флагом cache, а пакеты публичных скриншотов вмещают до 100 сохранённых снимков, причём оплата и возвраты считаются по каждому элементу отдельно.

Сравнение релизов без ложных срабатываний

Режимов сравнения два: точное попиксельное и перцептивное, которое терпит шум. На выходе может быть размеченный оверлей, контекстная тепловая карта, бинарная маска или только метаданные.

Сложность сравнения — в сдвигах. Добавьте новую секцию под hero-блоком, и обычный дифф целой картинки пометит изменённым всё, что ниже. Но если у обоих снимков совместимые манифесты регионов, каждая логическая секция сравнивается отдельно. Вставленный блок отмечается как добавленный, а футер, который просто съехал вниз, считается неизменным.

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

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

ИИ — только после детерминированных шагов

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

Модель, которую выбирает сервер, получает обзорное изображение ограниченного размера, упорядоченные картинки регионов и очищенную проекцию. Целевой URL, имя хоста, HTML, cookies, заголовки, селекторы, учётные данные и переданный текст страницы как текст ей не передаются. Конечно, тексты и бренд, видимые на экране, всё равно могут попасть в пиксели.

Результат описывает визуальную основу, цвет, типографику, отступы, компоненты, анимации, адаптивность и пробелы в данных, а утверждения сверяются с этими данными. Стайлгайды кешируются автоматически, а флаг regenerate запрашивает свежий. Можно также передать временный ключ OpenAI в отдельном заголовке, он не сохраняется. Если генерация не удалась, скриншот и регионы остаются доступны, а возвращается только доплата за ИИ.

Доступ для агентов через MCP

Удалённый MCP-сервер предлагает четыре инструмента:

  • capture_screenshot
  • compare_screenshots
  • get_job_status
  • get_usage

Подключение идёт через OAuth, запасной вариант — API-ключ. В Codex это выглядит так:

codex mcp add scrinly --url https://mcp.scrinly.com/mcp

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

npx skills add davmixcool/skills --skill scrinly -g

Платные операции MCP требуют значение maxCredits. Если списание в худшем случае превысит заявленный пользователем лимит, запрос отклоняется ещё до рендеринга и оплаты. Так появляется понятная граница между тем, что агент может делать сам, и тем, за что платит пользователь.

Уроки проектирования, которые пригодятся и в других местах

  1. Успешный вызов браузера не доказывает, что скриншот полный.
  2. Производные фрагменты нужно вырезать из того самого изображения, которое было отдано.
  3. Для стабильных доказательств нужно хранилище с адресацией по содержимому.
  4. Детерминированная обработка должна идти до интерпретации ИИ.
  5. При частичном успехе нужно отдавать полезный результат и возвращать деньги только за упавшую часть.
  6. Автономным инструментам нужны явные лимиты расходов, а не только аутентификация.
  7. Playwright управляет браузером, но рабочему процессу визуальных доказательств в продакшене нужна вокруг него солидная инфраструктура.

По ценам: бесплатный тариф даёт 100 кредитов в месяц. Голый скриншот стоит один кредит, с регионами — три, каждый визуальный дифф — один, а новый стайлгайд за счёт платформы — до шести.