Wire up all agents with LLM calls

- Worldsmith, Character Lead, Voice, Editor agents now call LLM
- All nonfiction agents wired (Researcher, Analyst, Writer, FactChecker, Editor)
- Orchestrator fully wired with agent pipeline
- Add python-dotenv dependency
This commit is contained in:
2026-03-12 18:42:15 +00:00
parent e151cee69f
commit dec5aae09a
7 changed files with 584 additions and 462 deletions
@@ -46,7 +46,7 @@ You are The Character Lead — the one who breathes life into the figures who in
- **Positive**: Growth from weakness
- **Negative**: Fall from grace
- **Flat**: No change, changes world
- **Disruption**: External力量打破平衡
- **Disruption**: External forces break equilibrium
## The Want/Need/Fear Triad
@@ -77,39 +77,52 @@ class CharacterLeadAgent(BaseAgent):
)
async def execute(self, input_data: Any, context: dict[str, Any]) -> AgentResponse:
"""Execute the Character Lead's task to generate character profiles.
Args:
input_data: Raw content + blueprint with character references
context: Additional context
Returns:
AgentResponse with character profiles
"""
"""Execute the Character Lead's task to generate character profiles."""
characters = input_data.get("characters", [])
raw_content = input_data.get("raw_content", "")
blueprint = input_data.get("blueprint", {})
user_prompt = f"""## Task
Create comprehensive character profiles for the following characters:
Create comprehensive character profiles for the following story:
{chr(10).join(f"- {c}" for c in characters) if characters else "Create profiles for all characters in the story."}
- Title: {blueprint.get('title', 'Untitled')}
- Genre: {blueprint.get('genre', 'general')}
{chr(10).join(f'- {c}' for c in characters) if characters else 'Create compelling characters that would drive this story.'}
## Raw Content Reference
{raw_content}
{raw_content if raw_content else 'Create original characters appropriate for this genre and story.'}
## Guidelines
Follow the Character Lead methodology from your system prompt.
Include the Want/Need/Fear triad for each major character.
Ensure each character has a distinct voice and arc.
"""
return AgentResponse(
success=True,
output={"status": "characters_created"},
metadata={"role": "Character Lead", "character_count": len(characters)},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={
"role": "Character Lead",
"character_count": len(characters) if characters else 0,
},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Character Lead"},
)
async def develop_relationship(
self,
@@ -129,14 +142,27 @@ Include the Want/Need/Fear triad for each major character.
Develop this relationship following the Character Lead methodology.
Include:
- Current dynamics
- Power balance
- Current dynamics and power balance
- History (if any)
- Potential arc
- Potential arc throughout the story
- Key moments that define the relationship
"""
return AgentResponse(
success=True,
output={"status": "relationship_developed"},
metadata={"role": "Character Lead", "characters": [character_a, character_b]},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Character Lead", "characters": [character_a, character_b]},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Character Lead"},
)
+103 -49
View File
@@ -64,12 +64,14 @@ You are The Editor — the quality control mechanism, identifying problems acros
- **Minor Revisions**: Continuity errors, style inconsistencies, pacing tweaks
- **Polish**: Grammar, punctuation, word choice refinement
## Quality Standards
## Output Format
- Every issue must have specific, actionable feedback
- Revision priorities must be clearly ordered
- Continuity issues must be flagged with exact locations
- Pacing analysis must be data-driven (scene lengths, tension scores)
Provide your critique as a structured review with:
1. Overall score (0.0-1.0)
2. Strengths (list)
3. Weaknesses (list)
4. Specific revision suggestions (prioritized)
5. Final verdict: major_revisions / minor_revisions / approved
"""
@@ -85,41 +87,43 @@ class EditorAgent(BaseAgent):
)
async def execute(self, input_data: Any, context: dict[str, Any]) -> AgentResponse:
"""Execute the Editor's task to review and assess the manuscript.
Args:
input_data: Chapter or manuscript to review
context: Review criteria and standards
Returns:
AgentResponse with editorial assessment
"""
"""Execute the Editor's task to review content."""
content = input_data.get("content", "")
review_type = input_data.get("review_type", "full")
user_prompt = f"""## Task
Perform a {review_type} editorial review on:
Perform a {review_type} editorial review on the following content:
{content[:5000]}... {'(truncated)' if len(content) > 5000 else ''}
{content}
## Review Type: {review_type}
## Guidelines
Follow the Editor methodology from your system prompt.
Include:
- Continuity verification
- Pacing analysis
- Quality assessment
- Specific revision directions
Be specific and actionable in your feedback.
Assign a clear revision priority.
"""
return AgentResponse(
success=True,
output={"status": "editorial_review_complete"},
metadata={"role": "Editor", "review_type": review_type},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Editor", "review_type": review_type},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Editor"},
)
async def review_chapter(
self,
@@ -132,14 +136,15 @@ Include:
- Chapter Number: {chapter.get('chapter_number')}
- Title: {chapter.get('title')}
- Content: {chapter.get('content', '')[:3000]}...
- Content:
{chapter.get('content', '')}
## Full Manuscript Context
- Total Chapters: {full_manuscript_context.get('total_chapters', 0)}
- Previous Chapters Summary: {full_manuscript_context.get('previous_summaries', [])}
- Characters in Story: {', '.join(full_manuscript_context.get('characters', []))}
- World Rules: {full_manuscript_context.get('world_rules', {})}
- Book Title: {full_manuscript_context.get('title', 'Untitled')}
- Genre: {full_manuscript_context.get('genre', 'general')}
## Task
@@ -150,18 +155,52 @@ Perform a complete editorial review of this chapter, considering:
- World-rule adherence
- Voice consistency
- Dialogue quality
- Show vs. tell balance
Assign a revision priority: major_revisions, minor_revisions, or approved
Provide:
1. Overall score (0.0-1.0)
2. Strengths (at least 3)
3. Weaknesses (at least 3)
4. Specific revision suggestions
5. Final verdict: major_revisions, minor_revisions, or approved
"""
return AgentResponse(
success=True,
output={
"status": "chapter_reviewed",
"chapter_number": chapter.get("chapter_number"),
},
metadata={"role": "Editor", "task": "chapter_review"},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
# Try to extract score from result
score = 0.5 # default
for line in result.split('\n'):
if 'score' in line.lower() or 'rating' in line.lower():
try:
# Look for number
import re
numbers = re.findall(r'0\.\d+|\d+\.\d+', line)
if numbers:
score = float(numbers[0])
break
except:
pass
return AgentResponse(
success=True,
output={
"critique": result,
"score": score,
"chapter_number": chapter.get("chapter_number"),
},
metadata={"role": "Editor", "task": "chapter_review"},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Editor"},
)
async def generate_revision_notes(
self,
@@ -169,23 +208,38 @@ Assign a revision priority: major_revisions, minor_revisions, or approved
context: dict[str, Any],
) -> AgentResponse:
"""Generate prioritized revision notes from multiple critiques."""
critiques_text = "\n\n".join(f"### Critique {i+1}:\n{c.get('critique', str(c))}" for i, c in enumerate(critiques))
user_prompt = f"""## Critiques to Synthesize
{chr(10).join(f"### Critique {i+1}:{c}" for i, c in enumerate(critiques))}
{critiques_text}
## Task
Synthesize these critiques into prioritized revision notes.
Group by:
1. Major revisions (structural, plot, arc issues)
2. Minor revisions (continuity, style, pacing)
3. Polish items (grammar, word choice)
1. Major revisions (structural, plot, arc issues) - must fix
2. Minor revisions (continuity, style, pacing) - should fix
3. Polish items (grammar, word choice) - nice to fix
For each item, provide specific, actionable feedback.
For each item, provide specific, actionable feedback with location if possible.
"""
return AgentResponse(
success=True,
output={"status": "revision_notes_generated"},
metadata={"role": "Editor", "critique_count": len(critiques)},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Editor", "critique_count": len(critiques)},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Editor"},
)
+83 -42
View File
@@ -78,17 +78,10 @@ class VoiceAgent(BaseAgent):
)
async def execute(self, input_data: Any, context: dict[str, Any]) -> AgentResponse:
"""Execute the Voice agent's task to create style guide and samples.
Args:
input_data: Genre, tone, target audience
context: Additional context
Returns:
AgentResponse with style guide and prose samples
"""
"""Execute the Voice agent's task to create style guide and samples."""
genre = input_data.get("genre", "general")
tone = input_data.get("tone", "neutral")
target_audience = input_data.get("target_audience", "General readers")
user_prompt = f"""## Task
@@ -96,41 +89,56 @@ Create a voice/style guide and prose samples for:
- Genre: {genre}
- Tone: {tone}
- Target Audience: {input_data.get('target_audience', 'General readers')}
- Target Audience: {target_audience}
## Guidelines
Follow the Voice agent methodology from your system prompt.
Include:
- Word bank
- Phrase patterns
- Rhythm map
- Tone guide
- 3 sample scenes (opening, dialogue, descriptive)
- Word bank (preferred vocabulary for this genre/tone)
- Phrase patterns (recurring constructions)
- Rhythm map (sentence length distribution)
- Tone guide (emotional range)
- 3 sample scenes:
1. Opening scene
2. Dialogue-heavy scene
3. Descriptive/pacific scene
Make the samples vivid and representative of the final prose style.
"""
return AgentResponse(
success=True,
output={"status": "voice_created"},
metadata={"role": "Voice", "genre": genre, "tone": tone},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Voice", "genre": genre, "tone": tone},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Voice"},
)
async def write_chapter(
self,
chapter_spec: dict[str, Any],
style_guide: dict[str, Any],
style_guide: str,
context: dict[str, Any],
) -> AgentResponse:
"""Write a complete chapter following the style guide.
This is the main writing task for the Voice agent.
"""
"""Write a complete chapter following the style guide."""
user_prompt = f"""## Chapter Specification
- Chapter Number: {chapter_spec.get('chapter_number')}
- Title: {chapter_spec.get('title')}
- Summary: {chapter_spec.get('summary')}
- Word Count Target: {chapter_spec.get('word_count_target')}
- Word Count Target: {chapter_spec.get('word_count_target', 3000)}
- POV Character: {chapter_spec.get('pov_character', 'Narrator')}
- Key Events: {', '.join(chapter_spec.get('key_events', []))}
@@ -141,22 +149,39 @@ Include:
## Task
Write the complete chapter following the style guide and chapter specification.
Maintain consistent voice throughout.
Maintain consistent voice throughout. Make it vivid, engaging, and professional quality.
Start with the chapter title as a heading.
"""
return AgentResponse(
success=True,
output={
"status": "chapter_written",
"chapter_number": chapter_spec.get("chapter_number"),
},
metadata={"role": "Voice"},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
word_count = len(result.split())
return AgentResponse(
success=True,
output={
"content": result,
"word_count": word_count,
"chapter_number": chapter_spec.get("chapter_number"),
},
metadata={"role": "Voice", "word_count": word_count},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Voice"},
)
async def polish_chapter(
self,
chapter_content: str,
style_guide: dict[str, Any],
style_guide: str,
context: dict[str, Any],
) -> AgentResponse:
"""Polish an existing chapter for voice consistency."""
@@ -174,12 +199,28 @@ Polish this chapter for voice consistency. Ensure:
- Sentence rhythm varies appropriately
- Word choice matches the style guide
- Tone remains consistent
- POV is maintained
- POV is maintained without head-hopping
- Prose flows smoothly
- Show don't tell where possible
Return the polished chapter as your output.
"""
return AgentResponse(
success=True,
output={"status": "chapter_polished"},
metadata={"role": "Voice", "task": "polish"},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Voice", "task": "polish"},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Voice"},
)
+46 -40
View File
@@ -79,18 +79,11 @@ class WorldsmithAgent(BaseAgent):
)
async def execute(self, input_data: Any, context: dict[str, Any]) -> AgentResponse:
"""Execute the Worldsmith's task to generate world documents.
Args:
input_data: Blueprint + genre + setting requirements
context: Additional context
Returns:
AgentResponse with world bible
"""
"""Execute the Worldsmith's task to generate world documents."""
blueprint = input_data.get("blueprint", {})
genre = input_data.get("genre", "fantasy")
setting_type = input_data.get("setting_type", "fantasy")
raw_content = input_data.get("raw_content", "")
user_prompt = f"""## Task
@@ -107,21 +100,31 @@ Ensure all elements are internally consistent and support the story.
## Content Seed
{input_data.get('raw_content', 'No additional content provided.')}
{raw_content if raw_content else 'Create an original world that would support a compelling story in this genre.'}
"""
return AgentResponse(
success=True,
output={
"status": "world_created",
"message": "World bible generation would be executed here with LLM",
},
metadata={
"role": "Worldsmith",
"genre": genre,
"setting_type": setting_type,
},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={
"role": "Worldsmith",
"genre": genre,
"setting_type": setting_type,
},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Worldsmith"},
)
async def expand_location(
self,
@@ -131,33 +134,36 @@ Ensure all elements are internally consistent and support the story.
pov_character: str,
context: dict[str, Any],
) -> AgentResponse:
"""Generate detailed location description.
From Template B in Fiction Fortress Level 2.
"""
"""Generate detailed location description."""
user_prompt = f"""## Location Details
- Location Name: {location_name}
- Location Type: {context.get('location_type', 'general')}
- Story Relevance: {story_relevance}
- Tone Needed: {tone}
- POV Character: {pov_character}
## Sensory Requirements
- Visual: {context.get('visual', 'Standard')}
- Auditory: {context.get('auditory', 'Standard')}
- Olfactory: {context.get('olfactory', 'Standard')}
- Tactile: {context.get('tactile', 'Standard')}
- Gustatory: {context.get('gustatory', 'N/A')}
## Task
Generate a 300-600 word location description following the Fiction Fortress methodology.
Include sensory details (visual, auditory, olfactory, tactile).
Make it atmospheric and story-relevant.
"""
return AgentResponse(
success=True,
output={"status": "location_expanded"},
metadata={"role": "Worldsmith", "location": location_name},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Worldsmith", "location": location_name},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Worldsmith"},
)
+110 -182
View File
@@ -1,14 +1,16 @@
"""Nonfiction agents for Opus Orchestrator.
Based on Nonfiction Fortress Level 1-3 methodology.
All agents are wired up to call the LLM.
"""
# Researcher Agent
from typing import Any
from opus_orchestrator.agents.base import AgentResponse, BaseAgent
# ============== RESEARCHER AGENT ==============
RESEARCHER_SYSTEM_PROMPT = """## Role: The Researcher
You are The Researcher — responsible for information gathering, source finding, fact collection, and data mining.
@@ -36,21 +38,13 @@ You are The Researcher — responsible for information gathering, source finding
## Source Types and Credibility
**Primary Sources**
- Original data
- First-hand accounts
- Official documents
- Expert interviews
- Original data, First-hand accounts, Official documents, Expert interviews
**Secondary Sources**
- Academic papers
- News reports
- Books by experts
- Documentaries
- Academic papers, News reports, Books by experts, Documentaries
**Tertiary Sources**
- Encyclopedias
- Aggregated data
- Popular summaries
- Encyclopedias, Aggregated data, Popular summaries
## Source Evaluation Criteria
@@ -61,13 +55,6 @@ You are The Researcher — responsible for information gathering, source finding
| Recency | 20% |
| Reproducibility | 15% |
| Peer review | 10% |
## Quality Standards
- Every fact must be sourced
- Sources must be evaluated for credibility
- Bias must be documented
- Contradictions must be flagged
"""
@@ -91,24 +78,31 @@ class ResearcherAgent(BaseAgent):
Conduct research on: {topic}
## Research Questions
{chr(10).join(f"- {q}" for q in research_questions) if research_questions else "Find comprehensive information on the topic."}
{chr(10).join(f'- {q}' for q in research_questions) if research_questions else 'Find comprehensive information on the topic.'}
## Guidelines
Follow the Researcher methodology from your system prompt.
Document all sources with citations.
Follow the Researcher methodology. Document all sources with citations.
Provide a comprehensive research dossier.
"""
return AgentResponse(
success=True,
output={"status": "research_complete"},
metadata={"role": "Researcher", "topic": topic},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Researcher", "topic": topic},
)
except Exception as e:
return AgentResponse(success=False, output=None, error=str(e), metadata={"role": "Researcher"})
# Analyst Agent
# ============== ANALYST AGENT ==============
ANALYST_SYSTEM_PROMPT = """## Role: The Analyst
You are The Analyst — responsible for information synthesis, pattern identification, argument construction, and insight extraction.
@@ -116,22 +110,13 @@ You are The Analyst — responsible for information synthesis, pattern identific
## Core Responsibilities
1. **Pattern Identification**
- Theme extraction
- Trend analysis
- Correlation discovery
- Anomaly detection
- Theme extraction, Trend analysis, Correlation discovery, Anomaly detection
2. **Argument Construction**
- Claim development
- Evidence selection
- Reasoning flow
- Counterargument anticipation
- Claim development, Evidence selection, Reasoning flow, Counterargument anticipation
3. **Insight Generation**
- Key takeaways
- Implications
- Connections
- Novel perspectives
- Key takeaways, Implications, Connections, Novel perspectives
## Argument Structure
@@ -141,29 +126,9 @@ You are The Analyst — responsible for information synthesis, pattern identific
- **Counterargument**: Acknowledged opposition
- **Rebuttal**: Response to opposition
## Argument Types
- **Causal**: A causes B
- **Comparative**: A is better/worse than B
- **Definition**: A means B
- **Historical**: A led to B
- **Predictive**: A will cause B
## Logical Fallacies to Avoid
- Ad hominem
- Straw man
- False dilemma
- Slippery slope
- Circular reasoning
- Hasty generalization
## Quality Standards
- All claims must be evidence-based
- Logical fallacies must be avoided
- Counterarguments must be addressed
- Implications must be explored
Ad hominem, Straw man, False dilemma, Slippery slope, Circular reasoning, Hasty generalization
"""
@@ -180,7 +145,7 @@ class AnalystAgent(BaseAgent):
async def execute(self, input_data: Any, context: dict[str, Any]) -> AgentResponse:
"""Execute analysis task."""
research_data = input_data.get("research_data", {})
research_data = input_data.get("research_data", "")
topic = input_data.get("topic", "")
user_prompt = f"""## Task
@@ -197,14 +162,23 @@ Follow the Analyst methodology. Construct clear arguments with evidence.
Address counterarguments. Generate insights.
"""
return AgentResponse(
success=True,
output={"status": "analysis_complete"},
metadata={"role": "Analyst", "topic": topic},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Analyst", "topic": topic},
)
except Exception as e:
return AgentResponse(success=False, output=None, error=str(e), metadata={"role": "Analyst"})
# Writer Agent (Nonfiction)
# ============== WRITER AGENT ==============
NONFICTION_WRITER_SYSTEM_PROMPT = """## Role: The Writer (Nonfiction)
You are The Writer — responsible for prose generation, clear explanation, engaging narrative, and voice development.
@@ -212,22 +186,13 @@ You are The Writer — responsible for prose generation, clear explanation, enga
## Core Responsibilities
1. **Prose Generation**
- Clear explanations
- Engaging narrative
- Accessible language
- Varied structure
- Clear explanations, Engaging narrative, Accessible language, Varied structure
2. **Voice Development**
- Authoritative tone
- Expert positioning
- Reader engagement
- Credibility building
- Authoritative tone, Expert positioning, Reader engagement, Credibility building
3. **Content Structuring**
- Introduction hooks
- Body organization
- Conclusion synthesis
- Transition flow
- Introduction hooks, Body organization, Conclusion synthesis, Transition flow
## Authorial Voice Elements
@@ -236,22 +201,6 @@ You are The Writer — responsible for prose generation, clear explanation, enga
- **Clarity**: Accessible explanations
- **Engagement**: Compelling narrative
- **Credibility**: Transparent sourcing
## Tone Calibration
| Genre | Tone |
|-------|------|
| Academic | Formal, precise |
| Popular | Accessible, lively |
| Professional | Practical, direct |
| Memoir | Personal, reflective |
## Quality Standards
- Complex ideas must be accessible
- Arguments must flow logically
- Voice must be consistent
- Readers must remain engaged
"""
@@ -268,7 +217,7 @@ class NonfictionWriterAgent(BaseAgent):
async def execute(self, input_data: Any, context: dict[str, Any]) -> AgentResponse:
"""Execute nonfiction writing task."""
analysis = input_data.get("analysis", {})
analysis = input_data.get("analysis", "")
chapter_spec = input_data.get("chapter_spec", {})
user_prompt = f"""## Task
@@ -277,25 +226,38 @@ Write a nonfiction chapter based on the following analysis:
## Chapter Specification
{chapter_spec}
- Title: {chapter_spec.get('title', 'Untitled')}
- Word Count Target: {chapter_spec.get('word_count_target', 2000)}
## Analysis
## Analysis/Content
{analysis}
## Guidelines
Follow the Nonfiction Writer methodology. Maintain authoritative yet accessible tone.
Structure with clear introduction, body, and conclusion.
"""
return AgentResponse(
success=True,
output={"status": "chapter_written"},
metadata={"role": "Nonfiction Writer"},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
word_count = len(result.split())
return AgentResponse(
success=True,
output={"content": result, "word_count": word_count},
metadata={"role": "Nonfiction Writer", "word_count": word_count},
)
except Exception as e:
return AgentResponse(success=False, output=None, error=str(e), metadata={"role": "Nonfiction Writer"})
# Fact Checker Agent
# ============== FACT CHECKER AGENT ==============
FACT_CHECKER_SYSTEM_PROMPT = """## Role: The Fact-Checker
You are The Fact-Checker — responsible for verification, citation validation, claim verification, and accuracy audit.
@@ -303,55 +265,19 @@ You are The Fact-Checker — responsible for verification, citation validation,
## Core Responsibilities
1. **Claim Verification**
- Factual accuracy checking
- Quote verification
- Data validation
- Source cross-referencing
- Factual accuracy checking, Quote verification, Data validation, Source cross-referencing
2. **Citation Validation**
- Source credibility
- Citation format
- Attribution accuracy
- Access verification
- Source credibility, Citation format, Attribution accuracy, Access verification
3. **Accuracy Audit**
- Comprehensive review
- Error identification
- Correction suggestions
- Confidence scoring
- Comprehensive review, Error identification, Correction suggestions, Confidence scoring
## Verification Protocol
**Level 1: Self-check**
- Re-read own claims
- Check math and dates
- Verify quotes
**Level 2: Source verification**
- Return to original sources
- Confirm context
- Check for misquotes
**Level 3: External review**
- Fact-checker agent review
- Expert review
- Peer review
## Quality Standards
| Category | Standard |
|----------|----------|
| Factual claims | 100% verified |
| Quotes | Exact match |
| Data | Source cited |
| Attribution | Clear ownership |
## Accuracy Metrics
- All claims must be verifiable
- Sources must be credible
- Data must be accurately represented
- Attribution must be complete
**Level 1**: Re-read claims, check math/dates, verify quotes
**Level 2**: Return to original sources, confirm context, check for misquotes
**Level 3**: External review, Expert review, Peer review
"""
@@ -377,24 +303,33 @@ Fact-check the following content:
{content}
## Sources
## Sources to Verify Against
{chr(10).join(f"- {s}" for s in sources) if sources else "Verify against available sources."}
{chr(10).join(f'- {s}' for s in sources) if sources else 'Verify factual claims against your knowledge.'}
## Guidelines
Follow the Fact-Checker methodology. Verify all claims, quotes, and data.
Provide confidence scores for each item.
Provide confidence scores and flag any issues.
"""
return AgentResponse(
success=True,
output={"status": "fact_check_complete"},
metadata={"role": "Fact-Checker"},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Fact-Checker"},
)
except Exception as e:
return AgentResponse(success=False, output=None, error=str(e), metadata={"role": "Fact-Checker"})
# Nonfiction Editor Agent
# ============== EDITOR AGENT (NONFICTION) ==============
NONFICTION_EDITOR_SYSTEM_PROMPT = """## Role: The Editor (Nonfiction)
You are The Editor — responsible for quality control, structure assessment, clarity evaluation, and style consistency.
@@ -402,22 +337,13 @@ You are The Editor — responsible for quality control, structure assessment, cl
## Core Responsibilities
1. **Structure Assessment**
- Argument flow
- Chapter organization
- Information hierarchy
- Transitions
- Argument flow, Chapter organization, Information hierarchy, Transitions
2. **Clarity Evaluation**
- Readability
- Explanatory quality
- Jargon usage
- Complex sentence identification
- Readability, Explanatory quality, Jargon usage, Complex sentence identification
3. **Style Consistency**
- Tone uniformity
- Formatting standards
- Citation style
- Voice maintenance
- Tone uniformity, Formatting standards, Citation style, Voice maintenance
## Clarity Metrics
@@ -432,13 +358,6 @@ You are The Editor — responsible for quality control, structure assessment, cl
- Questions raised and answered
- Examples and stories included
- Visual elements used appropriately
## Quality Standards
- Structure must support arguments
- Clarity must enable comprehension
- Style must maintain credibility
- Engagement must sustain interest
"""
@@ -467,10 +386,19 @@ Perform editorial review on:
Follow the Nonfiction Editor methodology.
Assess structure, clarity, style, and engagement.
Provide specific, actionable feedback.
"""
return AgentResponse(
success=True,
output={"status": "editorial_review_complete"},
metadata={"role": "Nonfiction Editor"},
)
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Nonfiction Editor"},
)
except Exception as e:
return AgentResponse(success=False, output=None, error=str(e), metadata={"role": "Nonfiction Editor"})