2026-03-12 17:44:51 +00:00
"""The Voice agent - Prose style and tone.
From Fiction Fortress Level 1-3:
- Role: Prose style and tone
- Responsibilities: Sentence-level writing, voice consistency
- Output: Prose samples, style guide
"""
from typing import Any
from opus_orchestrator.agents.base import AgentResponse , BaseAgent
VOICE_SYSTEM_PROMPT = """## Role: The Voice
You are The Voice — the owner of the prose itself, the sound, rhythm, and texture of the language. Your expertise lies in maintaining consistent style across thousands of words while adapting to scene-specific demands.
## Core Responsibilities
1. **Prose Style Control**
- Sentence rhythm variation (short/medium/long calibration)
- Vocabulary level management
- Figurative language deployment (metaphor, simile, symbolism density)
- Point of view intimacy maintenance
2. **Voice Consistency**
- Style guide creation and adherence
- Word bank maintenance
- Phrase pattern tracking
- Tone range specification (warm/cool, dark/light, etc.)
3. **Scene-Type Adaptation**
- Action scene pacing (sentence shortening)
- Emotional scene density (sentence complexity)
- Dialogue scene formatting
- Descriptive scene rhythm
- Exposition handling (invisible vs. visible)
4. **Point of View Management**
- Deep POV techniques
- Perspective consistency
- Head-hopping prevention
- Internal monologue integration
## Supporting Capabilities
- Dialogue attribution (said vs. action beats vs. no attribution)
- Punctuation style consistency
- Paragraph rhythm (white space management)
- Reader proximity calibration
## Voice Consistency Protocol
Maintain:
1. **Word bank** - Preferred vocabulary
2. **Phrase patterns** - Recurring constructions
3. **Rhythm map** - Sentence length distribution
4. **Tone guide** - Emotional range
## Quality Standards
- Voice must remain consistent across entire manuscript
- Scene type must inform prose style
- POV must be maintained without head-hopping
- Dialogue must sound distinct for each character
"""
class VoiceAgent ( BaseAgent ):
"""Agent responsible for prose style and voice consistency."""
def __init__ ( self , config = None ):
super () . __init__ (
role = "Voice" ,
description = "Prose style and tone" ,
system_prompt = VOICE_SYSTEM_PROMPT ,
config = config ,
)
async def execute ( self , input_data : Any , context : dict [ str , Any ]) -> AgentResponse :
2026-03-12 18:42:15 +00:00
"""Execute the Voice agent's task to create style guide and samples."""
2026-03-12 17:44:51 +00:00
genre = input_data . get ( "genre" , "general" )
tone = input_data . get ( "tone" , "neutral" )
2026-03-12 18:42:15 +00:00
target_audience = input_data . get ( "target_audience" , "General readers" )
2026-03-12 17:44:51 +00:00
user_prompt = f """## Task
Create a voice/style guide and prose samples for:
- Genre: { genre }
- Tone: { tone }
2026-03-12 18:42:15 +00:00
- Target Audience: { target_audience }
2026-03-12 17:44:51 +00:00
## Guidelines
Follow the Voice agent methodology from your system prompt.
Include:
2026-03-12 18:42:15 +00:00
- 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.
2026-03-12 17:44:51 +00:00
"""
2026-03-12 18:42:15 +00:00
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" },
)
2026-03-12 17:44:51 +00:00
async def write_chapter (
self ,
chapter_spec : dict [ str , Any ],
2026-03-12 18:42:15 +00:00
style_guide : str ,
2026-03-12 17:44:51 +00:00
context : dict [ str , Any ],
) -> AgentResponse :
2026-03-12 18:42:15 +00:00
"""Write a complete chapter following the style guide."""
2026-03-12 17:44:51 +00:00
user_prompt = f """## Chapter Specification
- Chapter Number: { chapter_spec . get ( 'chapter_number' ) }
- Title: { chapter_spec . get ( 'title' ) }
- Summary: { chapter_spec . get ( 'summary' ) }
2026-03-12 18:42:15 +00:00
- Word Count Target: { chapter_spec . get ( 'word_count_target' , 3000 ) }
2026-03-12 17:44:51 +00:00
- POV Character: { chapter_spec . get ( 'pov_character' , 'Narrator' ) }
- Key Events: { ', ' . join ( chapter_spec . get ( 'key_events' , [])) }
## Style Guide
{ style_guide }
## Task
Write the complete chapter following the style guide and chapter specification.
2026-03-12 18:42:15 +00:00
Maintain consistent voice throughout. Make it vivid, engaging, and professional quality.
Start with the chapter title as a heading.
2026-03-12 17:44:51 +00:00
"""
2026-03-12 18:42:15 +00:00
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" },
)
2026-03-12 17:44:51 +00:00
async def polish_chapter (
self ,
chapter_content : str ,
2026-03-12 18:42:15 +00:00
style_guide : str ,
2026-03-12 17:44:51 +00:00
context : dict [ str , Any ],
) -> AgentResponse :
"""Polish an existing chapter for voice consistency."""
user_prompt = f """## Chapter to Polish
{ chapter_content }
## Style Guide
{ style_guide }
## Task
Polish this chapter for voice consistency. Ensure:
- Sentence rhythm varies appropriately
- Word choice matches the style guide
- Tone remains consistent
2026-03-12 18:42:15 +00:00
- POV is maintained without head-hopping
2026-03-12 17:44:51 +00:00
- Prose flows smoothly
2026-03-12 18:42:15 +00:00
- Show don't tell where possible
Return the polished chapter as your output.
2026-03-12 17:44:51 +00:00
"""
2026-03-12 18:42:15 +00:00
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" },
)