> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# PreProcessors

> Filter and validate messages before they reach your agent

## What are PreProcessors?

**PreProcessors** intercept user messages before they reach your AI agent. They act as a middleware layer, allowing you to filter spam, validate inputs, route messages, or modify content before the agent processes it.

<Card title="Think of it as:" icon="filter">
  A security checkpoint and enrichment station - messages pass through preprocessors before reaching your agent's brain.
</Card>

<Note>
  Message preprocessing for content filtering, routing, and validation.
</Note>

## Why PreProcessors?

PreProcessors handle "meta" tasks that shouldn't consume your agent's context window or reasoning capabilities.

<CardGroup cols={2}>
  <Card title="Content Filtering" icon="shield">
    Block spam, profanity, or inappropriate content before it costs you tokens.
  </Card>

  <Card title="Input Validation" icon="check-circle">
    Ensure messages meet requirements (e.g., "must include an email") before the agent sees them.
  </Card>

  <Card title="Context Injection" icon="syringe">
    Fetch data from a CRM or database and append it to the user's message.
  </Card>

  <Card title="Rate Limiting" icon="gauge">
    Prevent abuse by limiting message frequency per user.
  </Card>
</CardGroup>

## PreProcessors vs Skills

| Feature      | PreProcessor                           | Skill                                      |
| :----------- | :------------------------------------- | :----------------------------------------- |
| **Timing**   | Runs **before** the agent thinks       | Runs **when** the agent decides to call it |
| **Decision** | Deterministic (code-based)             | Probabilistic (LLM-based)                  |
| **Use Case** | Security, formatting, required context | Actions, data retrieval, business logic    |
| **Access**   | Can block the agent completely         | Cannot block, returns data to agent        |

## How PreProcessors Work

<Steps>
  <Step title="User Sends Message">
    User types a message (e.g., "Check my order status") via WhatsApp, Web, or API.
  </Step>

  <Step title="Pipeline Execution">
    The system runs your active PreProcessors in order of **priority** (lowest first).
  </Step>

  <Step title="Transformation & Decision">
    Each preprocessor receives the output of the previous one. It can:

    * ✅ **Proceed**: Pass the (potentially modified) message to the next step.
    * ❌ **Block**: Stop the pipeline and return a response immediately.
  </Step>

  <Step title="Agent Handover">
    If no preprocessor blocks, the final message reaches the AI agent.
  </Step>
</Steps>

## Simple Example

Here is a simple profanity filter that runs early in the pipeline.

```typescript theme={null}
import { PreProcessor } from 'lua-cli';

const profanityFilter = new PreProcessor({
  name: 'profanity-filter',
  description: 'Block inappropriate content',
  priority: 10, // Run early (low number)
  
  execute: async (user, messages, channel) => {
    const text = messages
      .filter(m => m.type === 'text')
      .map(m => m.text.toLowerCase())
      .join(' ');
    
    if (text.includes('badword')) {
      // Block the message
      return {
        action: 'block',
        response: "Please keep the conversation respectful."
      };
    }
    
    // Allow message through
    return { action: 'proceed' };
  }
});
```

<Note>
  **Tip:** You can also access the channel via `Lua.request.channel`, the user via `User.get()`, and raw webhook data via `Lua.request.webhook?.payload`. See the [Lua API](/api/lua) for details.
</Note>

## Advanced Patterns

### Context Injection (RAG Lite)

You can use a preprocessor to fetch user data and "inject" it into the message, giving the agent context without it needing to ask tools.

```typescript theme={null}
execute: async (user, messages, channel) => {
  // Fetch recent order from your DB
  const recentOrder = await fetchRecentOrder(user.email);
  
  if (recentOrder) {
    // Append order info to the message
    const enrichedMessages = messages.map(msg => {
      if (msg.type === 'text') {
        return {
          ...msg,
          text: `${msg.text}\n\n[System Context: Last Order #${recentOrder.id} is ${recentOrder.status}]`
        };
      }
      return msg;
    });
    
    return { 
      action: 'proceed', 
      modifiedMessage: enrichedMessages 
    };
  }
  
  return { action: 'proceed' };
}
```

### Channel-Specific Logic

You can apply different rules based on where the user is chatting from.

```typescript theme={null}
execute: async (user, messages, channel) => {
  if (channel === 'whatsapp' && messages.some(m => m.type === 'file')) {
    return {
      action: 'block',
      response: "Sorry, we don't accept file uploads on WhatsApp yet."
    };
  }
  return { action: 'proceed' };
}
```

## Execution Pipeline

PreProcessors run in a **pipeline**. The output of one preprocessor becomes the input of the next.

1. **Priority 10**: `RateLimiter` checks if user is spamming.
2. **Priority 20**: `ProfanityFilter` checks for bad words.
3. **Priority 50**: `ContextInjector` adds user account info.
4. **Agent**: Receives a clean, verified, and context-rich message.

## Adding to Your Agent

Add preprocessors to your `LuaAgent` configuration.

```typescript theme={null}
import { LuaAgent } from 'lua-cli';
import profanityFilter from './preprocessors/profanity-filter';
import rateLimiter from './preprocessors/rate-limiter';

export const agent = new LuaAgent({
  name: "my-agent",
  persona: "...",
  skills: [...],
  
  // Add preprocessors here
  preProcessors: [
    rateLimiter,      // Will run first (assuming priority 5)
    profanityFilter   // Will run second (assuming priority 10)
  ]
});
```

## Testing PreProcessors

You can test preprocessors in isolation using the Lua CLI.

```bash theme={null}
lua test
# Select: PreProcessor → profanity-filter
# Provide test message
# See if it's blocked or allowed
```

## Next Steps

<CardGroup cols={2}>
  <Card title="PreProcessor API" icon="book" href="/api/preprocessor">
    Complete API documentation
  </Card>

  <Card title="PostProcessor Concept" icon="paper-plane" href="/overview/postprocessors">
    Learn about response formatting
  </Card>

  <Card title="Agent Concept" icon="robot" href="/overview/agent">
    Learn about LuaAgent
  </Card>

  <Card title="Workflows Guide" icon="diagram-project" href="/concepts/workflows">
    Development best practices
  </Card>
</CardGroup>
