SPB Git

spb/search-box Public

Agentic web research engine — hypotheses, verbatim evidence, contradictions, sourced answers streamed live. Claude Opus 5 + Firecrawl + PostgreSQL.

TypeScript 76.9% CSS 18.7% SQL 2.1% JavaScript 1.8% Shell 0.5%
2.7 KB

# Architecture

# Flow

text
question ─▶ POST /api/research ─▶ createSession ─▶ runSession (in-process)

              ┌─────────────────────────────────────────┤
              │ orchestrator loop (packages/agent)      │
              │  Claude decides: search / fetch /       │
              │  read_source / claims / evidence /      │
              │  contradictions / finish                │
              │  App enforces: budgets, schemas, SSRF   │
              └───────────────┬─────────────────────────┘

                    ResearchState (packages/research)
                    every mutation = 1 DB write + 1 event

                    PostgreSQL (packages/db)

        GET /api/research/:id/stream  (SSE, Last-Event-ID replay)

                    event-sourced UI (apps/web)

# Key decisions

  • No fixed pipeline. The model chooses strategy via tool use; the app owns safety (budgets in packages/shared/src/budgets.ts, zod-validated tool inputs, SSRF guard).
  • ResearchState is durable and lives in PostgreSQL, outside the model's context window. The ResearchState service is the single mutation path: state write and event append always happen together, so the UI can never show fabricated progress.
  • Event-sourced UI. The client rebuilds its entire view by replaying the event stream from seq 0 — the same mechanism gives live streaming, reconnection (Last-Event-ID), and full session replay for debugging.
  • Citations are mechanical. At synthesis time, sources carrying evidence receive stable indices (sources.assignCitationIndices, ordered by first evidence use). The synthesis model may only use the [n] markers provided; the UI links them back to sources.
  • In-process runner (apps/web/lib/runner.ts): sessions run inside the Next.js server process for the MVP. A queue (e.g. Redis-backed) only gets added when scale demands it.

# Model roles

Configured via env (CLAUDE_ORCHESTRATOR_MODEL, CLAUDE_SYNTHESIS_MODEL, …), all defaulting to claude-opus-5. The researcher/verifier roles are reserved for the post-MVP multi-agent phase (Explorer, Skeptic, Verifier, …) which only begins once the single-orchestrator engine is demonstrably reliable.