Skip to main content

Overview

Real estate agent assistant integrating with MLS (Multiple Listing Service) API and Lua Data API for enhanced property search. What it does:
  • Search properties via MLS API
  • Save favorite properties
  • Schedule viewings
  • Compare properties
  • Get neighborhood info
APIs used: External MLS API + Lua Data API

Complete Implementation

src/index.ts

import { LuaAgent, LuaSkill } from "lua-cli";
import {
  SearchPropertiesTool,
  GetPropertyDetailsTool,
  ScheduleViewingTool,
  SaveFavoriteTool,
  ComparePropertiesTool
} from "./tools/RealEstateTools";

// Real estate skill
const realEstateSkill = new LuaSkill({
  name: "real-estate-assistant",
  description: "Real estate search and showing scheduler",
  context: `
    This skill helps clients search and view properties.
    
    - search_properties: Search MLS for properties matching criteria
    - get_property_details: Get full details for a specific property
    - schedule_viewing: Book property showing appointment
    - save_favorite: Save property to client's favorites
    - compare_properties: Compare multiple properties side by side
    
    Always ask about budget, location preferences, and must-haves.
    Highlight unique features of properties.
    Be enthusiastic and professional.
  `,
  tools: [
    new SearchPropertiesTool(),
    new GetPropertyDetailsTool(),
    new ScheduleViewingTool(),
    new SaveFavoriteTool(),
    new ComparePropertiesTool()
  ]
});

// Configure agent (v3.0.0)
export const agent = new LuaAgent({
  name: "real-estate-assistant",
  
  persona: `You are an experienced and enthusiastic real estate agent.
  
Your role:
- Help clients find their dream home
- Search MLS listings based on preferences
- Schedule property viewings
- Provide market insights
- Guide through the home-buying process

Communication style:
- Enthusiastic and positive
- Professional and knowledgeable
- Patient and understanding
- Detail-oriented
- Market-savvy

Best practices:
- Always ask about budget and location preferences
- Inquire about must-have features vs nice-to-haves
- Highlight unique property features
- Provide honest market assessments
- Suggest neighborhoods that match lifestyle
- Offer to schedule viewings immediately

When to escalate:
- Making offers (requires human agent)
- Legal questions (refer to attorney)
- Complex financing (refer to mortgage specialist)
- Commercial properties (different department)`,

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

Tools Implementation

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

// 1. Search Properties (External MLS API)
export class SearchPropertiesTool implements LuaTool {
  name = "search_properties";
  description = "Search real estate listings";
  
  inputSchema = z.object({
    location: z.string(),
    minPrice: z.number().optional(),
    maxPrice: z.number().optional(),
    bedrooms: z.number().optional(),
    propertyType: z.enum(['house', 'condo', 'apartment', 'townhouse']).optional()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    const mlsApiKey = env('MLS_API_KEY');
    
    // Call MLS API
    const response = await fetch('https://api.mlslistings.com/api/v1/search', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${mlsApiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        location: input.location,
        price_min: input.minPrice,
        price_max: input.maxPrice,
        bedrooms: input.bedrooms,
        property_type: input.propertyType
      })
    });
    
    const data = await response.json();
    
    // Save to Lua Data for vector search capabilities
    for (const property of data.listings) {
      const searchText = `${property.address} ${property.city} ${property.description} ${property.features.join(' ')}`;
      await Data.create('property_cache', property, searchText);
    }
    
    return {
      properties: data.listings.map(p => ({
        id: p.mls_id,
        address: p.address,
        city: p.city,
        price: `$${p.price.toLocaleString()}`,
        bedrooms: p.bedrooms,
        bathrooms: p.bathrooms,
        sqft: p.square_feet,
        type: p.property_type,
        description: p.description.substring(0, 150) + '...'
      })),
      count: data.listings.length
    };
  }
}

// 2. Save Favorite (Lua Data)
export class SaveFavoriteTool implements LuaTool {
  name = "save_favorite";
  description = "Save a property to favorites";
  
  inputSchema = z.object({
    mlsId: z.string(),
    notes: z.string().optional()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    await Data.create('favorites', {
      mlsId: input.mlsId,
      notes: input.notes,
      savedAt: new Date().toISOString()
    });
    
    return {
      success: true,
      message: "Property saved to favorites"
    };
  }
}

// 3. Schedule Viewing
export class ScheduleViewingTool implements LuaTool {
  name = "schedule_viewing";
  description = "Schedule a property viewing";
  
  inputSchema = z.object({
    mlsId: z.string(),
    date: z.string(),
    time: z.string(),
    clientName: z.string(),
    clientEmail: z.string().email(),
    clientPhone: z.string()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    const viewing = await Data.create('viewings', {
      ...input,
      status: 'scheduled',
      createdAt: new Date().toISOString()
    });
    
    return {
      success: true,
      viewingId: viewing.id,
      message: `Viewing scheduled for ${input.date} at ${input.time}`
    };
  }
}

Environment Setup

# .env
MLS_API_KEY=your_mls_api_key
MLS_API_URL=https://api.mlslistings.com

Key Features

External MLS

Real MLS property data

Vector Search

Semantic property search