Back to skills

Debate Orchestrator

Orchestrates formal debates with proposition and opposition sides, coordinating debaters and judges through structured exchanges. Use when running debate exchanges, managing debate rounds, or continuing interrupted debates.

4 stars
0 votes
0 copies
0 views
Added 12/19/2025
data-aipython

Install via CLI

$openskills install urav06/dialectic
Download Zip
Files
SKILL.md
---
name: debate-orchestrator
description: Orchestrates formal debates with proposition and opposition sides, coordinating debaters and judges through structured exchanges. Use when running debate exchanges, managing debate rounds, or continuing interrupted debates.
---

# Debate Orchestrator

Manages formal debate execution through deterministic state tracking and resumability.

## State Machine

Debates cycle through 2 phases per exchange:

| current_phase | Action Required |
|---------------|-----------------|
| `awaiting_arguments` | Spawn both debaters in parallel |
| `awaiting_judgment` | Spawn judge to evaluate all new arguments |

After judgment: cycle repeats with `current_exchange` incremented.

**Key Properties:**
- No "complete" state - orchestrator decides when to stop based on requested exchange count
- Parallel execution - both sides argue simultaneously each exchange
- Resumable - read state, execute required action, repeat
- Exchange 0 is special (opening) - both sides produce 3 independent arguments
- Exchange 1+ are rebuttal - sides produce single arguments with attacks/defends

## Running Exchanges

### 1. Read State

Check `{debate}/debate.md` frontmatter (JSON format):
```json
{
  "current_exchange": 0,
  "current_phase": "awaiting_arguments"
}
```

Extract motion from the `# Motion` section (first markdown heading after frontmatter).

### 2. Determine Exchange Type

**Opening Exchange**: `current_exchange == 0`
- Both debaters produce 3 independent arguments simultaneously
- Judge scores all 6 arguments

**Rebuttal Exchange**: `current_exchange >= 1`
- Both debaters produce 1 argument simultaneously
- Judge scores both new arguments

### 3. Execute Based on Phase + Exchange Type

#### Opening Exchange (Exchange 0)

When `current_exchange == 0` and `current_phase == awaiting_arguments`:

**Load template:**

Read `templates/debater-opening.md` from this skill's directory.

**Spawn both debaters in parallel:**

Use a single message with two Task tool invocations to spawn both debaters simultaneously.

For each side (`proposition` and `opposition`):

1. Substitute placeholders in template:
   - `{motion}`: Extracted motion text
   - `{side}`: Side name (`proposition` or `opposition`)

2. Spawn debater:
   ```
   Use Task tool with subagent_type: "debater"
   Prompt: [substituted template content]
   ```

**Process outputs:**

After both debaters complete:

1. Write proposition output to `/tmp/prop_arg.json`
2. Write opposition output to `/tmp/opp_arg.json`
3. Execute the python package `debate_ops`: `python3 {skill_base_dir}/debate_ops process-exchange {debate} 0 --prop-file /tmp/prop_arg.json --opp-file /tmp/opp_arg.json`

Check result JSON for errors or warnings. On errors, state remains unchanged - report to user and halt. On warnings, note them and continue.

The script creates 6 argument files: `prop_000a.md`, `prop_000b.md`, `prop_000c.md`, `opp_000a.md`, `opp_000b.md`, `opp_000c.md`

State automatically updates to `current_phase: awaiting_judgment`.

**Judge opening arguments:**

When `current_exchange == 0` and `current_phase == awaiting_judgment`:

**Load template:**

Read `templates/judge.md` from this skill's directory.

**Substitute placeholders:**

- `{argument_files}`: Space-separated list of all 6 opening arguments:
  ```
  @{debate}/arguments/prop_000a.md @{debate}/arguments/prop_000b.md @{debate}/arguments/prop_000c.md @{debate}/arguments/opp_000a.md @{debate}/arguments/opp_000b.md @{debate}/arguments/opp_000c.md
  ```
- `{motion}`: Extracted motion text

**Spawn judge:**

```
Use Task tool with subagent_type: "judge"
Prompt: [substituted template content]
```

**Process output:**

1. Use Write tool to save agent output to `/tmp/judge.json`
2. Execute the python package `debate_ops`: `python3 {skill_base_dir}/debate_ops process-judge {debate} --json-file /tmp/judge.json`

Check result JSON for errors or warnings. On errors, state remains unchanged - report to user and halt. On warnings, note them and continue.

State automatically updates to `current_phase: awaiting_arguments`, `current_exchange: 1`.

#### Rebuttal Exchange (Exchange 1+)

When `current_exchange >= 1` and `current_phase == awaiting_arguments`:

**Build argument context:**

1. List all files in `{debate}/arguments/`
2. Separate into proposition and opposition arguments:
   - Proposition: Files matching `prop_*.md`
   - Opposition: Files matching `opp_*.md`
3. Filter to arguments from previous exchanges only:
   - Extract exchange number from filename (e.g., `prop_003` → exchange 3)
   - Include only arguments where exchange < current_exchange
4. Sort by exchange number (chronological order)

**Load template:**

Read `templates/debater-rebuttal.md` from this skill's directory.

**Spawn both debaters in parallel:**

Use a single message with two Task tool invocations to spawn both debaters simultaneously.

For proposition debater:
- Substitute placeholders:
  - `{motion}`: Extracted motion text
  - `{side}`: `proposition`
  - `{exchange}`: Current exchange number
  - `{your_arguments}`: Newline-separated list: `@{debate}/arguments/prop_000a.md`, `@{debate}/arguments/prop_000b.md`, etc.
  - `{opponent_arguments}`: Newline-separated list: `@{debate}/arguments/opp_000a.md`, `@{debate}/arguments/opp_000b.md`, etc.

For opposition debater:
- Substitute placeholders:
  - `{motion}`: Extracted motion text
  - `{side}`: `opposition`
  - `{exchange}`: Current exchange number
  - `{your_arguments}`: Newline-separated list of opposition arguments
  - `{opponent_arguments}`: Newline-separated list of proposition arguments

**Process outputs:**

After both debaters complete:

1. Write proposition output to `/tmp/prop_arg.json`
2. Write opposition output to `/tmp/opp_arg.json`
3. Execute the python package `debate_ops`: `python3 {skill_base_dir}/debate_ops process-exchange {debate} {current_exchange} --prop-file /tmp/prop_arg.json --opp-file /tmp/opp_arg.json`

Check result JSON for errors or warnings. On errors, state remains unchanged - report to user and halt. On warnings, note them and continue.

State automatically updates to `current_phase: awaiting_judgment`.

**Judge rebuttal arguments:**

When `current_exchange >= 1` and `current_phase == awaiting_judgment`:

**Load template:**

Read `templates/judge.md` from this skill's directory.

**Substitute placeholders:**

- `{argument_files}`: Space-separated list of both new arguments:
  ```
  @{debate}/arguments/prop_{current_exchange:03d}.md @{debate}/arguments/opp_{current_exchange:03d}.md
  ```
- `{motion}`: Extracted motion text

**Spawn judge:**

```
Use Task tool with subagent_type: "judge"
Prompt: [substituted template content]
```

**Process output:**

1. Use Write tool to save agent output to `/tmp/judge.json`
2. Execute the python package `debate_ops`: `python3 {skill_base_dir}/debate_ops process-judge {debate} --json-file /tmp/judge.json`

Check result JSON for errors or warnings. On errors, state remains unchanged - report to user and halt. On warnings, note them and continue.

State automatically updates to `current_phase: awaiting_arguments`, `current_exchange` incremented.

### 4. Decide When to Stop

After each phase, check if you should continue:
- Read the updated state from `{debate}/debate.md`
- Compare current exchange number to requested total exchanges
- If sufficient exchanges completed: stop and report
- Otherwise: loop back to step 1

The state itself doesn't track "completion" - you decide when done based on user request.

## Error Handling

Processing scripts return:
```json
{
  "success": true/false,
  "argument_id": "prop_001" | ["prop_000a", "prop_000b", "prop_000c"],
  "errors": ["fatal errors"],
  "warnings": ["non-fatal warnings"]
}
```

**On errors:**
- State remains unchanged - can safely retry
- Report error to user
- Ask how to proceed (retry, skip, abort)

**On warnings:**
- Note them
- Continue execution
- Mention warnings in completion summary

Note: By default the `tmp` files get deleted by the script. But if you face errors while writing to a `tmp` file because it already exists, just `Read` it and try again.

## Resumability

Execution can be interrupted at any point and resumed by reading state:
- State indicates exactly what phase is needed next
- Execute that phase
- State updates atomically on success
- On failure, state remains unchanged - retry is safe

## Completion Report

When requested exchanges complete, report current state:

```
✓ Completed {N} exchanges for '{debate_slug}'

**Current Scores** (zero-sum tug-of-war):
- Proposition: {total} ({count} arguments)
- Opposition: {total} ({count} arguments)

**Next steps**:
- Continue debating: `/debate-run {debate_slug} X` to run X more exchanges
- Generate report: `/debate-report {debate_slug}` to create comprehensive analysis with visualizations
```

Extract totals and counts from `cumulative_scores` in `{debate}/debate.md` frontmatter.
Total exchanges = current_exchange from debate.md.

**Note on zero-sum scoring:** Positive total = winning, negative total = losing, zero = even. One side typically has positive total, the other negative (tug-of-war).

Comments (0)

No comments yet. Be the first to comment!