home / skills / openclaw / skills / campaign-orchestrator

campaign-orchestrator skill

/skills/kesslerio/campaign-orchestrator

This skill orchestrates multi-channel follow-up campaigns (SMS and Email) with CRM logging and auto-termination on replies to accelerate demos.

npx playbooks add skill openclaw/skills --skill campaign-orchestrator

Review the files below or copy the command above to add this skill to your agents.

Files (8)
SKILL.md
7.3 KB
---
name: campaign-orchestrator
description: Multi-channel follow-up campaign orchestrator for ShapeScale sales. Schedules and executes SMS + Email sequences with CRM logging and auto-termination on replies. Use when following up with demo leads or managing outreach campaigns.
homepage: https://github.com/kesslerio/shapescale-moltbot-skills
metadata: {"moltbot":{"emoji":"šŸ“‹","requires":{"env":["DIALPAD_API_KEY","ATTIO_API_KEY","GOG_KEYRING_PASSWORD"]},"primaryEnv":"DIALPAD_API_KEY"}}
---

# Campaign Orchestrator Skill

Multi-channel follow-up campaign orchestrator for ShapeScale sales. Executes scheduled SMS + Email sequences with CRM integration and auto-termination on replies.

## Overview

A **Campaign** is a defined sequence of steps (SMS/Email) that executes over time. When a lead replies to any message, the campaign automatically terminates.

### Key Features

- **Multi-channel**: SMS (Dialpad) + Email (Gmail)
- **Scheduled**: Cron-based execution with configurable delays
- **Personalized**: Templates filled from Attio CRM data
- **Auto-terminating**: Replies stop all future scheduled steps
- **Logged**: All activities recorded in Attio

## Setup

**Environment variables required:**
```bash
DIALPAD_API_KEY=your_dialpad_api_key
ATTIO_API_KEY=your_attio_api_key
GOG_KEYRING_PASSWORD=your_google_password  # For Gmail access
```

**Also ensure:**
- Dialpad webhook is configured to hit this server
- Attio has company/contact records for leads
- Gmail API access enabled for sales email

## Usage

### Start a Campaign

```bash
# Start primary follow-up campaign for a lead
python3 campaign.py start "primary" --lead "Apex Fitness"

# Start with custom delay override (hours)
python3 campaign.py start "primary" --lead "Apex Fitness" --delay 2

# Start with Attio deal/company ID
python3 campaign.py start "post-demo" --lead "Apex Fitness" --attio-id "deal-uuid"
```

### Pre-Campaign Checklist (MANDATORY)

Before starting ANY campaign, verify:

1. **Customer Status Check**
   - Search memory/CRM for "already a customer" or "purchased" flags
   - Check exclusion list in campaigns.json
   - Verify email domain not in customer database

2. **Email Formatting Check** (for email steps)
   - Preview template renders as proper paragraphs
   - 2-4 sentences per paragraph, blank line between
   - No single-sentence orphan paragraphs
   - No hard line breaks mid-paragraph

3. **Tone Check**
   - No apologetic language ("no worries", "sorry to bother")
   - No easy outs ("if not relevant, no problem")
   - Professional, not needy

**NEVER campaign to existing customers unless explicitly requested for upsell.**

### Check Campaign Status

```bash
# Status for specific lead
python3 campaign.py status "Apex Fitness"

# All active campaigns
python3 campaign.py list
```

### Stop a Campaign

```bash
# Manual termination (lead replied, not interested, etc.)
python3 campaign.py stop "Apex Fitness" --reason "replied_interested"
```

### Remove a Lead

```bash
# Remove lead from campaigns (opted out, not interested)
python3 campaign.py remove "Apex Fitness"
```

### Check for Responses

```bash
# Check if lead has responded to any prior messages
python3 campaign.py check "Apex Fitness"
# Shows response status for each completed step
# Warns if responses detected (safe to proceed or terminate)
```

### View Pending Steps

```bash
# Show all pending campaign steps sorted by time
python3 campaign.py pending
# Useful for seeing what's due soon across all campaigns
```

### Template Management

```bash
# List available templates
python3 campaign.py templates

# Preview a template
python3 campaign.py preview "primary"
```

## Campaign Templates

| Template | Timing | Channel | Purpose |
|----------|--------|---------|---------|
| `primary` | +4 hours | SMS | Recap demo, share recording |
| `secondary` | +1 day | Email | Pricing, detailed ROI |
| `tertiary` | +4 days | SMS | Quick check-in |
| `quaternary` | +7 days | Email | Final follow-up, case study |
| `post-demo` | +0 hours | SMS | Immediate thank you |

### Template Variables

Templates support variable substitution:

```
{name}      - Lead first name
{company}   - Company name
{deal_value} - Deal value from Attio
{owner}     - Sales owner name
{demo_notes} - Notes from demo conversation
{checkout_link} - Personalized checkout URL
```

## Architecture

```
campaign-orchestrator/
ā”œā”€ā”€ SKILL.md              # This file
ā”œā”€ā”€ campaign.py           # Main CLI (start, stop, status, list)
ā”œā”€ā”€ webhook_handler.py    # Processes reply → termination
ā”œā”€ā”€ primary.md            # SMS follow-up template
ā”œā”€ā”€ secondary.md          # Email template
ā”œā”€ā”€ post-demo.md          # Immediate follow-up template
└── state/
    └── campaigns.json    # Campaign state persistence
```

