15 KiB
Task: Web Crawler Service (crawl4ai) & Agent Tool Integration
Goal
Інтегрувати crawl4ai в агентську систему MicroDAO/DAARION як:
- Окремий бекенд-сервіс Web Crawler, який:
- вміє скрапити сторінки з JS (Playwright/Chromium),
- повертати структурований текст/HTML/метадані,
- (опційно) генерувати події
doc.upsertedдля RAG-ingestion.
- Агентський tool
web_crawler, який викликається через Tool Proxy і доступний агентам (Team Assistant, Bridges Agent, тощо) з урахуванням безпеки.
Мета — дати агентам можливість читати зовнішні веб-ресурси (з обмеженнями) і, за потреби, індексувати їх у RAG.
Context
- Root:
microdao-daarion/. - Інфраструктура агентів та tools:
docs/cursor/12_agent_runtime_core.mddocs/cursor/13_agent_memory_system.mddocs/cursor/37_agent_tools_and_plugins_specification.mddocs/cursor/20_integrations_bridges_agent.md
- RAG-шар:
docs/cursor/rag_gateway_task.mddocs/cursor/rag_ingestion_worker_task.mddocs/cursor/rag_ingestion_events_wave1_mvp_task.md
- Event Catalog / NATS:
docs/cursor/42_nats_event_streams_and_event_catalog.mddocs/cursor/43_database_events_outbox_design.md
На сервері вже встановлено crawl4ai[all] та playwright chromium.
1. Сервіс Web Crawler
1.1. Структура сервісу
Створити новий Python-сервіс (подібно до інших внутрішніх сервісів):
- Директорія:
services/web-crawler/ - Файли (пропозиція):
main.py— entrypoint (FastAPI/uvicorn).api.py— визначення HTTP-ендпоїнтів.crawl_client.py— обгортка над crawl4ai.models.py— Pydantic-схеми (request/response).config.py— налаштування (timeouts, max_depth, allowlist доменів, тощо).
Сервіс не має прямого UI; його викликають Tool Proxy / інші бекенд-сервіси.
1.2. Основний ендпоїнт: POST /api/web/scrape
Пропонований контракт:
Request JSON:
{
"url": "https://example.com/article",
"team_id": "dao_greenfood",
"session_id": "sess_...",
"max_depth": 1,
"max_pages": 1,
"js_enabled": true,
"timeout_seconds": 30,
"user_agent": "MicroDAO-Crawler/1.0",
"mode": "public",
"indexed": false,
"tags": ["external", "web", "research"],
"return_html": false,
"max_chars": 20000
}
Response JSON (скорочено):
{
"ok": true,
"url": "https://example.com/article",
"final_url": "https://example.com/article",
"status_code": 200,
"content": {
"text": "... main extracted text ...",
"html": "<html>...</html>",
"title": "Example Article",
"language": "en",
"meta": {
"description": "...",
"keywords": ["..."]
}
},
"links": [
{ "url": "https://example.com/next", "text": "Next" }
],
"raw_size_bytes": 123456,
"fetched_at": "2025-11-17T10:45:00Z"
}
Використати API/параметри crawl4ai для:
- рендеру JS (Playwright),
- витягання основного контенту (article/reader mode, якщо є),
- нормалізації тексту (видалення зайвого boilerplate).
1.3. Додаткові ендпоїнти (опційно)
POST /api/web/scrape_batch— масовий скрап кількох URL (обмежений top-K).POST /api/web/crawl_site— обхід сайту зmax_depth/max_pages(для MVP можна не реалізовувати або залишити TODO).POST /api/web/scrape_and_ingest— варіант, який одразу шле подіюdoc.upserted(див. розділ 3).
1.4. Обмеження та безпека
У config.py передбачити:
MAX_DEPTH(наприклад, 1–2 для MVP).MAX_PAGES(наприклад, 3–5).MAX_CHARS/MAX_BYTES(щоб не забивати памʼять).- (Опційно) allowlist/denylist доменів для кожної команди/DAO.
- таймаут HTTP/JS-запиту.
Логувати тільки мінімальний технічний контекст (URL, код статусу, тривалість), не зберігати повний HTML у логах.
2. Обгортка над crawl4ai (crawl_client.py)
Створити модуль, який інкапсулює виклики crawl4ai, щоб API/деталі можна було змінювати централізовано.
Приблизна логіка:
- функція
async def fetch_page(url: str, options: CrawlOptions) -> CrawlResult:- налаштувати crawl4ai з Playwright (chromium),
- виконати рендер/збір контенту,
- повернути нормалізований результат: text, html (опційно), метадані, посилання.
Обовʼязково:
- коректно обробляти помилки мережі, редіректи, 4xx/5xx;
- повертати
ok=false+ error message у HTTP-відповіді API.
3. Інтеграція з RAG-ingestion (doc.upserted)
3.1. Подія doc.upserted для веб-сторінок
Після успішного скрапу, якщо indexed=true, Web Crawler може (в майбутньому або одразу) створювати подію:
event:doc.upsertedstream:STREAM_PROJECTабо спеціальнийSTREAM_DOCS
Payload (адаптований під RAG-дизайн):
{
"doc_id": "web::<hash_of_url>",
"team_id": "dao_greenfood",
"project_id": null,
"path": "web/https_example_com_article",
"title": "Example Article",
"text": "... main extracted text ...",
"url": "https://example.com/article",
"tags": ["web", "external", "research"],
"visibility": "public",
"doc_type": "web",
"indexed": true,
"mode": "public",
"updated_at": "2025-11-17T10:45:00Z"
}
Цю подію можна:
- заповнити в таблицю outbox (див.
43_database_events_outbox_design.md), - з неї Outbox Worker відправить у NATS (JetStream),
rag-ingest-worker(згідноrag_ingestion_events_wave1_mvp_task.md) сприймеdoc.upsertedі проіндексує сторінку в Milvus/Neo4j.
3.2. Підтримка у нормалізаторі
У services/rag-ingest-worker/pipeline/normalization.py уже є/буде normalize_doc_upserted:
- для веб-сторінок
doc_type="web"потрібно лише переконатися, що:source_type = "doc"або"web"(на твій вибір, але консистентний),- у
tagsвключено"web"/"external", - у metadata є
url.
Якщо потрібно, можна додати просту гілку для doc_type == "web".
4. Agent Tool: web_crawler
4.1. Категорія безпеки
Відповідно до 37_agent_tools_and_plugins_specification.md:
- Зовнішній інтернет — Category D — Critical Tools (
browser-full,external_api). - Новий інструмент:
- назва:
web_crawler, - capability:
tool.web_crawler.invoke, - категорія: D (Critical),
- за замовчуванням вимкнений — вмикається Governance/адміністратором для конкретних MicroDAO.
- назва:
4.2. Tool request/response контракт
Tool Proxy викликає Web Crawler через HTTP.
Request від Agent Runtime до Tool Proxy:
{
"tool": "web_crawler",
"args": {
"url": "https://example.com/article",
"max_chars": 8000,
"indexed": false,
"mode": "public"
},
"context": {
"agent_run_id": "ar_123",
"team_id": "dao_greenfood",
"user_id": "u_001",
"channel_id": "ch_abc"
}
}
Tool Proxy далі робить HTTP-запит до web-crawler сервісу (POST /api/web/scrape).
Відповідь до агента (спрощена):
{
"ok": true,
"output": {
"title": "Example Article",
"url": "https://example.com/article",
"snippet": "Короткий уривок тексту...",
"full_text": "... обрізаний до max_chars ..."
}
}
Для безпеки:
- у відповідь, яку бачить LLM/агент, повертати обмежений
full_text(наприклад, 8–10k символів), - якщо
full_textзанадто довгий — обрізати та явно це позначити.
4.3. PDP та quotas
- Перед викликом Tool Proxy повинен викликати PDP:
action = tool.web_crawler.invoke,subject = agent_id,resource = team_id.
- Usage Service (див. 44_usage_accounting_and_quota_engine.md) може:
- рахувати кількість викликів
web_crawler/день, - обмежувати тривалість/обʼєм даних.
- рахувати кількість викликів
5. Інтеграція з Bridges Agent / іншими агентами
5.1. Bridges Agent
Bridges Agent (20_integrations_bridges_agent.md) може використовувати web_crawler як один зі своїх tools:
- сценарій: "Підтяни останню версію документації з https://docs.example.com/... і збережи як doc у Co-Memory";
- Bridges Agent викликає tool
web_crawler, отримує текст, створює внутрішній doc (через Projects/Co-Memory API) і генеруєdoc.upserted.
5.2. Team Assistant / Research-агенти
Для окремих DAO можна дозволити:
Team Assistantвикликаєweb_crawlerдля досліджень (наприклад, "знайди інформацію на сайті Мінекономіки про гранти"),- але з жорсткими лімітами (whitelist доменів, rate limits).
6. Confidential mode та privacy
Згідно з 47_messaging_channels_and_privacy_layers.md та 48_teams_access_control_and_confidential_mode.md:
- Якщо контекст агента
mode = confidential:- інструмент
web_crawlerне повинен отримувати confidential plaintext із внутрішніх повідомлень (тобто, уargsне має бути фрагментів внутрішнього тексту); - зазвичай достатньо лише URL.
- інструмент
- Якщо
indexed=trueтаmode=confidentialдля веб-сторінки (рідкісний кейс):- можна дозволити зберігати plaintext сторінки в RAG, оскільки це зовнішнє джерело;
- але варто позначати таку інформацію як
source_type="web_external"і у PDP контролювати, хто може її читати.
Для MVP в цій задачі достатньо:
- заборонити виклик
web_crawlerіз confidential-контексту без явної конфігурації (тобто PDP повертає deny).
7. Логування та моніторинг
Додати базове логування в Web Crawler:
- при кожному скрапі:
team_id,url,status_code,duration_ms,bytes_downloaded.
Без збереження body/HTML у логах.
За бажанням — контрприклад метрик:
web_crawler_requests_total,web_crawler_errors_total,web_crawler_avg_duration_ms.
8. Files to create/modify (suggested)
Назви/шляхи можна адаптувати до фактичної структури, важлива ідея.
-
services/web-crawler/main.py -
services/web-crawler/api.py -
services/web-crawler/crawl_client.py -
services/web-crawler/models.py -
services/web-crawler/config.py -
Tool Proxy / агентський runtime (Node/TS):
- додати tool
web_crawlerу список інструментів (див.37_agent_tools_and_plugins_specification.md). - оновити Tool Proxy, щоб він міг робити HTTP-виклик до Web Crawler.
- додати tool
-
Bridges/Team Assistant агенти:
- (опційно) додати
web_crawlerу їхні конфіги як доступний tool.
- (опційно) додати
-
RAG ingestion:
- (опційно) оновити
rag-ingest-worker/docs, щоб описатиdoc_type="web"уdoc.upsertedподіях.
- (опційно) оновити
9. Acceptance criteria
- Існує новий сервіс
web-crawlerз ендпоїнтомPOST /api/web/scrape, який використовує crawl4ai+Playwright для скрапу сторінок. - Ендпоїнт повертає текст/метадані у структурованому JSON, з обмеженнями по розміру.
- Заготовлена (або реалізована) інтеграція з Event Catalog через подію
doc.upsertedдляdoc_type="web"(indexed=true). - У Tool Proxy зʼявився tool
web_crawler(категорія D, capabilitytool.web_crawler.invoke) з чітким request/response контрактом. - PDP/usage engine враховують новий tool (принаймні у вигляді basic перевірок/квот).
- Bridges Agent (або Team Assistant) може використати
web_crawlerдля простого MVP-сценарію (наприклад: скрапнути одну сторінку і показати її summary користувачу). - Конфіденційний режим враховано: у конфігурації за замовчуванням
web_crawlerнедоступний уconfidentialканалах/командах.
10. Інструкція для Cursor
You are a senior backend engineer (Python + Node/TS) working on the DAARION/MicroDAO stack.
Implement the Web Crawler service and agent tool integration using:
- crawl4ai_web_crawler_task.md
- 37_agent_tools_and_plugins_specification.md
- 20_integrations_bridges_agent.md
- rag_gateway_task.md
- rag_ingestion_worker_task.md
- 42_nats_event_streams_and_event_catalog.md
Tasks:
1) Create the `services/web-crawler` service (FastAPI or equivalent) with /api/web/scrape based on crawl4ai.
2) Implement basic options: js_enabled, max_depth, max_pages, max_chars, timeouts.
3) Add tool `web_crawler` to the Tool Proxy (category D, capability tool.web_crawler.invoke).
4) Wire Tool Proxy → Web Crawler HTTP call with proper request/response mapping.
5) (Optional but preferred) Implement doc.upserted emission for indexed=true pages (doc_type="web") via the existing outbox → NATS flow.
6) Add a simple usage example in Bridges Agent or Team Assistant config (one agent that can use this tool in dev).
Output:
- list of modified files
- diff
- summary