| 
 | 1 | +import { openai } from "@ai-sdk/openai";  | 
 | 2 | +import {  | 
 | 3 | +  Agent,  | 
 | 4 | +  MCPConfiguration,  | 
 | 5 | +  Memory,  | 
 | 6 | +  VoltAgent,  | 
 | 7 | +  VoltAgentObservability,  | 
 | 8 | +} from "@voltagent/core";  | 
 | 9 | +import { LibSQLMemoryAdapter, LibSQLObservabilityAdapter } from "@voltagent/libsql";  | 
 | 10 | +import { createPinoLogger } from "@voltagent/logger";  | 
 | 11 | +import { honoServer } from "@voltagent/server-hono";  | 
 | 12 | + | 
 | 13 | +// Create logger  | 
 | 14 | +const logger = createPinoLogger({  | 
 | 15 | +  name: "youtube-to-blog",  | 
 | 16 | +  level: "info",  | 
 | 17 | +});  | 
 | 18 | + | 
 | 19 | +// Create Memory instance with vector support for semantic search and working memory  | 
 | 20 | +const memory = new Memory({  | 
 | 21 | +  storage: new LibSQLMemoryAdapter({  | 
 | 22 | +    storageLimit: 100, // Keep last 100 messages per conversation  | 
 | 23 | +  }),  | 
 | 24 | +});  | 
 | 25 | + | 
 | 26 | +// Configure YouTube MCP with SSE transport  | 
 | 27 | +(async () => {  | 
 | 28 | +  const youtubeMcpConfig = new MCPConfiguration({  | 
 | 29 | +    servers: {  | 
 | 30 | +      youtube: {  | 
 | 31 | +        type: "http",  | 
 | 32 | +        url: process.env.YOUTUBE_MCP_URL || "",  | 
 | 33 | +      },  | 
 | 34 | +    },  | 
 | 35 | +  });  | 
 | 36 | + | 
 | 37 | +  // Get YouTube MCP tools  | 
 | 38 | +  const youtubeTools = await youtubeMcpConfig.getTools();  | 
 | 39 | + | 
 | 40 | +  // Create TranscriptFetcher subagent  | 
 | 41 | +  const transcriptFetcherAgent = new Agent({  | 
 | 42 | +    name: "TranscriptFetcher",  | 
 | 43 | +    instructions: `You are a transcript fetcher. Your ONLY job is to fetch transcripts from YouTube videos.  | 
 | 44 | +
  | 
 | 45 | +IMPORTANT:  | 
 | 46 | +- When given a YouTube URL, use your tools to extract the English transcript  | 
 | 47 | +- Return ONLY the raw transcript text  | 
 | 48 | +- DO NOT write blog posts  | 
 | 49 | +- DO NOT format the transcript into articles  | 
 | 50 | +- DO NOT add any additional content or commentary  | 
 | 51 | +- Just extract and return the transcript as-is`,  | 
 | 52 | +    model: openai("gpt-4o-mini"),  | 
 | 53 | +    tools: youtubeTools,  | 
 | 54 | +    memory,  | 
 | 55 | +  });  | 
 | 56 | + | 
 | 57 | +  // Create BlogWriter subagent  | 
 | 58 | +  const blogWriterAgent = new Agent({  | 
 | 59 | +    name: "BlogWriter",  | 
 | 60 | +    instructions: `You are an expert blog writer. When given a YouTube transcript, convert it into a well-structured, engaging blog post with:  | 
 | 61 | +- A catchy, SEO-friendly title  | 
 | 62 | +- An engaging introduction  | 
 | 63 | +- Clear sections with subheadings  | 
 | 64 | +- Key points and takeaways  | 
 | 65 | +- A compelling conclusion  | 
 | 66 | +Format the output in Markdown.`,  | 
 | 67 | +    model: openai("gpt-4o-mini"),  | 
 | 68 | +    memory,  | 
 | 69 | +  });  | 
 | 70 | + | 
 | 71 | +  // Create Coordinator supervisor agent  | 
 | 72 | +  const coordinatorAgent = new Agent({  | 
 | 73 | +    name: "YouTubeToBlogCoordinator",  | 
 | 74 | +    instructions: `You are a coordinator that orchestrates the process of converting YouTube videos to blog posts. You DO NOT write the blog post yourself - that is the BlogWriter's job.  | 
 | 75 | +
  | 
 | 76 | +IMPORTANT: You MUST follow these steps in EXACT ORDER:  | 
 | 77 | +
  | 
 | 78 | +STEP 1: Get the Transcript  | 
 | 79 | +- Delegate to the TranscriptFetcher agent with the YouTube URL  | 
 | 80 | +- WAIT for the TranscriptFetcher to complete and return the full transcript  | 
 | 81 | +- DO NOT proceed to Step 2 until you have the complete transcript  | 
 | 82 | +
  | 
 | 83 | +STEP 2: Generate the Blog Post  | 
 | 84 | +- After you have the COMPLETE transcript, delegate to the BlogWriter agent  | 
 | 85 | +- Pass the ENTIRE transcript to the BlogWriter  | 
 | 86 | +- DO NOT write the blog post yourself - let the BlogWriter do it  | 
 | 87 | +- WAIT for the BlogWriter to return the complete blog post  | 
 | 88 | +
  | 
 | 89 | +STEP 3: Return ONLY the Blog Post  | 
 | 90 | +- Return ONLY the blog post content that the BlogWriter created  | 
 | 91 | +- DO NOT add any additional commentary, explanations, or meta-information  | 
 | 92 | +- Just return the blog post as-is  | 
 | 93 | +
  | 
 | 94 | +CRITICAL RULES:  | 
 | 95 | +- Complete Step 1 entirely before starting Step 2  | 
 | 96 | +- You are ONLY a coordinator - BlogWriter creates the blog post, NOT you  | 
 | 97 | +- Your final response should be ONLY the blog post content from BlogWriter`,  | 
 | 98 | +    model: openai("gpt-4o-mini"),  | 
 | 99 | +    memory,  | 
 | 100 | +    subAgents: [transcriptFetcherAgent, blogWriterAgent],  | 
 | 101 | +    supervisorConfig: {  | 
 | 102 | +      fullStreamEventForwarding: {  | 
 | 103 | +        types: ["tool-call", "tool-result"],  | 
 | 104 | +      },  | 
 | 105 | +    },  | 
 | 106 | +  });  | 
 | 107 | + | 
 | 108 | +  new VoltAgent({  | 
 | 109 | +    agents: {  | 
 | 110 | +      coordinatorAgent,  | 
 | 111 | +      transcriptFetcherAgent,  | 
 | 112 | +      blogWriterAgent,  | 
 | 113 | +    },  | 
 | 114 | +    server: honoServer(),  | 
 | 115 | +    logger,  | 
 | 116 | +    observability: new VoltAgentObservability({  | 
 | 117 | +      storage: new LibSQLObservabilityAdapter(),  | 
 | 118 | +    }),  | 
 | 119 | +  });  | 
 | 120 | +})(); // IGNORE  | 
0 commit comments