Complete AI Course Generation Workflow

This document describes the end-to-end execution flow when generating a complete course using the AI system.

High-Level Overview

Admin UI → API Gateway → Step Functions State Machine
                              │
              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
         Validate      Generate Content   Save & Store
              │               │               │
              └───────────────┴───────────────┘
                              ▼
                    Course Ready (DRAFT)

Execution Order

The AI workflow consists of 22 sequential steps orchestrated by AWS Step Functions (EXPRESS type):

Step Handler Status Progress Duration
1 validate-input VALIDATING 5% ~5-30s
2 Choice: Check validation - - instant
3 save-course (updateStatus) GENERATING_OUTLINE 10% instant
4 generate-outline GENERATING_OUTLINE 30% ~30-60s
5 save-course (updateStatus) GENERATING_LESSONS 40% instant
6 generate-lesson-prompts GENERATING_LESSONS 40-70% ~5-15s per day
7 Choice: Video flag - - instant
8 save-course (updateStatus) GENERATING_VIDEO 70% instant
9 trigger-video GENERATING_VIDEO 70% ~10-20s
10 save-course (updateStatus) SAVING 90% instant
11 save-course (saveCourse) SAVING 90% ~5-15s
12 generate-thumbnail SAVING 90% ~30-60s
13 Choice: Thumbnail success - - instant
14 update-course-thumbnail SAVING 92% instant
15 Choice: Video polling - - instant
16 Wait (60s) - - 60s
17 poll-video-status SAVING 95% ~10-30s
18 Choice: Video status - - instant
19 copy-video-to-s3 SAVING 98% ~30-120s
20 update-course-video SAVING 100% instant
21 Mark video failed (if error) - - instant
22 Success COMPLETED 100% -

Detailed Step-by-Step Workflow

Phase 1: Entry & Validation

Step 1: API Entry Point

File: backend/functions/ai-generation/src/handlers/start-generation.ts

The workflow begins when an admin calls POST /ai-generation/start:

// Request body
{
  courseInput: {
    title: string;
    category_id: string;
    duration_days: 7 | 14 | 21;
    targetAudience?: string;
    difficultyLevel?: 'beginner' | 'intermediate' | 'advanced';
    learningObjectives?: string[];
    tone?: 'professional' | 'friendly' | 'academic';
  },
  options?: {
    generateVideo?: boolean;  // Trigger HeyGen video rendering
    avatarId?: string;        // HeyGen avatar ID
  }
}

Actions:

  1. Validates request body
  2. Creates course_generation_jobs record (status: PENDING)
  3. Handles PDF upload if provided (S3 presigned URL or base64)
  4. Triggers Step Functions state machine
  5. Returns jobId for status polling

Step 2: Validate Input

File: backend/functions/ai-generation/src/handlers/validate-input.ts

Lambda Config: 30s timeout, 256MB memory

Actions:

  1. Validates course input fields (title, category, duration, difficulty, tone)
  2. Estimates total tokens for entire workflow:
    • Course outline: ~2000 tokens
    • Lesson prompts: ~500 tokens × duration_days
    • Video script: ~300 tokens
  3. Calculates estimated cost (USD)
  4. Updates job status to VALIDATING (progress: 5%)

Output:

{
  jobId: string;
  isValid: boolean;
  validationErrors: string[];
  estimatedTokens: number;
  estimatedCost: number;
}

Phase 2: Content Generation

Step 3: Generate Course Outline

File: backend/functions/ai-generation/src/handlers/generate-outline.ts

Lambda Config: 120s timeout, 512MB memory

Prompt Template: prompts/templates/course-outline.md

Bedrock Config:

  • Model: anthropic.claude-3-sonnet-20240229-v1:0
  • Max tokens: 2000
  • Temperature: 0.7

Actions:

  1. Loads prompt template with `` placeholders
  2. Interpolates with course input data
  3. If PDF reference provided, uses invokeClaudeWithPdf()
  4. Calls Bedrock Claude model
  5. Parses and validates JSON response
  6. Updates progress to 30%

