In short
Two n8n workflows for a fertility clinic brief. The first answers patient questions in English, Arabic and Hebrew from approved clinic content only, with a citation on every line, and refuses with a handoff when the question falls outside that content. The second accepts scanned lab reports that contain no selectable text, OCRs a copy while the original is stored untouched, extracts the values, and pre-screens the case against eight criteria in plain code. The model never decides eligibility, and invented citations are stripped before a patient sees them.
Project description
Most clinic chatbots fail in the same two places. They answer from general medical knowledge instead of the clinic's own material, and they fold the moment a patient uploads a lab report. This build fixes both. One n8n workflow answers patient questions in English, Arabic and Hebrew from approved content only, citing the exact passage behind every line and refusing when the question falls outside it. A second workflow takes scanned lab reports that contain no selectable text, reads them, and pre-screens the case against the clinic's own criteria.
Tools & Deliverables
- Retrieval-augmented chat workflow in n8n: language detection, translation for retrieval, deterministic passage lookup, grounded answer, citation check, logged exchange
- Knowledge base and eligibility criteria held in a Google Sheet the clinic edits, so content and rules change without touching a workflow
- Citation verification in code after the model replies, so an invented reference is stripped before the patient sees it
- Refusal path that returns a handoff to the clinic team and an empty citation list, cleared by code rather than by the model's good behaviour
- OCR pipeline for image-only lab PDFs: the original is stored untouched, a copy is OCR'd, and the values are extracted
- Eight-criterion eligibility engine in plain code, returning a verdict with a pass or fail line per criterion, and a missing-data path that asks for exactly what it still needs
The problem
- General medical knowledge is the wrong source. A patient-facing assistant that answers from whatever the model absorbed in training will eventually contradict the clinic's own protocol, and the clinic carries the consequence.
- Models invent citations. Asking a model to cite its sources is not the same as the sources being real. A reference that looks plausible and does not exist is worse than no reference at all.
- Lab reports arrive as pictures. Patients photograph a printout or forward a scanned PDF. Those files contain zero selectable text, so any pipeline that assumes it can read the text layer returns nothing and stalls.
- Records arrive incomplete. A patient uploads one report out of three. A system that guesses the rest is dangerous, and a system that simply stops wastes the coordinator's time instead of saving it.
- The patient's language is not the clinic's. Approved material is written in English while patients write in Arabic or Hebrew, and a reply in the wrong language is no reply at all.
- Eligibility is not a job for a language model. Deciding whether someone meets clinical criteria has to be inspectable and repeatable, and a model producing a confident verdict is neither.
Approach
The chat workflow is built so the model only ever sees approved material. A patient question arrives on a webhook, the language is detected, and the question is translated into English for retrieval because the approved content is English. Retrieval itself runs with no AI: it reads the clinic's Google Sheet knowledge base and returns passage ids deterministically, and those passages are the only thing the model is given. The answer comes back in the patient's own language, with the passage code printed next to each claim. Arabic and Hebrew answers render right to left, with the English translation used for retrieval kept visible so a reviewer can follow what was searched.
The part that makes it safe to put in front of a patient happens after the model replies. The answer is checked against the passages that were actually retrieved, and any citation code the retrieval never returned is stripped out. If retrieval found nothing relevant, the assistant does not improvise: it refuses, offers a handoff to the clinic team, and returns an empty citation list, cleared in code rather than left to the model's discretion. The report pre-screen follows the same principle. Uploaded PDFs are stored untouched and OCR'd on a copy, the values are read off, and then plain code scores the case against eight criteria held in a spreadsheet. The model does not decide eligibility, which means a verdict can be explained line by line, argued with, and changed by editing a row rather than a prompt.
Solution
In the recorded runs, the same question was asked in English, Arabic and Hebrew. Each was detected, translated for retrieval, and answered in the language it was asked in, with every claim carrying the passage code it came from. Asked to prescribe a drug, the assistant refused, offered the clinic team, and returned no citations at all. On the report side, two scanned reports with no text layer were read and the values extracted, and the case scored eight out of eight against the criteria with a reason printed for each one, returning likely suitable for assessment. Uploading only one of the two reports produced a different and more useful outcome: cannot assess yet, three required items missing, followed by three specific questions for the hormone panel, the karyotype and the Y microdeletion test, generated from the criteria rows that failed.
Everything shown is output from real executions with run ids attached, so nothing on the demo page is staged. Two things are deliberately placeholder and labelled as such: the knowledge base passages and the eight criteria rows, both written as stand-ins for the clinic's real documents and rules. Because both live in a spreadsheet, swapping in approved content and real criteria points the same pipeline at the clinic's own material with no rebuild. The output carries its own disclaimer throughout: this is an automated pre-screen against clinic criteria, not a diagnosis and not medical advice, and a clinician reviews every case.
FAQ
How do you stop the model inventing citations?
By checking them afterwards in code. The answer is compared against the passages retrieval actually returned, and any code that was not in that set is stripped before the reply is sent. The model is never trusted to be honest about its own sources.
What happens when the answer is not in the approved content?
It refuses, says so, and offers a handoff to the clinic team, with the citation list cleared by code. A refusal with no sources is the correct output, and it is enforced rather than requested.
How does it read lab reports that are photos or scans?
The uploaded file is stored untouched for the record, a copy is OCR'd, and the values are extracted from that copy. The demo reports were verified to contain zero text characters, so nothing is relying on a hidden text layer.
Who decides whether a patient is eligible?
Plain code, against criteria the clinic edits in a spreadsheet, with a pass or fail line for each one. The model is not involved in the verdict. When required information is missing, the workflow asks for exactly the missing items instead of guessing or stopping.
What does the clinic have to maintain?
A spreadsheet. The approved passages, the criteria and the thresholds all live there, so changing what the assistant can say, or what counts as eligible, is a row edit rather than a developer task.





