Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/darkzOGx/youtube-automation-agent/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The YouTube Automation Agent is built with extensibility in mind. You can customize agents, add new content types, modify workflows, and integrate custom services.

Custom Agent Development

Creating a Custom Agent

All agents follow a consistent pattern. Here’s how to create your own:
agents/custom-agent.js
const { Logger } = require('../utils/logger');

class CustomAgent {
  constructor(db, credentials) {
    this.db = db;
    this.credentials = credentials;
    this.logger = new Logger('CustomAgent');
  }

  async initialize() {
    this.logger.info('Initializing Custom Agent...');
    // Load any required data or setup connections
    return true;
  }

  async performTask(input) {
    try {
      this.logger.info('Starting custom task...');
      
      // Your custom logic here
      const result = await this.processInput(input);
      
      // Save results to database
      await this.db.saveCustomData(result);
      
      this.logger.success('Custom task completed');
      return result;
    } catch (error) {
      this.logger.error('Custom task failed:', error);
      throw error;
    }
  }

  async processInput(input) {
    // Implement your custom processing logic
    return { processed: true, data: input };
  }
}

module.exports = { CustomAgent };

Integrating the Agent

Add your agent to the main application in index.js:69-84:
index.js
const { CustomAgent } = require('./agents/custom-agent');

async initializeAgents() {
  this.agents = {
    strategy: new ContentStrategyAgent(this.db, this.credentials),
    scriptWriter: new ScriptWriterAgent(this.db, this.credentials),
    thumbnailDesigner: new ThumbnailDesignerAgent(this.db, this.credentials),
    seoOptimizer: new SEOOptimizerAgent(this.db, this.credentials),
    production: new ProductionManagementAgent(this.db, this.credentials),
    publishing: new PublishingSchedulingAgent(this.db, this.credentials),
    analytics: new AnalyticsOptimizationAgent(this.db, this.credentials),
    custom: new CustomAgent(this.db, this.credentials) // Add your agent
  };

  for (const [name, agent] of Object.entries(this.agents)) {
    await agent.initialize();
    this.logger.info(`✓ ${name} agent initialized`);
  }
}

Custom Content Pipeline

Modifying the Generation Workflow

The content generation pipeline is defined in index.js:149-186. You can customize it:
async generateContent(topic = null, style = null, length = 'medium') {
  this.logger.info('Starting custom content generation pipeline...');
  
  // Step 1: Strategy
  const strategy = await this.agents.strategy.generateContentStrategy(topic);
  
  // Step 2: Script Writing
  const script = await this.agents.scriptWriter.generateScript(strategy);
  
  // Step 3: Add your custom processing
  const customData = await this.agents.custom.processScript(script);
  
  // Step 4: Thumbnail Design
  const thumbnail = await this.agents.thumbnailDesigner.generateThumbnail(script);
  
  // Step 5: SEO Optimization
  const seoData = await this.agents.seoOptimizer.optimize(script, strategy);
  
  // Step 6: Production Management
  const productionData = await this.agents.production.processContent({
    strategy,
    script,
    thumbnail,
    seo: seoData,
    custom: customData // Include custom data
  });
  
  // Step 7: Save to database
  const contentId = await this.db.saveProductionData(productionData);
  
  return {
    contentId,
    title: script.title,
    scheduledFor: productionData.scheduledPublishTime,
    customData
  };
}

Custom Scheduled Tasks

Adding New Automation Tasks

Extend the scheduler in schedules/daily-automation.js:25-84:
async setupScheduledTasks() {
  // Existing tasks...
  
  // Add your custom scheduled task
  this.scheduledTasks.set('custom-hourly-task',
    cron.schedule('0 * * * *', async () => {
      if (this.isEnabled) {
        await this.runCustomTask();
      }
    }, { scheduled: false })
  );

  // Start all scheduled tasks
  this.scheduledTasks.forEach((task, name) => {
    task.start();
    this.logger.info(`Started scheduled task: ${name}`);
  });
}

async runCustomTask() {
  try {
    this.logger.info('Running custom scheduled task...');
    
    // Your custom logic here
    const result = await this.performCustomOperation();
    
    await this.logAutomationEvent('custom_task', 'success', {
      result
    });
    
  } catch (error) {
    this.logger.error('Custom task failed:', error);
    
    await this.logAutomationEvent('custom_task', 'error', {
      error: error.message
    });
  }
}
Cron syntax: minute hour day month weekday
  • 0 6 * * * - Daily at 6:00 AM
  • */15 * * * * - Every 15 minutes
  • 0 8 * * 0 - Sundays at 8:00 AM

