Назад в Центр знаний
Идентичность

Изоляция профиля агента для каждой задачи

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

BotBrowser Team

Документация

Нужна структурированная документация по теме Идентичность?

Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.

Агент, который выполняет несколько задач, должен получить явное назначение профиля до запуска каждого браузера. BotBrowser может запустить браузер с профилем, переданным оператором, и показать результат страницы, но он не планирует задачи, не выбирает назначение и не гарантирует решение детектора. Оператор отвечает за соответствие taskId и profileId.

TL;DR

  • Создавайте связь задача-профиль до запуска; повторная попытка не должна молча наследовать профиль предыдущей задачи.
  • Давайте каждому профилю собственный раздел хранения и утверждённую сетевую политику. Общий профиль может перенести cookies, локальное хранилище, разрешения и тот же настроенный маршрут в следующую задачу.
  • Запустите приведённый fixture: сначала с двумя постоянными каталогами для доказательства разделения, затем с намеренно общим каталогом для демонстрации утечки.
  • Успешный fixture показывает то, что может прочитать страница. Он не доказывает решение детектора, процесс запуска браузера или соблюдение ограничений сторонней платформы.

Contents (Содержание)

Две задачи получают отдельные профили и хранилища, а общий профиль переносит cookie и значение local storage

Зачем циклу агента нужна граница профиля

Цикл агента превращает один браузерный сценарий в последовательность независимо ограниченных заданий. Задача A может войти в разрешённый тестовый tenant, а задача B должна начать без состояния этого tenant. Если оба запуска указывают на один постоянный профиль, вторая задача может получить cookies, локальное хранилище, разрешения, кеш и другое состояние ещё до первого действия.

Playwright называет BrowserContext изолированной сессией со своими cookies и хранилищем. Это полезная граница, но она не заменяет выбор профиля BotBrowser. Профиль является входом запуска и может нести настройки за пределами хранилища страницы. Руководство по управлению профилями описывает владельца, совместимость версий, хранение и жизненный цикл; планировщик агента применяет эти принципы при назначении профилей задачам.

Ближайшая статья об изоляции браузера для нескольких аккаунтов посвящена человеческим рабочим процессам, где аккаунты разделены. Цикл агента добавляет задачу назначения: каждая задача, повтор и перезапуск worker должны получить выбранный профиль. Руководство о headless-браузере для AI-агентов рассматривает передачу между агентом и браузером и доказательства процесса, но не устанавливает разделение идентичности между запусками.

Назначьте профиль до запуска

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

{
  "taskId": "tenant-a-checkout-042",
  "profileId": "profile-us-east-07",
  "storageDir": "/var/lib/agent-sessions/profile-us-east-07",
  "networkPolicyRef": "egress-us-east-07",
  "state": "approved"
}

Разрешите эту запись до вызова chromium.launchPersistentContext() или эквивалентного BotBrowser launcher. Отклоняйте отсутствующее, отозванное или уже занятое назначение. Повторная попытка должна ссылаться на собственное событие назначения, а не использовать каталог, оставшийся после worker.

В Playwright постоянный context даёт одному процессу браузера каталог пользовательских данных. При запуске BotBrowser оператор также передаёт аргумент профиля и утверждённые параметры сети. Храните эти значения вместе и записывайте только стабильные идентификаторы, не содержимое профиля и не секреты прокси.

Назначение профиля - операционный контроль, а не обещание решения сайта. Оно делает границу проверяемой. Оно не делает допустимыми несвязанные аккаунты, не разрешает игнорировать ограничение платформы и не гарантирует принятие сессии третьей стороной.

Запустите fixture разделения хранилища

Следующий fixture на Node.js использует Chromium из Playwright и локальный HTTP-сервер. Он записывает безопасные cookie и значение localStorage в задаче A, читает их в задаче B и выводит, унаследовала ли их вторая задача. В первом запуске задачи получают разные каталоги; во втором один каталог намеренно используется повторно, чтобы показать утечку.

// save as profile-isolation-fixture.mjs
import { chromium } from 'playwright';
import { createServer } from 'node:http';
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';

