Skip to main content

AI Architecture

YBH Pulse Content uses a multi-agent AI architecture where specialized agents handle different content types, each with custom prompts, RAG context, and validation rules.

Agent System

Each agent specializes in a specific content type with custom configuration.

Agent Structure

Every agent has:
interface Agent {
  id: AgentId                    // 'prf' | 'hooks' | 'linkedin' | ...
  name: string                   // Display name
  systemPrompt: string           // Instructions for AI
  model: string                  // AI model selection
  temperature: number            // Creativity level (0-1)
  ragEnabled: boolean            // Use RAG for context
  factCheckEnabled: boolean      // Validate output
}
Example agent:
{
  "id": "hooks",
  "name": "Viral Hooks Generator",
  "systemPrompt": "You are a viral content strategist...",
  "model": "claude-3.5-sonnet",
  "temperature": 0.8,
  "ragEnabled": true,
  "factCheckEnabled": true
}

Agent Workflow

1

User triggers generation

Click “Generate PRF” → Frontend calls /api/agent/prf
2

Backend loads agent config

const agent = settings.agents.find(a => a.id === 'prf')
const prompt = interpolatePrompt(
  agent.systemPrompt,
  settings.presetFields,
  { episodeNumber, guestName }
)
3

RAG retrieval (if enabled)

Fetch relevant context from vector database:
  • Previous PRF examples
  • Brand guidelines
  • YBH content patterns
4

AI generation with streaming

const stream = await generateText({
  model: agent.model,
  system: prompt,
  messages: [{ role: 'user', content: transcript }],
  temperature: agent.temperature
})

// Stream progress via SSE
for await (const chunk of stream) {
  sendSSE({ type: 'progress', content: chunk })
}
5

Validation & fact-check

If factCheckEnabled, validate output before returning
6

Response to frontend

Return generated content with metadata:
{
  "content": "<h2>Executive Summary</h2>...",
  "model": "claude-3.5-sonnet",
  "tokensUsed": 3420,
  "generationTime": 28.4,
  "factCheckPassed": true
}

RAG (Retrieval Augmented Generation)

RAG enhances AI responses with relevant context from a knowledge base.

Knowledge Base

Stored in Pinecone vector database:

Brand Guidelines

  • YBH brand voice examples
  • Sound bites and taglines
  • Tone and positioning docs
  • Target audience profiles
When used: All content generation

Design Database

  • 28 infographic layout types
  • 10 content templates
  • 5 color systems
  • Icon style examples
When used: Visual spec generation

Content Examples

  • Top-performing PRF docs
  • Viral hook patterns
  • Successful social posts
  • High-engagement visuals
When used: All generation for consistency

Generation History

  • Recent layouts used
  • Guest topics covered
  • Visual style patterns
  • Repetition tracking
When used: Ensure variety

Retrieval Process

// 1. Embed the query
const queryEmbedding = await embed(
  `Episode ${episodeNumber} with ${guestName}: ${transcript.slice(0, 500)}`
)

// 2. Search vector database
const results = await pinecone.query({
  vector: queryEmbedding,
  topK: 5,
  filter: { type: 'brand_guideline' }
})

// 3. Inject into prompt
const context = results.matches
  .map(m => m.metadata.content)
  .join('\n\n')

const enhancedPrompt = `
RELEVANT CONTEXT:
${context}

═══════════════════════════════════════
YOUR TASK:
${systemPrompt}
`
Benefits of RAG:
  • Consistent brand voice across episodes
  • Learns from past successful content
  • Adapts to new patterns without retraining
  • Reduces hallucinations via grounded context

Fact-Checking System

Fact-checking prevents AI hallucinations by validating generated content against the source transcript.

Why Fact-Checking Matters

AI models can generate plausible but false content:
Common hallucination examples:
  • Statistics: “73% of CIOs report…” (number invented)
  • Quotes: Compelling statement guest never said
  • Attribution: Quote from guest, actually said by host
  • Events: “In 2019, the company launched…” (date wrong)
Fact-checking catches these before they reach social media.

Fact-Check Process

1

Extract checkable items

Scan generated content for:
interface FactCheckItem {
  type: 'statistic' | 'quote' | 'claim' | 'list'
  content: string
  source: string  // Guest name or "Host"
}
Example extraction:
[
  {
    "type": "statistic",
    "content": "73% of IT leaders regret vendor choice within 6 months",
    "source": "Mark Baker"
  },
  {
    "type": "quote",
    "content": "The challenge is finding the vendor who sucks the least",
    "source": "Mark Baker"
  }
]
2

Search transcript for evidence