Custom Logger Configuration

Creating Specialized Loggers

The logging system (from utils/logger.js:90-101) supports custom loggers:
const { Logger } = require('./utils/logger');

// Create specialized loggers for different components
const apiLogger = Logger.createAPILogger();
const systemLogger = Logger.createSystemLogger();
const customLogger = Logger.createAgentLogger('MyCustomComponent');

// Use structured logging for events
customLogger.logEvent('custom_event', {
  userId: 'user123',
  action: 'processed_video',
  duration: 1500
});

// Log with performance timing
const timer = customLogger.startTimer('Video Processing');
// ... do work ...
timer.end(); // Logs: "Video Processing completed in Xms"

// Log errors with context
customLogger.logErrorWithContext(error, {
  videoId: 'vid123',
  stage: 'thumbnail_generation',
  retryCount: 2
});

Custom Log Transports

Extend logging to external services:
const winston = require('winston');
const { Logger } = require('./utils/logger');

class CustomLogger extends Logger {
  createWinstonLogger() {
    const baseLogger = super.createWinstonLogger();
    
    // Add custom transport (e.g., send to external service)
    baseLogger.add(new winston.transports.Http({
      host: 'logging.example.com',
      port: 8080,
      path: '/logs'
    }));
    
    return baseLogger;
  }
}

Environment Configuration

Custom Environment Variables

Add custom settings to .env:
.env
# Custom AI Model Settings
CUSTOM_AI_MODEL=gpt-4-turbo-preview
CUSTOM_AI_TEMPERATURE=0.7
CUSTOM_MAX_TOKENS=2000

# Custom Content Settings
CUSTOM_VIDEO_LENGTH=10-15
CUSTOM_THUMBNAIL_STYLE=minimalist
CUSTOM_CONTENT_TONE=professional

# Custom Integration Keys
CUSTOM_WEBHOOK_URL=https://example.com/webhook
CUSTOM_ANALYTICS_KEY=your-analytics-key
Access them in your code:
const customModel = process.env.CUSTOM_AI_MODEL || 'gpt-4';
const temperature = parseFloat(process.env.CUSTOM_AI_TEMPERATURE) || 0.7;
const webhookUrl = process.env.CUSTOM_WEBHOOK_URL;

if (webhookUrl) {
  await sendWebhook(webhookUrl, data);
}

Database Extensions

Adding Custom Tables

Extend the database schema in database/db.js:34-195:
async createCustomTables() {
  const customTables = [
    `CREATE TABLE IF NOT EXISTS custom_data (
      id TEXT PRIMARY KEY,
      content_id TEXT NOT NULL,
      custom_field_1 TEXT,
      custom_field_2 INTEGER,
      metadata TEXT,
      created_at TEXT DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (content_id) REFERENCES productions(id)
    )`
  ];

  for (const tableQuery of customTables) {
    await this.executeQuery(tableQuery);
  }
}

// Add custom methods
async saveCustomData(data) {
  const id = this.generateId('custom');
  await this.executeQuery(
    `INSERT INTO custom_data (
      id, content_id, custom_field_1, custom_field_2, metadata
    ) VALUES (?, ?, ?, ?, ?)`,
    [
      id,
      data.contentId,
      data.field1,
      data.field2,
      JSON.stringify(data.metadata)
    ]
  );
  return id;
}

async getCustomData(contentId) {
  return await this.getRow(
    'SELECT * FROM custom_data WHERE content_id = ?',
    [contentId]
  );
}

API Endpoint Customization

Adding Custom Routes

