---
name: 0xjitsu/campaign-sequencer
source: https://app.decimal.ai/s/0xjitsu-campaign-sequencer@1/SKILL.md
source_sha256: 236e88296e89
---

# Campaign Sequencer

Multi-channel drip sequence orchestrator for outbound campaigns.

## When to Trigger

Activate this skill when the user:

- Asks to set up an outbound campaign or drip sequence
- Wants to run multi-channel outreach (email + Slack + DM)
- Requests creator outreach, partnership outreach, or cold outreach programs
- Needs to schedule follow-up messages across multiple touchpoints
- Says "campaign", "drip", "sequence", "outreach", "nurture", or "cadence"

## MCP Tool Mappings

This skill orchestrates across five MCP servers. Always verify each server is connected before starting.

| MCP Server       | Tools Used                                                                 | Purpose                        |
|------------------|----------------------------------------------------------------------------|--------------------------------|
| Clay             | `find-and-enrich-company`, `find-and-enrich-contacts-at-company`, `add-contact-data-points` | Lead enrichment and data append |
| Gmail            | `gmail_create_draft`, `gmail_search_messages`                              | Email composition and reply detection |
| Slack            | `slack_send_message`, `slack_search_users`                                 | Slack DM outreach              |
| Scheduled Tasks  | `create_scheduled_task`                                                    | Delayed follow-up scheduling   |
| Supabase         | `execute_sql`                                                              | State tracking and analytics   |

## Stage Template System

Define each stage of the sequence with these fields:

```yaml
stages:
  - id: 1
    name: "Initial Outreach"
    channel: email          # email | slack | dm
    timing: "Day 0"         # Relative to sequence start
    template: "intro_email"
    fallback_channel: slack  # If primary channel unavailable

  - id: 2
    name: "Follow-up Nudge"
    channel: email
    timing: "Day 3"
    template: "follow_up_1"
    skip_if: replied         # Skip if contact already replied

  - id: 3
    name: "Slack Touch"
    channel: slack
    timing: "Day 5"
    template: "slack_casual"
    skip_if: replied

  - id: 4
    name: "Final Follow-up"
    channel: email
    timing: "Day 7"
    template: "break_up_email"
    skip_if: replied
```

### Channel Definitions

- **email**: Uses Gmail MCP to create drafts. User reviews and sends, or auto-send if explicitly approved.
- **slack**: Uses Slack MCP to send DMs. Requires the contact's Slack workspace membership.
- **dm**: Platform-specific DM (Twitter, Discord). Manual send -- skill generates the message text only.

## Sequence Workflow

Execute these steps in order. Report progress after each step.

### Step 1: Define Target List

Pull contacts from Supabase or accept manual input.

```sql
-- Example: pull from an existing prospects table
SELECT id, first_name, last_name, email, company, linkedin_url
FROM prospects
WHERE campaign_id IS NULL
  AND unsubscribed = false
ORDER BY created_at DESC
LIMIT 50;
```

If no Supabase table exists, accept a list of names/emails/companies from the user and create the tracking table (see State Machine below).

### Step 2: Enrich Each Contact via Clay

For each contact in the target list:

1. Call `find-and-enrich-company` with the company name or domain
2. Call `find-and-enrich-contacts-at-company` to get role, seniority, tech stack
3. Call `add-contact-data-points` to append social profiles, recent funding, headcount

Store enrichment results back to Supabase for use in personalization.

### Step 3: Score Leads

Invoke the `lead-scorer` skill if available. Pass enriched contact data and receive a score + tier.

```
For each contact:
  score = lead-scorer(contact_data)
  UPDATE prospects SET score = {score}, tier = {tier} WHERE id = {contact_id};
```

Filter out contacts with tier = "Skip" (score < 20). Flag "Hot" leads (80+) for priority sequencing.

### Step 4: Generate Personalized Messages

Invoke the `template-personalizer` skill for each stage and each contact.

Pass:
- Template ID from the stage definition
- Contact enrichment data from Clay
- Tone setting from user preference
- Personalization depth level (L1/L2/L3 based on tier)

Hot leads get L3 (hyper-personalized). Warm get L2. Cold get L1.

### Step 5: Queue Day 0 Actions

For all contacts, execute the first stage immediately:

- **Email**: Call `gmail_create_draft` with personalized subject and body
- **Slack**: Call `slack_search_users` to find the user, then `slack_send_message`
- **DM**: Output the message text for manual sending

Update state to `contacted` in Supabase after each send.

### Step 6: Schedule Follow-ups

For stages with timing beyond Day 0, use Scheduled Tasks MCP:

```
For each future stage:
  create_scheduled_task({
    name: "campaign_{campaign_id}_contact_{contact_id}_stage_{stage_id}",
    scheduled_time: now() + stage.timing,
    task: {
      action: "send_message",
      channel: stage.channel,
      contact_id: contact_id,
      template: stage.template
    }
  })
```

Before scheduling, check if the contact has already replied (query Gmail or Slack). If replied, skip remaining stages.

### Step 7: Track Opens and Replies

Set up monitoring queries:

