Campaign Types & Schema

Purpose: TypeScript schemas and types for all campaign playbooks
Use: Import these schemas in your message sequence agent
Status: Reference Implementation
Last Updated: 2026-01-26


Core Types

Campaign Type Enum

export type CampaignType =
  | 'event-follow-up'
  | 'mutual-intro'
  | 'partnership-outreach'
  | 'product-launch'
  | 'content-syndication'
  | 're-engagement'
  | 'cold-outbound'
  | 'referral-request';

Campaign-Specific Segments

Event Follow-Up Segments

export type EventFollowUpSegment =
  | 'booth-visitor'
  | 'panelist-speaker'
  | 'vip-dinner'
  | 'meeting-log'
  | 'general-attendee';
 
export interface EventFollowUpContext {
  eventName: string;
  eventDate: Date;
  eventType: 'conference' | 'dinner' | 'meetup' | 'demo-day' | 'panel';
  interactionType: EventFollowUpSegment;
  conversationTopics?: string[];
  boothNumber?: string;
  panelTopic?: string;
  meetingNotes?: string;
}

Mutual Introduction Segments

export type MutualIntroSegment =
  | 'warm-intro-executive'
  | 'warm-intro-peer'
  | 'cold-intro-context'
  | 'multi-hop-intro';
 
export interface MutualIntroContext {
  introducerName: string;
  introducerRelationship: 'investor' | 'customer' | 'partner' | 'advisor' | 'peer';
  introducerContext: string;
  sharedConnections?: string[];
  introMessage?: string;
  urgency: 'high' | 'medium' | 'low';
}

Partnership Outreach Segments

export type PartnershipSegment =
  | 'cold-partner-rep'
  | 'engaged-partner-rep'
  | 'active-deal-support'
  | 'partner-leadership'
  | 'ecosystem-intro';
 
export interface PartnershipContext {
  partnerName: string;
  partnerType: 'technology' | 'referral' | 'reseller' | 'services';
  repName?: string;
  repTitle?: string;
  accountsShared?: string[];
  activationGoal?: string;
  slackChannelActive?: boolean;
}

Product Launch Segments

export type ProductLaunchSegment =
  | 'active-user'
  | 'churned-user'
  | 'prospect-good-fit'
  | 'prospect-early-stage'
  | 'waitlist-member';
 
export interface ProductLaunchContext {
  productName: string;
  releaseDate: Date;
  featureType: 'major' | 'minor' | 'integration' | 'improvement';
  relevanceToProspect: string;
  usageHistory?: {
    lastActive?: Date;
    featureUsage?: string[];
    churnReason?: string;
  };
}

Content Syndication Segments

export type ContentSegment =
  | 'by-persona'
  | 'by-industry'
  | 'by-engagement-history'
  | 'by-funnel-stage';
 
export interface ContentContext {
  contentType: 'blog' | 'case-study' | 'whitepaper' | 'webinar' | 'guide';
  contentTitle: string;
  contentUrl: string;
  publishDate: Date;
  targetPersona: PersonaType;
  targetIndustry?: string;
  relevanceReason: string;
}

Re-engagement Segments

export type ReEngagementSegment =
  | 'inactive-prospect'
  | 'stalled-deal'
  | 'churned-customer'
  | 'ghosted-conversation';
 
export interface ReEngagementContext {
  lastInteraction: Date;
  lastInteractionType: 'email' | 'call' | 'demo' | 'proposal' | 'usage';
  stallReason?: string;
  churnReason?: string;
  objections?: string[];
  newValue?: string; // What's changed since last interaction
}

Persona Types

export type PersonaType =
  | 'executive'
  | 'practitioner'
  | 'champion'
  | 'blocker';
 
export interface PersonaProfile {
  type: PersonaType;
  title: string;
  seniority: 'ic' | 'manager' | 'director' | 'vp' | 'c-level';
  department: string;
  decisionAuthority: 'decision-maker' | 'influencer' | 'user' | 'gatekeeper';
}
 
export const PersonaTone = {
  executive: {
    style: 'concise and ROI-driven',
    focus: ['outcomes', 'strategic value', 'business impact'],
    avoid: ['technical jargon', 'long emails', 'process details'],
    emailLength: 'short (3-4 paragraphs max)',
  },
  practitioner: {
    style: 'tactical and use-case focused',
    focus: ['technical depth', 'specific examples', 'how it works'],
    avoid: ['buzzwords', 'vague benefits', 'sales speak'],
    emailLength: 'medium (4-6 paragraphs)',
  },
  champion: {
    style: 'collaborative and enablement-focused',
    focus: ['internal selling', 'success stories', 'team impact'],
    avoid: ['pressure', 'external focus only', 'ignoring their needs'],
    emailLength: 'medium (4-6 paragraphs)',
  },
  blocker: {
    style: 'risk-aware and proof-driven',
    focus: ['risk mitigation', 'proof points', 'alternatives considered'],
    avoid: ['overpromising', 'dismissing concerns', 'rushing'],
    emailLength: 'medium-long (5-7 paragraphs with proof)',
  },
} as const;

