Blog Post

Azure Communication Services Blog
4 MIN READ

Building an AI Receptionist: A Hands-On Demo with Azure Communication Services and OpenAI

seankeegan's avatar
seankeegan
Icon for Microsoft rankMicrosoft
Aug 13, 2025

Ever missed an appointment because of a rigid SMS system? What if you could text a change and get an immediate, natural response that understands your intent and confirms a new slot quickly?

In this post, we'll show you how to build an AI receptionist that does just that, using Azure Communication Services and Azure OpenAI. We'll guide you through a hands-on demo that uses a simulated but realistic calendar for reliable confirmations and rescheduling, and show you how to make it production-ready.

A natural text thread with the scheduling agent

Watch the Walkthrough

Prefer a walkthrough? Watch the video demo to see the app in action with live code explanations.

This demo is ideal for anyone who wants to explore conversational AI with minimal setup -- whether you're a developer, product manager, or just curious about integrating Azure services.

What Actually Happens Under the Hood

Here’s the simple set of moving parts behind the “AI receptionist” feel. First a quick look at each piece, then the exact path a message takes.

Core pieces we’re using for this demo:

  • Azure Communication Services: Provides the real phone number, receives incoming text messages, and sends replies.
  • Azure Event Grid: Immediately forwards each new message event to a public URL (the webhook) your app exposes.
  • FastAPI: Hosts that webhook (an HTTP endpoint) and keeps simple in‑memory conversation and calendar data.
  • Azure OpenAI: Generates the receptionist’s reply using the running conversation plus a small snapshot of available appointment times.
  • Simulated calendar: Thirty upcoming business days with realistic fullness so the system can offer believable open slots.

Then the message moves through this path:

  1. You send a text message to the demo phone number (handled by Azure Communication Services).
  2. Azure Communication Services raises a “message received” event.
  3. Azure Event Grid delivers that event as an HTTP POST to the FastAPI webhook (a regular URL).
  4. The webhook quickly returns “OK” and kicks off a background function (process_sms in main.py) so the user is never kept waiting.
  5. If this is your first message, it creates a mock appointment for “tomorrow” and sends a reminder; otherwise it adds your new message to the conversation history.
  6. It selects a few upcoming open slots from the simulated calendar, adds them to the system prompt, asks Azure OpenAI for a receptionist‑style reply, and receives the response.
  7. The reply goes back through Azure Communication Services, and the conversation state stays in memory.

That’s the loop. An event arrives, flows through a thin path, and a reply goes out. No constant checking (polling) or scheduled scripts needed.

Demo vs Production

In the demo you start the conversation by texting the number. In a production rollout, you usually send an automated reminder (for example 24 hours before) and let the patient reply to confirm or change. From there the path is straightforward: swap the simulated calendar for a real scheduling API, persist conversation and appointment state, add authentication and signed webhook validation, and layer in logging and compliance. The event flow itself staysthe same.

The Calendar Trick

We prebuild the next 30 business days (weekdays only), 09:00–17:00 in 30-minute slots, mark about 80 percent as “booked,” and keep the rest “available.” On each turn we pull a small handful of near-term open times and add them to the system prompt. That gives the model concrete, bounded choices and prevents it from inventing odd times like “3:10 AM” or “Saturday 7 PM.” A single snapshot replaces custom slot logic while still feeling live.

 

The FastAPI routes for getting calendar logic

 

Prompt Strategy

The system prompt frames a single role: a friendly receptionist limited to scheduling (no medical advice, within business hours, 30-minute increments). Each user message refreshes the availability lines so the model always sees current openings. The rules: only offer specific times when rescheduling, stay concise, and confirm final details. This balance keeps replies natural while keeping time suggestions controlled.

Where to Take It Next

To evolve the demo into a dependable production service you layer durability, richer scheduling logic, safety, and observability onto the same event path - no rewrite required.

Productization

  • Persist conversations and appointments (database + real scheduling/calendar API)
  • Authentication, signed webhook validation, rate limiting
  • Structured logging, tracing, latency and token metrics

Scheduling intelligence

  • Function / tool calls for explicit slot selection
  • Real calendar integration (Outlook, scheduling API, electronic health record system)
  • Time zones, appointment types, user preferences (language, time windows)

Safety & context

  • Moderation / compliance filters
  • Retrieval for policies, preparation instructions, service types

Insights & analytics

  • Analytics (reminder → confirmation rate, response latency, fallback counts)

Getting It Running (You’ll Spend Minutes, Not Hours)

This setup is intentionally light. The only potentially slow step is acquiring a phone number in Azure Communication Services (see the official quickstart). Full step-by-step instructions (environment variables, dev tunnel, Event Grid subscription) live in the demo repository README. The high-level overview is:

  1. Clone the repository and copy .env.example to .env
  2. Add Azure Communication Services connection string + phone number and Azure OpenAI endpoint/key/model.
  3. Install dependencies and start the app on port 8000.
  4. Expose port 8000 with a dev tunnel and point an Event Grid SMSReceived subscription to /api/sms/webhook.
  5. Text your Azure Communication Services number and observe inbound event and reply in the terminal.

Screenshot of a terminal log with inbound event + “SMS sent to ACS number"

Closing

You now have an event‑driven SMS conversation that feels like a live receptionist using only a phone number, a webhook, a lightweight availability snapshot, and a model prompt. Clone the repository, run the demo, and try a reschedule from your own phone. Extend it and make it your own - whether that means integrating a real scheduling API, adding persistence, or incorporating compliance features. We’d love to see what you build.

Published Aug 13, 2025
Version 1.0
No CommentsBe the first to comment