Skip to content

Narrative Agent Split Change Breakdown

Created: 2026-05-29 07:32 UTC

Summary

This change splits the current narrative stage into two explicit contracts and two workflow phases:

  • a preview-only narrative pass that produces reviewable voiceover sentences
  • a post-approval expansion pass that derives scene semantics needed by visuals, slides, direction, and compile

The main architectural goal is to make narrative-review the real human approval boundary instead of a UI pause over a payload that already contains downstream scene semantics. The current codebase already has the suspend/resume boundary, but the narrative agent, schema, persisted review payload, and workflow step ordering still treat preview text and scene semantics as one artifact.

Target Flow

flowchart TD
  prepare["prepare-presentation-run"] --> intakeGate{"Need IntentAgent?"}
  intakeGate -->|No, request already explicit| ragGate
  intakeGate -->|Yes| intent["intent-agent"]
  intent --> ragGate

  ragGate{"Need KnowledgeOrchestrator?"} -->|uploaded-only| rag["retrieve persisted/uploaded RAG context"]
  ragGate -->|mixed or remote sources| knowledge["ragWorkflow"]
  knowledge --> rag

  rag --> preview["generatePreviewSentences"]
  preview --> suspend["narrative-review suspend with preview-only payload"]
  suspend --> approve["approved preview sentences"]
  approve --> expand["expandSceneDetails"]
  expand --> visuals["visualsWorkflow"]
  visuals --> slides["slidesWorkflow"]
  slides --> direction["directionWorkflow"]
  direction --> compile["compile"]

Current Touchpoints

  • src/mastra/agents/presentationvideo-agent-contracts.ts Current narrative definition still advertises agent.narrative.generateScenes returning VoiceoverScriptJson/NarrativeSceneList.
  • src/mastra/agents/narrative.agent.ts Current narrative agent description says it generates scene-level voiceover and semantics together.
  • src/mastra/schemas/scene.schema.ts narrativeSceneSchema currently bundles preview fields with semantic-expansion fields such as caption, sceneQuery, recommendedVisualType, and visualGenerationPrompt.
  • src/mastra/workflows/sub/narrative.workflow.ts Current subworkflow builds one prompt, runs one agent step, and normalizes one combined NarrativeSceneList.
  • src/mastra/workflows/presentationvideo.workflow.ts Current master workflow already suspends at narrative-review, but the suspend payload stores full narrativeScenes rather than a preview-only contract.
  • src/mastra/workflows/sub/rag.workflow.ts Current knowledge flow always runs the knowledge-agent before collecting sources, even for uploaded-only runs.
  • src/mastra/tools/presentation/index.ts persistNarrativeReviewTool persists full narrativeScenes into presentationStatusJson.setup.narrativeReview.
  • src/app/(frontend)/app/presentation/actions.ts generatePresentationNarrativePreview parses the suspended payload as voiceoverPreview + narrativeScenes, and continuePresentationFromNarrative resumes with approved scenes plus identity selection.
  • src/lib/anuva/contracts-v1.ts VoiceoverScriptJson already exists as a preview-friendly voiceover-only contract and is a likely candidate for one side of the split.
  • docs/core/PresentationVideoWorkflow.md, docs/state/WorkflowMap.md, docs/state/ServerActionsMap.md Current docs already describe narrative-review as a VO preview boundary, but code-level contracts still over-deliver richer scene semantics before approval.

Current Behavior Snapshot

  • narrativeWorkflow currently returns a NarrativeSceneList where each scene includes both:
  • preview fields: sceneId, index, text, estimatedDurationSec
  • downstream semantic fields: caption, sceneQuery, recommendedVisualType, visualGenerationPrompt
  • presentationVideoWorkflow suspends after narrative generation, but the review payload persists the full scene list rather than a narrower preview artifact.
  • ragWorkflow always invokes KnowledgeOrchestrator first, even when the source set may already deterministically imply uploaded only.
  • intent-agent always runs in the master workflow, even when the create action already passes stable name, prompt, and VO guidance.
  • visualsWorkflow, slidesWorkflow, and directionWorkflow all currently consume the post-narrative scenes object as if semantic expansion is already complete.

Grouped Changes

1. Split the narrative contract into preview and expansion artifacts

Explanation:

