> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.agentduet.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.agentduet.com/_mcp/server.

# Voice AI Agent for Appointment Booking

An automated Voice AI agent handles appointment scheduling over the phone, checks real-time availability against a clinic calendar, confirms the booking only after explicit patient agreement, and delivers booking reference IDs.

## What it does

1. Greets the caller and gathers patient name, phone number, preferred date/time, and appointment type
2. Respects all information given upfront in a single utterance (never re-asking details already provided)
3. Queries open slots from the calendar in real-time (never inventing availability)
4. Confirms details explicitly before writing to the calendar
5. Reads back the confirmed booking reference ID over the phone
6. Optionally delivers an instant Telegram confirmation with event IDs
7. Delivers a polite goodbye and disconnects cleanly

## This sample

**Amy** at **HealthFirst Clinic** on [AgentDuet](https://pypi.org/project/agentduet/1.0.0/) with **Gemini Live** and **Google Calendar** (or an in-memory calendar backend). Optional Telegram confirmation. Full source: [agentduet-samples / appointment-booking](https://github.com/AgentDuet/agentduet-samples/tree/main/use-cases/appointment-booking).

**State flow:** `NEW → LIVE` (`answer()`) → Gemini Live bidirectional scheduling loop → `disconnect()` / `close()`

## Prerequisites

- Python **3.12+**
- Get an API key and connector UUID at [agentduet.com](https://agentduet.com)
- Google Gemini API key ([Google AI Studio](https://aistudio.google.com/apikey), [Gemini Live](https://ai.google.dev/gemini-api/docs/live))
- Optional: [Google Calendar API](https://developers.google.com/calendar/api/guides/overview) service-account JSON ([Google Cloud Console](https://console.cloud.google.com/))
- Optional: Telegram bot token and chat ID for confirmation messages

## Tutorial

### Step 1: Clone the sample

```bash
git clone https://github.com/AgentDuet/agentduet-samples.git
cd agentduet-samples/use-cases/appointment-booking
```

### Step 2: Install

```bash
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

### Step 3: Configure `.env`

```bash
cp .env.example .env
```

```env
AGENTDUET_API_KEY=your-connector-api-key
AGENTDUET_CONNECTOR_UUID=your-connector-uuid
GEMINI_API_KEY=your-gemini-key

# Google Calendar (skip these to use the in-memory demo calendar)
GOOGLE_CALENDAR_CREDENTIALS=./calendar-service-account.json
GOOGLE_CALENDAR_ID=primary
BUSINESS_TZ=UTC

# Optional confirmation
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=
```

Share the target calendar with the service account email (**Make changes to events**).

### Step 4: Run

```bash
python main.py
```

### Step 5: Place a call and test

Call your connector number. Amy should greet as HealthFirst. Try:

| Caller says | Expected |
|---|---|
| “Hi, I'm Claudia from HealthFirst. General checkup tomorrow at 10 AM. My number is +65 XXXXXXXX.” | Acknowledge; check slots; confirm details; book |
| “Hi, I'm Joy. Specialist next Monday at 2 PM, +65 XXXXXXXX.” | Fill only missing pieces; confirm before book |
| “I'm Alex - book me something this week.” | Ask for appointment type / time / phone (+65 XXXXXXXX) |

After a successful booking, Amy reads back the booking ID and concludes the call. If Telegram is configured, the booking confirmation arrives in chat.

## How it works

Gemini Live streams PCM audio bidirectionally over WebSockets. Structured tool calls handle calendar operations and call lifecycle. When a slot is confirmed, the calendar backend writes the appointment and returns a verified booking ID. Once the booking is read back and acknowledged, the agent speaks its closing greeting and disconnects cleanly.

## Key APIs

| Piece | Role |
|---|---|
| Gemini Live | Real-time speech reasoning and structured tool execution |
| Google Calendar API | Source of truth for slot availability and booking persistence |
| `call.caller.audio_stream()` | Captures caller microphone audio |
| `call.send_audio(chunk)` | Delivers synthesized agent voice |
| `call.clear_send_audio_buffer()` | Zero-latency barge-in handling |
| `call.disconnect()` | Clean call hangup upon booking completion |

## Related

- [Gemini Live Integration](/integrations/gemini-live)
- [AI Receptionist with CRM Lookup](/use-cases/ai-receptionist-with-crm-lookup)
- [Feedback Collection with Outbound Calls](/use-cases/feedback-collection-with-outbound-calls)
- [Document Collection with Outbound Calls](/use-cases/document-collection-with-outbound-calls)