# Triggers Skill - The Fates (Moirai)

Event-driven automation for Familiar.
React to webhooks, schedules, and events automatically.

## The Three Fates

In Greek mythology, the Moirai controlled destiny:
- **Clotho** (spinner) - Creates triggers, spins the thread of events
- **Lachesis** (allotter) - Matches events to actions
- **Atropos** (unturnable) - Executes actions

## Features

- **Webhooks** - Receive HTTP callbacks from external services
- **Schedules** - Run actions at intervals (hourly, daily, etc.)
- **Polling** - Periodically check sources for changes
- **Event bus** - React to internal events
- **Conditions** - Filter events with rules
- **Action chains** - Multi-step workflows
- **Rate limiting** - Prevent runaway triggers
- **Audit logging** - Track all executions

## Use Cases

```
New email → triage → notify if urgent
GitHub push → summarize changes → post to Discord
Calendar event starting → send reminder
Stripe payment → log donor → send thank you
RSS new item → summarize → add to knowledge base
Daily 8am → morning briefing → send to Telegram
```

## Quick Start

### Create a Webhook
```
"Create a webhook called 'github' at /hooks/github"
```

### Create a Scheduled Task
```
"Create a trigger that runs my morning briefing every day at 8am"
```

### Create an Event Handler
```
"When I get an urgent email, send me a Telegram notification"
```

## Trigger Types

### Webhook
Receives HTTP POST/GET from external services.

```json
{
  "type": "webhook",
  "config": {
    "path": "/hooks/github",
    "secret": "your-webhook-secret",
    "methods": ["POST"]
  }
}
```

Supports GitHub-style signature verification (X-Hub-Signature-256).

### Schedule
Runs at regular intervals.

```json
{
  "type": "schedule",
  "config": {
    "interval": "1h"
  }
}
```

Intervals: `30m`, `1h`, `6h`, `1d`

### Poll
Periodically calls a tool and triggers on results.

```json
{
  "type": "poll",
  "config": {
    "interval_seconds": 300,
    "source": "inbox_summary",
    "input": {}
  }
}
```

### Event
Reacts to internal events from other skills.

```json
{
  "type": "event",
  "config": {
    "event_type": "email.received"
  }
}
```

## Conditions

Filter events before triggering:

```json
{
  "conditions": [
    {"field": "subject", "operator": "contains", "value": "urgent"},
    {"field": "from", "operator": "not_contains", "value": "noreply"}
  ]
}
```

### Operators
| Operator | Description |
|----------|-------------|
| eq | Equals |
| ne | Not equals |
| gt | Greater than |
| lt | Less than |
| gte | Greater or equal |
| lte | Less or equal |
| contains | String contains (case insensitive) |
| not_contains | String doesn't contain |
| matches | Regex match |
| exists | Field exists |
| in | Value in list |

## Actions

### Chat
Send prompt to LLM:
```json
{
  "type": "chat",
  "config": {
    "prompt": "Summarize this: {{event.body}}"
  }
}
```

### Tool
Call a specific tool:
```json
{
  "type": "tool",
  "config": {
    "name": "add_task",
    "input": {
      "title": "{{event.subject}}",
      "priority": "high"
    }
  }
}
```

### Notify
Send notification:
```json
{
  "type": "notify",
  "config": {
    "channel": "telegram",
    "chat_id": "123456",
    "message": "New event: {{event.title}}"
  }
}
```

### Webhook
Call external service:
```json
{
  "type": "webhook",
  "config": {
    "url": "https://api.example.com/notify",
    "method": "POST",
    "headers": {"Authorization": "Bearer {{env.API_KEY}}"},
    "body": {"text": "{{event.summary}}"}
  }
}
```

### Chain
Trigger another trigger:
```json
{
  "type": "chain",
  "config": {
    "trigger_id": "abc123"
  }
}
```

### Script
Run shell command:
```json
{
  "type": "script",
  "config": {
    "command": "echo '{{event.data}}' >> /tmp/log.txt",
    "timeout": 30
  }
}
```

## Template Variables

Use `{{...}}` in action configs:

| Variable | Description |
|----------|-------------|
| `{{event.field}}` | Event data field |
| `{{result.field}}` | Previous action result |
| `{{env.VAR}}` | Environment variable |
| `{{now}}` | Current ISO timestamp |
| `{{trigger.id}}` | Trigger ID |
| `{{trigger.name}}` | Trigger name |

Nested fields: `{{event.user.email}}`

## Rate Limiting

Prevent runaway triggers:

```json
{
  "rate_limit": {
    "max": 10,
    "period_seconds": 3600
  }
}
```

This allows max 10 fires per hour.

## Example Workflows

### GitHub → Discord
```
Create trigger:
  name: "GitHub Notifications"
  type: webhook
  config:
    path: /hooks/github
    secret: your-secret
  conditions:
    - field: action
      operator: eq  
      value: opened
  actions:
    - type: chat
      config:
        prompt: "Summarize this PR: {{event.pull_request.title}}"
    - type: webhook
      config:
        url: https://discord.com/api/webhooks/...
        body:
          content: "New PR: {{result.response}}"
```

### Daily Briefing
```
Create scheduled trigger:
  name: "Morning Briefing"
  interval: 1d
  action: chat
  action_config:
    prompt: "Give me my morning briefing"
```

### Urgent Email Alert
```
Create trigger:
  name: "Urgent Email Alert"
  type: event
  config:
    event_type: email.received
  conditions:
    - field: priority
      operator: eq
      value: urgent
  actions:
    - type: notify
      config:
        channel: telegram
        message: "🚨 Urgent email from {{event.from}}: {{event.subject}}"
```

## Webhook Server

The trigger engine includes an HTTP server for receiving webhooks.

Default port: 8765

```bash
# Start with custom port
"Start triggers with webhook port 9000"
```

### Webhook URLs
```
http://your-host:8765/hooks/github
http://your-host:8765/hooks/stripe
http://your-host:8765/hooks/custom
```

### Security
- Use secrets for signature verification
- GitHub: X-Hub-Signature-256 header
- Run behind reverse proxy (nginx) with HTTPS

## Tools

| Tool | Description |
|------|-------------|
| create_trigger | Create full trigger |
| create_webhook | Create webhook (simplified) |
| create_scheduled_trigger | Create scheduled trigger |
| list_triggers | List all triggers |
| get_trigger | Get trigger details |
| enable_trigger | Enable a trigger |
| disable_trigger | Disable a trigger |
| delete_trigger | Delete a trigger |
| fire_test_event | Test trigger matching |
| execution_log | View recent executions |
| start_triggers | Start engine + webhook server |
| stop_triggers | Stop engine |

## File Locations

- Triggers: `~/.familiar/data/triggers/triggers.json`
- Webhooks: `~/.familiar/data/triggers/webhooks.json`
- Execution log: `~/.familiar/data/triggers/executions.log`

## Integration with Other Skills

Fire events from any skill:

```python
from skills.triggers.skill import _trigger_engine

# Fire event
if _trigger_engine:
    _trigger_engine.fire_event(
        "email.received",
        {"from": "...", "subject": "...", "priority": "urgent"},
        source="cerberus"
    )
```

## Raspberry Pi Notes

- Webhook server is lightweight
- Use rate limiting to prevent overload
- Consider running behind nginx for HTTPS
- Port forward 8765 on your router for external webhooks
