> ## 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.

# LuaAgent

> Unified agent configuration combining skills, webhooks, jobs, and processors

## Overview

`LuaAgent` is the recommended way to configure your AI agent in modern lua-cli. It provides a single, intuitive configuration object that combines skills, webhooks, jobs, and message processors.

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

export const agent = new LuaAgent({
  name: 'my-agent',
  persona: 'You are a helpful assistant...',
  skills: [skill1, skill2]
});
```

<Note>
  LuaAgent replaces the need to export individual skills, webhooks, and jobs separately.
</Note>

## Why LuaAgent?

<CardGroup cols={2}>
  <Card title="Single Source of Truth" icon="bullseye">
    All agent components in one configuration object
  </Card>

  <Card title="Auto-Sync" icon="arrows-rotate">
    CLI auto-manages `lua.skill.yaml` (do not edit manually)
  </Card>

  <Card title="Better IDE Support" icon="code">
    Improved autocomplete and type safety
  </Card>

  <Card title="Clear Organization" icon="layer-group">
    Organized, readable agent configuration
  </Card>
</CardGroup>

## Constructor

### new LuaAgent(config)

Creates a new agent configuration.

<ParamField path="config" type="LuaAgentConfig" required>
  Agent configuration object
</ParamField>

## Configuration Parameters

### Required Fields

<ParamField path="name" type="string" required>
  Agent identifier used for organization and logging

  **Examples**: `'customer-support-agent'`, `'sales-assistant'`
</ParamField>

<ParamField path="persona" type="string | { base?: string; voice?: string; text?: string }" required>
  Defines the agent's personality, behavior, tone, and capabilities

  **String form (recommended):**

  * Who the agent is
  * What role they play
  * How they should communicate
  * What they can and cannot do
  * Any specific behaviors or rules

  **Object form (channel-aware):** Only use when you need measurably different behavior on voice vs text channels.

  * `base` — Always rendered, on every channel
  * `voice` — Appended to `base` on voice channels, ignored on text
  * `text` — Appended to `base` on text channels (web, WhatsApp, SMS), ignored on voice

  See [Channel-aware Prompts](/concepts/channel-aware-prompts) for details.
</ParamField>

### Optional Fields

<ParamField path="skills" type="LuaSkill[]">
  Array of skills (tool collections) the agent can use

  **Default**: `[]`
</ParamField>

<ParamField path="webhooks" type="LuaWebhook[]">
  HTTP endpoints that can receive external events

  **Default**: `[]`
</ParamField>

<ParamField path="jobs" type="LuaJob[]">
  Scheduled tasks that run automatically

  **Default**: `[]`
</ParamField>

<ParamField path="preProcessors" type="PreProcessor[]">
  Functions that process messages before they reach the agent

  **Default**: `[]`
</ParamField>

<ParamField path="postProcessors" type="PostProcessor[]">
  Functions that process agent responses before sending to users

  **Default**: `[]`
</ParamField>

<ParamField path="mcpServers" type="LuaMCPServer[]">
  MCP (Model Context Protocol) servers providing external tools

  **Default**: `[]`

  **See**: [LuaMCPServer API](/api/luamcpserver)
</ParamField>

<ParamField path="model" type="string | ((request: LuaRequest) => string | Promise<string>)">
  The LLM your agent uses. Either a static `'provider/model'` string or a resolver function
  that selects the model dynamically per request.

  **Format**: `'provider/model'` — e.g. `'google/gemini-2.5-flash'`, `'openai/gpt-4o'`

  **Default**: `'google/gemini-2.5-flash'`

  <Note>
    Lua manages the API credentials — you don't need to configure any API keys.
    Support for user-provided API keys is coming in a future release.
  </Note>

  **Static model:**

  ```typescript theme={null}
  model: 'openai/gpt-4o'
  ```

  **Dynamic resolver** — receives the full request with all platform APIs available (`User`, `Baskets`, `Products`, etc.):

  ```typescript theme={null}
  model: async (request) => {
    const user = await User.get();
    return user.data?.isPremium ? 'openai/gpt-4o' : 'google/gemini-2.5-flash';
  }
  ```

  **See**: [Model Selection](/overview/model-selection)
</ParamField>

<ParamField path="modelSettings" type="AgentModelSettings">
  Per-call sampling settings forwarded to the model on every chat turn.
  Set them once on the agent instead of overriding them in every skill via
  `AI.generate({ temperature })`. Undefined leaves provider defaults in
  place.

  ```typescript theme={null}
  import { LuaAgent, type AgentModelSettings } from 'lua-cli';

  export const agent = new LuaAgent({
    name: 'role-scorer',
    persona: '...',
    modelSettings: {
      temperature: 0.2,
      maxOutputTokens: 4096,
    },
    skills: [scoreRoleSkill],
  });
  ```

  **Supported fields:**

  | Field              | Type       | Range / Notes                                                    |
  | ------------------ | ---------- | ---------------------------------------------------------------- |
  | `temperature`      | `number`   | `0`–`2` (provider-dependent; typical for OpenAI / Anthropic)     |
  | `topP`             | `number`   | `0`–`1`. Set either `temperature` or `topP`, not both.           |
  | `topK`             | `number`   | Top-K sampling (advanced)                                        |
  | `maxOutputTokens`  | `number`   | Maximum tokens to generate                                       |
  | `presencePenalty`  | `number`   | `-2`–`2` (OpenAI; not all providers support)                     |
  | `frequencyPenalty` | `number`   | `-2`–`2` (OpenAI; not all providers support)                     |
  | `stopSequences`    | `string[]` | Generation halts when the model emits one                        |
  | `seed`             | `number`   | Random seed for deterministic sampling (provider support varies) |

  Obviously-broken values (non-finite numbers, `temperature` outside `0..2`,
  `topP` outside `0..1`, non-positive `maxOutputTokens`, non-string
  `stopSequences`) are rejected at construction time. Provider-specific
  range checks are deferred to the provider.
</ParamField>

## Basic Example

```typescript theme={null}
import { LuaAgent, LuaSkill } from 'lua-cli';
import GetWeatherTool from './tools/GetWeatherTool';

