Bot WA AI untuk Appointment Booking

Cara membuat bot AI WhatsApp untuk booking appointment otomatis. Jadwal, konfirmasi, reminder. Tutorial lengkap!

Bot WA AI untuk Appointment Booking
Bot WA AI untuk Appointment Booking

AI booking assistant = 24/7 reservation!

Bot AI bisa handle booking appointment secara natural - tanya kebutuhan, cek availability, konfirmasi jadwal, dan kirim reminder otomatis.


Use Cases

📅 COCOK UNTUK:

HEALTHCARE:
- Klinik & dokter
- Dental
- Spa & wellness

BEAUTY:
- Salon
- Barbershop
- Nail art

PROFESSIONAL:
- Konsultasi
- Coaching
- Legal

SERVICES:
- Auto service
- Home repair
- Photography

Booking Flow

📋 FLOW IDEAL:

1. GREETING
   "Hai! Mau booking untuk layanan apa?"

2. SERVICE SELECTION
   "Pilih layanan: A, B, atau C"

3. DATE PREFERENCE
   "Mau booking tanggal berapa?"

4. TIME SELECTION
   "Jam berapa yang nyaman?"

5. AVAILABILITY CHECK
   "Slot tersedia! / Coba waktu lain?"

6. CONFIRMATION
   "Konfirmasi: [detail]. Benar?"

7. BOOKING SUCCESS
   "Done! Akan kirim reminder H-1"

System Prompt

javascript

const BOOKING_PROMPT = `Kamu adalah AI booking assistant untuk [SALON NAME].

TENTANG SALON:
- Salon kecantikan wanita
- Alamat: [ALAMAT]
- Jam buka: 09:00-21:00 (Senin-Sabtu)
- Minggu tutup

LAYANAN & HARGA:
1. Potong Rambut - Rp 75.000 (45 menit)
2. Hair Coloring - Rp 350.000 (2 jam)
3. Creambath - Rp 150.000 (1 jam)
4. Hair Treatment - Rp 250.000 (1.5 jam)
5. Manicure Pedicure - Rp 200.000 (1.5 jam)
6. Facial - Rp 300.000 (1.5 jam)

STYLISTS:
- Kak Rina (Senior) - Tersedia Senin-Jumat
- Kak Dewi (Senior) - Tersedia Selasa-Sabtu
- Kak Maya (Junior) - Tersedia setiap hari

TUGAS KAMU:
1. Sapa dengan ramah
2. Tanya layanan yang diinginkan
3. Tanya tanggal & waktu preferensi
4. Cek availability (panggil function)
5. Tawarkan alternatif jika tidak tersedia
6. Konfirmasi detail booking
7. Selesaikan booking (panggil function)

ATURAN:
- Hanya bisa booking H+1 sampai H+14
- Tidak bisa booking hari Minggu
- Maksimal 2 layanan per booking
- Minta nama & nomor WA untuk booking

RESPONSE STYLE:
- Bahasa Indonesia casual dengan "Kak"
- Ramah dan helpful
- Gunakan emoji 😊💇‍♀️💅`;

Function Calling Implementation

javascript

const bookingTools = [
    {
        type: 'function',
        function: {
            name: 'check_availability',
            description: 'Cek ketersediaan slot booking',
            parameters: {
                type: 'object',
                properties: {
                    service: {
                        type: 'string',
                        description: 'Nama layanan'
                    },
                    date: {
                        type: 'string',
                        description: 'Tanggal (YYYY-MM-DD)'
                    },
                    preferred_time: {
                        type: 'string',
                        description: 'Waktu preferensi (HH:MM)'
                    },
                    stylist: {
                        type: 'string',
                        description: 'Nama stylist (optional)'
                    }
                },
                required: ['service', 'date']
            }
        }
    },
    {
        type: 'function',
        function: {
            name: 'create_booking',
            description: 'Buat booking baru',
            parameters: {
                type: 'object',
                properties: {
                    customer_name: { type: 'string' },
                    customer_phone: { type: 'string' },
                    service: { type: 'string' },
                    date: { type: 'string' },
                    time: { type: 'string' },
                    stylist: { type: 'string' }
                },
                required: ['customer_name', 'customer_phone', 'service', 'date', 'time']
            }
        }
    },
    {
        type: 'function',
        function: {
            name: 'cancel_booking',
            description: 'Batalkan booking',
            parameters: {
                type: 'object',
                properties: {
                    booking_id: { type: 'string' }
                },
                required: ['booking_id']
            }
        }
    }
];