Output (CourseOutline):

{
  "title": "Refined course title",
  "description": "300-500 word description",
  "whatYouWillLearn": ["4-6 learning outcomes"],
  "requirements": ["3-5 prerequisites"],
  "instructor": {
    "name": "Realistic instructor name",
    "title": "Professional title",
    "avatar": "JD"
  },
  "curriculum": [
    {
      "week": "Week 1: [Theme]",
      "lessonsPreview": ["Day 1: ...", "Day 2: ...", "..."]
    }
  ]
}

Step 4: Generate Lesson Prompts

File: backend/functions/ai-generation/src/handlers/generate-lesson-prompts.ts

Lambda Config: 120s timeout, 512MB memory

Prompt Template: prompts/templates/lesson-prompt.md

Actions (loops for each day):

  1. For each day from 1 to duration_days:
    • Calculate week number: Math.ceil(day / 7)
    • Calculate day-in-week: ((day - 1) % 7) + 1
    • Determine progress: beginning middle end
  2. Build lesson prompt with course context
  3. Call Bedrock Claude for each lesson
  4. Parse into LessonPrompt structure
  5. Update progress: 40 + Math.round((day / totalDays) * 30)

Output per Lesson:

{
  day: number;
  title: string;
  duration: number;  // minutes (10-30)
  generationPrompt: string;  // Detailed prompt for content generation
  actionItemsHint: string;
  keyTakeawaysHint: string;
}

Phase 3: Video Generation

Step 5: Trigger Video Generation

File: backend/functions/ai-generation/src/handlers/trigger-video.ts

Lambda Config: 60s timeout, 256MB memory

Prompt Template: prompts/templates/video-script.md

Actions:

  1. Always: Generate intro video script via Bedrock
    • Script length: ~1300-1500 words
    • Duration: ~10-minute narration
    • Structure: Hook → Objective → Concept → Deep Explanation → Example → Common Mistakes → Practice Prompt
  2. If generateVideo: true: Trigger HeyGen API
    • Endpoint: POST /v1/video_generators
    • Returns video_id for status polling

Output:

{
  status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'SKIPPED';
  script: string | null;
  videoId: string | null;  // HeyGen video_id
  estimatedCompletionSeconds?: number;
}

Phase 4: Persistence

Step 6: Save Course to Database

File: backend/functions/ai-generation/src/handlers/save-course.ts

Lambda Config: 30s timeout, 256MB memory

Actions (within database transaction):

  1. Calculate quality score (0-1):
    • Outline completeness: 60% weight
    • Lessons completeness: 40% weight
  2. Create courses record:
    • Status: DRAFT
    • ai_generated: true
    • Store CourseOutline in metadata (JSONB)
    • Store video script in intro_video_script
  3. Create lessons records (one per day):
    • Store generation_prompt for later content generation
    • Store hints in metadata
  4. Link PDF references to course (if provided)

Database Tables Updated:

  • courses (1 record)
  • lessons (N records, where N = duration_days)
  • pdf_reference_documents (links to course)
  • course_generation_jobs (status update)

Step 7: Generate Thumbnail

File: backend/functions/ai-generation/src/handlers/generate-thumbnail.ts

Lambda Config: 90s timeout, 512MB memory

Prompt Template: prompts/templates/thumbnail-prompt.md

Bedrock Config:

  • Model: stability.sd3-5-large-v1:0
  • Region: us-west-2 (model availability)
  • Output: 512x512 PNG

Actions:

  1. Build image prompt from course metadata
  2. Call Bedrock Stable Diffusion
  3. Upload to S3: thumbnails/{courseId}-{timestamp}.png
  4. Generate presigned URL (24-hour expiration)

Phase 5: Video Processing (Optional)

Step 8: Poll Video Status

File: backend/functions/ai-generation/src/handlers/poll-video-status.ts

Lambda Config: 30s timeout, 256MB memory