const weatherSkill = new LuaSkill({
  name: 'weather-skill',
  description: 'Weather information',
  context: 'Use these tools to get weather data',
  tools: [new GetWeatherTool()]
});

export const agent = new LuaAgent({
  name: 'weather-assistant',
  persona: 'You are a friendly weather assistant. Provide weather information when asked.',
  skills: [weatherSkill]
});
```

## Complete Example

```typescript theme={null}
import { 
  LuaAgent, 
  LuaSkill, 
  LuaWebhook, 
  LuaJob,
  LuaMCPServer,
  PreProcessor,
  PostProcessor
} from 'lua-cli';

// Import your components
import { customerSupportSkill } from './skills/customer-support';
import { productSkill } from './skills/products';
import { orderSkill } from './skills/orders';
import paymentWebhook from './webhooks/payment';
import orderWebhook from './webhooks/order';
import dailyReportJob from './jobs/daily-report';
import cleanupJob from './jobs/cleanup';
import profanityFilter from './preprocessors/profanity-filter';
import addDisclaimer from './postprocessors/disclaimer';
import filesystemServer from './mcp/filesystem';

export const agent = new LuaAgent({
  name: 'ecommerce-assistant',
  
  persona: `You are Emma, a helpful e-commerce assistant for Acme Store.
  
Your role:
- Help customers find products
- Assist with orders and cart management
- Answer product questions
- Process returns and exchanges

Communication style:
- Friendly and professional
- Patient and understanding
- Proactive with suggestions
- Clear and concise

Capabilities:
- Search product catalog
- Manage shopping carts
- Track orders
- Process payments
- Answer product questions

Limitations:
- Cannot ship orders manually
- Cannot modify pricing (suggest contacting manager)
- Cannot issue refunds over $100 (requires manager approval)
`,

  skills: [
    customerSupportSkill,
    productSkill,
    orderSkill
  ],

  webhooks: [
    paymentWebhook,
    orderWebhook
  ],

  jobs: [
    dailyReportJob,
    cleanupJob
  ],

  preProcessors: [
    profanityFilter
  ],

  postProcessors: [
    addDisclaimer
  ],

  mcpServers: [
    filesystemServer
  ]
});
```

## Persona Best Practices

### ✅ Good Persona

```typescript theme={null}
persona: `You are Dr. Smith, a medical information assistant.

Role: Provide general health information and wellness tips.

Guidelines:
- Always clarify you're not a licensed doctor
- Recommend seeing professionals for serious concerns
- Use clear, non-technical language
- Be empathetic and supportive

Tone: Professional, caring, informative`
```

### ❌ Bad Persona

```typescript theme={null}
// Too vague
persona: `You are helpful`