The current NarrativeSceneList is doing two jobs. It acts as the UI approval payload and the downstream semantic scene model at the same time. That makes narrative-review a weak approval boundary because captions, scene queries, and visual prompts are already locked in before the user approves the spoken script.

The change should introduce explicit schema boundaries for:

  • preview sentences only
  • expanded scene details
  • final voiceover JSON where needed by compilation and runtime contracts

Likely affected code:

  • src/mastra/schemas/scene.schema.ts
  • src/lib/anuva/contracts-v1.ts
  • src/lib/anuva/voiceover-script.ts
  • src/mastra/agents/presentationvideo-agent-contracts.ts

2. Split the narrative stage into two agent actions with a hard approval boundary

Explanation:

The current agent.narrative.generateScenes step should be decomposed into:

  • a preview generation action such as agent.narrative.generatePreviewSentences
  • an expansion action such as agent.narrative.expandSceneDetails

The key constraint is that expansion must treat approved preview sentences as hard input. It should fill missing semantic fields without re-authoring the approved voiceover text unless that is an explicit product capability.

Likely affected code:

  • src/mastra/agents/narrative.agent.ts
  • src/mastra/agents/presentationvideo-agent-contracts.ts
  • src/mastra/workflows/sub/narrative.workflow.ts
  • src/mastra/workflows/presentationvideo.workflow.ts

3. Narrow the narrative-review suspend payload and persisted review state

Explanation:

The current suspend payload and persistNarrativeReviewTool both store narrativeScenes, which already include downstream semantic fields. After the split, the suspend state should persist only the preview artifact plus any metadata needed to safely resume expansion. That keeps the review UI aligned with the actual approved artifact and reduces drift between what the user approved and what downstream workflows consume.

Likely affected code:

  • src/mastra/workflows/presentationvideo.workflow.ts
  • src/mastra/tools/presentation/index.ts
  • src/app/(frontend)/app/presentation/actions.ts
  • any types describing presentationStatusJson.setup.narrativeReview

4. Add preview-mode branch rules for skipping intent and knowledge planning

Explanation:

The requested product flow wants deterministic shortcuts:

  • skip IntentAgent when videoName, description, and VO guidance are already explicit enough
  • skip KnowledgeOrchestrator when the source set is uploaded-only

This should not be implemented as ad hoc UI branching alone. The workflow needs explicit gating rules so API, worker, and CLI callers can share the same behavior. The implementation plan will need to define whether the skip logic is:

  • derived from input heuristics inside presentationVideoWorkflow
  • encoded as explicit workflow flags
  • or handled by a prepareRunStep normalization output that later steps consume

Likely affected code:

  • src/mastra/workflows/presentationvideo.workflow.ts
  • src/mastra/workflows/sub/rag.workflow.ts
  • src/mastra/tools/presentation/index.ts
  • src/app/(frontend)/app/presentation/actions.ts

5. Retarget downstream workflows to consume expanded scene details, not preview payloads

Explanation:

visualsWorkflow, slidesWorkflow, directionWorkflow, compile, and scene persistence currently rely on the narrative output already containing semantic scene fields. After the split, those consumers must clearly depend on the post-approval expanded artifact, while preview-only steps and UI payloads depend on the narrower contract.

This is also where reveal or slide-planning hints need ownership clarification. If those hints are still narrative-owned, they belong in expansion. If they are really slide-planning responsibilities, they should move there explicitly rather than remaining implied in the narrative payload.

Likely affected code:

  • src/mastra/workflows/sub/visuals.workflow.ts
  • src/mastra/workflows/sub/slides.workflow.ts
  • src/mastra/workflows/sub/direction.workflow.ts
  • src/mastra/tools/compiler/index.ts
  • src/mastra/tools/presentation/index.ts

6. Align docs and workflow maps with the real contract boundary

Explanation:

Current docs already describe narrative-review as a VO preview checkpoint, but the code still persists a richer scene payload. After the implementation, the docs should explicitly distinguish:

  • preview-generation contract
  • approved preview persistence
  • expansion contract
  • downstream consumers of expanded scene details

Likely affected docs:

  • docs/core/PresentationVideoWorkflow.md
  • docs/state/WorkflowMap.md
  • docs/state/ServerActionsMap.md
  • docs/state/KnownGaps.md
  • this change folder’s ImplementationPlan.md and ImplementationLog.md