Extend the Express API in index.js:87-147:
setupAPI() {
  this.app.use(express.json());
  this.app.use(express.static(path.join(__dirname, 'dashboard')));
  
  // Existing routes...
  
  // Add custom endpoint
  this.app.post('/api/custom/process', async (req, res) => {
    try {
      const { input } = req.body;
      const result = await this.agents.custom.performTask(input);
      res.json({ success: true, result });
    } catch (error) {
      res.status(500).json({ success: false, error: error.message });
    }
  });
  
  // Custom analytics endpoint
  this.app.get('/api/custom/metrics', async (req, res) => {
    try {
      const metrics = await this.getCustomMetrics();
      res.json(metrics);
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  });
  
  // Webhook receiver
  this.app.post('/webhook/:service', async (req, res) => {
    try {
      const { service } = req.params;
      await this.handleWebhook(service, req.body);
      res.json({ received: true });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  });
}
agents/brand-voice-agent.js
const { Logger } = require('../utils/logger');
const { Configuration, OpenAIApi } = require('openai');

/**
 * Brand Voice Agent
 * Ensures all content matches specific brand guidelines and tone
 */
class BrandVoiceAgent {
  constructor(db, credentials) {
    this.db = db;
    this.credentials = credentials;
    this.logger = new Logger('BrandVoice');
    this.brandGuidelines = null;
  }

  async initialize() {
    this.logger.info('Initializing Brand Voice Agent...');
    
    // Load brand guidelines from database or config
    this.brandGuidelines = await this.loadBrandGuidelines();
    
    // Initialize OpenAI client
    const configuration = new Configuration({
      apiKey: this.credentials.credentials.openai.apiKey,
    });
    this.openai = new OpenAIApi(configuration);
    
    return true;
  }

  async loadBrandGuidelines() {
    return {
      tone: process.env.BRAND_TONE || 'professional and friendly',
      vocabulary: {
        preferred: ['innovative', 'efficient', 'streamlined'],
        avoid: ['cheap', 'basic', 'simple']
      },
      style: {
        sentenceLength: 'short to medium',
        paragraphLength: '2-3 sentences',
        activeVoice: true
      }
    };
  }

  async reviewScript(script) {
    try {
      this.logger.info(`Reviewing script for brand voice: ${script.title}`);
      
      const fullText = this.extractScriptText(script);
      const analysis = await this.analyzeBrandAlignment(fullText);
      
      if (analysis.score < 80) {
        this.logger.warn(`Brand alignment score low: ${analysis.score}/100`);
        const improved = await this.improveAlignment(fullText, analysis);
        return { ...script, improved, brandScore: analysis.score };
      }
      
      this.logger.success('Brand voice alignment verified');
      return { ...script, brandScore: analysis.score };
    } catch (error) {
      this.logger.error('Brand voice review failed:', error);
      throw error;
    }
  }

  extractScriptText(script) {
    let text = script.title + '\n\n';
    text += script.hook.text + '\n\n';
    text += script.introduction.greeting + ' ';
    text += script.introduction.topicIntro + '\n\n';
    
    script.mainContent.sections.forEach(section => {
      if (Array.isArray(section.content)) {
        text += section.content.join(' ') + '\n\n';
      } else {
        text += section.content + '\n\n';
      }
    });
    
    return text;
  }

  async analyzeBrandAlignment(text) {
    const prompt = `Analyze the following text for brand voice alignment.

Brand Guidelines:
- Tone: ${this.brandGuidelines.tone}
- Preferred vocabulary: ${this.brandGuidelines.vocabulary.preferred.join(', ')}
- Words to avoid: ${this.brandGuidelines.vocabulary.avoid.join(', ')}

Text to analyze:
${text}

Provide a score (0-100) and specific feedback.`;

    const response = await this.openai.createChatCompletion({
      model: this.credentials.credentials.openai.model,
      messages: [{ role: 'user', content: prompt }],
      temperature: 0.3
    });

    // Parse AI response for score and feedback
    return {
      score: 85, // Extracted from response
      feedback: response.data.choices[0].message.content
    };
  }

  async improveAlignment(text, analysis) {
    // Use AI to improve brand alignment
    const prompt = `Rewrite the following text to better align with these brand guidelines:
${JSON.stringify(this.brandGuidelines, null, 2)}

Original text:
${text}

Provide improved version.`;

    const response = await this.openai.createChatCompletion({
      model: this.credentials.credentials.openai.model,
      messages: [{ role: 'user', content: prompt }],
      temperature: 0.5
    });

    return response.data.choices[0].message.content;
  }
}

module.exports = { BrandVoiceAgent };
When extending the system:
  • Always use the Logger class for consistent logging
  • Follow the existing error handling patterns
  • Use database transactions for multi-step operations
  • Validate inputs before processing
  • Add appropriate try-catch blocks

Next Steps

Custom Content Types

Learn how to add new content formats

Multiple Channels

Manage multiple YouTube channels

Build docs developers (and LLMs) love