DentinFlow
An AI voice agent, "Mila," that answers the phone for dental practices day and night, books appointments through normal conversation, and keeps after-hours calls from rolling to voicemail.
DentinFlow automates the front desk for dental practices. The product is Mila, an AI voice agent that answers inbound calls day or night, books and reschedules appointments through normal conversation, and hands the call to a human the moment one is actually needed.
The problem
A dental front desk is a queue with no backpressure. Calls arrive in bursts (the lunch hour, the first hour after opening), and every ringing phone competes with the patient already standing at the counter. When the desk is underwater, calls roll to voicemail, and a voicemail from someone trying to book a paying appointment is usually a lost patient, not a deferred one.
The bursts are only half of it. The phone also rings after the lights go off: evenings, weekends, the long weekend. Plenty of people only find a free minute to call once their own workday ends, which is exactly when no one is at the desk to pick up. Those calls don't wait in a queue, they go straight to voicemail, and the caller just dials the next practice that answers. A practice that is dark sixteen hours a day is dark for most of the hours people actually call.
The usual fixes all leak. Voicemail assumes the caller phones back, and plenty don't. A generic answering service can take a message but can't see the schedule, so it can't actually book anything. Mila is built to close the loop inside the call: understand the request, check the real schedule, and commit the appointment before the caller hangs up, whether that call lands at the lunch-hour peak or at eleven on a Sunday night.
What a call sounds like
A typical after-hours call, the kind that would otherwise have become a voicemail, runs something like this.
Caller: I didn't think anyone would pick up this late. Quick question, do you do Invisalign, and roughly what does it cost?
Mila: We do, and Dr. Chen takes on a lot of Invisalign cases. The exact cost depends on your teeth, so we'd start with a consult to map it out and give you a real number. Want me to get one booked?
Caller: Sure, sometime next week if you have it.
Mila: Happy to. Can I get your name and date of birth so I can pull up your file?
Mila: Found you. There's a consult open Tuesday at 9:20 in the morning or Thursday at 2:40 in the afternoon. Which works better?
Caller: Tuesday morning.
Mila: Booked, Tuesday at 9:20 with Dr. Chen. I've just texted the confirmation to this number. Anything else?
Two things are happening under that easy back and forth. Mila is answering from this practice's own facts rather than a generic script, and the moment she commits the slot she is reading the live schedule and writing through the backend, never guessing. The call that would have been a 9pm voicemail becomes a booked, confirmed patient instead.
See it run
The same workflows, live. This is the product walkthrough from the DentinFlow site, ported here: the after-hours booking flow, the morning dashboard, and how an empty slot gets refilled. Click through it, or let it play.
From first call to five-star review, fully automated.
A patient calls your practice after hours. Mila answers instantly, identifies the patient, and asks what they need.
Mila checks provider availability in real time, finds the best slot, and books the appointment, no human needed. The patient gets an instant SMS confirmation.
Smart reminders go out 72h and 24h before. Risk-scored patients get voice call reminders. After the visit, a review request SMS fires automatically.
Click through three of the most common workflows. No signup required.
Incoming Call
+1 (647) 555-0124
Downtown Dental, Dr. Chen's Practice
16 features live and growing, one platform for the entire front office.
Mila answers calls 24/7, books appointments, and handles questions automatically. No voicemails. No missed patients.
A clean booking page your patients actually use. New patients fill out their info once. Returning patients get auto-filled slots.
AI scores every appointment for no-show risk. High-risk patients get an extra reminder call. Empty slots get filled automatically.
Patients complete health history and consent forms on their phone before the visit. Data lands in their chart automatically.
Reply to patients, send campaigns, and manage all conversations from one inbox. Never lose a message again.
Automatically texts lapsed patients with the right message at the right time. They book. You grow.
Auto-verifies coverage 48 hours before every appointment. No more surprise billing conversations in the chair.
Coming soon
Native iOS and Android app for your whole team. Coming soon.
Under the hood
The system splits cleanly into a real-time voice layer and a transactional booking layer, and that split is the whole design.
- Voice, on Vapi. Vapi owns the hard real-time parts: telephony, speech recognition, turn-taking, and speech synthesis (the voice itself is an ElevenLabs voice). The conversation runs on a frontier model that reasons over the live transcript and decides when to reach for a tool, with a native speech-to-speech stack in pilot alongside it.
- Tools, on Express. The backend exposes a small, sharp set of functions the agent can call mid-conversation: pull the practice's hours and providers, find open slots, book or move an appointment, take a callback, transfer to a human. The agent calls these. It never reaches the database itself.
- State, on Prisma and Postgres. Practices, providers, services, the appointment ledger, and call records live in Postgres behind Prisma. The schedule is the source of truth; the agent is just a caller against it.
- Practice knowledge. Each practice's facts (hours, insurance accepted, provider specialties, new-patient policy, common questions) are embedded and retrieved by similarity, so Mila answers from this practice's reality instead of a generic script.
- Outcomes, on PostHog. Every call is tagged with how it ended (booked, rescheduled, transferred, message taken, question answered, no availability, caller hung up), so the funnel is something you measure rather than guess at.
The hardest part: an agent that can't lie about the calendar
The failure mode that matters in this product isn't an awkward sentence. It's a confidently wrong booking. An agent that cheerfully says "great, you're all set for Tuesday at 2" when that slot is gone does more damage than no agent at all: a patient shows up to a conflict, and the practice eats the trust.
So the governing rule is that the model is never allowed to invent the schedule. Availability is read live from Postgres at the moment of booking, never inferred from earlier in the conversation, and the write is owned entirely by the backend, not the model. If the slot is already taken, the booking is refused at the backend and Mila recovers inside the call, offering the next real opening instead of asserting a success that didn't happen.
That is the risk-desk instinct applied to a voice agent: assume the system will be asked to do the wrong thing, and put the hard stop in the code path that commits, not in the part that talks. The conversation can be flexible; the booking cannot. That hardening has since landed: every slot Mila offers is cryptographically signed by the server, and all she can hand back is a short label for a time that was really offered. A booking for a time the server never signed is impossible, not discouraged. The same posture runs through the privacy rules: she will not even confirm whether someone is a patient, let alone discuss an appointment, until the caller has verified their identity.
How I know she works
A voice agent demos well by default, so the demo is worth nothing. What I trust instead is a simulation harness: thirty scripted adversarial callers, played by one model against Mila's real production pipeline, with an independent LLM judge scoring every conversation for booking correctness, honesty, patient privacy, injection resistance, and plain phone manners. The cast is built from everything that should break her: a panicked emergency, a prompt-injection artist demanding a discount, someone fishing for another patient's information, a caller who keeps changing days mid-call.
The sweep is not a report, it is a gate. No change to Mila's voice behavior merges unless it passes, and because an LLM judge has moods, a finding only fails the build if it reproduces on a second run. The loop closes on real traffic too: a post-call checker reads every transcript and tool trace after hangup and flags the quiet failures (announced one day, booked another; promised a text with no number to send it to) into a human review queue, and any real call that goes wrong gets converted into a new scripted caller, so the same failure can never ship twice.
The privacy leak and the injection weakness this harness has caught so far were found and fixed before any real patient ever hit them. That is the point.
Running it like production, because it is
The newer speech-to-speech voice stack is rolling out the way I was taught to change anything that touches live customers: behind a per-practice flag, with a kill switch that has actually been flipped on a live line and verified, not assumed. A circuit breaker watches for model failures and drops a practice back to the proven voice stack on the first bad call, automatically. Every call records its cost and outcome, so the rollout decision is a spreadsheet, not a feeling.
Status
In active development with a live pilot: the voice loop, booking tools, and practice-knowledge layer run end to end in production, and every voice change ships through the adversarial gate. The first target is solo and small-group practices, where one missed call really is one lost patient. The honest version of impact, calls handled and hours handed back to the front desk, goes here once there are numbers worth standing behind.
What broke
The worst bug never showed up in a demo, because a demo has one user. Booking ran as check-then-create in four different places: the front desk creating an appointment, Mila creating one from a call, staff rescheduling, staff moving one. Each path checked that the slot was free, then inserted. Two requests arriving together could both pass the check and both insert, and now two patients own the same chair. Mila made it worse in the exact way an AI agent does: she books at machine speed, at any hour, while a human is doing the same thing on the dashboard.
The fix was to stop letting anyone check and then act. All four paths now go through a single Postgres function that takes an advisory lock on the practice, provider, and day, does the conflict check and the insert inside that lock, and returns booked, slot taken, or already processed. The test I trust most in the codebase fires concurrent bookings at one slot and asserts that exactly one wins. That is the whole design in one line: the model proposes, the backend commits, and the backend is the only one holding the lock.
Related writing: Book notes: the RAG chapter of AI Engineering, on why the hybrid retrieval here works, and What a risk desk taught me about evaluating AI agents.