A multi-agent referee for the Laws of Association Football.
Describe a scenario. Get a ruling — with citations, claim-by-claim verification, and the LangGraph reasoning trace shown live in the sidebar.
FastAPI Next.js TypeScript Python LangGraph Supabase pgvector Tailwind CSS v4 shadcn/ui Docker
Refbot UI — chat with live architecture sidebar and per-claim verdictsRefbot answers questions about the IFAB Laws of Football the same way an experienced referee does — by reading the Laws and applying the rule to your specific scenario.
You describe a situation:
"A defender deflects a clearance off a teammate's arm in the box. Handball?"
The system:
- Classifies the question by topic (
handball,offside,VAR, ...). - Routes it to specialist retrievers that scope-search the indexed Laws.
- Synthesizes an answer that must cite every claim.
- Verifies each claim against its citations — unsupported claims show up
as
(削除) struck-through prose (削除ここまで)in the final answer.
Nothing is invented. If the Laws don't cover a point, Refbot says so.
| Engineering decision | Why it matters |
|---|---|
| Multi-agent LangGraph pipeline | 9 topic-scoped specialists fan out in parallel. No single retrieval, no single prompt. |
| Per-claim verification | The synthesizer's draft is parsed into discrete claims, each re-grounded against its citations. Hallucinations surface as struck-through prose, not as confident lies. |
Mandatory [N] citation discipline |
Every factual sentence ends with a numeric marker that links to a specific Law chunk + page. The verifier rejects unmarked claims. |
| Inference-mode reasoning | The synthesizer can apply a closed list of criteria to a scenario (the contrapositive of an explicit IFAB rule is supported by the chunk containing it). That's what makes it a referee, not a search engine. |
| PyMuPDF + outline-aware chunker | Custom ingestion that respects the PDF's Law / section structure and recovers diagram-heavy pages a generic parser drops. |
| Streaming + live trace | Tokens stream over SSE while a left rail visualizes each LangGraph node firing in real time. |
| Supabase HTTP + RPC only | No direct Postgres connection. Vector search via pgvector is exposed as a SQL function (match_chunks) and called over HTTP. |
flowchart LR
Q([Question]) --> intake --> classifier --> router
router --> hb[handball]
router --> off[offside]
router --> disc[disciplinary]
router --> var[VAR]
router --> rst[restarts]
router --> gk[goalkeeping]
router --> phil[philosophy]
router --> gen[general]
router --> cmp[comparison]
hb & off & disc & var & rst & gk & phil & gen & cmp --> synthesizer
synthesizer -->|streams tokens| verifier --> emit --> A([Answer])
Every node fire is captured as a TraceEvent. The frontend renders them live
in the sidebar as the answer streams.
Backend
FastAPI · LangGraph · LangChain · DeepSeek V4 Flash · OpenAI embeddings
(text-embedding-3-small) · Supabase (pgvector + RPC) · PyMuPDF · uv
(Astral) · structlog · pytest
Frontend
Next.js 15 (App Router) · TypeScript · Tailwind CSS v4 · shadcn/ui · Zustand
(persisted) · @microsoft/fetch-event-source · Vitest
Infra Docker (multi-stage) · GitHub Actions · Caddy reverse proxy · Netcup VPS
backend/
ai_ref/
api/ FastAPI routes — /api/chat (SSE), /health, /admin/metrics
core/ Settings, Supabase client, model providers
graph/ LangGraph state machine
specialists/ 9 topic-scoped retrievers
ingest/ PyMuPDF parser, outline-aware chunker, LLM tagger
supabase/migrations/ pgvector schema + RPC functions
frontend/
app/ Next.js 15 App Router
components/refbot/
chat/ Composer, messages, citations
graph/ Live architecture left rail
trace/ Verifier verdict pills, trace events
lib/ SSE consumer, Zustand store
Backend (Python 3.12, uv):
cd backend uv sync cp .env.example .env # fill in DEEPSEEK / OPENAI / SUPABASE keys uv run uvicorn ai_ref.main:app --port 8005 --reload
Frontend (Node 20+):
cd frontend npm install npm run dev # http://localhost:3005
Ingest the IFAB Laws PDF:
cd backend
uv run -m ai_ref.ingest \
--source ifab --doc-type laws --season 2025-26 \
--file sources/ifab-laws-2025-26.pdfThe UI takes its cues from a printed referee's handbook: editorial typography (Geist + JetBrains Mono), a single muted pitch-green accent in OKLCH, tabular numerals throughout, and a vertical "rail" of status dots that reads like a margin column. Verdict pills use both color and glyph (●くろまる/◐/○しろまる) so they're colorblind-safe.
Built on the public IFAB Laws of the Game 2025/26. Refbot is an unofficial tool — IFAB remains the sole authority on the Laws.