Affected Product Surfaces

  • Create presentation flow
  • VO Script Preview step
  • Go To Scene Details resume path
  • Mastra narrative and RAG subworkflows
  • persisted presentationStatusJson.setup.narrativeReview review state
  • downstream scene semantic generation for visuals, slides, direction, and compile

Likely Affected Code Paths

  • src/mastra/agents/presentationvideo-agent-contracts.ts
  • src/mastra/agents/narrative.agent.ts
  • src/mastra/workflows/sub/narrative.workflow.ts
  • src/mastra/workflows/sub/rag.workflow.ts
  • src/mastra/workflows/presentationvideo.workflow.ts
  • src/mastra/schemas/scene.schema.ts
  • src/mastra/schemas/config.schema.ts
  • src/mastra/tools/presentation/index.ts
  • src/app/(frontend)/app/presentation/actions.ts
  • src/lib/anuva/contracts-v1.ts
  • src/lib/anuva/voiceover-script.ts
  • tests covering narrative preview, resume, and workflow contract behavior

Risks And Dependencies

  • Semantic drift: Expansion can diverge from the approved preview unless the preview text is passed through as immutable or strongly constrained input.
  • Contract overlap: Introducing both preview and expanded scene schemas can create ambiguity unless each downstream consumer has one clear contract owner.
  • Workflow branching complexity: Skip rules for intent and knowledge planning can become fragile if they are based on loose heuristics rather than explicit readiness criteria.
  • Persistence compatibility: Existing UI and server actions already parse narrativeScenes from suspended payloads and persisted review state, so schema changes will ripple through resume behavior.
  • Slide/reveal ownership: Some downstream assumptions may still treat narrative output as the place where reveal hints originate.
  • Test coverage gaps: Current docs describe the review boundary more cleanly than the contracts implement it, which is usually a sign that tests may not yet fully pin the desired split behavior.

Out Of Scope

  • Implementing the split in code during this planning phase
  • Reworking Step 3 scene editing beyond what is required to consume the new approved-preview artifact
  • Redesigning final audio generation, render handoff, or scene edit partial recompilation outside the narrative boundary change
  • Broad Payload collection redesign unless new persistent fields are proven necessary
  • General Mastra platform upgrades unrelated to the narrative split

Open Questions

Q1. Should the preview approval UI allow sentence-level edits before approval, or should it remain approve/regenerate-only for this change?

Answer: It should remain approve/regenerate-only for this change.

Q2. Should the post-approval expansion artifact be a new schema such as NarrativeSceneDetails, or should it normalize directly into the existing VoiceoverScriptJson plus separate scene-semantic structures?

Answer: Use a new post-approval schema such as NarrativeSceneDetails. VoiceoverScriptJson should remain the narrow voiceover-only contract for preview and approved script persistence. The expansion step should output a separate schema that preserves the approved sentences while adding caption, sceneQuery, recommendedVisualType, visualGenerationPrompt, and any other narrative-owned semantic fields needed downstream.

Q3. Should the workflow skip IntentAgent and KnowledgeOrchestrator through explicit input flags, or should it infer skipping entirely from normalized request/source shape?

Answer: Skip behavior should be inferred from normalized request and source shape, not driven primarily by caller-supplied flags. The workflow should decide whether intent and knowledge planning are necessary based on deterministic criteria derived during prepareRunStep or equivalent normalization. Internal booleans may still be produced for downstream branching, but they should be workflow-owned derived state so UI, API, CLI, and worker entry points all behave consistently.

Q4. Are sceneQuery, recommendedVisualType, and visualGenerationPrompt definitely expansion-owned, or should some of those fields move to visualsWorkflow instead of remaining part of narrative output?

Answer: sceneQuery should remain expansion-owned because it is a semantic retrieval/grounding field derived directly from the approved narrative. recommendedVisualType and visualGenerationPrompt should move to visualsWorkflow rather than remain narrative-owned. That creates a cleaner boundary where narrative expansion owns scene meaning and visualsWorkflow owns visual execution strategy.

Q5. When resuming from narrative-review, should the workflow accept edited approved preview sentences from the UI, or only the original generated preview payload plus an approval boolean?

Answer: For this change, resume should accept only the original generated preview payload plus approval and identity selections, not user-edited sentences.