Only executes if videoId exists from Step 5.

Polling Loop:

  1. Call HeyGen API: GET /v1/video_generators/{videoId}
  2. Check status:
    • processing → Wait 30s, retry (max 20 attempts)
    • completed → Proceed to download
    • failed → Mark as failed, continue workflow

Step 9: Copy Video to S3

File: backend/functions/ai-generation/src/handlers/copy-video-to-s3.ts

Lambda Config: 300s timeout, 1024MB memory

Actions:

  1. Download video from HeyGen URL
  2. Upload to S3: course-videos/{courseId}/{videoId}.mp4
  3. Set lifecycle policies

Step 10: Update Course with Video

File: backend/functions/ai-generation/src/handlers/update-course-video.ts

Updates courses table:

  • intro_video_url: S3 URL
  • intro_video_status: COMPLETED

Visual Flow Diagram

┌─────────────────────────────────────────────────────────────────────────────┐
│                              ADMIN UI                                        │
│                         POST /ai-generation/start                            │
└─────────────────────────────────────────────────────────────────────────────┘
                                     │
                                     ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                          start-generation.ts                                 │
│   • Validate request • Create job record • Handle PDF • Trigger Step Func   │
└─────────────────────────────────────────────────────────────────────────────┘
                                     │
                                     ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                       STEP FUNCTIONS STATE MACHINE                           │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ┌──────────────┐    ┌──────────────────┐    ┌─────────────────────────┐   │
│  │   VALIDATE   │───▶│ GENERATE OUTLINE │───▶│  GENERATE LESSON PROMPTS│   │
│  │   INPUT      │    │                  │    │      (loop: N days)     │   │
│  │   5%         │    │   10-30%         │    │       40-70%            │   │
│  └──────────────┘    └──────────────────┘    └─────────────────────────┘   │
│         │                    │                          │                   │
│         │              Bedrock Claude             Bedrock Claude            │
│         │                    │                    (N API calls)             │
│         ▼                    ▼                          ▼                   │
│  ┌──────────────────────────────────────────────────────────────────────┐  │
│  │                      TRIGGER VIDEO GENERATION                         │  │
│  │              • Generate video script (Bedrock Claude)                 │  │
│  │              • Trigger HeyGen (if generateVideo: true)                │  │
│  │                            70%                                        │  │
│  └──────────────────────────────────────────────────────────────────────┘  │
│                                     │                                       │
│                                     ▼                                       │
│  ┌──────────────────────────────────────────────────────────────────────┐  │
│  │                         SAVE TO DATABASE                              │  │
│  │        • Create course record • Create lesson records (N)             │  │
│  │        • Link PDFs • Calculate quality score                          │  │
│  │                            90%                                        │  │
│  └──────────────────────────────────────────────────────────────────────┘  │
│                                     │                                       │
│                    ┌────────────────┴────────────────┐                     │
│                    ▼                                 ▼                      │
│  ┌──────────────────────────┐      ┌────────────────────────────────────┐  │
│  │   GENERATE THUMBNAIL     │      │        VIDEO POLLING (optional)    │  │
│  │   Bedrock Stable Diff    │      │   • Wait 60s                       │  │
│  │   Upload to S3           │      │   • Poll HeyGen (max 20 attempts)  │  │
│  └──────────────────────────┘      │   • Download & copy to S3          │  │
│                    │               └────────────────────────────────────┘  │
│                    │                                 │                      │
│                    └────────────────┬────────────────┘                     │
│                                     ▼                                       │
│  ┌──────────────────────────────────────────────────────────────────────┐  │
│  │                         GENERATION COMPLETE                           │  │
│  │                    Job status: COMPLETED (100%)                       │  │
│  └──────────────────────────────────────────────────────────────────────┘  │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
                                     │
                                     ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                              DATABASE                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│  course_generation_jobs: Job tracking, progress, tokens, cost               │
