SMS Booking Assistant for a Clinical Practice
A conversational SMS assistant that books, reschedules and cancels appointments for a healthcare clinic by joining its booking platform to its CRM. The defining design decision was to give the language model no authority: it interprets the patient's message and may call two read-only tools, while every decision and every write happens in deterministic code, with the model's write-tools physically removed from the flow and a downstream guard blocking any booking language that isn't backed by a real appointment record. That constraint proved its worth when a treatment-naming collision between two clinically distinct services was caught and fixed with a guard that now refuses to book rather than risk booking the wrong treatment. Backed by simulation tests that execute the real production code.
The problem
A small clinic couldn't answer every SMS enquiry promptly, and a missed enquiry is a missed booking. Booking by text had to work for first visits and return visits across 18 services with different practitioners. And the stakes weren't ordinary: lipoedema, lymphoedema, oncology and mastectomy work have different practitioners and different clinical parameters. An AI that books the wrong treatment here is a clinical problem, not a bad user experience.
What was built
A 23-node workflow implementing a hybrid router:
- The AI agent interprets the inbound message and may call exactly two tools — check availability, search the knowledge base. Both read-only.
- A single decision engine in deterministic code makes every decision, every write, every state transition.
- A safety guard blocks any AI output that uses booking language without a real appointment ID attached.
- Conversational state persists in CRM contact custom fields with explicit expiry on offered slots, because each SMS is a separate stateless execution.
Four of the six booking tools are physically disconnected from the AI in the workflow graph — not discouraged in a prompt, disconnected.
The hard part
The clinic offers lipoedema therapy and manual lymphatic drainage. They sound related, patients use the words loosely, and they are genuinely different appointment types with different practitioners. The bot was booking lipoedema patients under the lymphatic type.
Two causes: the type was resolved loosely, and when a patient answered a "which service?" question, the appointment type held from an earlier internal availability search was being reused instead of the newly-named service's own type.
The fix resolves the type from the service the patient actually named, discards any held type when the service changes, revalidates the held start time against the new type, and — the part that matters — if no dedicated appointment type exists for that service, it books nothing at all and hands off to a human. In a clinical context, failing to book is a much better failure than booking the wrong treatment.
What can be verified
- Books, reschedules and cancels over SMS in production.
- A clinical-correctness defect was found, root-caused, and fixed with a fail-safe guard.
- A live acceptance test is documented that exercises the exact failure mode end to end in the real systems.
- Eight simulations load the actual production node source and run it against mocked APIs.
The workflow
(select to enlarge)
On numbers: every figure above is an artefact count or a measured technical value. No business-outcome metric, whether time saved, revenue or conversion, was captured on these engagements, so none is claimed.
On status: reflects repository evidence and platform backups, not a live systems check.