# Triggers

Triggers are the entry points into your agent's flows, handling incoming events and initializing conversations with context and memory.

## Trigger Types

MindedJS supports two types of triggers:

### 1. Webhook Triggers

Triggered by HTTP requests to specific endpoints in the Minded platform. Configured through the Minded platform interface. Each webhook trigger belongs to a specific agent and cannot be shared between agents.

> **Note**: All triggers are agent-specific and configured through the Minded platform.

#### Webhook Structure

For webhook triggers, `triggerBody` contains:

* **`body`**: The HTTP request body payload
* **`headers`**: The HTTP request headers

```typescript
// Webhook triggerBody structure
{
  body: any;        // Request payload
  headers: {        // Request headers
    'content-type': string;
    'x-forwarded-for': string;
    'user-agent': string;
    // ... other headers
  }
}
```

**Accessing headers:**

```typescript
agent.on(AgentEvents.TRIGGER_EVENT, async ({ triggerBody }) => {
  const senderIP = triggerBody.headers?.['x-forwarded-for'];
  const contentType = triggerBody.headers?.['content-type'];
  return { isQualified: true };
});
```

**Common headers:** `x-forwarded-for`, `content-type`, `user-agent`, and custom headers.

#### Validate Webhook Input

```typescript
// ✅ Good - Input validation
agent.on(AgentEvents.TRIGGER_EVENT, async ({ triggerBody, state }) => {
  if (triggerBody.headers?.authorization !== 'expected-token') {
    return { isQualified: false };
  }
  if (!triggerBody.body?.customerId || !triggerBody.body?.message) {
    return { isQualified: false };
  }
  return { isQualified: true };
});
```

#### Output Schema

Define an `outputSchema` on webhook triggers to automatically extract structured fields from the payload using LLM. Extracted fields are available via `{trigger.fieldName}` placeholders in prompts and parameters.

```yaml
# In your flow YAML
trigger:
  type: trigger
  triggerType: webhook
  outputSchema:
    - name: orderId
      type: string
      description: The order identifier
    - name: customerEmail
      type: string
      description: Customer email address
```

**Usage in prompts:**

```
Process order {trigger.orderId} for customer {trigger.customerEmail}
```

### 2. Schedule Triggers

Triggered automatically based on a cron schedule. Configured with a cron expression and optional timezone (defaults to UTC).

#### Cron Expression Format

**Examples:**

* `'0 0 * * *'` - Daily at midnight
* `'0 9 * * 1'` - Every Monday at 9:00 AM
* `'*/15 * * * *'` - Every 15 minutes
* `'0 12 * * 1-5'` - Every weekday at noon

#### Timezone Configuration

Use IANA timezone identifiers:

```typescript
{
  triggerType: TriggerType.SCHEDULE,
  cronExpression: '0 9 * * 1-5', // Weekdays at 9 AM
  timezone: 'America/New_York' // Optional, defaults to UTC
}
```

**Behavior:**

* Automatically deployed when agent is deployed
* Enabled when agent is "live", disabled otherwise
* Creates new session unless `sessionId` is provided

## Trigger Event

The `TRIGGER_EVENT` is emitted when any trigger is invoked, allowing you to qualify triggers and modify state before processing.

### TriggerEvent Interface

```typescript
export interface TriggerEvent {
  triggerBody: any;
  triggerName: string;
}
```

### Event Lifecycle

The handler serves two purposes:

1. **Qualifying Triggers**: Return `{ isQualified: boolean }` to determine if processing should continue
2. **Adding Information to State**: Modify `state` directly by reference

**Handler must return:**

```typescript
return { isQualified: true }; // Continue processing
return { isQualified: false }; // Stop processing
```

**Modifying state:**

```typescript
agent.on(AgentEvents.TRIGGER_EVENT, async ({ triggerBody, state }) => {
  state.memory.customerId = triggerBody.body?.customerId;
  state.messages.push(new SystemMessage('Processing request'));
  return { isQualified: true };
});
```

### Development Environment: Dashboard Messages

In development, agents are invoked with `triggerName = 'dashboard_message'` for dashboard messages. Handle this case to prevent default webhook behavior. Otherwise, avoid using this parameter.

```typescript
agent.on(AgentEvents.TRIGGER_EVENT, async ({ triggerName, triggerBody, state }) => {
  if (triggerName === 'dashboard_message') {
    return { isQualified: true };
  }

  // Handle webhook triggers
  if (triggerBody.body && triggerBody.headers) {
    if (!triggerBody.body.customerId) {
      return { isQualified: false };
    }
    state.memory.webhookData = triggerBody.body;
    return { isQualified: true };
  }

  return { isQualified: false };
});
```

## Extracting Session ID from Webhooks

Extract a unique `sessionId` from webhook payloads to maintain conversation continuity.

### Using parseSessionIdFromTrigger

Configure the Agent to automatically extract `sessionId`:

```typescript
const agent = new Agent({
  memorySchema,
  config,
  tools,
  parseSessionIdFromTrigger: (triggerBody) => triggerBody?.body?.data?.item?.id,
});
```

**How it works:**

* Receives `triggerBody` as parameter
* Returns a string session identifier
* If `undefined`/`null`, platform generates a new `sessionId`
* Used to resume existing agent sessions or create new ones

**Examples:**

```typescript
// Extract from nested structure
parseSessionIdFromTrigger: (triggerBody) => {
  return triggerBody?.body?.data?.item?.id;
};
```

**Fallback:** If not provided or returns `undefined`/`null`, checks `triggerBody.sessionId`, then generates a new UUID.

### Session ID in Trigger Events

* **Sandbox Playground**: Platform auto-generates `sessionId` for each execution
* **Production**: Users provide their own `sessionId` to support resuming sessions
* **Session Continuity**: Matching `sessionId` resumes previous state instead of starting fresh
* **Schedule Triggers**: Creates new session unless `sessionId` is explicitly provided