```sql
-- Check for replies (run daily or before each scheduled send)
SELECT p.id, p.email, p.state
FROM prospects p
WHERE p.campaign_id = {campaign_id}
  AND p.state = 'contacted'
  AND p.last_stage_sent_at < NOW() - INTERVAL '1 day';
```

Use `gmail_search_messages` to check for replies from each contact's email. Update state to `replied` when found.

## State Machine

Each contact progresses through these states:

```
new --> enriched --> contacted --> replied --> converted
                        |                        |
                        +----> churned <---------+
```

| State     | Meaning                                         | Transition Trigger                    |
|-----------|--------------------------------------------------|---------------------------------------|
| new       | Added to campaign, not yet enriched               | Contact added to target list          |
| enriched  | Clay enrichment complete                          | Enrichment data returned              |
| contacted | At least one message sent                         | First stage executed                  |
| replied   | Contact responded on any channel                  | Reply detected via Gmail/Slack search |
| converted | Contact completed desired action (meeting, signup) | Manual update by user                 |
| churned   | All stages exhausted with no reply, or opted out   | Final stage sent with no response     |

### Supabase Schema

```sql
CREATE TABLE IF NOT EXISTS campaign_contacts (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  campaign_id TEXT NOT NULL,
  contact_email TEXT NOT NULL,
  first_name TEXT,
  last_name TEXT,
  company TEXT,
  role TEXT,
  state TEXT DEFAULT 'new' CHECK (state IN ('new','enriched','contacted','replied','converted','churned')),
  score INTEGER,
  tier TEXT,
  enrichment_data JSONB,
  current_stage INTEGER DEFAULT 0,
  last_stage_sent_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  unsubscribed BOOLEAN DEFAULT FALSE
);

CREATE INDEX idx_campaign_state ON campaign_contacts(campaign_id, state);
```

## Safety Rules

These are non-negotiable. The skill must enforce all of them.

1. **Never send to unsubscribed contacts.** Check `unsubscribed = false` before every send.
2. **Always include opt-out.** Every email must end with: "Reply STOP to opt out of future messages."
3. **Max 50 contacts per batch.** If the target list exceeds 50, split into batches and confirm each.
4. **Require confirmation before sending.** Present a summary table (contact, channel, message preview) and wait for explicit user approval before executing sends.
5. **No duplicate sends.** Check state before each send -- never re-send a stage that was already delivered.
6. **Rate limiting.** Space emails at least 30 seconds apart to avoid spam flags.
7. **Reply detection before follow-ups.** Always check for replies before sending any follow-up stage. If the contact replied, skip all remaining stages and update state.
8. **No weekends or late nights.** Schedule sends for business hours (9 AM - 6 PM in the contact's timezone) on weekdays only.

## Example Sequence: Creator Program Outreach

Target: Web3 developers and content creators for a developer ambassador program.

```yaml
campaign:
  name: "Creator Program Q2 2026"
  goal: "Recruit 20 developer ambassadors"
  total_targets: 40
  tone: "CT-style"
  personalization_depth: "L3 for Hot, L2 for Warm"

stages:
  - id: 1
    name: "Warm Intro"
    channel: email
    timing: "Day 0"
    template: |
      Subject: Your {{recent_achievement}} caught my eye

      Hey {{first_name}},

      Saw your {{recent_achievement}} -- legit impressive work.
      We're building a creator program for devs who ship,
      and your background in {{tech_stack}} is exactly what
      we're looking for.

      Quick 15-min call this week? No pitch deck, just vibes.

      Reply STOP to opt out of future messages.

  - id: 2
    name: "Value Add"
    channel: slack
    timing: "Day 3"
    template: |
      hey {{first_name}} -- dropped you an email earlier this week
      about our creator program. thought you might also find this
      useful: [relevant resource link]. no pressure, just sharing.

  - id: 3
    name: "Social Proof"
    channel: email
    timing: "Day 5"
    template: |
      Subject: {{mutual_connection}} just joined -- thought of you

      {{first_name}},

      {{mutual_connection}} from {{mutual_company}} just came on
      board as a creator. Given your overlap in {{tech_stack}},
      figured you'd want to know.

      Interested? Just reply and I'll send details.

      Reply STOP to opt out of future messages.

  - id: 4
    name: "Last Call"
    channel: email
    timing: "Day 7"
    template: |
      Subject: closing the loop

      {{first_name}} -- wanted to follow up one last time.
      If the timing isn't right, totally get it. If you want
      in on the creator program, just reply and we'll make it
      happen.

      Either way, keep shipping.

      Reply STOP to opt out of future messages.
```

## Reporting

After campaign execution, generate a summary:

```
Campaign: Creator Program Q2 2026
Total Contacts: 40
Enriched: 38 (2 failed enrichment)
Contacted: 36 (2 scored as Skip)
Replied: 12 (33% reply rate)
Converted: 8 (22% conversion rate)
Churned: 24

Top performing stage: Stage 1 (8 replies)
Best channel: Email (10 replies vs 2 Slack)
Average score of converted leads: 84
```

Store the report in Supabase and present it as a formatted table.