Skip to main content

Overview

Hotel concierge AI agent for room bookings, reservations, and guest services using Lua Data API. What it does:
  • Check room availability
  • Create reservations
  • Modify bookings
  • Request room service
  • Provide local recommendations
APIs used: Lua Data API for reservations and rooms

Complete Implementation

src/index.ts

import { LuaAgent, LuaSkill } from "lua-cli";
import {
  CheckAvailabilityTool,
  CreateReservationTool,
  GetReservationTool,
  CancelReservationTool,
  RoomServiceTool
} from "./tools/HotelTools";

// Hotel concierge skill
const hotelSkill = new LuaSkill({
  name: "hotel-concierge",
  description: "Hotel booking and concierge services",
  context: `
    This skill helps guests with hotel bookings and services.
    
    - check_availability: Search for available rooms by date and guest count
    - create_reservation: Book a room for specified dates
    - get_reservation: Look up existing reservation details
    - cancel_reservation: Cancel a booking
    - room_service: Order room service or request amenities
    
    Always confirm dates and guest count before booking.
    Offer upgrade suggestions when available.
    Be warm and hospitable.
  `,
  tools: [
    new CheckAvailabilityTool(),
    new CreateReservationTool(),
    new GetReservationTool(),
    new CancelReservationTool(),
    new RoomServiceTool()
  ]
});

// Configure agent (v3.0.0)
export const agent = new LuaAgent({
  name: "hotel-concierge-assistant",
  
  persona: `You are a friendly and professional hotel concierge.
  
Your role:
- Help guests find and book the perfect room
- Assist with reservations and modifications
- Provide room service and amenity requests
- Offer local recommendations and directions
- Ensure excellent guest experience

Communication style:
- Warm and hospitable
- Professional and attentive
- Proactive with suggestions
- Detail-oriented
- Service-minded

Best practices:
- Always confirm check-in and check-out dates
- Mention amenities included with each room type
- Offer upgrades when available
- Ask about special occasions (anniversary, birthday)
- Provide clear cancellation policies
- Suggest local attractions and dining

When to escalate:
- VIP guest requests
- Complex group bookings
- Special event coordination
- Maintenance issues`,

  
  skills: [hotelSkill]
});
v3.0.0 Pattern: This demo now uses LuaAgent to configure the agent’s persona, welcome message, and skills.

src/tools/HotelTools.ts

import { LuaTool, Data } from "lua-cli";
import { z } from "zod";

// 1. Check Availability
export class CheckAvailabilityTool implements LuaTool {
  name = "check_availability";
  description = "Check room availability for specific dates";
  
  inputSchema = z.object({
    checkIn: z.string().describe("Check-in date (YYYY-MM-DD)"),
    checkOut: z.string().describe("Check-out date (YYYY-MM-DD)"),
    guests: z.number().min(1).max(10).describe("Number of guests")
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Get all rooms
    const rooms = await Data.get('hotel_rooms', {}, 1, 100);
    
    // Get existing reservations for these dates
    const reservations = await Data.get('reservations', {
      checkIn: { $lte: input.checkOut },
      checkOut: { $gte: input.checkIn },
      status: { $ne: 'cancelled' }
    });
    
    const bookedRoomIds = new Set(reservations.data.map(r => r.data.roomId));
    
    // Filter available rooms
    const available = rooms.data
      .filter(room => !bookedRoomIds.has(room.id))
      .filter(room => room.data.maxGuests >= input.guests)
      .map(room => ({
        roomId: room.id,
        roomType: room.data.type,
        maxGuests: room.data.maxGuests,
        pricePerNight: `$${room.data.pricePerNight}`,
        amenities: room.data.amenities,
        description: room.data.description
      }));
    
    const nights = this.calculateNights(input.checkIn, input.checkOut);
    
    return {
      available: available.length > 0,
      rooms: available,
      checkIn: input.checkIn,
      checkOut: input.checkOut,
      nights,
      message: available.length > 0
        ? `${available.length} rooms available for ${nights} nights`
        : "No rooms available for these dates. Try different dates?"
    };
  }
  
  private calculateNights(checkIn: string, checkOut: string): number {
    const start = new Date(checkIn);
    const end = new Date(checkOut);
    return Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
  }
}

// 2. Create Reservation
export class CreateReservationTool implements LuaTool {
  name = "create_reservation";
  description = "Book a hotel room";
  
