campaign-sequencer
Multi-channel drip sequence orchestrator that builds and executes outbound campaigns across email, Slack, and direct messages. Triggers when the user asks to set up an outbound campaign, drip sequence, multi-channel outreach, or creator outreach program. Coordinates Clay enrichment, Gmail drafts, Slack DMs, and scheduled follow-ups with full state tracking in Supabase. Enforces send limits, opt-out compliance, and batch confirmation before any messages go out.
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:
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.
-- 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:
- Call
find-and-enrich-companywith the company name or domain - Call
find-and-enrich-contacts-at-companyto get role, seniority, tech stack - Call
add-contact-data-pointsto 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_draftwith personalized subject and body - Slack: Call
slack_search_usersto find the user, thenslack_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:
-- 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
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.
- Never send to unsubscribed contacts. Check
unsubscribed = falsebefore every send. - Always include opt-out. Every email must end with: "Reply STOP to opt out of future messages."
- Max 50 contacts per batch. If the target list exceeds 50, split into batches and confirm each.
- Require confirmation before sending. Present a summary table (contact, channel, message preview) and wait for explicit user approval before executing sends.
- No duplicate sends. Check state before each send -- never re-send a stage that was already delivered.
- Rate limiting. Space emails at least 30 seconds apart to avoid spam flags.
- 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.
- 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.
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.