Greeter: An AI clinic receptionist that asks before it books
A front desk for dental clinics, built entirely on n8n. Patients write in Telegram, WhatsApp or the chat on the clinic's site, in English, Ukrainian or Russian. The assistant answers from the clinic's own data and books, moves and cancels visits. Status: open-source build, load-tested with a stub model; the end-to-end run on real keys is still to come.
In plain words: patients can book at night without a receptionist, and two of them never get the same slot.
For your business: it works for any business that books appointments: clinics, salons, studios, repair shops. Adapting it to your services and calendar usually takes 20–30 hours.
Built by Artem @0xNaezo
(opens the full-size image)
The problem
A clinic loses patients when nobody answers at night, and trust when two people get the same chair. A bot that answers is the easy part. The work is one that never books a slot it should not, never makes up a price, and hands a patient in pain to a person at once.
What it does
- Answers from the clinic's data. Prices, doctors and hours come straight from SQL, everything else from the clinic's own articles. No invented prices, no diagnoses.
- Books, moves and cancels. Always after the patient confirms. Visits are mirrored to Google Calendar, with reminders 24 and 2 hours before.
- Hands over to a person. Each patient gets a topic in the clinic's Telegram group with a short brief, and the bot stays silent until it is handed back.
- Serves many clinics. A clinic is a config file and a set of articles, added through a form in about 15 minutes.
Three decisions that carry it
- 01
The model proposes, the patient confirms. Only then does one SQL function apply the change, in one transaction. The model changes nothing by itself.
- 02
Double booking is impossible. Exclusion constraints in Postgres refuse it for doctors and patients alike, whoever writes the row: the bot, the admin grid or raw SQL.
- 03
Urgent symptoms skip the model. Keyword rules in three languages catch severe pain, swelling or bleeding first. The patient gets the emergency number at once, the clinic an urgent card.
One load test
- 100dialogs at once, 5 messages each
- 0messages lost
- 4.2 sreply p95 on 2 workers
- 22workflows
Run on 2026-09-27 through the whole stack, from the Telegram webhook to the reply. The model was a stub that answers in 1–3 s, so the test measures the system, not the provider. Full report
- n8n
- PostgreSQL
- pgvector
- Redis
- Caddy
- Grafana
- OpenRouter
- Telegram
- Google Calendar
- MessageTelegram, WhatsApp or the site chat
- Ingeststored once, under the channel's own id
- Turnone at a time per patient, under a lease
- Routeurgent, operator, button or agent
- Proposethe agent offers a time
- Confirmthe patient taps or says yes
- Bookone SQL function; calendar and reminders follow
Reply p95 for the same 100 dialogs
A CPU profile showed n8n's default sandbox for expressions taking most of the workers' time. The in-process engine cuts worker CPU about 4×. It is safe here because only the admin edits workflows and patient text never becomes an expression.
Engineering details
How it is built
- n8n is the application. Webhooks, the dialog, the agent, bookings, handoff, reminders, alerts and evaluations are 22 workflows. Their JSON in git is the source of truth, and a linter checks every export.
- Postgres keeps the rules. 82 SQL functions across 8 migrations. Every change is one function call, one transaction.
- One turn at a time. A lease on the conversation serializes turns. Messages that arrive during a turn are answered together in the next one.
- Clinics cannot see each other. Every row carries its clinic, references between tables are composite keys, and tools take clinic and patient ids from the turn, never from the model. The linter rejects a workflow that tries.
- Nothing left half done. Each side effect has a mark, and a reconcile run every minute finishes whatever is unmarked: replies, calendar syncs, operator cards.
- Alerts. Failures reach Telegram at most once per node every 10 minutes, with a Replay button where a retry is safe.
- Evaluation. 46 scenarios run through the real pipeline: bookings, prices, urgent symptoms, prompt injection, mixed languages. The pass rate gets published after a run on a real model.
Limits
- The site chat polls for replies, and every poll is an n8n execution. Fine for a demo; real traffic needs a push channel outside n8n.
- Urgent symptoms are caught by keywords. A small classifier is the next step if evaluations show misses.
- The decrypted channel token appears in the execution data of the delivery workflow. Successful runs of it are not saved, and failed ones expire after 14 days.
- Clinic isolation rests on the SQL functions, composite keys, tests and the linter, not on row-level security.
- Three acceptance criteria wait for a run on real keys: a booking end to end with real calendars, no invented answers, and a 90% evaluation pass.

