│  courses: Course record (DRAFT), metadata, video script                     │
│  lessons: N lesson records with generation_prompts                          │
│  pdf_reference_documents: Linked PDFs                                       │
└─────────────────────────────────────────────────────────────────────────────┘
                                     │
                                     ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                                 S3                                           │
├─────────────────────────────────────────────────────────────────────────────┤
│  thumbnails/{courseId}-{timestamp}.png                                      │
│  course-videos/{courseId}/{videoId}.mp4 (if video generated)                │
└─────────────────────────────────────────────────────────────────────────────┘

What Gets Generated vs. What Needs Manual Completion

Generated Automatically

Content Storage Status
Course title & description courses.title, courses.description Ready
Learning outcomes courses.metadata.whatYouWillLearn Ready
Requirements courses.metadata.requirements Ready
Instructor info courses.metadata.instructor Ready
Curriculum overview courses.metadata.curriculum Ready
Lesson titles lessons.title Ready
Lesson generation prompts lessons.generation_prompt Ready
Intro video script courses.intro_video_script Ready
Intro video (optional) courses.intro_video_url Ready (if enabled)
Course thumbnail courses.thumbnail Ready

Requires Separate Generation (Post-Course Creation)

Content How to Generate
Full lesson content Use lesson.generation_prompt with lesson-content.md template
Lesson video scripts Generate via separate endpoint/workflow
Lesson videos Trigger HeyGen for each lesson
Quiz questions Use quiz generation prompts

The initial workflow creates the course structure and generation prompts. Full lesson content is generated on-demand when users access lessons.


Timing Estimates

For a 7-Day Course

Phase Duration
Validation ~10s
Course Outline ~45s
Lesson Prompts (7×) ~60s
Video Script ~15s
Database Save ~10s
Thumbnail ~45s
Total (no video) ~3 minutes
Video Polling + Copy ~5-15 minutes
Total (with video) ~8-18 minutes

For a 21-Day Course

Phase Duration
Validation ~15s
Course Outline ~60s
Lesson Prompts (21×) ~3 minutes
Video Script ~15s
Database Save ~15s
Thumbnail ~45s
Total (no video) ~5 minutes
Video Polling + Copy ~5-15 minutes
Total (with video) ~10-20 minutes

Cost Estimation

Based on Claude 3 Sonnet pricing:

Course Duration Estimated Tokens Estimated Cost
7 days ~5,000-7,000 ~$0.15-0.25
14 days ~8,000-12,000 ~$0.25-0.40
21 days ~12,000-18,000 ~$0.35-0.55

Additional costs:

  • Thumbnail (Stable Diffusion): ~$0.04 per image
  • HeyGen video: Varies by plan (external service)

Error Handling

All errors are caught by Step Functions and handled by save-course.ts (action: handleError):

  1. Updates job status to FAILED
  2. Stores error message in course_generation_jobs.error_message
  3. Optionally sends SNS notification
  4. Workflow transitions to GenerationFailed state

Non-blocking failures (thumbnail, video) continue the workflow with partial results.


Monitoring

  • CloudWatch Logs: Each Lambda has dedicated log group
  • X-Ray Tracing: End-to-end request tracking
  • Status API: GET /ai-generation/status/{jobId} returns progress, tokens, cost

Key Files Reference

File Purpose
handlers/start-generation.ts API entry, job creation
handlers/validate-input.ts Validation, token estimation
handlers/generate-outline.ts Course structure generation
handlers/generate-lesson-prompts.ts Per-day lesson prompts
handlers/trigger-video.ts Video script + HeyGen trigger
handlers/save-course.ts Database transactions
handlers/generate-thumbnail.ts Image generation
handlers/poll-video-status.ts HeyGen polling
handlers/copy-video-to-s3.ts Video download/upload
prompts/templates/*.md All prompt templates
prompts/index.ts PROMPT_REGISTRY
services/bedrock-client.ts Claude model invocation
services/heygen-client.ts HeyGen API integration

Back to top

Momentum LMS © 2025. Distributed under the MIT license.