Inspiration

Even the biggest, best-resourced productions ship continuity errors — a character's appearance or a plot detail that contradicts something established earlier, caught by audiences instead of the production itself. That's not a lack of effort; it's a structural limit. Continuity is currently tracked by humans reading hundreds of pages across scripts and drafts, relying on memory and notes. As scripts and productions scale, that process doesn't scale with them. We wanted to see if a multi-agent system could give a production a persistent, structured memory of its own story — reading every scene the way a script supervisor would, but exhaustively and consistently.

What it does

Continuity reads a set of script scenes and builds a structured memory of the story, then flags:

  • Contradictions — the same event described incompatibly across scenes
  • State violations — something established as lost, destroyed, or dead reappearing with no explanation
  • Unresolved threads — a plot element introduced but never followed up
  • Legal clearance risks — real people, brands, or copyrighted references that might need review before production

Every flag comes with the exact source scenes, a confidence score, and a "requires human review" status. The system never claims to be the final word — it surfaces evidence for a script supervisor or legal team to review.

How we built it

Four agents, each with one job, orchestrated as a LangGraph state graph:

  • Extractor reads each scene and pulls structured facts (characters, props, setting, real-world references) — using a smaller, faster model since this is straightforward extraction, not nuanced judgment
  • Comparator reasons across each entity's entire scene history in a single call, not scene-pair by scene-pair — this came out of a real redesign, explained below
  • Legal Clearance checks extracted real-world references for clearance risk
  • Supervisor orchestrates the pipeline; Comparator and Legal Clearance run in parallel branches off the Extractor's output

The frontend renders the Extractor's literal structured output in a Story Timeline — every tracked character and prop's state, scene by scene — so nothing shown is a summary or reconstruction, it's the real data.

Challenges we ran into

This section is deliberately specific, because we think it's more useful (and more honest) than a generic list:

  • A model we built against got deprecated mid-project. Groq retired llama-3.3-70b-versatile while we were using it — we caught this from a live 404, not documentation, and learned to always verify available models directly against the API (client.models.list()) rather than trust a name from memory or docs.
  • Our first Comparator design didn't scale. Comparing every pair of scenes an entity appeared in meant a recurring prop could trigger 10+ separate LLM calls, each repeating the full system prompt — this burned through free-tier token budgets fast and couldn't reason across more than two scenes at once. We redesigned it to send one entity's entire scene history in a single call. This was both cheaper and better reasoning — it let the system catch a claim in one scene contradicted by a reveal several scenes later, which a pairwise comparison structurally couldn't see.
  • A LangGraph parallel-write bug. When two nodes (Comparator and Legal Clearance) branch off the same parent and both return the full pipeline state, LangGraph can't tell which write should win on unchanged fields. Fixed by having each node return only the state keys it actually changed.
  • Two real rate-limit walls — first a per-minute limit from running calls too concurrently, then a daily token cap from heavy testing. We added retry-with-backoff for the former and automatic model fallback for the latter, since waiting doesn't help against a daily quota.
  • A same-entity, different-name problem. Because the Extractor reads each scene independently, it sometimes called the same object "ring" in one scene and "gold ring" in another — splitting one entity into two in our tracking. We fixed this with word-subset matching on both the backend (for reasoning) and the frontend (for the Story Timeline visual), specifically checking word boundaries so it doesn't over-merge unrelated things that share letters (like "ring" and "earring").

Accomplishments that we're proud of

  • Every flag the system produces is genuinely evidence-based — no hardcoded outputs, no fallback that fabricates a result if something fails
  • We validated the system against six demo scripts at increasing difficulty, including one specifically designed to test false-positive avoidance (does it correctly leave explained changes alone), not just detection
  • We found and fixed real reasoning gaps through testing — a jacket swap the model initially missed, an ownership handoff it initially over-flagged — and can explain exactly why each happened and how the fix addressed it

What we learned

That a multi-agent architecture's real value shows up under stress, not in the happy path — the LangGraph parallel-write bug, the token-budget redesign, and the entity name-matching gap all only surfaced once we tested with real, varied, deliberately tricky scripts. Building it and testing it turned out to be inseparable steps.

What's next for Continuity

  • PDF script upload (currently plain-text scenes only)
  • Fully verified voice narration end-to-end with ElevenLabs
  • Deployment to a public URL
  • Semantic (not just word-based) entity matching, to catch same-object references that don't share any words at all

Built With

Share this project:

Updates

Submission history