Skip to main content

Overview

PreProcessor allows you to intercept and process user messages before they reach your AI agent. Use preprocessors to filter spam, route messages, validate inputs, or modify messages before the agent sees them.
import { PreProcessor } from 'lua-cli';

const profanityFilter = new PreProcessor({
  name: 'profanity-filter',
  description: 'Filter inappropriate content',
  priority: 10,
  execute: async (user, messages, channel) => {
    const hasProfanity = messages.some(msg => 
      msg.type === 'text' && msg.text.includes('badword')
    );
    
    if (hasProfanity) {
      // Block message and respond
      return {
        action: 'block',
        response: "Please keep the conversation respectful."
      };
    }
    
    // Allow messages to proceed
    return { action: 'proceed' };
  }
});

export default profanityFilter;
New in v3.0.0: Message preprocessing for filtering, routing, and validation. Use with LuaAgent.

Use Cases

Content Filtering

Block spam, profanity, or inappropriate content

Message Routing

Route messages to different agents or handlers

Input Validation

Validate message format or required information

Analytics

Track message metrics before processing

Constructor

new PreProcessor(config)

Creates a new message preprocessor.
config
PreProcessorConfig
required
Preprocessor configuration object

Configuration Parameters

Required Fields

name
string
required
Unique preprocessor nameExamples: 'profanity-filter', 'message-router'
execute
function
required
Function that processes incoming messagesSignature: (user: UserDataInstance, messages: ChatMessage[], channel: string) => Promise<PreProcessorBlockResponse | PreProcessorProceedResponse>Arguments:
  • user: The UserDataInstance representing the current user.
  • messages: Array of ChatMessage objects sent by the user.
  • channel: The channel identifier (e.g., 'whatsapp', 'web', 'api').
Recommended: Use the Lua Runtime API instead of the function parameters:
  • User: User.get() to retrieve the current user
  • Channel: Lua.request.channel for the current channel
  • Webhook: Lua.request.webhook?.payload for raw webhook data (WhatsApp, Slack, Teams, etc.)
The function parameters may be removed in a future version.

Optional Fields

description
string
Preprocessor description for documentation
priority
number
Execution priority (lower runs first). Default: 100

UserData Object

The user argument passed to execute provides access to the current user’s data and methods.
interface UserDataInstance {
  // Direct access to user data properties
  uid: string;
  name?: string;
  email?: string;
  [key: string]: any;

  // Helper methods
  getChatHistory(): Promise<ChatHistoryMessage[]>;
  // ... other user management methods
}

Message Structure

The messages array passed to your execute function contains ChatMessage objects:
type ChatMessage = TextMessage | ImageMessage | FileMessage;

interface TextMessage {
  type: 'text';
  text: string;
}

interface ImageMessage {
  type: 'image';
  image: string; // URL or base64
}

interface FileMessage {
  type: 'file';
  file: string; // URL
}

Return Type

Your execute function must return a PreProcessorBlockResponse or PreProcessorProceedResponse object indicating whether to proceed or block.

1. Proceed

To allow the message to continue to the next preprocessor or the agent:
// Proceed with original message
return { action: 'proceed' };

// OR proceed with a modified message
return { 
  action: 'proceed',
  modifiedMessage: [{ type: 'text', text: 'Modified content' }]
};

2. Block

To stop processing immediately and respond to the user:
return {
  action: 'block',
  response: "This message was blocked."
};

Complete Examples

Profanity Filter

import { PreProcessor } from 'lua-cli';

const profanityWords = ['badword1', 'badword2', 'badword3'];

const profanityFilter = new PreProcessor({
  name: 'profanity-filter',
  description: 'Block messages containing inappropriate language',
  priority: 10, // Run early
  
  execute: async (user, messages, channel) => {
    // Check all text messages
    const hasProfanity = messages.some(msg => {
      if (msg.type === 'text') {
        return profanityWords.some(word => msg.text.toLowerCase().includes(word));
      }
      return false;
    });
    
    if (hasProfanity) {
      console.log(`Blocked profanity from user ${user.uid}`);
      return {
        action: 'block',
        response: "Please keep the conversation respectful. Inappropriate language is not allowed."
      };
    }
    
    return { action: 'proceed' };
  }
});

export default profanityFilter;

Business Hours Filter

import { PreProcessor } from 'lua-cli';

const businessHoursFilter = new PreProcessor({
  name: 'business-hours-filter',
  description: 'Block messages outside business hours',
  
  execute: async (user, messages, channel) => {
    const now = new Date();
    const hour = now.getHours();
    const day = now.getDay();
    
    // Business hours: Mon-Fri, 9 AM - 5 PM
    const isWeekday = day >= 1 && day <= 5;
    const isBusinessHours = hour >= 9 && hour < 17;
    
    if (!isWeekday || !isBusinessHours) {
      return {
        action: 'block',
        response: "Thank you for contacting us. Our business hours are Monday-Friday, 9 AM - 5 PM. We'll respond to your message during our next business day."
      };
    }
    
    return { action: 'proceed' };
  }
});

export default businessHoursFilter;

Message Enrichment

import { PreProcessor } from 'lua-cli';

const messageEnricher = new PreProcessor({
  name: 'message-enricher',
  description: 'Add context to messages before processing',
  priority: 50,
  
  execute: async (user, messages, channel) => {
    // Enrich message with user info
    const enrichedMessages = messages.map(msg => {
      if (msg.type === 'text') {
        return {
          ...msg,
          text: `${msg.text}\n\n[Context: User ID ${user.uid}]`
        };
      }
      return msg;
    });
    
    return {
      action: 'proceed',
      modifiedMessage: enrichedMessages
    };
  }
});

export default messageEnricher;

Execution Flow

Preprocessors are executed in a pipeline:
  1. Sequential Execution: Preprocessors run one after another, sorted by priority.
  2. Modifications: If a preprocessor modifies a message, the next preprocessor receives the modified version.
  3. Blocking: If any preprocessor returns action: 'block', execution stops immediately, and the response is sent to the user. The agent is not called.

Testing Preprocessors

lua test
# Select: PreProcessor → your-preprocessor-name
# Provide test message

See Also