// Too robotic
persona: `I am an AI assistant that answers questions.`

// Missing boundaries
persona: `You can do anything the user asks.`
```

## Persona Storage

Persona is stored in your `LuaAgent` code definition (in `src/index.ts`). The `lua.skill.yaml` file is state-only and tracks IDs and versions, not persona content.

When you edit persona using `lua persona`, it updates the persona field in your `LuaAgent` code directly.

## Multiple Skills Example

```typescript theme={null}
import { LuaAgent, LuaSkill } from 'lua-cli';

// Organize tools by domain
const weatherSkill = new LuaSkill({
  name: 'weather-skill',
  description: 'Weather tools',
  context: 'Use for weather queries',
  tools: [getWeatherTool, getForecastTool]
});

const calculatorSkill = new LuaSkill({
  name: 'calculator-skill',
  description: 'Math tools',
  context: 'Use for calculations',
  tools: [addTool, multiplyTool, advancedMathTool]
});

const dataSkill = new LuaSkill({
  name: 'data-skill',
  description: 'Data management',
  context: 'Use for storing and retrieving user data',
  tools: [saveDataTool, queryDataTool]
});

export const agent = new LuaAgent({
  name: 'multi-purpose-assistant',
  persona: 'You are a versatile assistant that helps with weather, calculations, and data management.',
  skills: [weatherSkill, calculatorSkill, dataSkill]
});
```

## With All Components

```typescript theme={null}
import { LuaAgent } from 'lua-cli';
import { skills } from './skills';
import { webhooks } from './webhooks';
import { jobs } from './jobs';
import { preProcessors } from './preprocessors';
import { postProcessors } from './postprocessors';
import { mcpServers } from './mcp';

export const agent = new LuaAgent({
  name: 'enterprise-assistant',
  
  persona: `You are an enterprise-grade AI assistant.
  - Professional and efficient
  - Data-driven and accurate
  - Proactive with insights
  - Security and privacy conscious`,
  
  skills: skills,
  webhooks: webhooks,
  jobs: jobs,
  preProcessors: preProcessors,
  postProcessors: postProcessors,
  mcpServers: mcpServers
});
```

## Dynamic Configuration

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

// Load configuration from environment
const agentName = env('AGENT_NAME') || 'default-agent';
const customPersona = env('AGENT_PERSONA') || 'You are a helpful assistant';

// Conditionally add components
const skills = [coreSkill];
if (env('ENABLE_ANALYTICS') === 'true') {
  skills.push(analyticsSkill);
}

export const agent = new LuaAgent({
  name: agentName,
  persona: customPersona,
  skills: skills,
  // Add webhooks only in production
  webhooks: env('NODE_ENV') === 'production' ? productionWebhooks : []
});
```

## Migration from v2.x

**Before (v2.x):**

```typescript theme={null}
// Multiple exports
export const skill1 = new LuaSkill({...});
export const skill2 = new LuaSkill({...});
export const webhook1 = new LuaWebhook({...});
```

**After:**

```typescript theme={null}
// Single export with LuaAgent
export const agent = new LuaAgent({
  name: 'my-agent',
  persona: '...',
  skills: [skill1, skill2],
  webhooks: [webhook1]
});
```

## Related APIs

<CardGroup cols={2}>
  <Card title="LuaSkill" href="/api/luaskill" icon="puzzle-piece">
    Tool collections
  </Card>

  <Card title="LuaTool" href="/api/luatool" icon="wrench">
    Individual tools
  </Card>

  <Card title="LuaWebhook" href="/api/luawebhook" icon="webhook">
    HTTP endpoints
  </Card>

  <Card title="LuaJob" href="/api/luajob" icon="clock">
    Scheduled tasks
  </Card>

  <Card title="LuaMCPServer" href="/api/luamcpserver" icon="plug">
    External MCP tools
  </Card>
</CardGroup>

## See Also

* [Quick Start Guide](/getting-started/quick-start)
* [First Skill Tutorial](/getting-started/first-skill)
* [Skills and Tools Concept](/concepts/skills-and-tools)