async function handleBookingChat(userId, userMessage, conversationHistory) {
    const response = await openai.chat.completions.create({
        model: 'gpt-4o',
        messages: [
            { role: 'system', content: BOOKING_PROMPT },
            ...conversationHistory,
            { role: 'user', content: userMessage }
        ],
        tools: bookingTools,
        tool_choice: 'auto'
    });
    
    const message = response.choices[0].message;
    
    // Check if function called
    if (message.tool_calls) {
        const results = [];
        
        for (const toolCall of message.tool_calls) {
            const args = JSON.parse(toolCall.function.arguments);
            let result;
            
            switch (toolCall.function.name) {
                case 'check_availability':
                    result = await checkAvailability(args);
                    break;
                case 'create_booking':
                    result = await createBooking(args);
                    break;
                case 'cancel_booking':
                    result = await cancelBooking(args);
                    break;
            }
            
            results.push({
                tool_call_id: toolCall.id,
                role: 'tool',
                content: JSON.stringify(result)
            });
        }
        
        // Continue conversation with function results
        const finalResponse = await openai.chat.completions.create({
            model: 'gpt-4o',
            messages: [
                { role: 'system', content: BOOKING_PROMPT },
                ...conversationHistory,
                { role: 'user', content: userMessage },
                message,
                ...results
            ]
        });
        
        return finalResponse.choices[0].message.content;
    }
    
    return message.content;
}

Backend Functions

javascript

// Check availability
async function checkAvailability({ service, date, preferred_time, stylist }) {
    const serviceInfo = services[service];
    if (!serviceInfo) {
        return { available: false, error: 'Layanan tidak ditemukan' };
    }
    
    const duration = serviceInfo.duration;
    const bookingDate = new Date(date);
    
    // Check if Sunday
    if (bookingDate.getDay() === 0) {
        return { available: false, reason: 'Hari Minggu tutup' };
    }
    
    // Check if within booking window (H+1 to H+14)
    const today = new Date();
    const maxDate = new Date();
    maxDate.setDate(maxDate.getDate() + 14);
    
    if (bookingDate <= today || bookingDate > maxDate) {
        return { 
            available: false, 
            reason: 'Hanya bisa booking H+1 sampai H+14' 
        };
    }
    
    // Get existing bookings
    const existingBookings = await db.bookings.find({
        date: date,
        status: { $ne: 'cancelled' }
    }).toArray();
    
    // Find available slots
    const allSlots = generateTimeSlots('09:00', '21:00', 30);
    const availableSlots = allSlots.filter(slot => {
        return !hasConflict(slot, duration, existingBookings, stylist);
    });
    
    if (preferred_time) {
        const isPreferredAvailable = availableSlots.includes(preferred_time);
        
        if (isPreferredAvailable) {
            return {
                available: true,
                slot: preferred_time,
                service,
                date,
                price: serviceInfo.price
            };
        } else {
            // Suggest alternatives
            const alternatives = findClosestSlots(preferred_time, availableSlots, 3);
            return {
                available: false,
                reason: `Slot ${preferred_time} tidak tersedia`,
                alternatives: alternatives,
                date
            };
        }
    }
    
    return {
        available: true,
        availableSlots: availableSlots.slice(0, 10),
        date,
        service
    };
}

// Create booking
async function createBooking({ customer_name, customer_phone, service, date, time, stylist }) {
    const bookingId = generateBookingId();
    
    const booking = {
        bookingId,
        customerName: customer_name,
        customerPhone: customer_phone,
        service,
        date,
        time,
        stylist: stylist || 'Any',
        status: 'confirmed',
        createdAt: new Date()
    };
    
    await db.bookings.insertOne(booking);
    
    // Schedule reminders
    await scheduleReminder(booking, 'H-1');
    await scheduleReminder(booking, 'H-day');
    
    return {
        success: true,
        bookingId,
        details: {
            service,
            date,
            time,
            stylist: booking.stylist
        },
        message: 'Booking berhasil!'
    };
}

