# Workflow & Automation Engine

Workflows automate actions that happen **outside of the real-time conversation** — follow-ups,
notifications, scheduled reminders, and custom actions triggered by time or contact state.

---

## Workflow Types

### 1. FOLLOW_UP
Sends an automated message to a contact after a period of inactivity or after a specific
property is set.

- **When to use:** "Contact hasn't replied in 24 hours → send a check-in message."
- **How it works:** Agent generates the message using the workflow's prompt + conversation context.
- **Key settings:**
  - `intervalMinutes` — how often to check/run (e.g., every 60 minutes)
  - `minMinutesSinceLastInbound` — wait N minutes after the contact's last message before triggering
  - `executionWindowStart/End` — only run between HH:MM and HH:MM (e.g., 09:00–21:00)
  - `onlyRunOnce` — if true, fires once per conversation and stops

### 2. CUSTOM_NOTIFICATION
Sends an alert to an external channel (not to the contact).

- **When to use:** "When a lead books a call → notify the team on Slack/WhatsApp/Email."
- **Destination channels:**
  - EMAIL
  - SMS
  - WHATSAPP (direct message)
  - WHATSAPP_TEMPLATE (pre-approved Meta template)
  - TELEGRAM
  - SLACK
  - SNS (AWS Simple Notification Service)
- **Notification levels:** INFO, WARNING, ERROR, SUCCESS, MESSAGE

### 3. CUSTOM_ACTION
Executes a custom logic block — used for integrations, CRM updates, or webhook calls.

- **When to use:** Trigger an N8n flow, call an external API, sync data to a CRM.

### 4. SCHEDULE_REMINDER
Sends a reminder relative to a scheduled appointment.

- **When to use:** "Send reminder 24 hours before a booked call."
- **Key setting:** `minutesBeforeScheduleTime` — how early to fire the reminder.

---

## Execution Rules

Workflows have a rich set of conditions that control **when** they run:

| Setting | Description |
|---------|-------------|
| `enabled` | Master on/off toggle (safe to UPDATE) |
| `intervalMinutes` | How often the engine checks this workflow |
| `minMinutesSinceLastInbound` | Minimum idle time after last contact message |
| `executionWindowStart/End` | Time-of-day window (HH:MM format) |
| `onlyRunOnce` | Prevent re-triggering after first run |
| `delayTriggerPropertyId` | Trigger delay based on when a custom property was set |
| `delayMinutesAfterPropertySet` | Minutes to wait after the property is set |
| `minutesBeforeScheduleTime` | For SCHEDULE_REMINDER: minutes before the appointment |
| `channels` | Only run for specific platforms (WhatsApp, Instagram, Facebook, etc.) |

---

## Property Conditions

Workflows can be gated by **custom property conditions** — the workflow only runs if the
contact's properties match all conditions.

| Operator | Description |
|----------|-------------|
| EQUALS | Property value equals X |
| NOT_EQUALS | Property value is not X |
| CONTAINS | String property contains X |
| NOT_CONTAINS | String property does not contain X |
| GREATER_THAN | Numeric property > X |
| LESS_THAN | Numeric property < X |
| IS_EMPTY | Property has no value |
| IS_NOT_EMPTY | Property has a value |
| IS_NOT_DEFINED | Property doesn't exist for this contact |

**Example:** Only run the follow-up if `call_booked = false` AND `lead_score > 5`.

---

## Workflow Runs

Every time a workflow fires, a `workflow_runs` row is created:

| Status | Meaning |
|--------|---------|
| PENDING | Queued, waiting to execute |
| IN_PROGRESS | Currently running |
| COMPLETED | Finished successfully |
| FAILED | Error during execution (see error log) |

To debug a failed workflow:
```sql
SELECT id, status, error, created_at
FROM workflow_runs
WHERE workflow_id = '<workflow-id>'
ORDER BY created_at DESC
LIMIT 20
```

---

## N8n Integration

Workflows can trigger external N8n automations via webhook:

| Trigger event | When it fires |
|--------------|--------------|
| MESSAGE_RECEIVED | On every inbound message |
| MESSAGE_SENT | On every outbound message |
| CONVERSATION_CREATED | When a new conversation starts |
| AGENT_RESPONSE | When the agent sends a response |

**Filtering options:**
- Agent-specific (only fire for selected agents)
- Channel-specific (only fire for WhatsApp, Instagram, etc.)

**Payload includes:**
- Conversation and message data
- Contact properties (optional)
- Conversation history (optional, configurable)

**Reliability:**
- Retry logic with configurable max attempts and timeout
- Stats: `lastTriggeredAt`, `totalTriggers`, `totalFailures`

---

## Managing Workflows Safely

**Toggle a workflow off:**
```sql
UPDATE workflows
SET enabled = false, updated_at = NOW()
WHERE id = '<workflow-id>'
RETURNING id, name, enabled
```

**List all workflows with status:**
```sql
SELECT id, name, type, enabled, interval_minutes, execution_window_start, execution_window_end
FROM workflows
ORDER BY type, name
```

**Never DELETE workflow rows.** Use `enabled = false` to deactivate.

---

## Common Patterns

### 24-hour follow-up
```
Type: FOLLOW_UP
intervalMinutes: 60
minMinutesSinceLastInbound: 1440  (24 hours)
executionWindow: 09:00–21:00
onlyRunOnce: false
Condition: call_booked = false
Prompt: "Generate a warm follow-up message to reignite the conversation"
```

### Booking confirmation notification
```
Type: CUSTOM_NOTIFICATION
Channel: SLACK
Condition: call_booked = true
Prompt: "Notify the team that {contact_name} booked a call on {schedule_date}"
```

### Pre-call reminder
```
Type: SCHEDULE_REMINDER
minutesBeforeScheduleTime: 1440  (24 hours before)
Channel: WHATSAPP
Prompt: "Send a reminder about tomorrow's call and ask for confirmation"
```
