Skip to content

Debate

Cluster: Uncategorised | Type: component | MCP Tools: None

Overview

Multi-agent debate loop with role-differentiated agents (Proposer, Critic, Devil's Advocate, Synthesiser, Verifier). Runs structured multi-round debates on a question and extracts consensus using a conservative keyword-overlap heuristic with an AgreementLevel classification. The block output exposes canonical reliability fields (completion_state, warning_card, evidence, request_id, task_id, run_id) so callers can gate degraded results without nested parsing.

Heuristic output, not verification

Debate is useful for surfacing competing viewpoints and stress-testing a proposed decision, but it is not a formal verifier or a high-confidence decision oracle. ConsensusExtractor uses floor_type="keyword_overlap": lexical overlap, not semantic entailment or proof. Treat consensus as a lightweight triage signal and review the transcript before acting on the result.

When DebateLoop cannot reach the configured LLM, fallback responses are explicitly marked with [MOCK], each fallback exchange uses evidence_kind="llm_fallback_mock", and the transcript is marked degraded=True. Do not treat degraded transcripts as model-backed analysis. All-mock transcripts return AgreementLevel.NONE from ConsensusExtractor.

When to use:

  • Stress-testing a proposed solution by running structured critique rounds
  • Generating diverse perspectives on a design decision before committing
  • Extracting a provisional consensus signal from adversarial agent dialogue

Example:

from mvp.debate import DebateLoop, DebateInput, DebateAgent, AgentRole, ConsensusExtractor

agents = [
    DebateAgent(name="Alice", role=AgentRole.PROPOSER),
    DebateAgent(name="Bob", role=AgentRole.CRITIC),
    DebateAgent(name="Carol", role=AgentRole.SYNTHESISER),
]
loop = DebateLoop()
transcript = loop.run(DebateInput(question="Should we use SQLite or PostgreSQL?", agents=agents, rounds=2))

if transcript.degraded:
    raise RuntimeError("Debate used mock fallback responses; configure an LLM before relying on it.")

extractor = ConsensusExtractor()
result = extractor.extract(transcript)
# result.agreement_level, result.dominant_position, result.confidence
# Consensus is heuristic; inspect transcript.exchanges before acting.

Works well with: goal_engine, align_specs, autonomous_orchestrator

Public API

AgentRole(str, Enum)

DebateAgent

Field Type Default
name str required
role AgentRole required

DebateConsensusError(ValueError)

The runtime did not produce a usable debate consensus decision.

ConsensusDecision

Outcome of a debate consensus assessment.

Field Type Default
agreement_level str AgreementLevel.NONE.value
dominant_position str ''
dissenting_views list[str] field(default_factory=list)
confidence float 0.0
rationale str ''
signals list[str] field(default_factory=list)
completion_state str 'qualified-draft'
degraded bool False
diverged_from_floor bool False
raw_response str ''

DebateConsensusRuntime(Protocol)

The grounded consensus-assessment surface debate gains.

Methods:

assess_consensus(transcript: DebateTranscript) -> ConsensusDecision

LLMDebateConsensusRuntime

Provider-neutral consensus runtime backed by G6's LLM caller interface.

Constructor:

Parameter Type Default
llm LLMCaller \| None None

Methods:

assess_consensus(transcript: DebateTranscript) -> ConsensusDecision

DebateConsensusPlanner

Runtime-first consensus facade with a real deterministic fallback.

Constructor:

Parameter Type Default
runtime DebateConsensusRuntime \| None None

Methods:

assess(transcript: DebateTranscript) -> tuple[ConsensusDecision, list[dict[str, Any]]]

AgreementLevel(str, Enum)

ConsensusResult

Field Type Default
agreement_level AgreementLevel required
dominant_position str required
dissenting_views List[str] required
confidence float required
transcript_length int required
floor_type str 'keyword_overlap'
floor_limitations str 'Keyword-overlap floor only; not semantic consensus, proof, or verification.'
completion_state str 'qualified-draft'

ConsensusExtractor

Extract consensus from a DebateTranscript using keyword overlap.

Methods:

extract(transcript: DebateTranscript) -> ConsensusResult

DebateInput

Field Type Default
question str required
agents List[DebateAgent] required
rounds int 1
context str ''

DebateExchange

Field Type Default
agent_name str required
agent_role str required
round_number int required
response str required
evidence_kind str 'model_inference'
diagnostic str ''

DebateTranscript

Field Type Default
question str required
context str ''
exchanges List[DebateExchange] field(default_factory=list)
rounds_completed int 0
degraded bool False

Methods:

history_text() -> str

DebateTurnRuntime(Protocol)

Runtime seam for generating one debate turn.

Methods:

generate_turn(agent: DebateAgent, question: str, transcript: DebateTranscript) -> tuple[str, str, str]

capabilities() -> dict[str, Any]

LLMDebateTurnRuntime

Default debate-turn runtime backed by the existing LLMBlock path.

Methods:

generate_turn(agent: DebateAgent, question: str, transcript: DebateTranscript) -> tuple[str, str, str]

capabilities() -> dict[str, Any]

DebateLoop

Multi-agent debate loop.

Constructor:

Parameter Type Default
use_mock_llm bool False
turn_runtime DebateTurnRuntime \| None None

Methods:

run(debate_input: DebateInput) -> DebateTranscript

DebateBlockInput(BaseModel)

Field Type Default
op str required
parameters dict[str, Any] Field(default_factory=dict)

DebateBlockOutput(BaseModel)

Field Type Default
op str ''
result dict[str, Any] Field(default_factory=dict)
message str ''
degraded bool False
confidence float 0.0
evidence_kind str ''
agentic_evidence dict[str, Any] \| None None
completion_state str 'qualified-draft'
warning_card dict[str, Any] \| None None
evidence dict[str, Any] Field(default_factory=dict)
request_id str \| None None
task_id str \| None None
run_id str \| None None
error_code str ''

DebateBlock(AIBlock)

AIBlock wrapper for multi-agent debate rounds and proposition submission.

Methods:

infer(input: DebateBlockInput) -> Result[DebateBlockOutput]

DebatePatternRuntime

Load-bearing context-minimization mechanism for the consensus runtime.

Field Type Default
position_limit int 24
char_limit int 600

Methods:

minimize_positions(transcript: Any) -> list[dict[str, str]]

Bound the transcript payload sent to the LLM (context minimization).

DebateSkill

Field Type Default
name str required
pattern_slug str required
description str required
capabilities tuple[str, ...] required
triggers tuple[str, ...] required
risk_notes tuple[str, ...] required
executable bool False

Methods:

compact() -> dict[str, Any]

DebateSkillCatalog

Methods:

list_skills() -> list[DebateSkill]

get(slug: str) -> DebateSkill | None

Functions

summarize_debate_agentic_evidence(decisions: list[dict[str, Any]]) -> dict[str, Any]

Summarise the runtime-vs-fallback decision trace for debate consensus.

agentic_planner_enabled(default_enabled: bool) -> bool

Decide whether the agentic debate consensus planner should be used.

validate_consensus_decision(decision: ConsensusDecision) -> None

Reject malformed consensus decisions (output-verification-loop).

deterministic_consensus(transcript: DebateTranscript, reason: str = 'deterministic fallback') -> ConsensusDecision

Real demoted fallback: mvp.debate.consensus.ConsensusExtractor.extract.

applied_agentic_patterns() -> list[dict[str, Any]]

Return compact metadata for the debate-applied patterns.

get_skill_catalog() -> DebateSkillCatalog