Get Auction List — enterprise assistant architecture
Authenticated assistant on getauctionlist.com that answers only from approved sources — policy RAG, auction SQL, and allowlisted county tools — with citation grounding and typed failure modes.
As-built · 2026-07 · auction-lens-ai (Next.js BFF) · get-auction-list-api (FastAPI + LangGraph)
Business capability
Enterprise constraints: browser never calls LLMs or MCP; answers are citation-grounded; failures are typed (completed / partial / failed); no invented auction rows or county dates.
| Capability | Intent | Runtime path |
|---|---|---|
| Policy / product terms | knowledge_policy | Hybrid RAG (chunks + embeddings) |
| Indexed auction filters | auction_search | Deterministic SQL on ingested rows |
| County schedule / WCAD | public_property_lookup | Allowlisted HTTPS tools (live) |
| Multi-source research | combined_research | Parallel fan-out → correlate → synthesize |
| Refusal | unsupported_or_unsafe | Guardrail short-circuit |
Logical architecture
Hard boundary: the browser never holds service-role keys and never calls OpenAI, FastAPI, or /mcp for Front Door chat.

| Layer | Components | Responsibility |
|---|---|---|
| Presentation | AiFrontDoorLauncher / Dialog, dashboard, lib/ai | Chat UX, SSE reduce, Zod shapes; dashboard parses Storage xlsx locally |
| Edge BFF | app/api/ai/{chat,chat/stream,feedback} | Same-origin only; Supabase session → Bearer JWT; proxy to AGENT_SERVICE_URL |
| AI control plane | FastAPI :8000, JWKS auth, ControlledAgentGraph, OpenAI structured models | Route, retrieve/tools, ground, synthesize, stream |
| Data & tools | Postgres + pgvector, Storage, PublicRecordsService / MCP, OpenAI | Durable indexes, object bytes, allowlisted egress, LLM/embeddings |
| Worker | auction-ingestion-worker | Offline policy + spreadsheet ingest into Postgres |
Request path

Stack
| Layer | Technology | Role |
|---|---|---|
| UI | Next.js 16, React 19, Tailwind 4, Base UI | Chat + dashboard |
| Validation | Zod (FE), Pydantic (BE) | Contract enforcement |
| BFF | Next Route Handlers | Session gate, SSE proxy, no browser secrets |
| Auth | Supabase Auth + JWKS | Same project FE↔BE |
| Orchestration | LangGraph (StateGraph, Send) | Bounded intents & budgets |
| LLM | OpenAI Responses API (gpt-4.1-mini) | Classify, extract, synthesize |
| Embeddings | text-embedding-3-small @ 1536 dims | Policy RAG only |
| Primary DB | Supabase PostgreSQL | Auth, auctions, RAG tables, jobs |
| Vector / keyword | pgvector + tsvector (english) | Hybrid retrieve |
| Object store | Supabase Storage auction_files | Monthly xlsx bytes |
| Public tools | FastMCP Streamable HTTP /mcp | Ops tooling; graph uses in-process service |
| HTTP egress | ApprovedHttpClient | Host allowlist, SSRF-safe |
| Obs | Prometheus /metrics, optional OTEL / Langfuse | No prompt/PII dump |
Control plane
One typed LangGraph orchestrator — bounded intents and budgets, not unconstrained ReAct.

| Node | Responsibility |
|---|---|
validation | Length ≤ 4000; injection heuristic |
routing | Heuristics + optional OpenAIIntentClassifier |
extraction | Deterministic entities + optional OpenAIEntityExtractor |
knowledge_rag | Hybrid RAG — policy chunks only |
sql_auction_search | search_auction_records filters |
mcp_public_tools | County calendar / WCAD live tools |
grounding_verification | Drop uncited / ungrounded facts |
compliance_disclaimer | Auction/public intents |
synthesis | Grounded LLM or deterministic fallback |
Data planes
Dashboard Excel parse is a fourth UX path (browser-only) and is never the AI graph’s search source.
| Plane | Offline | Online | Vector? |
|---|---|---|---|
| Policy RAG | Yes — ingest URLs | Hybrid retrieve + LLM | Yes |
| Auction index | Yes — ingest xlsx | SQL filters (+ CTA to dashboard) | No |
| Public records | Optional registry only | Live scrape each ask | No |
Security
Decisions