Open-source RAG platform for companies

Your documents become an assistant that answers and shows where the answer came from. Documents, database, vector index and encryption keys stay on your infrastructure. You choose the models, and changing provider is a config file.

Our live demo answers, searches and stores files on Scaleway, a French cloud provider. Encryption keys stay there too. See what runs where

01 · How ingest works

Upload a file. Ragen does the rest in the background.

Seven steps turn any document, even a 400-page PDF, into chunks that know where they come from. It runs asynchronously, so nobody waits for indexing.

  1. Upload

    The file lands in storage. Any size, any team.

  2. Parse

    A queued job reads text, headings and tables.

  3. Chunk

    Split into chunks, with a splitter per file type.

  4. Summarize

    A summary of the whole file, stored as its own chunk.

  5. Add context

    Title, section and summary go in front of every chunk.

  6. Hybrid embed

    Embedded twice: dense for meaning, sparse for exact words.

  7. Index

    Upserted to Qdrant, ready for the first question.

  • Asynchronous. Each file is a BullMQ or Temporal.io job, the app stays responsive.
  • Parsing by Docling. Headings and tables survive the trip.
  • Stays on your servers. Files, database and index are yours.
Technical details

A file lands in storage and a BullMQ job on Redis, or a Temporal.io workflow, takes over: parse, chunk with a splitter chosen for the file type, generate a summary of the whole document and prepend it as its own chunk, then embed densely and sparsely and upsert into the organization's Qdrant collection. Before the dense embedding, every chunk is given a short prefix: the document's title, the section it sits under and the first sentence of the summary. A passage that says only "the notice period is 30 days" can then be found by a question that names the contract. The prefix costs no model call and is stored beside the chunk, never inside it, so the model and the citation still see the text as written. It runs asynchronously, so a 400-page PDF does not block anything.

02 · How answering works

Asked once, searched twice, answered with sources.

Ragen rewrites the question, searches with two phrasings at once, keeps the best passages with their neighbours, and only then asks the model to answer and cite.

  1. 01

    Understand

    How many leave days can I carry over?
    And part-time staff?

    ↓ STANDALONE

    How many leave days can part-time staff carry over?

    +1 VARIANT

    Carry-over rules for part-time employees' annual leave

    The conversation history turns a follow-up into a full question. A second phrasing is generated alongside it.

  2. 02

    Search

    2× HYBRID SEARCH

    Q1 dense sparse
    Q2 dense sparse

    RRF FUSION

    DEDUPE

    chunk #42
    chunk #42
    chunk #17

    Meaning and exact words, both phrasings, in parallel. Qdrant merges the lists server-side.

  3. 03

    Select

    RERANK

    optional
    chunk #173 → 1
    chunk #421 → 2
    chunk #082 → 3

    ±1 NEIGHBOURS

    #16 · before
    #17 · the hit
    #18 · after

    If reranking is switched on, a reranker re-scores the shortlist. Neighbouring chunks from the same file are joined, overlap trimmed.

  4. 04

    Answer

    EXAMPLE

    Part-time staff carry over unused leave in proportion to their hours 1. Carried-over days have their own deadline 2.

    • 1Employee handbook › 4.2 Part-time
    • 2Leave policy › Carry-over

    The model gets only the selected passages and is prompted to cite them. Every claim links back to its file.

Technical details

A question is first rewritten into a standalone one using the conversation so far, then a second phrasing is generated. Both run as hybrid searches in parallel. Qdrant fuses dense and sparse results server-side with RRF and the union is deduplicated. When reranking is switched on, the candidates are re-scored by a reranker: Scaleway's by default, or Cohere's cross-encoder. Each chunk that makes the cut is then read together with the chunks on either side of it in the same file, joined into one passage with the overlap trimmed, so an answer that starts at the end of one chunk keeps its first half. The model sees the result with citation prompting on top.

Hybrid search is not a toggle. It is part of the schema collections are created with, so it is always on. Reranking is opt-in: it needs a feature flag and a provider's credentials, and a default install does not rerank. Reading neighbours is on by default, capped at three times the usual context, and can be turned off per organization. Section selection is an opt-in alternative to the reranker: a model is shown the question and the candidates and names the passages worth reading, in one call per turn. Every stage degrades rather than fails – a reranker or selection error falls back to the raw vector order, an expansion error falls back to a single query.

03 · Permissions at retrieval

People only get answers from files they can open.

Every chunk carries an accessible_by filter applied at query time, from the permissions recorded when the document was indexed. A document a user cannot open will not enter an answer, a citation, or the context sent to the model.

Per file and folder, enforced at retrieval, not on display

WHO ASKS

Finance analyst
role: finance

QUERY-TIME FILTER