Fact-check agent searches transcript:
For each item:
1. Search for exact match
2. Search for paraphrase
3. Verify attribution (who said it)
4. Check context (is meaning preserved)
3

Classify verification status

Each item gets a status:
  • Verified - Found in transcript, correct attribution
  • Unverified - Not found in transcript
  • Misattributed - Found but wrong speaker
  • Fabricated - Clearly invented, contradicts transcript
4

Generate validation report

{
  "overallScore": 85,
  "passedValidation": true,
  "results": [
    {
      "item": { "type": "quote", "content": "..." },
      "status": "verified",
      "confidence": 95,
      "transcriptEvidence": "Found at timestamp 23:45..."
    },
    {
      "item": { "type": "statistic", "content": "73%..." },
      "status": "unverified",
      "confidence": 30,
      "issue": "Statistic not found in transcript",
      "suggestion": "Remove or verify source"
    }
  ],
  "criticalIssues": [
    "Statistic '73% of IT leaders' not found in transcript"
  ]
}

Validation Thresholds

// Overall score must be ≥80% to pass
if (factCheck.overallScore < 80) {
  showWarning('Content accuracy issues detected')
}

// Critical issues always warn
if (factCheck.criticalIssues.length > 0) {
  showWarning(factCheck.criticalIssues.join('; '))
}
Best practice: Always run fact-check before approving content for publication, especially visual assets that will be widely shared.

Brand Consistency

All generated content adheres to YBH brand guidelines automatically.

Brand Voice Rules

Injected into every system prompt:
YBH BRAND VOICE:
- "We don't sell. We unsell."
- Anti-spin, anti-transactional, pro-IT leader
- Professional but bold, witty, direct
- Challenge vendor BS and corporate jargon
- Respect IT leaders' intelligence

TARGET AUDIENCE:
- CIOs, CTOs, IT Directors
- Decision-makers, not influencers
- Tired of vendor spin
- Want honest, practical insights

AVOID:
- Vendor-speak ("leverage", "synergy", "best-in-class")
- Empty buzzwords ("digital transformation", "innovation")
- Patronizing tone
- Hard selling

Visual Brand Consistency

Design specs include brand requirements:
// YBH color palette
const BRAND_COLORS = {
  primary: {
    yellow: '#F7B500',
    orange: '#F17529',
    red: '#EF4136'
  },
  secondary: {
    towerGray: '#A4BFC1'
  }
}

// Typography
const BRAND_FONTS = {
  display: 'Fonseca',  // Headlines
  body: 'Montserrat'   // Body text
}

// Every visual spec includes:
"Include YBH branding: gradient (yellow→orange→red) or 
single accent color. Typography: Fonseca for headlines, 
Montserrat for body. Professional but bold aesthetic."

Content Quality Standards

PRF Documents

  • Executive summary: 2-3 sentences
  • Key themes: 2-4 themes max
  • Quotes: Direct, attributed, verified
  • Takeaways: Specific, actionable, numbered

Viral Hooks

  • Length: 1-2 sentences
  • Hook: Grab attention in first 3 words
  • Content: Contrarian, specific, memorable
  • Verification: All facts from transcript

Social Posts

  • LinkedIn: 500-800 chars, professional
  • Instagram: 150-300 chars, visual
  • Hashtags: 1-3 (LinkedIn), 3-5 (Instagram)
  • CTA: Clear, single action

Visual Assets

  • Title: Under 10 words
  • Message: Obvious within 5 seconds
  • Text: Minimal, high contrast
  • Branding: YBH colors or logo present

Prompt Engineering

Effective prompts are crucial for consistent, high-quality output.

Prompt Structure

[ROLE & EXPERTISE]
You are a [specific role] with expertise in [domain].

[BRAND CONTEXT]
{brand_guidelines}

[TASK DEFINITION]
Your task: [specific output required]

[INPUT CONTEXT]
{episode_metadata}
{transcript}
{prf}

[OUTPUT FORMAT]
- Format: [JSON | HTML | Markdown]
- Structure: [specific schema]
- Constraints: [length, style, etc.]

[VALIDATION RULES]
- All facts MUST be verifiable in transcript
- No fabricated statistics or quotes
- Match brand voice: [specific guidelines]

[EXAMPLES]
{few_shot_examples}

Variable Interpolation

Prompts support dynamic variables:
const prompt = `
Generate viral hooks for Episode {{episodeNumber}} 
featuring {{guestName}}.

Recent styles used: {{recentStyles}}
Avoid repetition of these patterns.
`

