I already had a local RAG system that could search my Obsidian vault, Drive, and Nextcloud. I wrote about building it in an earlier article. It worked, but it was passive: the search only ran when I explicitly asked the assistant to find something.
The next question was more interesting. Could the same search help process a real sales lead?
Not by letting AI reply to a customer on its own. That felt like an unnecessary risk. I wanted a pipeline that could recognize a lead, retrieve the right Nice Events information, write a draft, and leave the final decision to me.
It now runs in n8n.
A message labelled as a lead in the Nice Events Gmail account triggers the workflow. From there it does the following:

The Nice Events lead pipeline in the n8n editor. Classification, local retrieval, the CRM update, and the Gmail draft remain visible as separate stages.
Then it stops.
Nothing is sent to the customer automatically, even when the classification looks certain and the draft sounds convincing.
That boundary was the most important decision in the whole project. A good draft saves time. A confident but wrong email sent to a real customer can burn trust much faster than AI can build it.
The tempting version would have been one model doing everything: read the email, classify it, decide what information is needed, write the reply, and update the CRM.
I did not build it that way.
Classification is its own step. Writing only begins after the message has been accepted as a lead and local retrieval has returned a bounded evidence package. I can see each stage separately in n8n. When something fails, I can tell whether the problem came from classification, retrieval, drafting, or the CRM update.
This is also why I used n8n instead of one free-roaming agent. A visual workflow does not make a system safe by itself, but it makes the boundaries visible.
My local knowledge store contains thousands of chunks from different projects. It includes event information, client notes, artist records, and plenty of material that has no business appearing in a Nice Events sales reply.
The lead pipeline cannot search that whole store freely.
I built a separate retrieval surface with an explicit allowlist. It accepts only approved Nice Events documents, including the 2026 service price list, sales packages, service model, and selected artist information. Biletti, other clients, diaries, and old proposal folders remain outside the scope.
Retrieval is hybrid. Vector search finds similar meaning, keyword search catches names and exact terms, and a local model reranks the best candidates. The final context is limited to three sources and 4,000 characters.
If local reranking fails or no approved evidence is found, the API returns an error. It does not fill the gap with a guess.
There is an important distinction here.
The knowledge store, embeddings, retrieval, and reranking stay inside my own network. n8n reaches them through a token-protected internal HTTP API. The firewall only accepts connections from the TrueNAS machine running n8n, and the retrieval service is read-only.
DeepSeek still writes the reply draft. It receives the customer's message and the small context package selected by local retrieval.
The raw Obsidian vault does not leave my network, but selected Nice Events excerpts do leave it for drafting. This is not a fully local AI system. It is local, scoped retrieval connected to a cloud model.
That difference matters. The phrase "local RAG" can easily make people assume no data ever leaves the network. That would not be true for this implementation.
The drafting prompt has a few strict rules.
The reply should be warm, natural, and written in the customer's language. It must not mention RAG or internal sources. It cannot confirm a price, availability, or equipment unless the retrieved context supports the claim. If the customer's email is missing the date, venue, guest count, or another detail needed for a quote, the draft should ask for it.
This does not magically eliminate hallucinations. It reduces the space in which the model can improvise.
The stronger protection is that the result remains a draft. I see the sources and lead notification in Telegram, check the Gmail draft, and edit it before anything is sent.
Just before publishing this article, I ran one more realistic query through the API: a customer asking about DJ services and sound reinforcement for a 150-person company event.
The API returned 503. Every dependency was green. ChromaDB was running, the embedding service was up, and the reranker answered its health probe.
The failure was in candidate retrieval. A generic customer message did not contain enough Nice Events-specific language, so the approved sales documents failed to reach the first 60 candidates. The scope filter did exactly what it was supposed to do and rejected everything else. The result was a safe miss, but not a useful one.
I wrote a regression test first. Then I added Nice Events anchors such as the service price list and sales packages to candidate retrieval. The local reranker still evaluates candidates against the customer's original question, not the added search terms.
All 161 tests passed. The same live query then returned three approved sources: the service price list, the Nice Events service model, and the sales packages. The bounded context contained 3,086 characters.
That was a useful reminder. A health endpoint tells me the components respond. It does not tell me a real work question retrieves the right evidence.
The workflow checks Twenty CRM for the person or company. When needed, it creates or updates the sales opportunity and marks that a reply draft is waiting for review.
The CRM exists here to preserve continuity. It keeps the lead from disappearing into Gmail and records what has happened. It does not decide a price, turn a draft into an approved reply, or make a promise to the customer.
Telegram works as my attention queue. I do not need to watch n8n to notice a processed lead. The notification tells me a draft is ready to review.
The pipeline does not send email. It does not confirm that an artist is available. It does not accept an offer, promise a final price, or decide on a discount. It also does not use the entire CRM history or mailbox as RAG evidence.
These are not missing features. They are boundaries.
The value comes from automating the repetitive groundwork: recognize the message, retrieve the right context, create the first draft, and keep the CRM current. The human stays responsible for judgment, context, and promises made to a customer.
The best feature of this AI lead pipeline is not how much it can do.
It is knowing where it has to stop.