finance matches

WHAT THE CHUNK REACHES

Answer
Citation
Model context

WHO ASKS

Sales rep
role: sales

QUERY-TIME FILTER

filtered out

WHAT THE CHUNK REACHES

Answer
Citation
Model context

The filter runs inside the search itself. A chunk the user may not see is never retrieved, so it cannot leak through a summary or a quote. Permissions are read when a document is indexed, so a share revoked later takes effect after the next re-index.

04 · Multi-tenancy

Many companies, one installation, zero shared data.

Each organization gets its own vector collection and roles. A guard in the data layer flags a query on a tenant-scoped table that misses its organization filter.

ONE RAGEN INSTALLATION · YOUR SERVER

Company A

collection_a

own users & roles

Company B

collection_b

own users & roles

Company C

collection_c

own users & roles
Data-layer guard. Tenant-scoped queries must carry their org filter.
query · org filter missing FLAGGED
  • 1 vector collection per organization
  • 2 separate role hierarchies
  • 1 installation serves many clients
  • 0 per-seat fees

How it compares

Criterion Hosted "chat with your docs" Your own LangChain stack Ragen
Where your documents live Hosted "chat with your docs" Vendor's cloud Your own LangChain stack Yours Ragen Yours
Choice of model Hosted "chat with your docs" Vendor's shortlist Your own LangChain stack Anything Ragen Any provider, or any OpenAI-compatible endpoint
Access control Hosted "chat with your docs" Usually per workspace Your own LangChain stack Whatever you build Ragen Per file and folder, enforced at retrieval
Multi-tenant Hosted "chat with your docs" Per seat, per workspace Your own LangChain stack Whatever you build Ragen Built in, org-scoped data and index
Retrieval quality Hosted "chat with your docs" Opaque Your own LangChain stack Yours to tune, and to debug Ragen Hybrid, rerank and multi-query, a recorded decision per change
Time to a working answer Hosted "chat with your docs" Minutes Your own LangChain stack Weeks Ragen Minutes, one command plus your own model keys
Cost shape Hosted "chat with your docs" Per seat, forever Your own LangChain stack Your engineers' time Ragen Your infrastructure plus model spend
When it breaks Hosted "chat with your docs" Support ticket Your own LangChain stack You Ragen You, with the source and the recorded decisions

If your requirements are genuinely unusual, building it yourself is a legitimate answer. Ragen is the better trade when you want those decisions already made, and documented, rather than made by you.

05 · Requirements

Runs on a modest server. No GPU, unless you want one.

Chat, embeddings and reranking are calls to the providers you name in your configuration, so the machine running Ragen does no LLM or embedding inference of its own. Document parsing runs small CPU models locally.

Where the memory actually goes

idle, per service

  • Docling 1.4–1.7 GiB
  • Presidio analyzer (optional, PII masking) 959 MB
  • Postgres 93 MB
  • Presidio anonymizer (optional, PII masking) 55 MB
  • Qdrant 43 MB
  • Redis 11 MB
Hardware and software. Guidance, not enforced limits.
Hardware and software EVALUATION PRODUCTION
CPU 4 cores 8 cores
RAM 8 GB 16 GB
Disk 25 GB 100 GB SSD
Docker Compose v2 Compose v2
Node.js ^24.15.0 || ≥26 ^24.15.0 || ≥26

Guidance, not enforced limits. An API key for an LLM provider is required.

GPU not required. Add one only for self-hosted models.

~1.6–1.9 GB

docker compose up

~2.6–2.9 GB

everything switched on

Technical details

Point it at a hosted provider and a laptop is enough. A GPU only enters the picture if you decide to serve models yourself, say with vLLM or Ollama plugged in as a route, which is supported and is a separate box.

RAM is what is available to Docker. Disk grows with your documents. These are recommendations: nothing in the stack enforces them. The Ragen applications run on the host and need Node.js ^24.15.0 or ≥26.0.0, which the installer checks.

Measured on an idle stack, backing services only. A default docker compose up idles at about 1.6–1.9 GB. Presidio is not part of it: both containers sit behind the pii profile and add roughly 1 GB only if you turn PII masking on. DOCUMENT_PARSER=legacy skips Docling and gives back its memory, but your PDFs are then parsed by an external model, so they leave your network. Qdrant is the line that moves as you add documents, because the figure above is a near-empty index. Size that one against your own corpus rather than against this chart. The five Ragen applications run on top of all this and are not included. In development they are the larger half.

Stand it up yourself

One command, npx create-ragen-app, sets up the lot: it clones the repository, generates secrets, starts Postgres, Qdrant, Redis and Docling, and prepares the database. Then start the web app, API and worker, upload a document and ask it something.