Reel Coach

Reel Coach generates production-ready short-form video scripts (TikTok / Reels / YouTube Shorts) from your note library. The AI retrieves relevant notes, produces a shot-by-shot script with timing, then annotates the draft with "Coach Notes" that explain why each section works and cite the exact source-note sentences that informed them. After generation, you can refine the draft inline and persist it as a Filmwork project.

Flow overview

StepActionCostEndpoint
1Generate script1-2 creditsPOST /api/chat/stream with activeTool: "reel_coach"
2aGet refine suggestions (optional)1 creditPOST /api/filmwork/coach/refine-suggestions
2bRefine draft (optional)1 creditPOST /api/filmwork/coach/refine (SSE stream)
3Persist as Filmwork project0 creditsPOST /api/filmwork/director/persist

Step 1: Generate script

Send a chat stream request with activeTool: "reel_coach". The backend runs two parallel Qdrant searches (breakdown notes + supporting notes), merges with pinned notes, then streams a JSON draft followed by Coach Notes annotations.

Request
curl -N https://narrativelion.com/api/chat/stream \
  -H "Authorization: Bearer nlk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "threadId": "your-thread-uuid",
    "actionId": "unique-action-uuid",
    "event": {
      "type": "user_text",
      "payload": {
        "text": "Create a reel about productivity tips",
        "activeTool": "reel_coach",
        "reelCoachTopic": "Productivity tips from my notes",
        "reelCoachTargetDurationSec": 30,
        "reelCoachPinnedNoteIds": ["note-uuid-1", "note-uuid-2"],
        "reelCoachAutoRetrieve": true
      }
    }
  }'

Payload fields

NameTypeRequiredDescription
activeTool"reel_coach"RequiredMust be "reel_coach" to trigger the Reel Coach pipeline.
reelCoachTopicstringOptionalTopic / creative brief (max 2000 chars). Falls back to the text field if omitted.
reelCoachTargetDurationSecnumberOptionalTarget video duration in seconds. Max 120, default 30.
reelCoachPinnedNoteIdsstring[]OptionalNote IDs to always include as sources (max 20). Breakdown notes are prioritized.
reelCoachAutoRetrievebooleanOptionalWhether to auto-retrieve relevant notes via semantic search. Default true.

SSE response

The stream emits token events with the draft content, then a complete event containing the structured artifacts.

SSE complete event
event: complete
data: {
  "finalMessage": "...",
  "artifacts": {
    "reelCoachSetup": {
      "topic": "Productivity tips from my notes",
      "targetDurationSec": 30,
      "pinnedNoteIds": ["note-uuid-1", "note-uuid-2"],
      "autoRetrieve": true
    },
    "reelCoachAnnotations": [
      {
        "draftExcerpt": "Start with the hardest task...",
        "rationale": "Opens with a counterintuitive hook that challenges common advice",
        "confidence": 0.85,
        "references": [
          {
            "noteId": "note-uuid-1",
            "noteTitle": "Deep Work Summary",
            "confidence": 0.9,
            "mode": "quote",
            "quotedSentences": ["The key to productivity is starting with your hardest task."]
          }
        ]
      }
    ],
    "reelCoachStats": {
      "totalBreakdownCount": 5,
      "usedSourceCount": 3,
      "validatedQuoteCount": 7
    }
  }
}

Artifact fields

ArtifactDescription
reelCoachSetupThe resolved setup parameters used for generation. Pass this back for refine/persist calls.
reelCoachAnnotationsCoach Notes: annotation items with draft excerpts, rationale, and validated source quotes. Items below 0.65 confidence are filtered out.
reelCoachStatsStats: total breakdown notes in library, notes actually used, and validated quote count.

Draft structure

The streamed draft content (from token events) is a JSON object with the following structure. Parse it from finalMessage in the complete event.

Draft JSON
{
  "shots": [
    {
      "title": "Hook — Start with the hardest task",
      "durationSec": 5,
      "script": "You've been doing productivity wrong. Here's why."
    },
    {
      "title": "Core insight — Deep work blocks",
      "durationSec": 10,
      "script": "Block your first 2 hours for deep work. No meetings, no email."
    },
    {
      "title": "CTA — Try it tomorrow",
      "durationSec": 5,
      "script": "Try this tomorrow morning. Save this for the reminder."
    }
  ],
  "coachOverview": "A punchy 20s reel using the eat-the-frog framework...",
  "sourceRelevance": [
    { "noteTitle": "Deep Work Summary", "relevanceScore": 0.92 },
    { "noteTitle": "Morning Routine", "relevanceScore": 0.75 }
  ]
}

Draft fields

NameTypeRequiredDescription
shotsShot[]RequiredArray of shots. Each has title (string), durationSec (number), and script (string).
coachOverviewstringRequiredAI summary of the draft strategy and how sources were used.
sourceRelevancearrayRequiredPer-source relevance scores: { noteTitle, relevanceScore (0-1) }.