## State Management

Campaign state is stored in `<workspace>/state/campaigns.json`:

```json
{
  "campaigns": {
    "Apex Fitness": {
      "template": "primary",
      "attio_id": "deal-uuid",
      "started": "2026-01-27T13:00:00Z",
      "steps_completed": ["sms_primary"],
      "next_step": "email_secondary",
      "next_scheduled": "2026-01-28T13:00:00Z",
      "status": "active"
    }
  },
  "templates": {
    "primary": {...},
    "secondary": {...}
  }
}
```

## Cron Integration

Campaign steps are executed via Clawdbot's cron system:

- **Executor job**: Runs every 5 minutes to check for due steps
- **Per-campaign jobs**: Created for each scheduled step

The scheduler script creates and manages these jobs automatically.

## Webhook Handling

When Dialpad receives a reply to a campaign message:

1. Dialpad sends webhook to server
2. `webhook_handler.py` parses the reply
3. Looks up which campaign the original message belonged to
4. Marks campaign as terminated
5. Logs the reply to Attio

## Integration Points

### Dialpad SMS
```bash
python3 /home/art/niemand/skills/dialpad/send_sms.py --to "+14155551234" --message "..."
```

### Gmail (via gog)
```bash
gog-shapescale --account [email protected] send-email --to "[email protected]" --subject "..." --body "..."
```

### Attio CRM
```bash
attio note companies "company-uuid" "Campaign message sent: {message}"
```

## Examples

### Full Campaign Workflow

```bash
# 1. After demo, start campaign
/campaign start "post-demo" --lead "Dr. Smith's Clinic"

# 2. Check status next day
/campaign status "Dr. Smith's Clinic"
# Output: Step 1 sent, Step 2 scheduled for tomorrow

# 3. Lead replies "interested"
# Webhook automatically terminates campaign
# Logs reply to Attio

# 4. Manual follow-up if needed
/campaign start "secondary" --lead "Dr. Smith's Clinic" --delay 0
```

### Monitoring Active Campaigns

```bash
# List all active
/campaign list

# Output:
# Active Campaigns:
# - Apex Fitness (primary) - Step 2/4, next: email
# - Dr. Smith's Clinic (post-demo) - Complete
# - Wellness Center (tertiary) - Step 1/3, next: sms
```

## Troubleshooting

**Campaign not sending:**
- Check `cron` is running: `crontab -l`
- Check logs: `journalctl -u moltbot` or campaign logs
- Verify API keys: `echo $DIALPAD_API_KEY`

**Webhook not terminating:**
- Verify Dialpad webhook URL is configured
- Check webhook handler is running
- Check `campaigns.json` for matching lead

**Template variables not filling:**
- Verify lead exists in Attio with required fields
- Check template syntax: `{variable}` not `{ variable }`

## License

Part of shapescale-moltbot-skills. See parent repository.

Overview

This skill orchestrates multi-channel follow-up campaigns for ShapeScale sales, combining scheduled SMS and email sequences with CRM logging and automatic termination on replies. It runs cron-driven schedules, personalizes templates from Attio CRM data, and records all activity back to Attio. Use it to reliably manage post-demo and outreach workflows without manual scheduling overhead.

How this skill works

Define a Campaign as an ordered sequence of steps (SMS or Email) with configurable delays. A scheduler runs every few minutes to execute due steps, sending messages via Dialpad and Gmail and logging actions to Attio. Incoming replies received via Dialpad webhooks are parsed to find the originating campaign and immediately terminate any future steps. Campaign state is persisted in a JSON state file so status, pending steps, and history are always available.

When to use it

  • Following up with demo leads to ensure timely touchpoints and recording
  • Running multi-step outreach sequences that combine SMS and email
  • Managing outreach at scale while avoiding duplicate touches after replies
  • When you need CRM-linked messaging with audit logging in Attio
  • Automating routine follow-ups so reps can focus on qualified leads

Best practices

  • Always verify the lead is not an existing customer or on an exclusion list before starting
  • Preview templates to ensure clean paragraph breaks and 2–4 sentences per paragraph
  • Avoid apologetic or needy language; keep tone professional and concise
  • Ensure Dialpad webhook and Gmail API access are configured and keys are valid
  • Monitor pending steps regularly and use manual stop/remove when opt-outs occur

Example use cases

  • Post-demo thank-you sequence that sends an immediate SMS, then email with ROI and a checkout link
  • Primary outreach campaign: SMS recap after demo, follow-up pricing email, then a final check-in
  • Re-engagement of warm leads with timed SMS reminders and logged notes in Attio
  • Quick stop of all future steps when a lead replies or indicates interest via webhook

FAQ

How does the campaign stop when a lead replies?

Dialpad webhooks deliver replies to the webhook handler, which matches the original message to the campaign, marks the campaign terminated, and logs the reply to Attio.

Where is campaign state stored?

State is stored in a workspace state file (state/campaigns.json) containing active campaigns, completed steps, next scheduled time, and templates.