Skip to main content

Overview

The Lua API provides access to request-level runtime information. Use it in your tools, tool conditions, preprocessors, and postprocessors to access context about the current request.
import { Lua } from 'lua-cli';

// Access the current channel
const channel = Lua.request.channel;

if (channel === 'whatsapp') {
  // WhatsApp-specific logic
}

Import

import { Lua, Channel } from 'lua-cli';

Availability

The Lua API is available in:
ContextAvailable
Tool execute✅ Yes
Tool condition✅ Yes
Preprocessor execute✅ Yes
Postprocessor execute✅ Yes

Lua.request

The request object contains information about the current request context.

channel

The channel through which the current request originated.
Lua.request.channel: Channel
Type: Channel
type Channel = 
  | 'web'       // Chat widget on a website
  | 'whatsapp'  // WhatsApp integration
  | 'facebook'  // Facebook Messenger integration
  | 'instagram' // Instagram integration
  | 'slack'     // Slack integration
  | 'api'       // Direct HTTP API call
  | 'dev'       // Local development / CLI testing
  | 'email'     // Email integration
  | string;     // Any other channel
Example - Channel-specific behavior:
import { Lua } from 'lua-cli';

const channel = Lua.request.channel;

switch (channel) {
  case 'whatsapp':
    // Keep responses concise for mobile
    return { format: 'brief' };
  case 'web':
    // Can use rich formatting
    return { format: 'rich' };
  case 'api':
    // Return structured data
    return { format: 'json' };
  default:
    return { format: 'standard' };
}

webhook

The webhook object contains information about the incoming webhook request from channel integrations. This provides access to the original data sent by the channel provider (WhatsApp, Slack, Teams, etc.).
Lua.request.webhook: { payload: any } | undefined
Type: { payload: any } | undefined The webhook object is only available when the request originated from a webhook-based channel. For direct API calls or the web chat widget, this will be undefined.

webhook.payload

The raw, unmodified webhook payload from the channel provider. Available for channels:
  • whatsapp - Full WhatsApp Cloud API webhook payload
  • slack - Slack Events API payload
  • teams - Microsoft Teams activity object
  • front - Front webhook body
  • facebook - Facebook Messenger webhook event
  • instagram - Instagram Messaging webhook event
  • messagebird - MessageBird webhook body
Example - Accessing WhatsApp webhook data:
import { Lua } from 'lua-cli';

const webhook = Lua.request.webhook;

if (Lua.request.channel === 'whatsapp' && webhook) {
  // Access WhatsApp-specific data
  const entry = webhook.payload.entry?.[0];
  const value = entry?.changes?.[0]?.value;
  const messageId = value?.messages?.[0]?.id;
  const phoneNumberId = value?.metadata?.phone_number_id;
  
  return {
    messageId,
    phoneNumberId,
    raw: webhook.payload,
  };
}
Example - Slack event data:
import { Lua } from 'lua-cli';

const webhook = Lua.request.webhook;

if (Lua.request.channel === 'slack' && webhook) {
  const event = webhook.payload.event;
  const teamId = webhook.payload.team_id;
  const channelId = event?.channel;
  
  return {
    teamId,
    channelId,
    eventType: event?.type,
  };
}
Example - Teams activity:
import { Lua } from 'lua-cli';

const webhook = Lua.request.webhook;

if (Lua.request.channel === 'teams' && webhook) {
  const activity = webhook.payload;
  const conversationId = activity.conversation?.id;
  const tenantId = activity.conversation?.tenantId;
  const serviceUrl = activity.serviceUrl;
  
  return {
    conversationId,
    tenantId,
    serviceUrl,
  };
}

Complete Examples

Conditional Tool Availability

Make a tool available only on certain channels:
import { LuaTool, Lua } from 'lua-cli';
import { z } from 'zod';

export default class WhatsAppOnlyTool implements LuaTool {
  name = 'send_whatsapp_template';
  description = 'Send a WhatsApp message template';

  inputSchema = z.object({
    templateId: z.string(),
  });

  // Tool only shows up on WhatsApp
  condition = async () => {
    return Lua.request.channel === 'whatsapp';
  };

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Implementation
    return { success: true };
  }
}

Channel-Aware Tool Logic

Adjust tool behavior based on channel:
import { LuaTool, Lua } from 'lua-cli';
import { z } from 'zod';

export default class GetSupportInfoTool implements LuaTool {
  name = 'get_support_info';
  description = 'Get customer support information';

  inputSchema = z.object({});

  async execute() {
    const channel = Lua.request.channel;

    const baseInfo = {
      email: '[email protected]',
      hours: '9 AM - 5 PM EST',
    };

    // Add channel-specific info
    switch (channel) {
      case 'whatsapp':
        return {
          ...baseInfo,
          message: 'You can also reply here for quick support!',
        };
      case 'web':
        return {
          ...baseInfo,
          phone: '1-800-SUPPORT',
          liveChatUrl: 'https://example.com/chat',
        };
      default:
        return baseInfo;
    }
  }
}

Preprocessor with Channel Context

Use channel in preprocessors:
import { Preprocessor, PreprocessorConfig, Lua } from 'lua-cli';

const channelGreeting: PreprocessorConfig = {
  name: 'channel-greeting',
  description: 'Add channel-specific greeting context',
  priority: 1,
  execute: async (userInstance, messages, channel) => {
    // Prefer using Lua.request.channel
    const currentChannel = Lua.request.channel;

    return {
      additionalContext: `User is chatting via ${currentChannel}.`,
    };
  },
};

export default Preprocessor.create(channelGreeting);

Postprocessor with Channel-Specific Formatting

Format responses based on channel:
import { Postprocessor, PostprocessorConfig, Lua } from 'lua-cli';

const formatForChannel: PostprocessorConfig = {
  name: 'format-for-channel',
  description: 'Format response based on channel',
  execute: async (user, message, response, channel) => {
    // Prefer using Lua.request.channel
    const currentChannel = Lua.request.channel;

    // WhatsApp has character limits - truncate long responses
    if (currentChannel === 'whatsapp' && response.length > 4096) {
      return {
        modifiedResponse: response.substring(0, 4093) + '...',
      };
    }

    return { modifiedResponse: response };
  },
};

export default Postprocessor.create(formatForChannel);

Future Expansion

The Lua API will be expanded to include additional runtime information, such as:
  • User profile data
  • Session information
  • More request metadata
This API is designed to grow. Check back for new properties as they become available.

Best Practices

Always import the Lua API from lua-cli:
import { Lua } from 'lua-cli';

const channel = Lua.request.channel;
The channel type includes unknown for unrecognized values:
const channel = Lua.request.channel;

if (channel === 'whatsapp' || channel === 'web') {
  // Known channel handling
} else {
  // Fallback for unknown channels
}
Use channel for minor adjustments, not completely different flows:
// ✅ Good - Minor adjustments
const maxLength = channel === 'whatsapp' ? 4096 : 10000;

// ❌ Avoid - Completely different tools per channel
// Instead, use tool conditions to show/hide tools
For channel-specific tools, use the condition function:
condition = async () => {
  return Lua.request.channel === 'whatsapp';
};
Always check if webhook exists before accessing it:
const webhook = Lua.request.webhook;

if (webhook) {
  // Safe to access webhook.payload properties
  const data = webhook.payload.entry?.[0]?.changes?.[0]?.value;
}
For channel-specific webhook handling, always check both:
if (Lua.request.channel === 'whatsapp' && Lua.request.webhook) {
  // WhatsApp-specific webhook handling
  const payload = Lua.request.webhook.payload;
}