Skip to main content

Overview

Industry: Retail A customer-facing kiosk that prints receipts, reads NFC loyalty cards, displays messages on screen, and lets customers request help from the AI agent. Commands:
  • print_receipt — Print a formatted receipt
  • read_nfc_card — Read an NFC loyalty card
  • display_message — Show a message on the kiosk screen
Triggers:
  • customer_help_requested — Fires when a customer presses the help button

Device Client (Node.js)

import { DeviceClient } from '@lua-ai/device-client';

// Simulated hardware interfaces
const printer = {
  print: async (lines: string[]) => {
    console.log('--- RECEIPT ---');
    lines.forEach(l => console.log(l));
    console.log('--- END ---');
    return { printed: true, lineCount: lines.length };
  },
};

const nfc = {
  read: async () => ({
    cardId: 'NFC-8847-2024',
    memberName: 'Jane Smith',
    tier: 'Gold',
    points: 2450,
  }),
};

const display = {
  show: async (message: string, style: string) => {
    console.log(`[DISPLAY ${style}] ${message}`);
    return { displayed: true };
  },
};

const device = new DeviceClient({
  agentId: process.env.LUA_AGENT_ID!,
  apiKey: process.env.LUA_API_KEY!,
  deviceName: 'store-kiosk-01',
  group: 'retail-kiosks',
  commands: [
    {
      name: 'print_receipt',
      description: 'Print a receipt on the kiosk thermal printer. Provide an array of text lines to print.',
      inputSchema: {
        type: 'object',
        properties: {
          lines: {
            type: 'array',
            items: { type: 'string' },
            description: 'Array of text lines to print on the receipt',
          },
          header: { type: 'string', description: 'Store name or header text' },
          footer: { type: 'string', description: 'Footer text (e.g., return policy)' },
        },
        required: ['lines'],
      },
      timeoutMs: 15000,
    },
    {
      name: 'read_nfc_card',
      description: 'Activate the NFC reader and scan a loyalty card. Returns member name, tier, and points balance. Prompts the customer to tap their card.',
      timeoutMs: 30000,
    },
    {
      name: 'display_message',
      description: 'Show a message on the kiosk display screen',
      inputSchema: {
        type: 'object',
        properties: {
          message: { type: 'string', description: 'Message text to display' },
          style: { type: 'string', enum: ['welcome', 'info', 'success', 'error'], default: 'info' },
        },
        required: ['message'],
      },
    },
  ],
});

device.onCommand('print_receipt', async (payload) => {
  const lines: string[] = [];

  if (payload.header) {
    lines.push('================================');
    lines.push(`  ${payload.header}`);
    lines.push('================================');
  }

  lines.push('');
  lines.push(...(payload.lines || []));
  lines.push('');

  if (payload.footer) {
    lines.push('--------------------------------');
    lines.push(payload.footer);
  }

  lines.push(`  ${new Date().toLocaleString()}`);

  const result = await printer.print(lines);
  return { ...result, totalLines: lines.length };
});

device.onCommand('read_nfc_card', async () => {
  await display.show('Please tap your loyalty card...', 'info');
  const card = await nfc.read();
  await display.show(`Welcome back, ${card.memberName}!`, 'success');
  return card;
});

device.onCommand('display_message', async (payload) => {
  const result = await display.show(payload.message, payload.style || 'info');
  return { ...result, message: payload.message };
});

async function main() {
  await device.connect();
  console.log('Retail kiosk online');

  await display.show('Welcome! How can I help you today?', 'welcome');

  // Simulate a customer pressing the help button every few minutes
  setInterval(async () => {
    if (Math.random() < 0.1) {
      await device.trigger('customer_help_requested', {
        kiosk: 'store-kiosk-01',
        location: 'entrance',
        timestamp: new Date().toISOString(),
      });
    }
  }, 30000);
}

main().catch(console.error);

Agent-Side Trigger Handler

// src/triggers/customer-help.ts
import { defineDeviceTrigger } from 'lua-cli';
import { z } from 'zod';

export const customerHelp = defineDeviceTrigger({
  name: 'customer-help-requested',
  description: 'Fired when a customer presses the help button on a retail kiosk',
  payloadSchema: z.object({
    kiosk: z.string(),
    location: z.string(),
    timestamp: z.string(),
  }),
  execute: async (payload, { agent, device }) => {
    await agent.chat(
      `A customer at kiosk "${payload.kiosk}" (${payload.location}) ` +
      `is requesting help. Please display a helpful greeting and ` +
      `ask what they need assistance with.`
    );
  },
});

Agent Configuration

// src/index.ts
import { LuaAgent, LuaSkill } from 'lua-cli';
import { customerHelp } from './triggers/customer-help';

const retailSkill = new LuaSkill({
  name: 'retail-kiosk',
  description: 'Retail kiosk customer service',
  context: `
    You operate customer-facing retail kiosks.

    Device tools:
    - print_receipt: Print receipts. Format nicely with header, items, and footer.
    - read_nfc_card: Scan loyalty cards. Use when customer wants to check points or redeem rewards.
    - display_message: Show messages on screen. Use 'welcome' for greetings, 'success' for confirmations.

    Guidelines:
    - Always greet customers warmly
    - After reading a loyalty card, mention their tier and points
    - Include store name in receipt headers
    - Add return policy in receipt footers
  `,
  tools: [],
});

export const agent = new LuaAgent({
  name: 'retail-assistant',
  persona: `You are a friendly retail assistant at a kiosk. Help customers check loyalty points,
    print receipts, and find information. Be warm, concise, and helpful.`,
  skills: [retailSkill],
  deviceTriggers: [customerHelp],
});

Next Steps

CDN Uploads

Upload screenshots and logs from kiosk devices

Smart Office

Facilities management example

Warehouse Scanner

Logistics and inventory management

Agent Tools

How device commands become agent tools