"""Nonfiction Writing Crew for Opus Orchestrator. A CrewAI-powered crew for writing nonfiction with research and fact-checking. """ from typing import Any, Optional from crewai import Agent, Process from dotenv import load_dotenv from opus_orchestrator.crews.base_crew import OpusCrew from opus_orchestrator.config import get_config class NonfictionCrew(OpusCrew): """Nonfiction writing crew with Researcher, Writer, Fact-Checker, and Editor.""" def __init__( self, topic: str = "general", tone: str = "informative", target_word_count: int = 1000, verbose: bool = True, ): """Initialize the nonfiction crew. Args: topic: Main topic/subject area tone: Writing tone (academic, conversational, etc.) target_word_count: Target word count for the piece verbose: Enable verbose output """ self.topic = topic self.tone = tone self.target_word_count = target_word_count super().__init__(verbose=verbose, process=Process.sequential) self._setup_agents() def _setup_agents(self) -> None: """Set up the nonfiction writing team.""" # Researcher Agent - gathers information self.researcher = self.create_agent( role="Researcher", goal=f"Thoroughly research {self.topic} to provide accurate, comprehensive " f"information for the writer.", backstory=f"""You are an expert researcher specializing in {self.topic}. You know how to find reliable sources, verify information, and synthesize complex topics into clear, accurate summaries. You have access to vast knowledge and can explain nuanced subjects with clarity.""", verbose=self.verbose, ) # Writer Agent - creates the initial draft self.writer = self.create_agent( role="Nonfiction Writer", goal=f"Write compelling {self.topic} content that informs, educates, " f"and engages readers with {self.tone} tone.", backstory=f"""You are an experienced nonfiction writer known for your ability to explain complex topics clearly. You write in a {self.tone} style that resonates with general audiences while maintaining accuracy. You know how to structure arguments and present evidence effectively.""", verbose=self.verbose, ) # Fact-Checker Agent - verifies accuracy self.fact_checker = self.create_agent( role="Fact-Checker", goal="Verify all factual claims in the draft for accuracy and cite sources properly.", backstory="""You are a meticulous fact-checker with experience in journalism and academic publishing. You know how to verify claims, check statistics, and ensure all assertions are backed by reliable sources. You catch errors that others miss.""", verbose=self.verbose, ) # Editor Agent - reviews and refines self.editor = self.create_agent( role="Nonfiction Editor", goal="Edit and improve the nonfiction draft for clarity, structure, " "and reader engagement while maintaining accuracy.", backstory="""You are a senior nonfiction editor with years of experience working with authors on books, articles, and essays. You ensure content is well-structured, arguments are logical, and the writing is clear and engaging. You preserve the author's voice while improving the manuscript.""", verbose=self.verbose, ) self.agents = [self.researcher, self.writer, self.fact_checker, self.editor] def write_section( self, section_outline: str, research_findings: str = "", style_guide: str = "", ) -> str: """Write a section using the crew. Args: section_outline: Outline/summary of the section research_findings: Existing research to incorporate style_guide: Writing style guidelines Returns: Final polished section text """ # Task 1: Research (if not already done) if research_findings: research_task = self.create_task( description=f"""Research the following topic to provide accurate information: {section_outline} Provide key facts, statistics, and insights that will be needed for writing.""", agent=self.researcher, expected_output="Comprehensive research findings on the topic.", ) self.tasks.append(research_task) # Task 2: Write initial draft write_task = self.create_task( description=f"""Write a nonfiction section based on this outline: {section_outline} RESEARCH FINDINGS: {research_findings} STYLE GUIDE: {style_guide} Write approximately {self.target_word_count} words. Make it informative, well-structured, and engaging in {self.tone} tone.""", agent=self.writer, expected_output=f"A complete section of {self.target_word_count}+ words.", ) # Task 3: Fact-check factcheck_task = self.create_task( description="""Review and fact-check the section. Verify: - All statistics and numbers are accurate - Claims are supported by evidence - Sources are reliable - No misinformation or outdated claims If issues found, note them for revision.""", agent=self.fact_checker, expected_output="Fact-checked section with verified claims.", ) # Task 4: Edit and refine edit_task = self.create_task( description="""Edit and improve the section. Ensure: - Clear structure with logical flow - Strong introduction and conclusion - Smooth transitions between points - Appropriate tone ({self.tone}) - Reader engagement throughout Address any fact-checking concerns. Make it publication-ready.""", agent=self.editor, expected_output="A polished, publication-ready nonfiction section.", ) self.tasks = [t for t in self.tasks if t] + [write_task, factcheck_task, edit_task] result = self.run(inputs={ "section_outline": section_outline, "research_findings": research_findings, "style_guide": style_guide, }) return str(result) def write_chapter( self, chapter_outline: str, source_materials: str = "", style_guide: str = "", ) -> str: """Write a chapter using the crew. Args: chapter_outline: Outline/summary of the chapter source_materials: Source materials to draw from style_guide: Writing style guidelines Returns: Final polished chapter text """ # Task 1: Research research_task = self.create_task( description=f"""Research thoroughly for this chapter: {chapter_outline} Use these source materials: {source_materials} Provide comprehensive research findings including key facts, expert opinions, and supporting evidence.""", agent=self.researcher, expected_output="Comprehensive research findings for the chapter.", ) # Task 2: Write write_task = self.create_task( description=f"""Write a complete nonfiction chapter based on this outline: {chapter_outline} Use the research findings to support your arguments and provide valuable insights. STYLE GUIDE: {style_guide} Write a chapter of approximately {self.target_word_count} words in {self.tone} tone. Make it informative, engaging, and well-structured.""", agent=self.writer, expected_output=f"A complete chapter of {self.target_word_count}+ words.", ) # Task 3: Fact-check factcheck_task = self.create_task( description="""Fact-check the entire chapter. Verify: - All statistics, dates, and numbers - Quoted statements and attributions - Scientific claims and studies - Historical facts and events - Any potentially controversial claims Provide a detailed report of any issues found.""", agent=self.fact_checker, expected_output="Fact-checked chapter with verified information.", ) # Task 4: Edit edit_task = self.create_task( description=f"""Edit and finalize the chapter. Ensure: - Clear chapter structure with logical flow - Strong opening and closing - Smooth transitions between sections - Consistent {self.tone} tone throughout - All fact-check issues addressed - Publication-ready quality This is the final polish pass.""", agent=self.editor, expected_output="A polished, publication-ready chapter.", ) self.tasks = [research_task, write_task, factcheck_task, edit_task] result = self.run(inputs={ "chapter_outline": chapter_outline, "source_materials": source_materials, "style_guide": style_guide, }) return str(result) def create_nonfiction_crew( topic: str = "general", tone: str = "informative", target_word_count: int = 1000, verbose: bool = True, ) -> NonfictionCrew: """Factory function to create a nonfiction crew. Args: topic: Main topic/subject tone: Writing tone target_word_count: Target word count verbose: Enable verbose output Returns: Configured NonfictionCrew instance """ return NonfictionCrew( topic=topic, tone=tone, target_word_count=target_word_count, verbose=verbose, )