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 inindex.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 inindex.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 inschedules/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 weekday0 6 * * *- Daily at 6:00 AM*/15 * * * *- Every 15 minutes0 8 * * 0- Sundays at 8:00 AM
Custom Logger Configuration
Creating Specialized Loggers
The logging system (fromutils/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
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 indatabase/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 inindex.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 });
}
});
}
Complete Custom Agent Example
Complete Custom Agent Example
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