Appointment and screening reminders

Reminders that get confirmed, not just sent.

Your booking system hands the loop tomorrow’s list. The loop queues each reminder for the right time, calls the patients who matter most to confirm, and writes the result back to the booking.
The problem

Why reminders don’t stop no-shows

“The text goes out and that’s it.”

Nobody knows who read it, so the slot is lost anyway.

“Reception calls when they can.”

Confirmation calls happen between walk-ins, so most never happen.

“Screenings get booked and forgotten.”

A reminder months ahead does little on the day.
How the loop works

How the reminder loop runs

  1. Your booking system sends the list. Once a day, it starts the loop with the next day’s appointments.
  2. Reminders are queued for the right time. One step queues every text for delivery at the hour you choose, with opt-out checks on.
  3. Calls where it matters. First visits and long procedures get a confirmation call, so a cancelled slot can be offered to someone else.
  4. The booking is updated. The call summary goes back to the booking, for reception to act on.
tomorrow-reminders.tsTypeScript
interface Visit {
  visitId: string;
  phone: string;
  time: string;
  first: boolean;
}
interface Day { clinic: string; sendAtUtc: string; visits: Visit[] }

export class HealthLoop extends Workflow {
  async run(event: HealthEvent<Day>, step: HealthStep) {
    const { clinic, sendAtUtc, visits } = event.body;

    await step.do("Queue reminders", ({ ctx }) =>
      ctx.SMS.send({
        messages: visits.map((v) => ({
          destination: v.phone,
          content: `Reminder: your visit at ${clinic} is tomorrow, ${v.time}.`,
        })),
        options: { startDeliveryUtc: sendAtUtc, checkOptOuts: true },
      }),
    );

    for (const v of visits.filter((v) => v.first)) {
      const { sessionId } = await step.do(`Confirm ${v.visitId}`, ({ ctx }) =>
        ctx.startVoice({ loopId: "visit-confirmation", to: v.phone, body: { clinic, time: v.time } }),
      );
      const call = await step.waitForVoiceComplete({
        sessionId,
        timeout: "30 minutes",
      });

      await step.do(`Update ${v.visitId}`, async () => {
        await fetch(`${this.env.BOOKING_API}/visits/${v.visitId}/notes`, {
          method: "POST",
          body: JSON.stringify({ confirmationCall: call.summary }),
        });
      });
    }
  }
}
Channels and integrations

What the loop works with

SMS. One message or up to 500 at once, with opt-out checks and timed delivery.
Phone calls. Outbound calls to a phone number, or a browser call from your app. Each call ends with a transcript and a summary.
Your own systems. Loops call your endpoints to read data and send results back. Your systems start loops with one authenticated API call.
Data and compliance

How data is handled

Your own data plane. Each organisation’s loops, runs, members and keys live in that organisation’s own store, apart from every other customer.
Opt-outs respected. Texts check the opt-out list before sending, unless you turn it off.
A record of every run. The trigger, each step and its result, every tool call, every log line and every error are kept for your team to review.
FAQ

Questions

How does a Health Loop send appointment reminders?

Your booking system starts the loop with the next day’s appointments. The loop queues every reminder text for the time you choose, calls the patients you pick to confirm, and writes each call summary back to the booking.

Can it remind people about screenings?

Yes. A loop can remind someone a screening is due or booked, by text or call. It does not carry out or interpret the screening.

Can a patient reschedule on the call?

The voice loop can take the request and pass it to reception with the call summary. If your booking system has an API, the voice loop can look up open slots too.

See this loop run on your own journey.