StoryMatrix uses CrewAI crews to plan stories, produce timelines, generate image prompts, and cast voices.
π Crews
| Crew | Source | Process | Agents and tasks |
|---|---|---|---|
| Story generation | crew/configs/story_crew.yaml, loaded by CrewFactory.load_crew("story_crew", ...) | Sequential; the factory defaults a missing process to sequential | Six agents and five tasks |
| Timeline generation | crew/configs/timeline_crew.yaml, loaded by CrewFactory.load_crew("timeline_crew", ...) | Sequential | audio_director, audio_intelligence_agent, and audio_direction_task |
| Image-prompt generation | crew/image_prompt_crew.py:create_image_prompt_generation_crew | Sequential | Three visual agents and three image-prompt tasks |
| Voice casting | crew/voice_casting_crew.py:create_voice_casting_crew | Sequential default; the Crew constructor omits an explicit process | casting_director and casting_task |
The factory maps the YAML values sequential and hierarchical to CrewAI process types and falls back to sequential for any other value (crew/factory.py). No crew configuration selects hierarchical processing.
π§βπ» Story agents
The story YAML defines six agents. The factory ignores each agentβs llm and tools keys: every agent receives the crew-level LLM, and no tools argument is passed (crew/configs/story_crew.yaml, crew/factory.py).
| YAML key | Role | LLM actually wired | Tools actually wired | Wired into a crew? |
|---|---|---|---|---|
planner_agent | Story Planner | Crew-level LLM | None | Yes, story crew |
persona_architect_agent | Author Persona Architect | Crew-level LLM | None | Yes, story crew |
authorial_voice_agent | Authorial Voice Specialist | Crew-level LLM | None | Yes, story crew |
visionary_agent | Creative Visionary & Style Coordinator | Crew-level LLM | None | Yes, story crew |
reviewer_agent | Narrative Coherence Analyst | Crew-level LLM | None | Yes, story crew |
writer_agent | Creative Writer | Crew-level LLM | None | Yes, story crew |
π§Ύ Story tasks and schemas
| YAML key | Owning agent | Output schema class |
|---|---|---|
planning_task | planner_agent | storymatrix.crew.schemas.StoryPlan |
review_task | reviewer_agent | storymatrix.crew.schemas.StoryPlanReview |
persona_selection_task | persona_architect_agent | storymatrix.crew.schemas.AuthorPersonaSelection |
writing_task | writer_agent | storymatrix.crew.schemas.StoryData |
style_consistency_task | visionary_agent | storymatrix.crew.schemas.StoryPlanReview (reused for the consistency assessment) |
The task contexts form a sequential dependency: review follows planning; persona selection consumes planning and review; writing consumes all three; style consistency consumes the produced story as well (crew/configs/story_crew.yaml).
π§° Tool registry
crew/tools/registry.py registers the following exact names when ensure_defaults_loaded() runs:
| Registry name | Used by |
|---|---|
audio_timing_validator | Timeline crew |
sfx_duration_classifier | Timeline crew |
sfx_type_classifier | Timeline crew |
music_segmentation_analyzer | Timeline crew |
audio_conflict_resolver | Timeline crew |
timeline_sequence_optimizer | Timeline crew |
music_scene_mapper | Timeline crew |
visual_style_mapper | Story YAML |
aesthetic_coherence_analyzer | Story YAML |
cross_modal_consistency_checker | Story YAML |
voice_consistency_checker | Story YAML |
style_analysis_tool | Story YAML |
dialogue_attribution_validator | Story YAML |
The factory calls ensure_defaults_loaded() during initialization, which populates the registry, but it does not resolve YAML tool names into agents (crew/factory.py).
β Timeline contract
TimelineContractValidator.validate() accepts either a dictionary with tracks or an object exposing .tracks; each track may be a dictionary or an object exposing track_type and events (crew/validators/timeline_contract.py). It normalizes track names such as background_music / bgm to music and sound_effects / sound_effect / effects to sfx in the compatibility function.
| Rule | Accepted | Rejected |
|---|---|---|
| Structure | At least one track | Empty or missing tracks |
| Event timing | metadata.start_time_ms and metadata.end_time_ms; start is non-negative and end is greater than start | Missing metadata, missing timing keys, negative start, non-numeric timing, or end not greater than start |
| Layer | Missing layer or integer layer 0, 1, or 2 | Non-integer layer or any other layer |
| Volume | Missing volume or numeric volume_db from -12.0 through 0.0 | Non-numeric volume or a value outside that range |
| Scene index | Missing scene index or non-negative integer | Non-integer or negative scene index |
| Requested SFX | No extra track requirement when disabled; when enabled, an sfx track with at least two events per scene | Missing sfx or fewer than max(2 Γ scenes_count, 2) SFX events |
| Requested music | When enabled, a music track with at least one event; when disabled, no music track | Missing enabled music, zero music events, or music present while disabled |
Strict mode is enabled by default and raises TimelineValidationError when issues exist. Non-strict mode returns the issue list. The compatibility function validate_timeline_contract() returns (ok, message) with the same required-track, count, and timing checks.
π§© Persona selection
The persona-selection task names three genre choices inline: Sci-Fi selects Dr. Elias Voss, Fantasy selects Lady Elowen Stormweaver, and Mystery selects Detective Inspector Marcus Hale (crew/configs/story_crew.yaml). The corresponding templates are crew/prompts/personas/sci_fi_author_template.md, fantasy_author_template.md, and mystery_author_template.md; each defines genre, influences, core characteristics, writing approach, voice guidelines, and signature elements. The task selects by genre alignment, requested style guide, character requirements, and thematic consistency, then emits AuthorPersonaSelection.
No source code references the three template filenames, so the current runtime path does not load those Markdown files; the selection prompt carries the persona descriptions instead. The factory does support a file: prefix for agent backstories and resolves such files below crew/prompts/, but the story YAML uses inline backstories for all six agents. The standalone crew/prompts/planner.md, reviewer.md, and writer.md files therefore remain unwired.
β οΈ Known crew breaks and gaps
- B2 β legacy fallback:
_create_legacy_story_crew_inline()references the undefined namellmwhile constructing its fallback LLM, so that path raisesNameErrorrather than creating the legacy crew. Track it at index > b2. - B5 β mock image-prompt crew:
create_image_prompt_generation_crew()assigns the sentinel model stringmock-provider/mock-responseforMockLLMService; that string reaches LiteLLM and fails because no provider is supplied, so mock mode cannot complete image-prompt generation. Track it at index > b5. - Duplicate timeline configuration:
crew/timeline_crew.yamlexists besidecrew/configs/timeline_crew.yaml.CrewFactoryresolvesconfigs_dir / "timeline_crew.yaml", andcreate_timeline_generation_crew()requests that factory path, socrew/configs/timeline_crew.yamlis live; the root-levelcrew/timeline_crew.yamlis dead and remains in the repository.