Skip to content

Automation Engine

The Automation Engine enables podcast hosts to create automated workflows triggered by events (booking confirmed, episode published) or time-based schedules (24 hours before recording). It features a visual step-based workflow builder (click a step type to add it; the layout is derived, not dragged), a magic tag system for dynamic content, and reliable execution via Cloudflare Workers and Queues.

DocumentDescription
ArchitectureSystem design, data flow, and component interactions
Queue ProducersEvent emission and time-based scheduling (app-side)
Database SchemaTables, enums, RLS policies, and relationships
API ReferenceAll automation API endpoints
Magic TagsDynamic content replacement system
Workflow BuilderVisual UI components and state management
Scheduler WorkerCron-based job scheduler
Executor WorkerQueue-based action executor

Architecture Overview

Key Concepts

Automation Rules

An automation rule defines what triggers the automation and what actions to perform. Each rule belongs to a podcast and contains:

  • Trigger Type: The event or time-based condition (e.g., booking.confirmed, time.before_recording)
  • Trigger Config: Additional configuration (e.g., delay amount for time-based triggers)
  • Workflow Data: JSON structure of nodes and connections from the visual builder
  • Actions: One or more actions to execute (email, webhook, field update)

Execution Flow

  1. Event Emission: When a triggering event occurs (booking confirmed, episode published), the system calls emitAutomationEvent()
  2. Rule Matching: The scheduler finds all enabled rules matching the trigger type for that podcast
  3. Job Creation: For time-based triggers, jobs are scheduled; for event triggers, executions are created immediately
  4. Queue Processing: The executor worker processes executions from the queue
  5. Action Execution: Each action (email, webhook, field update) is executed with magic tag replacement
  6. Result Recording: Success/failure status and results are recorded in automation_executions

Magic Tags

Magic tags like {guest_first_name} and {recording_date} are placeholders replaced with actual values at execution time. See Magic Tags for the complete reference.

File Structure

src/
├── api/routes/automations/
│   ├── index.ts              # Route aggregator
│   ├── templates.ts          # Template CRUD endpoints
│   ├── rules.ts              # Rule CRUD + toggle + manual trigger
│   ├── executions.ts         # Execution history + retry + stats
│   └── scheduled-jobs.ts     # Scheduled job management
├── lib/
│   ├── automation/
│   │   ├── index.ts          # Module exports (magic tags, scheduler)
│   │   ├── magic-tags.ts     # Tag definitions and categories (29 tags)
│   │   ├── tag-parser.ts     # Tag extraction and replacement
│   │   ├── events.ts         # Event emission producers (import directly)
│   │   ├── scheduler.ts      # Time-based job scheduling producers
│   │   └── __tests__/        # Unit tests (123 tests)
│   ├── stores/automation/
│   │   ├── index.ts          # Store exports
│   │   ├── workflow.svelte.ts    # Workflow state (nodes, connections)
│   │   ├── canvas.svelte.ts      # Canvas state (pan, zoom)
│   │   └── history.svelte.ts     # Undo/redo state
│   ├── components/automation/
│   │   ├── automation-list-item.svelte  # List view row component
│   │   ├── view-switcher.svelte         # Grid/list toggle
│   │   ├── TemplateEditorModal.svelte
│   │   ├── TestAutomationDialog.svelte  # Manual trigger testing UI
│   │   ├── MagicTagInserter.svelte
│   │   └── workflow/
│   │       ├── WorkflowBuilder.svelte
│   │       ├── WorkflowCanvas.svelte
│   │       ├── WorkflowTopBar.svelte    # Name/save controls
│   │       ├── NodePalette.svelte
│   │       ├── NodeConfigPanel.svelte
│   │       ├── NodeConnection.svelte
│   │       ├── nodes/
│   │       │   └── WorkflowNode.svelte
│   │       └── config/
│   │           ├── TriggerConfig.svelte
│   │           ├── ActionEmailConfig.svelte
│   │           ├── ActionWebhookConfig.svelte
│   │           ├── ActionFieldUpdateConfig.svelte
│   │           ├── ConditionConfig.svelte
│   │           └── DelayConfig.svelte
│   └── types/
│       └── automation.types.ts   # All TypeScript types
├── routes/(app)/p/[slug]/
│   ├── automations/
│   │   ├── +page.svelte          # Automations list
│   │   ├── +page.server.ts       # Server-side data loading
│   │   ├── new/+page.svelte      # Create automation
│   │   ├── [id]/+page.svelte     # Edit automation
│   │   └── history/
│   │       ├── +page.svelte      # Execution history view
│   │       └── +page.server.ts   # History data loading
│   └── templates/
│       └── +page.svelte          # Template management

