wiki/sources/legacy/Spec.md
Scout — Platform Spec
What It Is
Scout is a self-hosted web intelligence platform built on Crawl4AI. It is the data acquisition layer for PRISM — replacing Apify — and a general-purpose company intelligence crawler embeddable in any tool (Claude via skill, CLI, N8N).
Scout is NOT a general-purpose scraper. It is purpose-built for specific company intelligence use cases: About page, executive team, hiring openings, investor relations, and PDF reports.
Why It Exists
- Replace Apify (SaaS billing, TypeScript FFI, vendor data access, no Python integration)
- Firecrawl rejected: AGPL-3.0 core, loses Fire-engine on self-host, TypeScript stack
- Crawl4AI: Apache 2.0, Python-native, stealth Playwright, LLM extraction built-in
- PRISM intel modules need a consistent, schema-validated crawling interface
License note: Crawl4AI is Apache 2.0 (NOT MIT). Attribution required per project custom requirement: "This product includes software developed by UncleCode (https://x.com/unclecode) as part of the Crawl4AI project, licensed under the Apache License 2.0." Attribution appears in README.md and CLI --help.
Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
| /scrape | POST | Single URL → markdown + optional screenshot + metadata (handles PDFs natively) |
| /crawl | POST | BFS recursive multi-page crawl via BFSDeepCrawlStrategy |
| /extract | POST | LLM structured extraction (Pydantic schema + instruction) OR CSS fallback |
| /map | POST | Fast URL discovery (no content) — sitemap-first + BFS fallback |
| /screenshot | POST | Visual capture only |
| /health | GET | Readiness probe (unauthenticated) |
| /search | — | DROPPED — Crawl4AI doesn't do web search; Perplexity handles this in PRISM |
| /interact | — | DROPPED from Phase 1 — action chains deferred to Phase 2+ |
API Contracts (source of truth: scout/core/types.py)
All request/response shapes are Pydantic v2 models. No raw dicts cross boundaries.
Authentication: X-API-Key header. /health exempt. Missing/wrong key → 403.
ExtractRequest — dual-mode extraction:
- LLM mode: schema (dict) + instruction (str) + llm_provider. Requires LLM_API_KEY env var.
- CSS mode: css_schema (dict: {name, baseSelector, fields: [{name, selector, type}]}). No API key needed, fast.
- If no API key AND no css_schema → returns success=False with clear error message.
MapResponse: urls: list[str] — always plain strings. aseed_urls normalisation applied server-side.
Architecture
scout/
core/ ← Python library (PRISM imports directly — no HTTP)
types.py ← All Pydantic contracts
version.py ← Crawl4AI version pin (currently 0.7.7)
crawler.py ← ScoutCrawler: unified async entry point
modes/ ← scrape, crawl, extract, map, screenshot
api/ ← FastAPI service (external callers: Claude skill, CLI, N8N)
main.py ← App + lifespan (ScoutCrawler singleton)
routers/ ← 5 endpoint routers + health
middleware/ ← API key auth
config.py ← Pydantic Settings
cli.py ← Typer CLI (scout scrape/crawl/map/extract/screenshot)
skill/ ← Claude Code skill (scout.md)
scout.md ← Company intelligence playbook (map→scrape pattern, 5 use cases)
docker/ ← Dockerfile + docker-compose.yml
Key design decision: PRISM uses from scout.core import ScoutCrawler directly (zero HTTP overhead). FastAPI is for external callers only.
Critical Crawl4AI API Facts (verified against v0.7.7)
aseed_urls(domain, config=SeedingConfig)→ takes BARE domain string (not full URL); returnslist[str]ORlist[dict]depending on domain — normalise output unconditionally (extractu["url"]from dicts)crawler.arun(url, config=run_cfg)withdeep_crawl_strategy=bfsinCrawlerRunConfig→ returnsAsyncGenerator[CrawlResult, None]in stream mode- BFSDeepCrawlStrategy entry point: attach to
CrawlerRunConfig(deep_crawl_strategy=bfs, stream=True)then callcrawler.arun(url, config)—DeepCrawlDecoratorinterceptsarun()and dispatches BFS internally. Do NOT callarun_many()from outside — it bypasses the decorator. result.markdown→ usestr(result.markdown or "")to safely handle Noneresult.links→{"internal": [{"href": "...", "text": "..."}], "external": [...]}FilterChaindefault:FilterChain()notNone
Known Limitations
| Limitation | Detail |
|---|---|
| ATS SPA job boards | Workday, Greenhouse (React) load job listings via authenticated XHR after mount — Scout cannot paginate these. Detect ATS redirect and document the platform. |
| /map dict normalisation | aseed_urls returns dicts on some domains (shopify.com, algolia.com). Fixed in 4cbd952 — normalised to list[str] server-side. |
| /extract end-to-end | LLM mode requires LLM_API_KEY in Scout's .env. CSS fallback available without key. |
| Docker smoke test | Dockerfile exists, not fully end-to-end tested (docker compose up → /health) |
Claude Code Skill
scout/skill/scout.md — installed at ~/.claude/commands/scout.md.
The skill is a company intelligence playbook, not an API reference. It teaches:
1. Full Company Profile pattern: map once → scrape all 5 sections (About, Exec team, Hiring, Investor, PDFs)
2. formats: ["raw_html"] technique for JS-rendered team pages that return sparse markdown
3. ATS detection guidance (Workday, Greenhouse, Lever)
4. Map → Filter → Scrape pattern for single intelligence types
Phase Status
| Phase | Status | Description |
|---|---|---|
| Phase 1 — Core library | ✅ COMPLETE | types, crawler, 5 modes, 78 tests passing |
| Phase 1 — API layer | ✅ COMPLETE | FastAPI, auth, 5 routers, DI pattern |
| Phase 1 — Docker | ✅ COMPLETE | Dockerfile + docker-compose, shm_size=1gb |
| CSS extraction fallback | ✅ COMPLETE | JsonCssExtractionStrategy when no LLM key |
| CLI | ✅ COMPLETE | Typer CLI (scout scrape/crawl/map/extract/screenshot) |
| README + attribution | ✅ COMPLETE | Crawl4AI Apache 2.0 attribution in README |
| Claude skill | ✅ COMPLETE | Installed at ~/.claude/commands/scout.md |
| /map dict bug fix | ✅ COMPLETE | aseed_urls normalisation — 4cbd952 |
| Phase 4 — PRISM integration | ✅ COMPLETE | intel-hiring 2-track pipeline. 213/213 tests. |
| Feature complete | ✅ 2026-05-04 | All planned capabilities shipped and validated |
| Phase 3 — MCP server | ⏳ Future | MCP server for direct tool use |
| Phase 5 — intel-company migration | ⏳ Future | intel-company still uses httpx/Jina for Track 1 |
Repo
/Users/arijitchowdhury/AI-Development/Scout/
Branch: main
Latest commits:
- 4cbd952 fix(map): normalise aseed_urls output to list[str] for all domains
- 2aee8a9 feat(cli): add Scout CLI with scrape/crawl/map/extract/screenshot commands
- d14c248 docs: add README with Crawl4AI attribution and usage guide
- 0d9aaa7 feat(extract): add CSS fallback when no LLM API key configured
- e8b06bd refactor(core): use native Crawl4AI for map + crawl modes