Step 2a: Get refine suggestions (optional)

Generate AI suggestions for improving the draft. Returns 2 suggestion chips the user can pick from.

Request
curl -X POST https://narrativelion.com/api/filmwork/coach/refine-suggestions \
  -H "Authorization: Bearer nlk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "draft": "<the streamed draft text>",
    "setup": {
      "topic": "Productivity tips from my notes",
      "targetDurationSec": 30,
      "pinnedNoteIds": [],
      "autoRetrieve": true
    }
  }'
NameTypeRequiredDescription
draftstringRequiredCurrent draft text (max 50,000 chars).
setupobjectRequiredThe reelCoachSetup object from the generate step.
Response
{
  "suggestions": [
    { "label": "Add emotional hook", "prompt": "Add a personal story opening..." },
    { "label": "Tighten pacing", "prompt": "Cut each shot to under 5 seconds..." }
  ]
}

Step 2b: Refine draft (optional)

Stream a revised draft based on a refinement instruction. Returns SSE token events with the revised content. Does not persist anything.

Request
curl -N -X POST https://narrativelion.com/api/filmwork/coach/refine \
  -H "Authorization: Bearer nlk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "currentDraft": "<the current draft text>",
    "setup": {
      "topic": "Productivity tips from my notes",
      "targetDurationSec": 30,
      "pinnedNoteIds": [],
      "autoRetrieve": true
    },
    "refinementPrompt": "Make the hook more dramatic and shorten to 20 seconds",
    "pinnedNoteIds": ["note-uuid-1"]
  }'
NameTypeRequiredDescription
currentDraftstringRequiredCurrent draft text.
setupobjectRequiredThe reelCoachSetup object from the generate step.
refinementPromptstringRequiredWhat to change about the draft.
pinnedNoteIdsstring[]OptionalNote IDs to include as context for the refinement.
SSE event stream
event: token
data: {"content":"Revised draft content..."}

event: complete
data: {}

Step 3: Persist as Filmwork project

Save the finalized draft as a Filmwork note with shot records. Uses the same /api/filmwork/director/persist endpoint as Film Director, but with shots[] + setup instead of draftMarkdown.

Request
curl -X POST https://narrativelion.com/api/filmwork/director/persist \
  -H "Authorization: Bearer nlk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "shots": [
      { "title": "Hook", "durationSec": 5, "script": "You've been doing it wrong." },
      { "title": "Core insight", "durationSec": 10, "script": "Block your first 2 hours." },
      { "title": "CTA", "durationSec": 5, "script": "Try this tomorrow." }
    ],
    "setup": {
      "topic": "Productivity tips",
      "targetDurationSec": 20,
      "pinnedNoteIds": [],
      "autoRetrieve": true
    },
    "coachOverview": "A punchy 20s reel using the eat-the-frog framework."
  }'
NameTypeRequiredDescription
shotsShot[]RequiredArray of shots (min 1). Each has title, durationSec, and script.
setupobjectRequiredThe reelCoachSetup object from the generate step.
coachOverviewstringOptionalCoach overview text from the draft.
Response
{
  "noteId": "new-filmwork-note-uuid",
  "title": "Productivity tips"
}

The response returns the new Filmwork note ID. Use Filmwork GraphQL operations (see Filmwork docs) to manage shots, upload assets, and generate rolls.

Coach Notes (annotations)

After the draft streams, a second LLM pass produces annotation items that explain why specific draft excerpts work and cite exact source-note sentences. All quoted sentences are validated as exact substrings of the source note text. Items below 0.65 confidence are dropped.

AnnotationItem

NameTypeRequiredDescription
draftExcerptstringRequiredThe part of the draft this annotation refers to.
rationalestringRequiredWhy this section works or how it uses the source material.
confidencenumberRequiredConfidence score (0-1). Only items >= 0.65 are included.
referencesReference[]RequiredSource notes cited by this annotation.

Reference

NameTypeRequiredDescription
noteIdstringRequiredSource note ID.
noteTitlestringRequiredSource note title.
confidencenumberRequiredConfidence that this note informed the excerpt (0-1).
mode"quote"RequiredAlways "quote".
quotedSentencesstring[]RequiredExact sentences from the source note. Validated as substrings.

Important notes

  • Reel Coach uses the chat scope for generation and notes:read for refine/suggestions.
  • Persist uses notes:write (same as Film Director persist).
  • The generate step auto-retrieves notes via semantic search when autoRetrieve is true (default). Pinned notes are always included regardless of this setting.
  • Breakdown notes (notes with structured breakdowns) are prioritized in retrieval and receive a higher source budget.
  • Each source note is capped at 5,000 characters with a 70/30 head/tail split. Total source budget is 30,000 characters (25,000 on Starter plan).
  • After persisting, the Filmwork note stores metadata.reelCoach with the topic, duration, pinned note IDs, and coach overview for later hydration.