const server = createServer((request, response) => {
  response.setHeader('Content-Type', 'text/html');
  response.end('<!doctype html><title>profile fixture</title><p data-fixture="profile-isolation">owned fixture</p>');
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const port = server.address().port;
const origin = `http://127.0.0.1:${port}`;

async function runTask(taskId, storageDir, writeState) {
  const context = await chromium.launchPersistentContext(storageDir, { headless: true });
  const page = await context.newPage();
  await page.goto(origin);
  if (writeState) {
    await page.context().addCookies([{ name: 'task_marker', value: taskId, url: origin }]);
    await page.evaluate(value => localStorage.setItem('task_marker', value), taskId);
  }
  const observed = {
    cookie: (await context.cookies()).find(cookie => cookie.name === 'task_marker')?.value ?? null,
    localStorage: await page.evaluate(() => localStorage.getItem('task_marker')),
  };
  await context.close();
  return observed;
}

const root = await mkdtemp(join(tmpdir(), 'agent-profile-fixture-'));
const separateA = await runTask('task-a', join(root, 'profile-a'), true);
const separateB = await runTask('task-b', join(root, 'profile-b'), false);
console.log(JSON.stringify({ case: 'separate', taskA: separateA, taskB: separateB }));

const sharedA = await runTask('task-a', join(root, 'shared-profile'), true);
const sharedB = await runTask('task-b', join(root, 'shared-profile'), false);
console.log(JSON.stringify({ case: 'shared', taskA: sharedA, taskB: sharedB }));

await rm(root, { recursive: true, force: true });
server.close();

Запустите node profile-isolation-fixture.mjs. Ожидаемая форма:

{"case":"separate","taskA":{"cookie":"task-a","localStorage":"task-a"},"taskB":{"cookie":null,"localStorage":null}}
{"case":"shared","taskA":{"cookie":"task-a","localStorage":"task-a"},"taskB":{"cookie":"task-a","localStorage":"task-a"}}

Раздельный случай устанавливает видимую странице границу хранения: задача B не читает маркер задачи A. Общий случай - fixture отказа; оба значения показывают, что второй запуск открыл то же постоянное хранилище. Это локальный запускаемый пример, а не результат наблюдения BotBrowser.

Fixture намеренно использует локальный origin и синтетические данные. Он не записывает учётные данные, не посещает сторонний сервис и не утверждает, что страница видит все настройки браузера. Для производственной проверки сохраните ту же структуру сравнения, используйте утверждённый endpoint только для чтения и сохраните ID назначения вместе с результатом.

Что проверяет fixture и чего он не проверяет

Цель - сделать утечку заметной с помощью значений без делового смысла. Cookie ограничена локальным origin, а localStorage записывает сама страница. Поскольку оба значения читаются после нового запуска, ненулевой результат задачи B связывается с постоянным каталогом, а не с переменной в процессе Node.js. Очистка удаляет временные каталоги, поэтому следующий запуск начинается из известного состояния.

Fixture не проверяет кеш, регистрации фоновых worker, разрешения, IndexedDB, загрузки или состояние расширений. В реальной нагрузке эти поверхности могут быть важны; добавьте их в отдельный утверждённый fixture, если они входят в границу идентичности. Добавляйте по одному именованному маркеру, записывайте ожидаемое пустое значение для новой задачи и не изменяйте внешний сервис.

Fixture также не выбирает профиль BotBrowser. Производственный launcher может обернуть ту же функцию задачи разрешённым аргументом --bot-profile и назначенным каталогом. Держите оболочку вне кода страницы, чтобы не путать наблюдение с доказательством командной строки. Настройка Playwright для BotBrowser описывает интеграцию; выбор пакета и его назначение остаются ответственностью оператора.

Сделайте ожидаемый результат машинно проверяемым

Не заставляйте человека сравнивать две строки JSON. Планировщик может завершить задачу ошибкой, если новая задача видит маркер или если общий случай его не видит:

function requireValue(value, expected, label) {
  if (value !== expected) throw new Error(`${label}: expected ${expected}, got ${value}`);
}

requireValue(separateB.cookie, null, 'separate cookie');
requireValue(separateB.localStorage, null, 'separate localStorage');
requireValue(sharedB.cookie, 'task-a', 'shared cookie');
requireValue(sharedB.localStorage, 'task-a', 'shared localStorage');

Держите это утверждение рядом с результатом fixture, а не в общем health check. Проверка, которая подтверждает только загрузку страницы, может пройти при неправильном хранилище. При сбое включите taskId, profileId, метку пути хранения, версию браузера и результат fixture в ограниченную запись. Не записывайте реальные cookies или секрет прокси в общий журнал.

Проверяйте сетевую идентичность отдельно

Разделение хранения автоматически не разделяет сетевую идентичность. Свяжите каждый профиль с утверждённой сетевой политикой и регионом, затем проверьте маршрут через endpoint оператора, который сообщает публичный адрес и регион запроса. Запишите результат рядом с profileId; не выводите его из cookies или успешной загрузки страницы.

Если оператор назначил двум задачам одну и ту же ссылку на сетевую политику, обе используют настроенные прокси и маршрут; повторное использование профиля само по себе не доказывает, что маршрут общий. В руководстве BotBrowser по настройке прокси отдельно описаны параметры запуска и маршрутизации. Это проверка конфигурации, а не решение детектора. Другой каталог хранения не превращает один настроенный маршрут в два.

ПоверхностьПроверкаЧто устанавливаетЧто сама по себе не устанавливает
ХранилищеCookie task_marker и localStorageВидимое странице состояние разделеноИсполняемый файл, пакет профиля или публичный IP
СетьEndpoint-эхо оператораЗапрос использовал записанный маршрут в этот моментКлассификацию третьей стороны или будущую стабильность
ЗапускСокращённая команда и запись назначенияОператор передал ожидаемый профильЧто все сигналы страницы совпадают с политикой

Документация BotBrowser по отпечатку на уровне context описывает входы идентичности, ограниченные контекстом, а управление профилями - жизненный цикл и владельца. Используйте эти ссылки для определения утверждённого назначения. Руководство о headless-браузере для AI-агентов объясняет, почему вывод страницы и доказательство процесса должны оставаться раздельными; применяйте то же правило к сетевым результатам.

Ответ endpoint должен содержать время и ссылку на назначение. Публичный адрес и регион меняются после ротации, отказа инфраструктуры или обновления политики. Считайте результат измерением этого запроса, а не постоянным свойством профиля. Если задаче нужен стабильный регион, планировщик должен отклонить маршрут вне политики до открытия страницы и закрыть сессию при недоступности маршрута.

Не заменяйте проверку маршрута догадкой браузера. navigator.language, часовой пояс или результат разрешения геолокации описывают настройку или разрешение; ни один из них сам по себе не идентифицирует публичный сетевой путь. Endpoint организации, управляющей планировщиком, может связать ответ с назначением, не прося сторонний сайт классифицировать сессию. Делайте ответ минимальным, редактируйте широкие отчёты и храните полный результат только установленный срок.

Закрывайте, повторяйте и проверяйте каждое назначение

Изоляция зависит от жизненного цикла не меньше, чем от команды запуска. Завершайте задачу так: прекратите принимать работу, дайте странице достичь контролируемого состояния, соберите результат, закройте context и отметьте судьбу хранилища. Только после этого планировщик должен выдавать worker другой задаче. Процесс, который ещё записывает cookies во время повторного назначения каталога, создаёт утечку, похожую на случайную.

Для каждой попытки используйте неизменяемое событие назначения. Повтор получает новое событие с причиной вроде navigation-timeout, fixture-mismatch или route-unavailable. Сохраняйте предыдущее событие вместе с результатом вместо перезаписи его profileId. Так можно установить, относится ли сбой к приложению, launcher или пакету.

Проверка до запускаОтклонять, еслиЗачем
Состояние профиляОтсутствует, retired или не утверждёнНе даёт непроверенной идентичности получить работу
Аренда хранилищаКаталог активен для другого назначенияПредотвращает одновременные записи и перенос состояния
Сетевая политикаСсылка отсутствует или регион не подходитДелает владельца маршрута явным
Пара браузер-релизРелиз не совпадает с утверждённой записьюПредотвращает непроверенную комбинацию
Предыдущее закрытиеПредыдущий владелец не закрыл сессию чистоНе даёт переиспользовать загрязнённый каталог

При отказе проверки возвращайте очереди короткую причину, а подробную запись - в ограниченный канал поддержки. “Аренда хранилища активна” помогает оператору; выгрузка пакета или полной командной строки в общий журнал - нет. Управление профилями описывает состояния владельца и отзыва, делающие такие проверки аудируемыми.

При проверке сравнивайте три записи: событие назначения, видимый странице результат fixture и доказательство запуска или маршрута от оператора. Они должны совпадать по задаче и времени, но отвечают на разные вопросы. Одинаковая cookie не доказывает одинаковый маршрут; одинаковый маршрут не доказывает открытие нужного профиля; одинаковая команда не доказывает загрузку нужного origin.

Для долгоживущего worker планируйте чистый перезапуск на границе, заданной политикой, вместо бесконечного сохранения назначения. Перезапуск не заменяет изоляцию, но выявляет проблемы закрытия, скрытые в одном процессе. Записывайте, был ли перезапуск ожидаемым, какой профиль освобождён и получил ли следующий task новый или ещё утверждённый постоянный каталог.

Та же запись помогает при инциденте. Если tenant видит баннер предыдущей задачи, сначала сравните события и метки хранения, затем проверьте результат fixture у затронутого worker. Если маркер виден только на одном worker, изолируйте его каталог и остановите новые задачи, пока владелец проверяет закрытие. Если маркер виден на всех, проверьте отображение планировщика и общий том до изменения кода страницы.

Интерпретация и ограничения

Рассматривайте чистое сравнение как узкий результат приёмки. Оно означает, что этот fixture на этой машине увидел ожидаемые значения хранения и, если проверялось отдельно, что endpoint оператора вернул записанный результат. Оно не означает, что сайт примет сессию, браузер неотличим от другого или детектор выдаст определённое решение.

Исследуйте сбой в принадлежащем ему слое. Ненулевой маркер в раздельном случае указывает на каталог, закрытие или назначение. Изменение сети указывает на политику маршрута, прокси или толкование endpoint. Другой launcher - доказательство процесса; его нельзя исправить просьбой к агенту изучить JavaScript страницы.

Не используйте профили на задачу, чтобы игнорировать лимиты аккаунтов или условия платформы. Изоляция подходит для разрешённых tenant, тестов и границ приватности. Оператор отвечает за учётные данные, согласие, хранение, лимиты частоты и правила сервиса.

Вопросы и ответы

Достаточно ли одного Playwright BrowserContext для двух задач?

Только если контексты создаются и закрываются по явной политике назначения. Контекст разделяет cookies и хранилище, но не заменяет решение о профиле BotBrowser, сетевой политике и владельце каждой задачи.

Доказывает ли fixture запуск двух профилей BotBrowser?

Нет. Он доказывает только значения хранения, которые прочитала локальная страница. Подтвердите исполняемый файл, сокращённый аргумент профиля и запись назначения через доказательство процесса оператора.

Гарантируют ли отдельные профили решение детектора?

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

Что делать при повторной попытке после сбоя?

Закройте старый context, сохраните его ID и результат, затем получите новое утверждённое назначение по политике нагрузки. Не наследуйте каталог, оставшийся у worker, только потому, что он доступен.

Источники

Практический вывод

Назначайте profileId, хранилище и сетевую политику до запуска каждой задачи агента. Докажите границу двумя каталогами и намеренным случаем общего каталога, затем проверьте сеть через endpoint оператора. Храните отдельно наблюдения страницы, доказательства запуска и классификацию третьей стороны. Так изоляция профиля агента для каждой задачи становится проверяемой без обещания решения детектора и без игнорирования правил платформы.

#Ai Agents#профили#Isolation#хранилище#Network Identity

Эта статья входит в руководство: Поверхности идентичности браузера: обзор согласованности

Выполните ту же проверку в BotBrowser

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