Skip to content

Marketing Pipeline Improvements #232

@Deodat-Lawson

Description

@Deodat-Lawson

Marketing Pipeline Upgrade

Current Architecture

flowchart LR
    User["User: picks platform + writes prompt"] --> Context["context.ts: company name, employee count, categories, KB snippets"]
    Context --> Trends["research.ts: generic trend search"]
    Trends --> Generator["generator.ts: single LLM call"]
    Generator --> Output["Output: platform post + media type"]
Loading

The user prompt is the primary driver. The system is a copywriter, not a strategist.

Proposed Architecture

flowchart TD
    User["User: picks platform + optional topic"] --> Phase1
    subgraph Phase1 ["Phase 1: Intelligence Gathering"]
        CompanyDNA["Company DNA Extraction"]
        CompetitorResearch["Competitor Research"]
        TrendResearch["Trend Research"]
    end
    Phase1 --> Phase2
    subgraph Phase2 ["Phase 2: Strategic Synthesis"]
        Positioning["Competitive Positioning: why we win"]
    end
    Phase2 --> Phase3
    subgraph Phase3 ["Phase 3: Content Generation"]
        Generator["Humanized message with limited tech depth"]
    end
    Phase3 --> Output["Output: post + competitive angle + media type"]
Loading

Implementation

1. New module: Company DNA extraction (context.ts enhancement)

Currently buildCompanyKnowledgeContext() returns flat data. Enhance it to run two RAG queries:

  • General context query (existing): company facts and capabilities
  • Differentiator query (new): targeted search for unique strengths, open-source mentions, competitive advantages, awards, metrics, customer outcomes

Add a new function extractCompanyDNA() that uses LLM to distill the raw KB snippets into structured insights:

interface CompanyDNA {
  coreMission: string;
  keyDifferentiators: string[];   // e.g., "open source", "no vendor lock-in"
  provenResults: string[];        // metrics, outcomes from KB
  humanStory: string;             // founding story, team ethos, values
  technicalEdge: string;          // simplified explanation of how it works
}

This replaces the raw context string with a structured, LLM-distilled profile. File: context.ts.

2. New module: Competitor analysis (competitor.ts)

New file at src/lib/tools/marketing-pipeline/competitor.ts. This module:

  1. Uses company categories + name to build competitor search queries (via the existing trend-search web search infrastructure)
  2. Searches for competitors' messaging, positioning, and recent posts
  3. Uses LLM to synthesize a competitive landscape:
interface CompetitorAnalysis {
  competitors: Array<{
    name: string;
    positioning: string;
    weaknesses: string[];
  }>;
  ourAdvantages: string[];       // where we clearly win
  marketGaps: string[];          // opportunities competitors miss
  messagingAntiPatterns: string[]; // what competitors say that we should avoid
}

Uses the existing runTrendSearch or direct web search providers from trend-search to gather raw data, then an LLM call to synthesize.

3. New module: Strategic positioning (positioning.ts)

New file at src/lib/tools/marketing-pipeline/positioning.ts. This is the "brain" that combines Company DNA + Competitor Analysis + Trends into a focused messaging angle:

interface MessagingStrategy {
  angle: string;                 // the single tension/insight to lead with
  keyProof: string;              // the differentiator that backs it up
  humanHook: string;             // the relatable, human framing
  avoidList: string[];           // competitor cliches to steer clear of
}

Single LLM call that takes all three inputs and produces one focused strategy.

4. Shared model factory via LangChain (models.ts)

The project already has a getChatModel() factory in models.ts that supports OpenAI, Anthropic, and Google Gemini models through LangChain's BaseChatModel interface. The marketing pipeline currently bypasses this and hardcodes new ChatOpenAI() directly — which is both inflexible and caused the temperature bug (gpt-5-mini rejects temperature: 0.7).

Move getChatModel() to a shared location at src/lib/models.ts (or src/lib/models/index.ts) so it can be imported by both the marketing pipeline and other agents. Then use it in every LLM call within the marketing pipeline:

  • generator.ts — main content generation (currently broken with temperature error)
  • context.ts — new CompanyDNA extraction call
  • competitor.ts — new competitor analysis synthesis call
  • positioning.ts — new strategic positioning call

This gives you one place to swap models. Want to try Claude Sonnet for marketing content? Change one line. All calls go through LangChain's BaseChatModel interface, so any provider LangChain supports (OpenAI, Anthropic, Google, Mistral, Cohere, etc.) works with zero changes to the pipeline logic.

For the marketing pipeline specifically, we can define a config object:

const MARKETING_MODELS = {
  dnaExtraction: "gpt-5-mini" as AIModelType,
  competitorAnalysis: "gpt-5-mini" as AIModelType,
  positioning: "gpt-5-mini" as AIModelType,
  contentGeneration: "gpt-5.2" as AIModelType,
};

This makes it trivial to experiment with different models for different pipeline stages.

5. Generator rewrite (generator.ts)

Update the system prompt and buildPrompt() in generator.ts. Replace new ChatOpenAI(...) with getChatModel(MARKETING_MODELS.contentGeneration):

  • System prompt changes:
    • Add explicit humanization rules: "Write as if explaining to a smart friend over coffee, not presenting at a conference"
    • Add technical depth constraint: "If you mention how something works, keep it to one sentence max. Focus on what it means for the reader, not the implementation"
    • Add competitor-awareness rules: "Use competitive insights to create contrast, but never name competitors directly"
  • Prompt structure changes:
    • Replace raw company context with structured CompanyDNA
    • Add CompetitorAnalysis summary
    • Add MessagingStrategy as the primary directive
    • Make the user prompt an optional "topic focus" rather than the primary driver
  • Output schema update: Add a competitiveAngle field so the UI can show why this message was crafted this way.

6. Pipeline orchestration update (run.ts)

Update run.ts to add the new steps. Run Company DNA + Competitor Research + Trend Research in parallel for speed:

1. extractCompanyDNA()          ─┐
2. analyzeCompetitors()          ├─ parallel
3. researchPlatformTrends()     ─┘
4. buildMessagingStrategy()      ← sequential (needs 1-3)
5. generateCampaignOutput()      ← sequential (needs 4)

7. Types update (types.ts)

In types.ts:

  • Make prompt optional in MarketingPipelineInputSchema (with .optional())
  • Add CompanyDNA, CompetitorAnalysis, MessagingStrategy interfaces
  • Extend MarketingPipelineResult with competitiveAngle: string and strategyUsed: MessagingStrategy
  • Add output schema for the new competitiveAngle field

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions