Skip to content
Homelab project · The Archives · Multi-Agent Document AI

Ask anything across your documents.
Answers cited from your own files.

A self-hosted team of specialist AI agents — finance, health, tax, and retrieval — that read every document, connect them in a knowledge graph, and answer in plain English. Your data never leaves your infrastructure.

Cross-document reasoning A team of specialist agents 100% self-hosted & encrypted

Not one chatbot — a team

One generic model can't file your taxes and read your lab results. The Archives runs a team: specialists do the work you came for, while a core of shared-intelligence agents reads, connects, and enriches everything behind them.

Specialist agents — what you came for

  • Retrieval agent

    Answers questions across your whole archive in plain English, citing the exact source paragraphs it used.

    8-model embeddingsReciprocal Rank FusionGraph traversalLocal LLM
  • Finance agent

    Pulls transactions, merchants, amounts, and line items out of receipts and statements into a single spend view.

    Transaction schemaMerchant resolutionSpend dashboard
  • Health agent

    Extracts biomarkers, providers, prescriptions, and appointments, then plots the values on a timeline.

    Biomarker timelineProvider linkingStructured medical schema
  • Tax agent

    Gathers tax-relevant documents, figures, and deductions across the year — so filing season is a query, not a shoebox.

    Document gatheringDeduction hintsYear grouping

Core intelligence — the engine behind them

  • Triage agent

    Reads every upload, classifies its domain, and routes it to the right specialist — the dispatcher for the whole team.

    Docling OCRContent analysisDomain classification
  • Entity & graph agent

    Runs a multi-provider NER ensemble, resolves duplicates to canonical entities, and links them into a graph that grows with every document.

    NER ensembleCanonical resolutionFalkorDB graphCross-doc reasoning
  • Insight agent

    Builds rich entity profiles, generates LLM insights, detects when they go stale, and refreshes them on demand.

    Entity profilesLLM insightsStaleness detectionWeb enrichment

How a document flows through the team

  1. Upload
  2. Triage reads & routes
  3. Specialists extract
  4. Entity & graph links
  5. Insight enriches
  6. Retrieval answers

Every hand-off is an event on NATS JetStream — each agent is a separate worker.

See it in action

Pick a specialist. Same knowledge-graph engine, three lenses — general retrieval, spend intelligence, and health timelines. Not keyword search: cross-document reasoning, grounded in a graph and cited to the source.

The Librarian
3 Documents
📄 Apartment lease — Jun 2023 ✉️ Landlord email — Feb 2025 📄 Renewal notice — Mar 2025
Entity agent — extraction & graph linking
Lease graph 8 nodes · 8 edges · live link
DOCUMENTS LEASE GRAPH MENTIONS ×3 RENEWS_AT HAS_TERM REQUIRES INFORMS SOURCE 📄 Apartment lease Jun 2023 Landlord email Feb 2025 📄 Renewal notice Mar 2025 12 Maple St. LEASE · hub New rent $1,924 / mo Lease term ends 31 Aug 2025 Notice 60 days written Rent now $1,850
Document Entity Lease / current value → typed relationship
Retrieval agent — graph + vector search
retrieval-agent · generated graph traversal + vector recall
MATCH (l:Lease {address:"12 Maple St"})-[:HAS_TERM]->(t:Term)
MATCH (l)-[:RENEWS_AT]->(r:Rent)
OPTIONAL MATCH (l)-[:REQUIRES]->(n:Notice)
WHERE t.end_date >= $today        // "before I have to move"
RETURN t.end_date, r.amount, n.days
⊥ hybrid  RRF( vector_topk(q_embed, k=8), graph_paths )   // Qdrant + graph fusion
You ask
“When does my lease end, and how much notice must I give to move out?”
BlueRobin: Based on your lease (Jun 2023) and the renewal notice (Mar 2025), your current term ends 31 Aug 2025. To move out you must give 60 days’ written notice — so notify the landlord by 1 Jul 2025. If you stay, rent rises 4% to $1,924/mo.
Cited: apartment-lease-jun-2023.pdf Cited: renewal-notice-mar-2025.pdf

How it's built

The platform underneath the agents — private storage, async messaging, and an event-driven pipeline, all self-hosted with no third-party AI APIs.

Per-User Encryption

A unique key per user (HKDF-SHA256 + AES-256-GCM) over Cloudflare R2 storage — every account is cryptographically isolated.

Archive Management

Per-document lifecycle from Pending to Indexed, with real-time Blazor updates — no polling.

Event-Driven Pipeline

NATS JetStream for async processing, with distributed worker deduplication via a KV store.

100% Self-Hosted

Ollama inference, Flux GitOps, and Linkerd mTLS on a homelab K3s cluster.

Architecture

.NET 10 with Clean Architecture and DDD aggregates. NATS JetStream for async event processing. Flux GitOps on K3s. Full documentation in the Architecture section.

.NET 10 Blazor NATS PostgreSQL Qdrant Cloudflare R2 FalkorDB Ollama Kubernetes
Frontend
Blazor Server
Interactive UI · Real-time updates
Application
FastEndpoints API
REST · OpenAPI
Background Workers
OCR · Embeddings · NER
Messaging
NATS JetStream
Event-Driven Messaging · KV Store
Data Layer
PostgreSQL
Metadata
Qdrant
Vectors
Cloudflare R2
Documents
FalkorDB
Graph
AI Services
Ollama
LLM · Embeddings
D
Docling OCR
Text Extraction
Entity Extraction
NER Pipeline
Orchestration
Kubernetes (K3s)
Container Orchestration · Flux GitOps · Linkerd mTLS

100+ Engineering Articles

The decisions behind each component: why NATS, how multi-model RAG works in practice, what broke in production, and how it was fixed.