Newsletter image

Subscribe to the Newsletter

Join 10k+ people to get notified about new posts, news and tips.

Do not worry we don't spam!

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Search

GDPR Compliance

We use cookies to ensure you get the best experience on our website. By continuing to use our site, you accept our use of cookies, Privacy Policy, and Terms of Service.

n8n - Automation

Scale Your n8n Chatbot With a Supabase Vector Database (RAG)

A folder of markdown files makes a fine chatbot right up until it does not. Move to retrieval by meaning: embed your documents into vectors, store them in Supabase, and let the agent search for the most relevant chunks instead of guessing a file name.

A folder of markdown files makes a fine chatbot right up until it does not. Add enough documents and the agent can no longer keep every file name in its head, and it starts answering from the wrong one. The fix is not a bigger prompt. It is retrieval by meaning: embed your documents into vectors, store them in a database, and let the agent search for the most relevant chunks instead of guessing a file name. This is retrieval-augmented generation, and Supabase gives you the vector database for it without leaving the stack you already run.

This is part two of a two part thread. Part one built a website chatbot backed by markdown files. Everything there still stands: the same AI Agent, the same Chat Trigger, the same website widget. We change exactly one thing, the tool the agent uses to find information, and in return the chatbot scales from a dozen documents to thousands.

What Actually Changes

Part Markdown chatbot Vector RAG chatbot
Knowledge store Files on disk Supabase table of embedded chunks
Ingestion None, just edit files A workflow that embeds and upserts
Retrieval Read a whole named file Semantic search for top matching chunks
Agent, memory, Chat Trigger, website embed Identical. Only the retrieval tool is swapped.

Because only the tool changes, you can run both side by side and migrate when you are ready. The website embed from part one does not change at all.

Prerequisites

You need n8n, Ollama, and Supabase. The local-ai-packaged stack ships all three together, which is why we recommend it for this series. Pull an embedding model alongside your chat model:

ollama pull nomic-embed-text
ollama pull qwen2.5:7b-instruct-q4_K_M

nomic-embed-text turns text into 768 dimensional vectors and runs comfortably on a CPU. It is the embedding model the reference workflows use, and the vector width matters in the next step.

Step 1: Turn Supabase Into a Vector Store

Supabase is Postgres, and Postgres becomes a vector database with the pgvector extension. In the Supabase SQL editor, enable the extension, create a table for embedded chunks, and add the search function n8n calls. Run this once:

create extension if not exists vector;

create table documents (
  id bigserial primary key,
  content text,
  metadata jsonb,
  embedding vector(768)
);

create function match_documents (
  query_embedding vector(768),
  match_count int default null,
  filter jsonb default '{}'
) returns table (
  id bigint,
  content text,
  metadata jsonb,
  similarity float
) language plpgsql as $$
begin
  return query
  select id, content, metadata,
    1 - (documents.embedding <=> query_embedding) as similarity
  from documents
  where metadata @> filter
  order by documents.embedding <=> query_embedding
  limit match_count;
end;
$$;

Two details decide whether this works. The vector width, 768, must match your embedding model exactly, or inserts fail. And match_documents is the function n8n's Supabase Vector Store node calls by name, so do not rename it without updating the node.

Step 2: The Ingestion Loop

Now build a second workflow whose only job is to get documents into that table. This is the part markdown lookup did not have. A production version, like the one behind the Decred knowledge assistant, walks a folder, skips anything it has already embedded, and re-embeds only what changed. The node chain looks like this:

[
  "Manual or Schedule Trigger",
  "Read Files from Disk (glob /data/shared/**/*.md)",
  "Loop Over Items (Split in Batches)",
  "Hash File (crypto, SHA-256)",
  "Check hash against document_metadata (Supabase)",
  "Switch: new file / unchanged / changed",
  "Extract Document Text",
  "Supabase Vector Store (insert)"
]

The Supabase Vector Store node in insert mode does the heavy lifting. Attach three sub-nodes to it:

  • Embeddings Ollama pointed at nomic-embed-text. This turns each chunk into the 768 dimensional vector the table expects.
  • Default Data Loader to carry document metadata (file name, source URL, hash) alongside the text.
  • Recursive Character Text Splitter with a chunk size around 400 and a small overlap. Chunking is what makes semantic search precise: the agent retrieves a paragraph, not a whole file.

The dedup step is what keeps a growing knowledge base cheap. Hash each file, store the hash in a document_metadata table, and on the next run compare. Unchanged files are skipped, changed files get their old vectors deleted and re-inserted. Without this, every run re-embeds everything.

Step 3: Swap the Retrieval Tool

Back in the chatbot workflow from part one, delete the lookup_document tool and add a Supabase Vector Store node in retrieve-as-tool mode. Give it the same documents table, the match_documents query name, and its own Embeddings Ollama sub-node, again nomic-embed-text, so the query is embedded the same way the documents were.

Name the tool something the agent will understand, like search_knowledge, and set a topK of 4 or 5 to start. That is the number of chunks the search returns per question. The system prompt gets simpler than the markdown version, because the agent no longer needs a list of file names:

You answer questions about MySite from a knowledge base.
Use search_knowledge to find relevant information before answering.
Answer only from what the search returns. If it returns nothing useful,
say you do not have that information. Never invent product details.

The chat model, the memory with Session ID set to From input, and the Chat Trigger are untouched. Reactivate the workflow. The website widget from part one keeps talking to the same chat URL, and now every answer is backed by semantic search.

Why the Numbers Matter

Three settings shape answer quality, and all three are worth a moment.

Setting Start with What it trades
Chunk size 400 characters Smaller is more precise but loses context; larger keeps context but blurs the match
Chunk overlap 40 to 80 characters Overlap stops ideas from being cut in half at a boundary
topK 4 to 5 More chunks give the model more to work with, but add noise and tokens

If answers feel thin, raise topK before you touch chunk size. If answers wander, lower it. Retrieval tuning is empirical, so change one number at a time and re-test the same handful of questions.

Local or Cloud

Everything above runs locally on Ollama, which keeps your documents and your queries on your own hardware and costs nothing per call. If you would rather trade privacy for a bit more accuracy, swap the two Ollama sub-nodes for OpenAI equivalents: an OpenAI Embeddings node (remember to change the table to vector(1536) to match) and an OpenAI Chat Model. The rest of the workflow, and the entire website embed, stay exactly the same. That is the point of building it this way: the pieces are independent, so you can upgrade one without rebuilding the others.

Where You Land

You now have a chatbot on your website that searches a real vector database by meaning, dedupes its own ingestion, and runs on hardware you control. It scales to thousands of documents, answers from specific paragraphs rather than whole files, and shares its plumbing with anything else in your n8n instance that reads the same documents table.

The natural next step is to let other systems reach this knowledge base, not just the website widget. That is exactly what turning the workflow into an MCP tool does, so an AI agent elsewhere can query your knowledge base directly.

Sources and Further Reading

Back to the start of the thread: the simple markdown chatbot, if you skipped straight here. Build that first, then come back and swap in the vector tool. It is a fifteen minute change once the ingestion loop is running.

The workflow

Prev Article
Build a Website Knowledge Chatbot With n8n (No Vector Database Needed)
Next Article
How to create Logos with Midjourney

Related to this topic: