browser-agent
by maxmkab
README.md
# Autonomous Browser Agent — без скриншотов
Агент управляет реальным Chromium через Playwright, а решения принимает LLM на основе
**структурного текстового снимка страницы** (`ref | role | name | состояния`), а не картинок.
Vision-модель не нужна, скриншоты не делаются ни на одном шаге.
Три режима работы из одной кодовой базы:
| Режим | Как включается | Зачем |
|---|---|---|
| Локально, видимый браузер | `HEADLESS=false` | отладка, визуальный контроль |
| Твой реальный Chrome по CDP | `CDP_URL=http://127.0.0.1:9222` | живые сессии, лучший фингерпринт |
| VPS headless 24/7 | `HEADLESS=true` + Docker/systemd | автономная работа по очереди задач |
## Архитектура
| Файл | Назначение |
|---|---|
| `snapshot.py` | JS-инжект: обход DOM + open Shadow DOM + iframes, отбор видимых интерактивных элементов, `data-agent-ref`, компактный текст для LLM |
| `browser.py` | сессия Playwright (headless/headful/CDP, stealth-init, прокси, блокировка картинок) и исполнитель 14 действий |
| `llm.py` | планировщик: Anthropic / OpenAI-совместимые / Ollama, строгий JSON-протокол действий |
| `agent.py` | LangGraph-цикл `observe → decide → act`, сжатие истории, детект зацикливания, HITL, лимиты |
| `main.py` | CLI: `run`, `login`, `snapshot`, `daemon` + Telegram-уведомления и подтверждения |
| `mcp_server.py` | MCP-сервер: 13 инструментов браузера для Claude Code / Cursor / своего оркестратора |
| `scripts/chrome-cdp.*` | запуск твоего Chrome с отладочным портом (Linux/macOS и Windows) |
| `Dockerfile` | образ на базе `mcr.microsoft.com/playwright/python` для VPS |
## 1. Установка на локальный комп
```bash
git clone https://github.com/maxmkab/autonomous-browser-agent.git
cd autonomous-browser-agent
python -m venv .venv
source .venv/bin/activate # Windows: .venv\\Scripts\\activate
pip install -r requirements.txt
playwright install chromium
cp .env.example .env # вписать ANTHROPIC_API_KEY
```
Проверка без трат на LLM — посмотреть, что именно видит модель:
```bash
python main.py snapshot --url https://example.com
```
Запуск задачи с видимым браузером:
```bash
HEADLESS=false python main.py run \
--task "Найди раздел с ценами и извлеки все тарифы через extract" \
--url https://example.com \
--json state/report.json
```
## 2. Встраивание в твой реальный браузер (CDP)
Агент может работать не в своём чистом Chromium, а в твоём Chrome — с живыми сессиями,
расширениями и настоящим фингерпринтом. Никакие расширения ставить не нужно —
управление идёт по Chrome DevTools Protocol.
```bash
# 1) запустить Chrome с открытым портом (отдельный профиль для агента)
chmod +x scripts/chrome-cdp.sh
./scripts/chrome-cdp.sh 9222 # Windows: scripts\\chrome-cdp.bat 9222
# 2) в другом терминале отдать задачу агенту в этом же браузере
CDP_URL=http://127.0.0.1:9222 python main.py run --task "..."
```
В этом режиме агент не трогает `storage_state.json`: сессии берутся из профиля Chrome.
Первый запуск — залогинься в нужных сервисах руками, дальше профиль их помнит.
## 3. Встраивание в Claude Code / Cursor через MCP
`mcp_server.py` поднимает MCP-сервер со stdio-транспортом. Инструменты:
`browser_open`, `browser_snapshot`, `browser_click`, `browser_type`, `browser_select`,
`browser_check`, `browser_scroll`, `browser_press`, `browser_back`, `browser_tabs`,
`browser_save_session`, `browser_run_task`, `browser_close`.
Конфиг для Claude Code (`~/.claude.json` или `.mcp.json` в корне проекта):
```json
{
"mcpServers": {
"browser-agent": {
"command": "/absolute/path/autonomous-browser-agent/.venv/bin/python",
"args": ["/absolute/path/autonomous-browser-agent/mcp_server.py"],
"env": {
"HEADLESS": "false",
"CDP_URL": "http://127.0.0.1:9222",
"ANTHROPIC_API_KEY": "sk-ant-...",
"REQUIRE_APPROVAL": "true"
}
}
}
}
```
Или одной командой:
```bash
claude mcp add browser-agent -- /absolute/path/.venv/bin/python /absolute/path/mcp_server.py
```
После этого модель в Claude Code ведёт браузер циклом
`browser_snapshot → browser_click → browser_snapshot`, получая только текстовые снимки.
Сессия браузера живёт между вызовами, поэтому сценарий можно вести шаг за шагом.
Для полной автономии есть `browser_run_task` — агент сам крутит цикл и возвращает JSON-отчёт.
## 4. Перенос авторизации на сервер
```bash
# локально, в видимом окне: залогинился → Enter в консоли
HEADLESS=false python main.py login --url https://site.ru/login
# переносим cookies + localStorage на сервер
scp state/storage_state.json root@YOUR_VPS_IP:/opt/browser-agent/state/
```
## 5. Деплой на VPS (Ubuntu 24.04 + Docker)
```bash
mkdir -p /opt/browser-agent/state && cd /opt/browser-agent
git clone https://github.com/maxmkab/autonomous-browser-agent.git .
cp .env.example .env && nano .env
docker build -t browser-agent .
docker run -d --name browser-agent --restart unless-stopped \
--shm-size=1g \
--env-file .env \
-v /opt/browser-agent/state:/app/state \
browser-agent
```
`--shm-size=1g` обязателен: Chromium в контейнере с дефолтными 64 МБ /dev/shm падает
на тяжёлых страницах.
Разовая задача на сервере:
```bash
docker exec -it browser-agent python main.py run --task "..." --url https://...
```
### Без Docker (systemd)
```bash
apt update && apt install -y python3-venv
cd /opt/browser-agent && python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
playwright install --with-deps chromium
```
`/etc/systemd/system/browser-agent.service`:
```ini
[Unit]
Description=Autonomous browser agent
After=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/browser-agent
EnvironmentFile=/opt/browser-agent/.env
ExecStart=/opt/browser-agent/.venv/bin/python main.py daemon --interval 300
Restart=always
RestartSec=10
StandardOutput=append:/var/log/browser-agent.log
StandardError=append:/var/log/browser-agent.log
[Install]
WantedBy=multi-user.target
```
```bash
systemctl daemon-reload && systemctl enable --now browser-agent
journalctl -u browser-agent -f
```
## 6. Постановка задач и n8n
Демон читает `state/tasks.jsonl` — одна строка = одна задача:
```jsonl
{"id":"price-check-1","task":"Открой карточку товара, извлеки цену и наличие через extract","url":"https://site.ru/item/123"}
{"id":"lead-form","task":"Заполни форму заявки: имя Иван, телефон +79990000000. Отправку подтвердит человек."}
```
Результаты пишутся в `state/results.jsonl` с полями `success`, `result`, `extracted`,
`steps`, `tokens_in/out` и полной трассой `history`. n8n может писать задачи в этот файл
(нода Execute Command / SSH) и читать результаты.
## 7. Экономия токенов
- **Никаких скриншотов**: только текст, без vision-модели.
- **Фильтрация DOM**: в контекст идут лишь видимые интерактивные элементы с непустым именем, максимум 250 на фрейм.
- **Блокировка картинок/шрифтов/медиа** на уровне сети (`BLOCK_MEDIA=true`).
- **Сжатие истории** (`HISTORY_WINDOW`): полные снимки только для последних шагов, старые сворачиваются в `action → result`.
- **Детект зацикливания**: если fingerprint снимка не меняется, модели даётся указание сменить стратегию.
## 8. Безопасность
Действия, попадающие под `RISKY_PATTERNS` (оплата, купить, заказать, удалить, отправить,
checkout, pay, delete), требуют подтверждения: в консоли локально или ответом «да» в Telegram
на сервере (`APPROVAL_MODE=telegram`). `ALLOW_EVAL=false` по умолчанию запрещает выполнение
произвольного JS. Все ошибки действий возвращаются модели как observation и не роняют процесс.
Секреты хранятся только в `.env`, который исключён из git.
## 9. Проверка перед продакшеном
1. `python main.py snapshot --url <целевой сайт>` — нужные элементы попадают в снимок?
2. Прогон задачи локально в headful с `REQUIRE_APPROVAL=true`.
3. Та же задача локально в headless — ловит различия рендеринга до деплоя.
4. Только потом деплой на VPS и запуск демона.
## Лицензия
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues