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.