  inputSchema = z.object({
    roomId: z.string(),
    checkIn: z.string(),
    checkOut: z.string(),
    guestName: z.string(),
    guestEmail: z.string().email(),
    guestPhone: z.string(),
    guests: z.number().min(1),
    specialRequests: z.string().optional()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Get room details
    const room = await Data.getEntry('hotel_rooms', input.roomId);
    
    if (!room) {
      throw new Error('Room not found');
    }
    
    // Calculate total
    const nights = this.calculateNights(input.checkIn, input.checkOut);
    const totalPrice = room.data.pricePerNight * nights;
    
    // Create reservation
    const reservation = await Data.create('reservations', {
      roomId: input.roomId,
      roomType: room.data.type,
      checkIn: input.checkIn,
      checkOut: input.checkOut,
      guestName: input.guestName,
      guestEmail: input.guestEmail,
      guestPhone: input.guestPhone,
      numberOfGuests: input.guests,
      nights,
      pricePerNight: room.data.pricePerNight,
      totalPrice,
      specialRequests: input.specialRequests,
      status: 'confirmed',
      confirmationCode: this.generateConfirmationCode(),
      createdAt: new Date().toISOString()
    }, `${input.guestName} ${input.guestEmail} ${input.checkIn}`);
    
    return {
      success: true,
      reservationId: reservation.id,
      confirmationCode: reservation.data.confirmationCode,
      roomType: room.data.type,
      checkIn: input.checkIn,
      checkOut: input.checkOut,
      nights,
      total: `$${totalPrice.toFixed(2)}`,
      message: `Reservation confirmed! Your confirmation code is ${reservation.data.confirmationCode}`
    };
  }
  
  private calculateNights(checkIn: string, checkOut: string): number {
    const start = new Date(checkIn);
    const end = new Date(checkOut);
    return Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
  }
  
  private generateConfirmationCode(): string {
    return 'HTL-' + Math.random().toString(36).substring(2, 10).toUpperCase();
  }
}

// 3. Get Reservation
export class GetReservationTool implements LuaTool {
  name = "get_reservation";
  description = "Look up reservation details";
  
  inputSchema = z.object({
    confirmationCode: z.string().describe("Reservation confirmation code"),
    email: z.string().email().describe("Guest email for verification")
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Search reservations
    const results = await Data.get('reservations', {
      confirmationCode: input.confirmationCode,
      guestEmail: input.email
    });
    
    if (results.data.length === 0) {
      throw new Error('Reservation not found. Please check your confirmation code and email.');
    }
    
    const reservation = results.data[0];
    
    return {
      reservationId: reservation.id,
      confirmationCode: reservation.data.confirmationCode,
      guestName: reservation.data.guestName,
      roomType: reservation.data.roomType,
      checkIn: reservation.data.checkIn,
      checkOut: reservation.data.checkOut,
      nights: reservation.data.nights,
      guests: reservation.data.numberOfGuests,
      total: `$${reservation.data.totalPrice.toFixed(2)}`,
      status: reservation.data.status,
      specialRequests: reservation.data.specialRequests
    };
  }
}

// 4. Cancel Reservation
export class CancelReservationTool implements LuaTool {
  name = "cancel_reservation";
  description = "Cancel a hotel reservation";
  
  inputSchema = z.object({
    confirmationCode: z.string(),
    email: z.string().email()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    const results = await Data.get('reservations', {
      confirmationCode: input.confirmationCode,
      guestEmail: input.email
    });
    
    if (results.data.length === 0) {
      throw new Error('Reservation not found');
    }
    
    const reservation = results.data[0];
    
    // Update status to cancelled
    await Data.update('reservations', reservation.id, {
      ...reservation.data,
      status: 'cancelled',
      cancelledAt: new Date().toISOString()
    });
    
    return {
      success: true,
      confirmationCode: input.confirmationCode,
      refundAmount: `$${reservation.data.totalPrice.toFixed(2)}`,
      message: "Reservation cancelled. Refund will be processed within 5-7 business days."
    };
  }
}

// 5. Room Service
export class RoomServiceTool implements LuaTool {
  name = "room_service";
  description = "Order room service or request amenities";
  
  inputSchema = z.object({
    confirmationCode: z.string(),
    request: z.string().describe("Room service order or amenity request")
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Log room service request
    const request = await Data.create('room_service_requests', {
      confirmationCode: input.confirmationCode,
      request: input.request,
      status: 'pending',
      requestedAt: new Date().toISOString()
    }, input.request);
    
    return {
      success: true,
      requestId: request.id,
      estimatedTime: "15-30 minutes",
      message: `Room service request received. Estimated delivery: 15-30 minutes.`
    };
  }
}

Deployment

lua push
lua deploy

Key Features

Lua Data API

Stores rooms and reservations

Vector Search

Search reservations by guest info

Date Logic

Availability checking

Confirmation Codes

Unique booking identifiers