// Interpolated:
const interpolated = interpolatePrompt(prompt, presetFields, {
  episodeNumber: '348',
  guestName: 'Mark Baker',
  recentStyles: 'Contrarian, Data-Driven, Story Hook'
})
Preset fields are configurable in Settings:
  • Company name
  • Podcast name
  • Host names
  • Brand taglines
  • Social handles

Few-Shot Examples

Include examples in prompts for pattern matching:
EXAMPLE 1:
Input: [Transcript about vendor selection]
Output: "The challenge isn't finding a vendor. It's finding 
the one who sucks the least."

EXAMPLE 2:
Input: [Transcript about IT respect]
Output: "After interviewing 380 IT professionals, one pattern 
stands out: respect shouldn't only show up when the system 
goes down."

EXAMPLE 3:
Input: [Transcript about uptime]
Output: "Most CIOs focus on uptime. The best ones focus on 
why systems go down in the first place."

Now generate hooks for this episode:
{transcript}

Model Configuration

Fine-tune AI behavior with model parameters.

Temperature

Controls creativity vs consistency:
// Temperature scale: 0.0 - 1.0

const configs = {
  factual: { temperature: 0.2 },     // PRF, fact-check
  balanced: { temperature: 0.7 },    // Social posts, hooks
  creative: { temperature: 0.9 }     // Visual specs, titles
}
Use for: Fact-heavy content
  • PRF documents
  • Fact-checking
  • Metadata generation
  • Spell checking
Characteristics:
  • Deterministic output
  • Conservative language
  • High factual accuracy
  • Low variability

Token Limits

Manage context window usage:
// Context windows by model
const LIMITS = {
  'claude-3.5-sonnet': 200_000,
  'claude-3-opus': 200_000,
  'gpt-4-turbo': 128_000,
  'gpt-4o-mini': 128_000
}

// Truncate transcript if needed
if (transcript.length > 10_000) {
  const truncated = transcript.slice(0, 10_000)
  const warning = '\n\n[...transcript truncated for context window...]'
  transcript = truncated + warning
}
Long transcripts (60+ min episodes) may exceed token limits. The system automatically truncates with a warning, but quality may suffer. Consider splitting very long episodes.

Performance Optimization

Streaming Responses

Real-time progress via Server-Sent Events:
// Backend streams progress
for await (const chunk of stream) {
  sendSSE({
    type: 'progress',
    step: 'generating',
    detail: 'Analyzing key themes...',
    progress: 45
  })
}

// Frontend updates UI in real-time
eventSource.onmessage = (event) => {
  const { step, detail, progress } = JSON.parse(event.data)
  updateProgressBar(progress)
  updateStatus(detail)
}

Parallel Generation

Multiple AI calls simultaneously:
// Instead of sequential:
const prf = await generatePRF(transcript)
const hooks = await generateHooks(prf)
const posts = await generatePosts(prf, hooks)
// Total time: 90 seconds

// Parallel where possible:
const [dataviz, cinematic, quotes] = await Promise.all([
  generateDataViz(prf, hooks),
  generateCinematic(prf, hooks),
  generateQuoteCards(hooks)
])
// Total time: 45 seconds (vs 135 sequential)

Caching (Future)

Planned optimization for repeated content:
// Cache transcript embeddings
const embeddingKey = `transcript:${episodeId}`
const cached = await cache.get(embeddingKey)

if (cached) {
  return cached
} else {
  const embedding = await embed(transcript)
  await cache.set(embeddingKey, embedding, { ttl: 86400 })
  return embedding
}

Troubleshooting

”AI generated incorrect facts”

Solution: Run fact-check before approving
// Enable fact-check in agent config
agent.factCheckEnabled = true

// Or run manually
const result = await factCheckContent(...)
if (!result.passedValidation) {
  showWarning(result.criticalIssues)
}

”Content doesn’t match brand voice”

Solution: Review and customize system prompt
  1. Go to Settings > Agents
  2. Select agent (e.g., “Hooks”)
  3. Edit system prompt with specific voice examples
  4. Test with regeneration

”Generation takes too long”

Solution: Switch to faster model or reduce content
// Faster model
agent.model = 'gpt-4o-mini'  // vs 'claude-3-opus'

// Reduce transcript length
const truncated = transcript.slice(0, 5000)  // First 5000 chars

”Repeated suggestions across episodes”

Solution: Enable variety tracking
// Include generation history in prompt
const history = await getRecentLayouts(10)  // Last 10 episodes

const prompt = `
Avoid these recently used layouts:
${history.join(', ')}

Prefer fresh patterns from the design database.
`

Build docs developers (and LLMs) love