Evidence-grounded document investigation

Answers that carry
their evidence.

Orion answers questions about documents you give it. Every statement it makes shows the passage it came from, and it refuses rather than guessing when the evidence isn’t there. It is not a general chatbot: if the answer isn’t in your documents, there is no answer.

How Orion works

Illustration — not live activity
  1. active
    Frontend

    Next.js — question submitted

  2. pending
    API

    FastAPI — run created, tenant-scoped

  3. pending
    Knowledge

    Embedding → pgvector semantic + Postgres lexical → RRF fusion

  4. pending
    Execution

    Configured LLM provider — structured output

  5. pending
    Verification

    Citation membership → citation validity → quote grounding

A diagram of the path a question takes — no timings, no data, nothing running. See a real trace on any investigation — every run records its own actual times, watchable live as it happens and replayable afterwards.

How it works

  1. 01

    Give it your documents

    Policies, contracts, reports, notes. Orion reads only what you add — it has no other source, and it will not fall back on general knowledge to fill a gap.

  2. 02

    Ask a question

    In plain language. Orion searches your documents and pulls out the passages that actually bear on the question.

  3. 03

    Get an answer, or an honest no

    Every statement it makes shows the exact words from your document that support it. If your documents don’t answer the question, it says so instead of guessing.

Why you can check its work

Language models make things up. Orion’s design assumes that, and puts ordinary, testable code between the model and you. Three checks run on every single answer, after the model has already replied — and any answer that fails one is discarded rather than softened.

It cannot invent a source

Each statement must point at a passage that this specific search actually returned. Orion then goes back to the database and re-checks that the passage is real. A made-up reference fails both checks and the whole answer is thrown away.

It cannot misquote a source

Alongside each statement, Orion shows the exact words it is relying on — and those words must appear, character for character, in the passage it cites. A near-miss paraphrase is rejected, not shown to you.

It would rather say nothing

If the evidence isn’t there, Orion refuses and tells you which kind of gap it hit: nothing matched, your sources disagree, the question was ambiguous, or the evidence simply didn’t support an answer.

What Orion does not promise

  • It is not always right. The checks above prove where a statement came from and that it quotes its source exactly. They do not prove the source is correct, or that Orion read it the way you would.
  • It does not decide anything. Orion presents evidence and refusals; a person makes the call. It takes no action on your behalf.
  • Its answer quality is measured, and published. The evaluation page shows how often it refused when it shouldn’t have, and answered when it shouldn’t have, from real recorded runs — including where a number hasn’t been measured yet.

Built with

Versions below are read from this repository’s own pyproject.toml and package.json when this page renders — not typed out here, so they cannot drift from what is actually installed. Where a choice has a recorded decision, it links to it.

Backend

  • fastapi0.115ADR-0001API framework
  • uvicorn0.32ASGI server
  • pydantic2.9Typed contracts at every boundary
  • sqlalchemy2.0ORM and query builder
  • alembic1.13Hand-written, verified migrations
  • psycopg3.2PostgreSQL driver
  • polars1.12Deterministic analytics primitives
  • pgvector0.3ADR-0003Vector similarity in Postgres
  • anthropic1.0LLM provider SDK (one file may import it)

Frontend

  • next16.3.1React framework, App Router
  • react19.2.8UI runtime
  • @playwright/test1.62.1Browser acceptance suite
  • tailwindcss4Design tokens and styling
  • typescript5Types across the frontend
  • vitest3.2.7Unit tests
Backendwaking upThe API is on free-tier hosting that sleeps when idle, so the first request after a quiet period takes around 50 seconds. This page did not wait for it — it is still checking, and will update here on its own.