"""Configuration classes for debate agent setup and customization.
This module provides comprehensive configuration options for debate agents,
including format-specific presets, role assignments, timing controls, and
engine configurations. The configuration system supports various debate
formats from formal parliamentary debates to trial simulations.
The configuration classes use Pydantic for validation and provide factory
methods for common debate formats including standard debates, presidential
debates, trial formats, and panel discussions.
Examples:
Creating a standard debate configuration:
.. code-block:: python
config = DebateAgentConfig.default()
agent = DebateAgent(config)
Creating a custom trial simulation::
config = DebateAgentConfig.trial()
config.time_limit = 600 # 10 minutes per phase
config.participant_roles["witness_1"] = "witness"
agent = DebateAgent(config)
Creating a presidential debate format::
config = DebateAgentConfig.presidential()
config.allow_interruptions = True
config.moderator_role = "moderator"
agent = DebateAgent(config)
Creating a custom configuration::
config = DebateAgentConfig(
name="custom_debate",
debate_format="oxford",
time_limit=300,
max_statements=5,
allow_interruptions=False,
voting_enabled=True,
participant_roles={
"pro_1": "pro", "pro_2": "pro",
"con_1": "con", "con_2": "con",
"moderator": "moderator"
}
)
Note:
All configuration classes inherit from AgentConfig and include automatic
engine setup through the build_debate_engines factory function.
Custom engine configurations can be provided to override defaults.
"""
from haive.core.engine.agent.agent import AgentConfig
from haive.core.engine.aug_llm import AugLLMConfig
from pydantic import BaseModel, Field, field_validator
from haive.games.debate.engines import build_debate_engines
from haive.games.debate.state import DebateState
[docs]
class DebateAgentConfig(AgentConfig):
"""Comprehensive configuration for debate agents with format-specific settings.
This configuration class provides extensive customization options for debate
agents, supporting various debate formats, role assignments, timing controls,
and engine configurations. It includes validation for debate-specific parameters
and provides factory methods for common debate formats.
The configuration system supports:
- Multiple debate formats (standard, parliamentary, oxford, trial, presidential)
- Flexible role assignment system for participants
- Timing controls and statement limits
- Interruption and voting settings
- Custom engine configurations for different participant roles
Attributes:
debate_format (str): Format type determining debate structure and rules.
Supported formats: "standard", "parliamentary", "oxford", "trial",
"presidential", "panel", "lincoln_douglas".
time_limit (Optional[int]): Maximum time in seconds per debate phase.
None means no time limit. Typical values: 60-600 seconds.
max_statements (Optional[int]): Maximum statements per participant per phase.
None means unlimited statements. Typical values: 1-5 statements.
allow_interruptions (bool): Whether participants can interrupt each other
during their statements. Common in presidential and panel formats.
voting_enabled (bool): Whether to include a voting phase at debate end.
Typically enabled for competitive debates, disabled for discussions.
moderator_role (Optional[str]): Specific role identifier for the moderator.
None means no dedicated moderator. Common value: "moderator".
participant_roles (Dict[str, str]): Mapping of participant IDs to their roles.
Keys are participant identifiers, values are role names like "pro",
"con", "judge", "moderator", "prosecutor", "defense", "witness".
state_schema (Type[BaseModel]): Pydantic model class for debate state.
Defaults to DebateState but can be customized for specific formats.
engines (Dict[str, AugLLMConfig]): Engine configurations for different roles.
Automatically built by build_debate_engines but can be customized.
Examples:
Basic debate configuration:
.. code-block:: python
config = DebateAgentConfig(
name="climate_debate",
debate_format="oxford",
time_limit=300,
max_statements=3,
participant_roles={
"scientist": "pro",
"economist": "con",
"moderator": "moderator"
}
)
Trial simulation configuration::
config = DebateAgentConfig(
name="murder_trial",
debate_format="trial",
time_limit=600,
allow_interruptions=False,
participant_roles={
"prosecutor": "prosecutor",
"defense_attorney": "defense",
"judge": "judge",
"witness_1": "witness",
"witness_2": "witness"
}
)
Parliamentary debate configuration::
config = DebateAgentConfig(
name="parliament_session",
debate_format="parliamentary",
time_limit=180,
allow_interruptions=True,
voting_enabled=True,
participant_roles={
"pm": "government",
"deputy_pm": "government",
"leader_opposition": "opposition",
"deputy_opposition": "opposition",
"speaker": "moderator"
}
)
Note:
The configuration automatically sets up appropriate engines for each role
using the build_debate_engines factory. Custom engines can be provided
to override defaults for specific use cases or to add specialized capabilities.
"""
debate_format: str = Field(
default="standard",
description="Format type determining debate structure and rules",
examples=[
"standard",
"parliamentary",
"oxford",
"trial",
"presidential",
"panel",
"lincoln_douglas",
],
)
time_limit: int | None = Field(
default=None,
ge=30,
le=3600,
description="Maximum time in seconds per debate phase (30-3600 seconds, None for no limit)",
examples=[60, 120, 300, 600, None],
)
max_statements: int | None = Field(
default=None,
ge=1,
le=20,
description="Maximum statements per participant per phase (1-20, None for unlimited)",
examples=[1, 3, 5, 10, None],
)
allow_interruptions: bool = Field(
default=False,
description="Whether participants can interrupt each other during statements",
examples=[True, False],
)
voting_enabled: bool = Field(
default=True,
description="Whether to include a voting/judgment phase at debate conclusion",
examples=[True, False],
)
# Role configurations
moderator_role: str | None = Field(
default=None,
description="Specific role identifier for the debate moderator (None for no moderator)",
examples=["moderator", "judge", "chair", "speaker", None],
)
participant_roles: dict[str, str] = Field(
default_factory=dict,
description="Mapping of participant IDs to their debate roles",
examples=[
{"debater_1": "pro", "debater_2": "con", "moderator": "moderator"},
{"prosecutor": "prosecutor", "defense": "defense", "judge": "judge"},
{"panelist_1": "expert", "panelist_2": "expert", "host": "moderator"},
],
)
# State schema
state_schema: type[BaseModel] = Field(
default=DebateState,
description="Pydantic model class for managing debate state and transitions",
)
# Engine configurations
engines: dict[str, AugLLMConfig] = Field(
default_factory=build_debate_engines,
description="LLM engine configurations for different participant roles",
)
[docs]
@field_validator("participant_roles")
@classmethod
def validate_participant_roles(cls, v: dict[str, str]) -> dict[str, str]:
"""Validate participant role assignments.
Args:
v (Dict[str, str]): Role assignments to validate.
Returns:
Dict[str, str]: Validated role assignments.
Raises:
ValueError: If role assignments are invalid.
"""
valid_roles = {
"pro",
"con",
"neutral",
"moderator",
"judge",
"jury",
"prosecutor",
"defense",
"witness",
"expert",
"panelist",
"government",
"opposition",
"chair",
"speaker",
"timekeeper",
}
for participant_id, role in v.items():
if not isinstance(participant_id, str) or not participant_id.strip():
raise ValueError("Participant IDs must be non-empty strings")
role_lower = role.lower().strip()
if role_lower not in valid_roles:
raise ValueError(
f"Role '{role}' not recognized. Valid roles: {
', '.join(valid_roles)
}"
)
return {pid: role.lower().strip() for pid, role in v.items()}
[docs]
@classmethod
def default(cls):
"""Create a default configuration for standard debate."""
return cls(
name="standard_debate",
debate_format="standard",
time_limit=120,
max_statements=3,
allow_interruptions=False,
voting_enabled=True,
)
[docs]
@classmethod
def presidential(cls):
"""Create a configuration for presidential debate."""
return cls(
name="presidential_debate",
debate_format="presidential",
time_limit=120,
max_statements=None,
allow_interruptions=True,
voting_enabled=False,
moderator_role="moderator",
)
[docs]
@classmethod
def trial(cls):
"""Create a configuration for a trial format."""
return cls(
name="trial_debate",
debate_format="trial",
time_limit=300,
max_statements=None,
allow_interruptions=False,
voting_enabled=True,
participant_roles={
"judge": "judge",
"prosecution": "prosecutor",
"defense": "defense",
"jury": "jury",
},
)
[docs]
@classmethod
def panel_discussion(cls):
"""Create a configuration for a panel discussion."""
return cls(
name="panel_discussion",
debate_format="panel",
time_limit=180,
max_statements=None,
allow_interruptions=True,
voting_enabled=False,
moderator_role="moderator",
)