Sequence Schemas

Sequence Step

import { z } from 'zod';
 
export const sequenceStepSchema = z.object({
  step: z.number().int().positive(),
  channel: z.enum(['email', 'linkedin', 'slack', 'phone', 'video']),
  timing: z.string().describe('When to send: immediate, day-2, day-7, day-14, etc.'),
  subject: z.string().optional().describe('Email subject line (if email)'),
  body: z.string().describe('Full message body with personalization'),
  cta: z.string().describe('Clear call-to-action'),
  attachments: z.array(z.string()).optional().describe('URLs to attachments'),
  personalizationNotes: z.array(z.string()).describe('Notes on personalization for human reviewer'),
  fallbackTrigger: z.string().optional().describe('What triggers fallback sequence'),
});
 
export type SequenceStep = z.infer<typeof sequenceStepSchema>;

Full Sequence

export const sequenceSchema = z.object({
  campaignType: z.enum([
    'event-follow-up',
    'mutual-intro',
    'partnership-outreach',
    'product-launch',
    'content-syndication',
    're-engagement',
    'cold-outbound',
    'referral-request',
  ]),
  segment: z.string().describe('Campaign-specific segment'),
  persona: z.enum(['executive', 'practitioner', 'champion', 'blocker']),
  sequenceLength: z.number().int().min(2).max(6),
  priority: z.enum(['high', 'medium', 'low']),
  reasoning: z.string().describe('Why this classification and sequence'),
  
  primarySequence: z.array(sequenceStepSchema),
  fallbackSequence: z.array(sequenceStepSchema).optional(),
  
  metadata: z.object({
    generatedAt: z.date(),
    model: z.string(),
    confidence: z.number().min(0).max(1),
    playbookVersion: z.string(),
  }),
});
 
export type Sequence = z.infer<typeof sequenceSchema>;

Research Report Schema

export const researchReportSchema = z.object({
  prospect: z.object({
    name: z.string(),
    email: z.string().email(),
    title: z.string(),
    company: z.string(),
    linkedin: z.string().url().optional(),
    location: z.string().optional(),
  }),
  
  intelligence: z.object({
    companyInfo: z.object({
      stage: z.string(),
      funding: z.string().optional(),
      size: z.string(),
      industry: z.string(),
      techStack: z.array(z.string()).optional(),
    }),
    recentNews: z.array(z.object({
      title: z.string(),
      url: z.string().url(),
      date: z.date(),
      relevance: z.string(),
    })),
    painPoints: z.array(z.string()),
    competitors: z.array(z.string()),
  }),
  
  personalization: z.object({
    signals: z.array(z.string()).describe('Specific personalization opportunities'),
    context: z.string().describe('Overall context for outreach'),
    relevance: z.string().describe('Why Brainforge is relevant'),
    mutualConnections: z.array(z.string()).optional(),
    sharedInterests: z.array(z.string()).optional(),
  }),
  
  engagementHistory: z.object({
    lastContact: z.date().optional(),
    interactions: z.number().int(),
    stage: z.string(),
    previousCampaigns: z.array(z.string()).optional(),
    responseRate: z.number().min(0).max(1).optional(),
  }),
});
 
export type ResearchReport = z.infer<typeof researchReportSchema>;

Campaign Classification Schema

export const campaignClassificationSchema = z.object({
  campaignType: z.enum([
    'event-follow-up',
    'mutual-intro',
    'partnership-outreach',
    'product-launch',
    'content-syndication',
    're-engagement',
    'cold-outbound',
    'referral-request',
  ]),
  segment: z.string().describe('Campaign-specific segment (e.g., booth-visitor, warm-intro-executive)'),
  persona: z.enum(['executive', 'practitioner', 'champion', 'blocker']),
  sequenceLength: z.number().int().min(2).max(6),
  priority: z.enum(['high', 'medium', 'low']),
  reasoning: z.string().describe('Explanation of classification decisions'),
  confidence: z.number().min(0).max(1),
});
 
export type CampaignClassification = z.infer<typeof campaignClassificationSchema>;

Slack Approval Schema

export interface SlackApprovalRequest {
  workflowId: string;
  prospectName: string;
  prospectCompany: string;
  campaignType: CampaignType;
  segment: string;
  persona: PersonaType;
  sequence: Sequence;
  researchReport: ResearchReport;
  approvalDeadline: Date;
}
 
export type ApprovalAction = 'approve' | 'edit' | 'reject';
 
export interface SlackApprovalResponse {
  workflowId: string;
  action: ApprovalAction;
  editedSequence?: Sequence;
  rejectionReason?: string;
  approvedBy: string;
  approvedAt: Date;
}

CRM Integration Schema