Natural Conversation Example

👤: Hai mau booking

🤖: Hai Kak! Selamat datang di [Salon] 💇‍♀️

Mau booking untuk layanan apa nih?

1️⃣ Potong Rambut - Rp 75k
2️⃣ Hair Coloring - Rp 350k
3️⃣ Creambath - Rp 150k
4️⃣ Hair Treatment - Rp 250k
5️⃣ Manicure Pedicure - Rp 200k
6️⃣ Facial - Rp 300k

---

👤: Mau creambath, hari sabtu bisa?

🤖: Creambath ya kak! ✨

Sabtu ini tanggal 22 Februari ya?
Jam berapa yang nyaman kak?

Slot tersedia:
- 09:00, 10:00, 11:00
- 13:00, 14:00, 15:00
- 17:00, 18:00, 19:00

---

👤: Jam 2 siang aja

🤖: Oke kak, aku cek dulu ya...

[check_availability called]

✅ Slot tersedia!

📋 Konfirmasi booking:
━━━━━━━━━━━━━━━━━━━━
💇 Layanan: Creambath
📅 Tanggal: Sabtu, 22 Feb 2026
⏰ Jam: 14:00 (1 jam)
💰 Harga: Rp 150.000
━━━━━━━━━━━━━━━━━━━━

Boleh tau nama lengkapnya kak?

---

👤: Dina Pratiwi

🤖: Baik Kak Dina! 😊

Nomor WA ini yang akan dihubungi ya?
(untuk reminder H-1)

---

👤: Iya bener

🤖: [create_booking called]

✅ BOOKING BERHASIL!

📋 Detail Booking:
━━━━━━━━━━━━━━━━━━━━
🎫 Kode: #BK-20260222-001
👤 Nama: Dina Pratiwi
💇 Layanan: Creambath
📅 Sabtu, 22 Feb 2026
⏰ 14:00 WIB
📍 [Alamat Salon]
━━━━━━━━━━━━━━━━━━━━

💡 Info:
- Datang 10 menit lebih awal ya
- Reminder akan dikirim H-1
- Reschedule? Reply UBAH

Sampai jumpa Kak Dina! 💕

Reminder System

javascript

async function sendReminder(booking, type) {
    const templates = {
        'H-1': `⏰ REMINDER BESOK!

Hai Kak ${booking.customerName}!

Jangan lupa appointment besok ya:

📅 ${formatDate(booking.date)}
⏰ ${booking.time}
💇 ${booking.service}
📍 [Alamat]

Reply OK untuk konfirmasi!
Reply UBAH untuk reschedule.`,

        'H-day': `🌅 HARI INI!

Hai Kak ${booking.customerName}!

Appointment kamu HARI INI:

⏰ ${booking.time}
📍 [Alamat]

Sampai jumpa! 😊`
    };
    
    await sendWhatsApp(booking.customerPhone, templates[type]);
}

Best Practices

DO ✅

- Konfirmasi setiap detail
- Kirim reminder H-1 dan H-day
- Sediakan opsi reschedule mudah
- Handle edge cases (full, closed)
- Store booking dengan proper ID

DON'T ❌

- Book tanpa konfirmasi
- No reminder
- Complicated reschedule
- Ignore availability check
- Manual booking ID

FAQ

Bisa handle reschedule?

Ya! Tambahkan function reschedule_booking dan handle keyword "ubah jadwal".

Kalau slot penuh semua?

Tawarkan hari lain atau masukkan ke waiting list.


Kesimpulan

AI Booking = 24/7 reservation!

Manual BookingAI Booking
Limited hours24/7
Phone callsWhatsApp chat
Human errorConsistent
No reminderAuto reminder

Setup AI Booking →


Artikel Terkait