1. Inbound Booking Qualification and Routing
Trigger: Booking Qualifier submitted, inbound SMS containing booking intent, web chat conversation started, or inbound call captured with no appointment booked.
Conditions and branches, evaluated in this order:
- Urgency screen first, always. If the inbound text matches the urgency lexicon. Chest pain, cannot breathe, shortness of breath, bleeding, severe pain, fainted, overdose, suicidal, self-harm, labor, contractions, water broke, head injury, stroke, numbness, emergency, 911. Stop everything: apply triage-human, move to Needs Human Triage, notify the clinical line, and send the fixed response: "I am not able to help with medical questions or urgent symptoms. If this is an emergency, call 911 or go to your nearest emergency room now. For an urgent clinical question, call us on {{custom_values.clinical_line}} and a member of our clinical team will speak with you." End the workflow. BO does not assess, reassure, or offer an appointment.
- If scheduling_flag is Do Not Self-Book, or tag do-not-self-book is present, route to Needs Human Triage with a call-back task and send "Thanks {{contact.first_name}}, I will have someone from our front desk call you to get this booked."
- BO collects, in this sequence: location, new-or-established, service from the controlled list, provider preference, and whether that preference is firm. Writes home_location, patient_status, visit_type_requested, provider_preference and preference_is_hard. If BO cannot map the stated reason to a defined service in two attempts, route to Needs Human Triage rather than guessing.
- Apply tags: new-patient or established; pref-hard or pref-soft or pooled-ok.
- Move to Eligible - Awaiting Slot Choice and send the service-specific booking link: "Here is the live schedule for {{contact.visit_type_requested}} at our {{contact.home_location}} office: {{booking_link}}. Pick anything that works. It books instantly. Reply STOP to opt out of texts."
- Wait 2 hours. If no booking, send one nudge with the link. Wait 22 hours. If still no booking, create a front-desk call task and end.
Stop and exit conditions: appointment booked; triage-human applied; sms-opted-out; urgency match at any point in the conversation, including mid-way, which terminates BO's turn immediately.
2. Provider Match, Eligibility Enforcement and Load Balancing
Trigger: a booking page is loaded, or BO requests available slots.
Conditions and branches:
- Resolve the service. Pull duration, pre-buffer, post-buffer, minimum notice, horizon, daily cap, per-provider daily cap, and the required resource calendars.
- Build the eligible provider pool. Start from every provider calendar at the requested location, then remove: providers not credentialled for the service; providers closed to new patients when patient_status is New; providers outside the service's age or scope rules; providers whose per-provider daily cap for this service is already met; providers on the exception calendar for that date.
- Hard preference branch. If preference_is_hard is true, reduce the pool to that one provider. If the result is empty inside the horizon, do not substitute. Send "Dr. {{contact.provider_preference}} has nothing open in the next {{horizon}} days. I can add you to the list for the first cancellation, or book you with another clinician, which would you prefer?" and branch on the reply. Silently substituting a provider is the single most reliable way to manufacture a late cancellation.
- Soft or pooled branch. Keep the full pool and order it by load balancing: for each provider, compute booked clinical minutes divided by available clinical minutes for the target week, then sort ascending so the least-loaded calendar surfaces first. Break ties by assigned_provider match, then by continuity with the patient's last three visits, then round-robin by last-assigned timestamp so the same name does not always win.
- Resource intersection. For any service requiring a room, device or assistant, intersect the provider's open slots with the resource calendar's open slots. A slot that exists on only one of the two is not offered.
- Render only legal slots. Apply minimum notice, horizon, buffers and the clinic-wide daily cap last. If fewer than three slots survive inside 14 days, append the Waitlist Join link to the page.
Stop and exit conditions: no eligible provider at all, which routes to Needs Human Triage with a notification rather than showing an empty calendar; resource calendar unavailable, which hides the service entirely rather than offering an unfulfillable slot.
3. Booking Confirmation, Registration and Verification Chain
Trigger: appointment created on any provider calendar.
Actions in order:
- Immediately, create or update the opportunity in Booked - Unverified. Write the provider, location, service and start time to the opportunity, never a clinical reason.
- Immediately, send confirmation on preferred_contact_channel. SMS: "You are booked, {{contact.first_name}}. {{appointment.date}} at {{appointment.time}}, {{appointment.location}}, with {{appointment.provider}}. Add to your calendar: {{calendar_link}}. Need to change it? {{reschedule_link}}. Reply STOP to opt out." Note what is absent: no reason for visit, no clinical label beyond the neutral service name.
- Wait 5 minutes. Branch on patient_status. New: send the registration link: "Two things to do before {{appointment.date}}, {{contact.first_name}}: your registration and insurance details take about 6 minutes and save you fifteen at the desk. Secure link: {{registration_link}}." Set forms_status Sent, tag forms-outstanding. Established: send the short demographics-confirmation form instead.
- Wait 48 hours. If forms_status is not Complete, send one reminder on the same channel and one on the alternate channel if consent exists. If still incomplete 5 days before the visit, create a front-desk task "Collect registration by phone."
- On registration submission: set insurance_status to Verification Requested, tag needs-insurance-verify, create a front-desk task due 2 business days before the visit, and prefill the internal verification form.
- Branch on the verification outcome. Verified: move to Booked - Verified, remove needs-insurance-verify, continue to the reminder ladder. Issue: tag insurance-issue, pause the reminder ladder, create an urgent call task, and notify the front-desk lead: "Coverage issue on a booked visit {{appointment.date}}. Call before the reminder ladder resumes." Self-Pay: tag self-pay, send the practice's self-pay information page, and continue.
- Branch on referral_required. If true and referral_on_file is false, create a task and send "Your insurer needs a referral from your primary care doctor before this visit. Here is what to ask them for: {{referral_info_link}}."
Stop and exit conditions: appointment canceled or rescheduled, which restarts the chain from step 1 with the new slot; triage-human applied; opt-out, which switches the chain to email if email_consent is Granted and otherwise to a front-desk call task.
4. Reminder Ladder with Confirm and Reschedule Branches
Trigger: opportunity enters Booked - Verified, or 7 days before start time, whichever is later.
Conditions: not tagged insurance-issue; not tagged triage-human; appointment still active.
Actions in order:
- 7 days out, email. Subject "Your {{appointment.date}} visit at {{custom_values.practice_name}}." Body carries date, time, location, provider, directions, parking, what to bring, and the forms link if forms_status is not Complete.
- 72 hours out, SMS, quiet-hours gated. "Hi {{contact.first_name}}, confirming {{appointment.date}} at {{appointment.time}} with {{appointment.provider}}, {{appointment.location}}. Reply YES to confirm or use {{reschedule_link}} to move it."
- Branch on the reply. YES or C: move to Confirmed, suppress rungs 4 and 5 but keep the day-of nudge. NO or CANCEL: run workflow 6 immediately. Anything else: hand the conversation to BO, which re-runs the urgency screen before answering anything.
- 24 hours out, SMS if not yet confirmed. "Tomorrow at {{appointment.time}}, {{contact.first_name}}. Reply YES to confirm, or {{reschedule_link}} if you need a different time. If we do not hear back we will hold your slot but a confirmation really helps us plan."
- Double-confirm branch. If noshow_count_12mo is 2 or more, add a rung at 4 hours out and require an explicit YES. If no YES by 2 hours out, release the slot to the waitlist and notify the front desk: "Unconfirmed high-risk slot released, {{appointment.time}}." This rule must be a written practice policy and disclosed at booking, not a surprise.
- 2 hours out, SMS. "See you at {{appointment.time}} today, {{contact.first_name}}. {{appointment.location}}, {{directions_link}}. Running late? Reply here and we will tell the team."
- On any inbound "late" or "running behind", notify the front desk with the record and the appointment time and reply "Thanks: I have let the front desk know." BO does not promise the slot will be held; only a human can make that call.
Stop and exit conditions: appointment canceled, rescheduled or marked Showed; sms-opted-out, which drops the ladder to email only; insurance-issue applied mid-ladder, which pauses it; triage-human applied, which ends it. Hard cap of five appointment messages per visit, four for confirmed patients.
5. No-Show and Late-Cancel Recovery
Trigger: appointment status set to No-Show, or cancellation received inside the notice window defined per service.
Actions in order:
- Move the opportunity to No-Show or Late Cancel. Increment noshow_count_12mo or late_cancel_count_12mo. Apply noshow-1, noshow-2 or noshow-3plus by the new count.
- Immediately release the provider slot and any linked resource calendar, then start workflow 6 so the slot has a chance of being refilled today.
- Wait 1 hour, then send a non-judgemental rebooking offer. "We missed you today, {{contact.first_name}}, no problem at all. Here is the live schedule to pick a new time: {{booking_link}}. If something is getting in the way of getting here, reply and tell me; we may be able to help with timing or a telehealth slot."
- Wait 48 hours. If no rebooking, send one more on the alternate channel.
- Wait 5 days. If still no rebooking, create a front-desk call task and move the opportunity to the recall system rather than leaving it open.
- Branch on the new count. 1: nothing further. 2: set scheduling_flag to Requires Front Desk, tag do-not-self-book, and notify the front-desk lead so the next booking happens in conversation. 3 or more: additionally set scheduling_flag to Deposit Required if the practice operates a deposit policy, tag deposit-required, and create a task for the practice manager to review under the written attendance policy. Never apply a deposit or a booking restriction that is not in a disclosed, consistently applied policy; have the practice's own counsel review it before it goes live.
- If the no-show was on a service with a scarce resource (procedure room, device, interpreter) notify the resource owner separately so the resource is re-offered, not just the provider slot.
Stop and exit conditions: patient rebooks, which ends the sequence and starts workflow 3 on the new appointment; opt-out; triage-human.
6. Waitlist Backfill on Cancellation
Trigger: any appointment canceled, released or marked No-Show, freeing a slot inside the next 10 business days.
Conditions: the freed slot is at least 2 hours in the future; the service is one the practice allows short-notice booking on; at least one contact is tagged waitlist-active.
Actions in order:
- Query waitlist contacts matching all of: service equal to the freed slot's service; home_location equal to the slot's location; waitlist_window overlapping the slot's day and time band; provider eligible under preference_is_hard; no triage-human; consent on at least one channel.
- Rank the matches: hard-preference matches for this exact provider first, then longest time on the waitlist, then clinical priority where the practice maintains one set by a clinician: never set by BO.
- Send a single offer to the top three simultaneously, framed as first-come. "Good news {{contact.first_name}}, a slot just opened at {{custom_values.practice_name}}: {{slot.date}} at {{slot.time}} with {{slot.provider}}, {{slot.location}}. Reply TAKE to claim it. First reply gets it. Reply STOP to leave the short-notice list."
- First TAKE reply wins: book the slot, tag waitlist-contacted, remove waitlist-active, and start workflow 3.
- Send the other two "That one went, {{contact.first_name}}, you are still on the list and I will message you the moment the next one opens."
- Wait 45 minutes. If nobody claimed it, offer to the next three. Repeat up to three rounds, then publish the slot to the public booking page and notify the front desk: "Unfilled slot {{slot.date}} {{slot.time}}, {{slot.provider}}, waitlist exhausted."
- Every Friday, prune: remove waitlist-active from anyone who has since been seen, has declined three offers, or has been on the list beyond the practice's agreed maximum.
Stop and exit conditions: slot filled; slot now inside 2 hours; three offer rounds exhausted. Never message the same contact about more than two freed slots in one day: short-notice offers go stale fast and over-offering burns the list.
7. Availability Change Propagation and Overbook Guard
Trigger: Provider Availability Change form submitted, or a busy event appears on a provider's synced personal calendar that overlaps already-booked clinical time.
Actions in order:
- Query every booked appointment inside the affected window. Branch on the count.
- Zero affected: apply the change to the provider calendar, recalculate the load-balancing weights for that week, notify the front desk: "Availability updated: {{provider}}, {{window}}. No bookings affected." End.
- One or more affected: do not change the calendar. Create a high-priority task on the front-desk lead listing each affected appointment with patient record identifier, time and service (identifiers only, no clinical detail) and notify the provider: "{{count}} patients are booked in the time you have blocked. The front desk will contact them before the change is applied."
- For each affected appointment, offer a move rather than a cancellation: run workflow 2 restricted to the same service and location, find the three nearest alternative slots, and send "{{contact.first_name}}, we need to move your {{appointment.date}} visit. Here are the closest options: {{reschedule_link}}. Sorry for the disruption: call us on {{custom_values.front_desk}} if none of these work."
- Move each opportunity to Rescheduled on rebooking. After all affected appointments are resolved, apply the availability change and confirm to the provider.
- Overbook guard, running continuously: if any provider calendar ever shows two clinical appointments overlapping, or a service booked without its required resource calendar, raise an immediate alert to the front-desk lead and the practice manager and create a task "Double-booking detected. Resolve before end of day." Log every occurrence; a rising count means a rule is wrong, not that staff are careless.
Stop and exit conditions: change applied and provider notified; change withdrawn by the provider; task closed by the front desk. The calendar is never modified under booked patients without a human in the loop.
8. Recall and Next-Due Rebooking
Trigger: next_due_date minus 45 days, evaluated nightly.
Conditions: no future appointment for the service; patient_status is not Transferred Out; no triage-human; consent on at least one channel.
Actions in order:
- Day 0: email with a continuity-first booking link scoped to assigned_provider: "It has been about a year, {{contact.first_name}}. Dr. {{contact.assigned_provider}}'s schedule is open: {{booking_link}}." No clinical reason stated.
- Wait 7 days. If unbooked, SMS: "Time to book your next visit, {{contact.first_name}}? Here is Dr. {{contact.assigned_provider}}'s schedule: {{booking_link}}. Reply STOP to opt out."
- Wait 10 days. If unbooked, widen: send a pooled link covering every eligible provider at the home location, since continuity is worth less than attendance at this point.
- Wait 14 days. If unbooked, create a front-desk call task. After the call task is closed unbooked, tag lapsed-12mo and hand to the longer-cycle nurture list, capped at one message per quarter.
Stop and exit conditions: appointment booked; opt-out; Transferred Out. Maximum three recall messages per cycle.
9. Daily Schedule Health Report and Weekly Utilization Rollup
Trigger: scheduled daily 06:45 local, plus Monday 07:15 for the weekly rollup.
Actions in order:
- Compute, per provider per location: unfilled clinical hours today and for the next 5 business days; appointments unconfirmed for today; bookings in Booked - Unverified starting inside 48 hours; contacts tagged forms-outstanding with a visit inside 72 hours; waitlist depth by service; and any double-booking alerts open.
- Email the front-desk lead and practice manager, ordered as a work queue: unverified first, unconfirmed second, unfilled third. Aggregate figures and record identifiers only. No clinical content in a routine internal report.
- Branch: if any provider's unfilled clinical hours for today exceed the practice's threshold, add "ACTION: run a same-day waitlist sweep for {{provider}}" and fire workflow 6 manually across that provider's open slots.
- Branch: if any booking inside 24 hours is still unverified, add "ACTION: verify now or call the patient" and escalate to the practice manager.
- Monday rollup: utilization percentage per provider per location, no-show rate per provider and per service, late-cancel rate, reschedule churn count, waitlist fill rate, average days-to-third-available-slot per service, and new-patient slots offered versus filled. Create a task on the practice manager: "Review the two services with the worst days-to-third-available and decide whether to add capacity or change the rules."
Stop and exit conditions: none. If the report stops arriving, treat it as an outage. This report is how the practice knows the rules engine is still right.