export interface CRMContact {
  id: string;
  email: string;
  firstName: string;
  lastName: string;
  company: string;
  title: string;
  hubspotContactId?: string;
  customProperties?: Record<string, any>;
}
 
export interface CRMSequenceTracking {
  sequenceId: string;
  contactId: string;
  campaignType: CampaignType;
  currentStep: number;
  totalSteps: number;
  status: 'active' | 'paused' | 'completed' | 'opted-out';
  performance: {
    sent: number;
    opened: number;
    clicked: number;
    replied: number;
    meetingBooked: boolean;
  };
  nextActionDate: Date;
}

Trigger Event Schema

export type TriggerSource =
  | 'form-submission'
  | 'crm-webhook'
  | 'manual-trigger'
  | 'event-integration'
  | 'api-request';
 
export interface CampaignTrigger {
  source: TriggerSource;
  triggeredAt: Date;
  triggeredBy?: string;
  
  prospect: {
    email: string;
    name?: string;
    company?: string;
    title?: string;
  };
  
  context: 
    | EventFollowUpContext
    | MutualIntroContext
    | PartnershipContext
    | ProductLaunchContext
    | ContentContext
    | ReEngagementContext
    | Record<string, any>;
  
  metadata?: Record<string, any>;
}

Playbook Structure (Markdown)

Each campaign playbook should follow this structure:

# [Campaign Name] Playbook
 
> **Purpose**: [One-line description]
> **Use Case**: [When to use this campaign]
> **Last Updated**: [Date]
 
---
 
## Overview
 
**Use Case:** [Description]
**Goal:** [Specific outcome]
**Key Principle:** [Core messaging principle]
 
---
 
## Segmentation Strategy
 
### Segment 1: [Name]
- **Context**: [When this segment applies]
- **Engagement Level**: [Light/Moderate/High]
- **Personalization Angle**: [What to personalize on]
- **Example Context**: [Sample opening line]
 
### Segment 2: [Name]
...
 
---
 
## Persona-Based Messaging
 
### Persona 1: [Executive/Practitioner/Champion/Blocker]
 
**Tone & Style:**
- [Style description]
 
**Key Messages:**
- [Message 1]
- [Message 2]
 
**What to Avoid:**
- [Anti-pattern 1]
- [Anti-pattern 2]
 
**Example Opening:**

[Sample opening line]


**Example Value Prop:**

[Sample value prop]


**Example CTA:**

[Sample call-to-action]


---

## Multi-Step Sequences

### Sequence Template 1: [Segment + Persona]

**Length**: [N] touchpoints over [X] days

#### Step 1 (Immediate)
- **Channel**: Email
- **Goal**: [Goal of this step]
- **Template**:

Subject: [Subject template]

[Body template with [PERSONALIZATION] markers]

[CTA]


#### Step 2 (Day [N])
...

---

## Examples

### Example 1: [Real example name]
[Full example with context]

### Example 2: [Real example name]
[Full example with context]

---

## Success Metrics

- **Open Rate**: [Target]%
- **Response Rate**: [Target]%
- **Meeting Booked**: [Target]%

Usage in Agent

Import Playbook

// lib/playbooks/event-follow-up.ts
import playbookMd from '@/memory/event-follow-up-playbook.md';
 
export const eventFollowUpPlaybook = {
  type: 'event-follow-up' as const,
  content: playbookMd,
  version: '1.0.0',
  lastUpdated: new Date('2026-01-26'),
};

Load Playbook in Generator

// lib/services/generator.ts
import { eventFollowUpPlaybook } from '@/lib/playbooks/event-follow-up';
 
export async function generateSequence(
  classification: CampaignClassification,
  research: ResearchReport
): Promise<Sequence> {
  
  // Load appropriate playbook
  const playbook = getPlaybook(classification.campaignType);
  
  // Generate sequence with AI SDK
  const { object: sequence } = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: sequenceSchema,
    messages: [
      {
        role: 'system',
        content: GENERATOR_PROMPT,
      },
      {
        role: 'user',
        content: `
Campaign Playbook:
${playbook.content}
 
Research Report:
${JSON.stringify(research, null, 2)}
 
Classification:
${JSON.stringify(classification, null, 2)}
 
Generate a personalized sequence following the playbook guidelines.
        `,
      },
    ],
  });
  
  return sequence;
}

Adding New Campaign Types

  1. Define segment type in this file
  2. Define context interface in this file
  3. Add to CampaignType enum
  4. Create playbook markdown following structure above
  5. Import playbook in lib/playbooks/
  6. Update classifier to recognize new type
  7. Test with sample triggers

Validation

Use Zod schemas for runtime validation:

import { sequenceSchema, researchReportSchema } from './schema';
 
// Validate research report
const validatedReport = researchReportSchema.parse(rawReport);
 
// Validate generated sequence
const validatedSequence = sequenceSchema.parse(generatedSequence);