workers/
├── automation-scheduler/
│   ├── wrangler.toml
│   └── src/index.ts              # Cron + HTTP handlers
└── automation-executor/
    ├── wrangler.toml
    └── src/
        ├── index.ts              # Queue + HTTP handlers
        ├── types/
        │   └── env.ts            # Environment bindings
        └── executors/
            ├── email.ts
            ├── webhook.ts
            └── field-update.ts

supabase/migrations/
└── 20260107164436_automation_engine.sql

Environment Variables

Main Application

Required in wrangler.toml or environment:

VariableDescription
SUPABASE_URLSupabase project URL
SUPABASE_SERVICE_ROLE_KEYService role key for admin access

Workers

Both workers require:

VariableDescription
HYPERDRIVEHyperdrive binding for database connection
SUPABASE_URLSupabase project URL
SUPABASE_SERVICE_ROLE_KEYService role key
RESEND_API_KEYResend API key (executor only)
AUTOMATION_QUEUEQueue binding (scheduler → executor)

Testing

Run automation tests:

bash
pnpm test src/lib/automation --run

Current coverage: 123 tests across 4 test files:

  • src/lib/automation/__tests__/magic-tags.test.ts - Tag definitions and utilities
  • src/lib/automation/__tests__/tag-parser.test.ts - Tag extraction, validation, replacement
  • src/lib/automation/__tests__/scheduler.test.ts - Time-based job scheduling (32 tests)
  • src/lib/automation/__tests__/events.test.ts - Event emission and rule matching

Common Tasks

Adding a New Trigger Type

  1. Add to AutomationTriggerType enum in automation.types.ts
  2. Add label in TRIGGER_TYPE_LABELS constant
  3. Add to TriggerConfig.svelte options
  4. Add event emission in the appropriate route/worker

There is deliberately no per-trigger tag-scoping function. getMagicTagsForTrigger() used to fill that role but had no production caller, and its hardcoded claim that every booking.* trigger carries episode context stopped being true when general booking links shipped (#295 item 1). Tags that cannot resolve for a given trigger render empty via the zero-fill contract instead.

Adding a New Action Type

  1. Add to AutomationActionType enum in automation.types.ts
  2. Add label in ACTION_TYPE_LABELS constant
  3. Create config component in workflow/config/
  4. Add to NodeConfigPanel.svelte routing
  5. Add to NodePalette.svelte node types
  6. Create executor in workers/automation-executor/src/executors/
  7. Add to executor worker action routing

Adding a New Magic Tag

  1. Add definition to MAGIC_TAGS array in magic-tags.ts
  2. Add to appropriate category
  3. Add context population in tag-parser.tsbuildMagicTagContext()
  4. Add to events.tsbuildFullContext() if from new data source
  5. Add test case in magic-tags.test.ts

Version History

DateChangeAuthor
2026-01-07Initial automation engine implementationDevelopment Team
2026-01-13Documentation audit - file structure updated, new components documentedDevelopment Team
2026-01-16Documentation update - corrected test count (123 tests), updated tag count (29 tags)Claude Code

Internal documentation - Not for public distribution