Skip to content
Back to skills

Council

ASecurity

Structured multi-agent debate for non-trivial decisions. Load when the user asks to "debate this", "get second opinions", "help me decide", "run this by council", or invokes `/council`. Orchestrates 3-10 persona CLI sessions across N rounds with structured verdicts, a live chamber board, and interactive interludes, then a clean synthesizer sub-agent writes the final decision report.

  • 13 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 29, 2026
ai-agentsrustgobashreactapi

Works with

  • claude code
  • terminal
  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add meanllbrl/dreamcontext --skill council --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Council?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Council
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/meanllbrl-council/badge)](https://www.skillsdirectory.com/skills/meanllbrl-council)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: council
description: >
  Structured multi-agent debate for non-trivial decisions. Load when the user asks to
  "debate this", "get second opinions", "help me decide", "run this by council", or
  invokes `/council`. Orchestrates 3-10 persona CLI sessions across N rounds with
  structured verdicts, a live chamber board, and interactive interludes, then a clean
  synthesizer sub-agent writes the final decision report.
tags: [council, debate, decision, sub-agents, orchestration, verdicts]
alwaysApply: false
---

# Council v2, The Chamber: persona sessions debate, a clean judge decides

You are the **orchestrator** of a council: a cast of persona sessions that debate a
non-trivial decision across rounds, submitting structured verdicts as they go, while
you run the chamber. You stay **light**: you never argue a side yourself, and you
never read full persona reports, only `council summaries`, `council board`, and
`council timeline` output. Personas build their own context on disk via the
dreamcontext CLI so rounds compound without ballooning your context.

You are also the **single writer** of `debate.md`. Personas write only their own
persona folder; the session registry and any mid-debate constraint edits go through
you (or through the CLI commands built for them).

## When to invoke

- `/council` (primary entry)
- "debate this" / "get a second opinion on..." / "help me decide..."
- "run this by council" / "council mode"

**Use it for**: architecture choices, vendor switches, hiring decisions, product
scope calls, incident post-mortems, anything where perspective diversity matters.

**Do NOT use it for**: quick factual lookups, mechanical refactors, "what's the best
variable name", or anything where the answer is knowable without debate. A debate
spends real tokens; if the answer is obvious, say so and answer.

## Commitment ritual (do this FIRST, non-negotiable)

Before creating anything, **YOU MUST**:

1. **Announce**: restate the decision question back to the user in one sentence, and
   say "I'm convening the council."
2. **Create a TodoWrite list** with the phases as items: scope, create + roster,
   one item per round, synthesis, report + promote. A phase is not done until its
   exit condition holds.
3. **Track round state in TodoWrite**: each round's todo carries the live state,
   e.g. `Round 2: 3/5 verdicts in, waiting on user-advocate`. This keeps the debate
   externally observable, so you cannot silently skip a round or a missing persona.

Skipping the ritual is the first step toward a sloppy debate. Don't.

## Depth router

| Depth | Rounds | Personas | Interludes | Use when |
|---|---|---|---|---|
| **Quick** | 1 | 3 | none | Low-stakes, reversible, you just want three angles fast |
| **Standard** (DEFAULT) | 2 | 4-6 | after round 1 | Most real decisions |
| **Deep** | 3 | 5-8 | after every round, cross-examination expected | High-stakes, contested, many dimensions |

**Hot override:** if the decision is **irreversible or costly to reverse** (vendor
lock-in, public API contract, layoff, migration with no rollback), force **Deep**
regardless of what the user picked. Say you did and why.

## Phase 0: scope (ONE batched ask)

Ask the user **one batched message** covering everything, then go hands-off until
the first interlude:

1. **Confirm the question verbatim** ("Is this the question: ...?").
2. **Depth**: Quick / Standard / Deep (recommend one, note the hot override).
3. **Decision options**: named options (A/B/...) or open-ended? If named, capture
   `key=label` pairs for `--options`.
4. **Interludes on or off**: do they want to intervene between rounds?

**Autonomous fallback**: running with no user available, default to Standard depth,
open options, interludes off. Record the chosen defaults in `debate.md` constraints
via `council inject` so the record shows they were defaults, not answers.

## The two-lane model (read before dispatching anything)

| Lane | Who | Context | Rule |
|---|---|---|---|
| **Debaters** | persona ×N | CLI sessions, spawned once at round 1, resumed each later round | Resume pays only the delta; the persona keeps its own memory of the debate |
| **Judge** | `council-synthesizer` | Claude Code Agent-tool subagent | Always clean and fresh, meets the debate only through files and CLI output, **never forked, never resumed** |

**Never make the judge a debater.** A synthesizer that lived through the debate
inherits its framing and anchors toward the loudest persona. The clean-context
Agent-tool synthesizer is the design, not an option.

### Persona session mechanics (proven flags, use exactly these)

Personas are spawned and driven via the `claude` CLI, not the Agent tool:

1. **Spawn each persona at round 1** (one spawn per persona, run them in parallel
   as background Bash calls):
   ```
   claude -p "<brief>" --model <m> --output-format json \
     --permission-mode acceptEdits \
     --allowedTools "Bash" "Read" "WebSearch" "WebFetch" < /dev/null
   ```
   `< /dev/null` matters: a headless `-p` invocation with no stdin redirect can hang
   waiting for input. The permission flags are not optional: without them a headless
   session stalls at its first CLI write with a "please approve" message and zero
   work done. Parse the JSON response for `session_id`.

   The `<brief>` contains: debate_id, persona slug, round number, and the standing
   orders: first call `dreamcontext council round-context <id> <slug>`, submit
   `dreamcontext council verdict` before `dreamcontext council report append`,
   follow the council-persona contract.

2. **Record session ids in the Session registry.** You (single writer) append this
   block to `debate.md` after the round-1 spawns, and keep it updated:
   ```
   ## Session registry
   <persona-slug>:        <session_id>
   <persona-slug>-refork: <session_id | ->
   ```

3. **Resume each persona for round N ≥ 2** with only the delta (the round number
   and any directives; the persona re-reads peers itself via `round-context`):
   ```
   claude -p --resume <session_id> "<round N brief, delta only>" \
     --output-format json --permission-mode acceptEdits \
     --allowedTools "Bash" "Read" "WebSearch" "WebFetch" < /dev/null
   ```

4. **Re-fork rule**: a persona that stops engaging (repeats its prior round nearly
   verbatim, ignores directives) gets **ONE** fresh spawn with the original brief
   plus a note of what it must react to. Record the new id under
   `<slug>-refork`. If the fresh spawn also disengages, note it for the
   synthesizer and move on; do not loop.

5. **Verify before trusting**: after each round's sessions return, `council round
   end` lists any personas whose report is missing. A confident session reply plus
   a missing report means the session stalled; resume it with the reminder, or
   re-fork.

**Fallback mode (no CLI spawn available)**: dispatch `council-persona` Agent-tool
subagents in parallel instead, one per persona per round, in a single message,
passing debate_id, slug, round, and model. Everything else (verdict before report,
round-context first, board, interludes) works identically. Document in the debate
log which mode ran.

## Orchestration flow

```mermaid
flowchart TD
    P0[Phase 0, one batched ask: question, depth, options, interludes] --> DR[Depth router: Quick / Standard / Deep, irreversible forces Deep]
    DR --> C[council create with --rounds and --options]
    C --> R[Generate roster, council agent create per persona, show to user]
    R --> RS[Round N: council round start]
    RS --> D[Dispatch personas in parallel: spawn round 1, resume later rounds]
    D --> RE[council round end, re-dispatch any missing personas]
    RE --> B[council board, SHOW the output to the user]
    B --> CONV{Convergence check}
    CONV -->|90 percent or more, two rounds in a row| CV[Offer Call the vote]
    CONV -->|rounds remain| I{Interludes on?}
    I -->|yes| IC[Intervention cards 1-6]
    IC --> RS
    I -->|no| RS
    CONV -->|rounds done, convergence under 40 percent| ESC[ESCALATE: offer one extra round or a split verdict]
    CV --> S
    CONV -->|rounds done| S[council synthesize, dispatch clean council-synthesizer]
    ESC -->|extra round| RS
    ESC -->|split verdict| S
    S --> X[Optional: Excalidraw decision board, soft-skip if pack absent]
    X --> F[council complete, show Verdict, promote y/n/later]
    F --> L[council live clear]
```

## Phase 1: create the debate

```
dreamcontext council create "<topic>" --rounds <N> [--interrupt] [--options "A=Keep sync,B=Drop it"]
```

Capture the returned `debate_id` (printed on its own last line). Pass `--options`
when the user named options in Phase 0; stances then must match an option key. With
no `--options`, stances are free-form and first-seen stances become dynamic options.

## Phase 2: generate personas (3-10, per depth)

Generate personas **specific to this topic**. No preset library. Each persona has:
- A **slug** (kebab-case): `migration-risk-auditor`, `growth-cfo`, `user-advocate`
- A **model**: `opus` for strategy-heavy roles, `sonnet` for most, `haiku` for
  narrow advocates. Vary them; cognitive diversity matters.
- 2-5 **aspects**: `[data-integrity, downtime, rollback]`
- A **body** (100-250 words): who they are, what they obsess over, what biases they
  bring, what would make them push back.

For each persona:
```
echo "<body>" | dreamcontext council agent create <debate_id> <slug> \
  --model <model> --aspects "<aspect1,aspect2,aspect3>"
```

Show the roster to the user and let them adjust before round 1 (skip the pause in
autonomous mode).

## Phase 3: run each round

```
dreamcontext council round start <debate_id> <N>
```

For N ≥ 2 this injects prior-round peer summaries into each persona's context.

**Dispatch all personas in parallel** (round 1: spawn; round N ≥ 2: resume; see
mechanics above). Every persona MUST, per its contract:
1. First call: `dreamcontext council round-context <id> <slug>` (now includes the
   verdict landscape, injected facts, and its pending directives).
2. Submit its verdict **before** its report:
   `dreamcontext council verdict <id> <slug> <round> --stance <s> --conviction <n> --headline "<h>" [--concession "<c>"]`
3. Last call: `dreamcontext council report append <id> <slug>`.

After all personas return:
```
dreamcontext council round end <debate_id> <N>
dreamcontext council summaries <debate_id> <N>
dreamcontext council board <debate_id>
```

**Show the `council board` output to the user every round.** It is the chamber's
scoreboard: per-persona stance, conviction bars, shift markers, convergence meter.
`summaries` now appends each persona's stance and conviction line; read it, never
the full reports.

## Interludes (the interactive layer)

When interludes are on and a user is present, offer these **intervention cards**
after each non-final round, as a numbered pick list:

| # | Card | What you run |
|---|---|---|
| 1 | **Inject fact** | `dreamcontext council inject <id> <fact...>` appends it to Constraints & Known Facts; personas see it next round |
| 2 | **Cross-examine** | `dreamcontext council question <id> <slug> <question...>` queues a directive; the persona must answer in `### Cross-examination` next round |
| 3 | **Steelman swap** | a `council question` directive ordering the persona to argue the OPPOSING stance for one round, then return to honest conviction |
| 4 | **Wildcard persona** | `council agent create` a new persona mid-debate, spawn it fresh next round |
| 5 | **Call the vote** | skip remaining rounds, go straight to synthesis |
| 6 | **Continue** | no intervention, next round |

Multiple cards can stack in one interlude (e.g. inject a fact AND cross-examine).
With interludes off, go straight to the next round.

## Convergence rules (how the debate ends)

- The debate ends when **the planned rounds are done**, OR
- **Convergence ≥ 90% two rounds in a row**: early consensus, offer **Call the
  vote** rather than grinding out remaining rounds, OR
- **The user calls the vote** at any interlude.
- **Escalate instead of forcing a verdict** when convergence is **< 40% after the
  planned rounds**: tell the user the chamber is genuinely split and offer either
  one extra round or a split verdict (the synthesizer records both positions with
  revisit conditions). Never paper over a split with fake confidence.

## Phase 4: synthesize

```
dreamcontext council synthesize <debate_id>
```

This prints the manifest of files the synthesizer must read. Dispatch the
`council-synthesizer` **Agent-tool subagent** (single call, model: opus, clean
context) with the manifest. It also reads `verdicts.json` and runs
`dreamcontext council timeline <debate_id>` itself; do not paste reports into its
prompt.

The synthesizer writes `_dream_context/council/<debate_id>/final-report.md` with
the v2 section order: Verdict, Decision card, Why, Position timeline, What was
debated, Minority view & revisit conditions, Open risks, Appendix.

### Optional: Excalidraw decision board

If the excalidraw skill/pack is available in this session, generate
`_dream_context/council/<debate_id>/decision-board.excalidraw.md` from
`dreamcontext council timeline <debate_id> --json`: a verdict KPI tile, a
per-persona conviction line chart across rounds, the decision-card table, and a
minority panel. **Soft-skip silently when the pack is absent**; the debate is
complete without it.

## Phase 5: complete + promote

```
dreamcontext council complete <debate_id>
```

Show the user the `## Verdict` section (read just that section) and the report
location. Ask:

> "Promote this decision to knowledge? (y / n / later)"

- **y** → `dreamcontext council promote <debate_id>` (writes
  `_dream_context/knowledge/decision-<slug>.md`, trimmed to Verdict, Decision card,
  Why, Minority view & revisit conditions, Open risks)
- **n / later** → leave as-is. The next sleep consolidation picks it up
  (`dreamcontext council list --unpromoted`) and decides from engagement signals.

Then clean up the live surface:
```
dreamcontext council live clear
```

## Live surfaces

The CLI writes `_dream_context/tmp/.council-live.json` **automatically** on every
state-changing command (create, verdicts, round start/end, inject, synthesize,
complete). Your only live-state duties:

1. **Show `council board` output to the user each round** (the terminal surface).
2. **Run `dreamcontext council live clear` after the final report** (or after an
   abandoned debate).

The dreamcontext app renders a live chamber panel automatically from the same file —
above the composer in Terminal view, on the live rail in Chat view: round dots, persona
stance dots, convergence meter, click for the full chamber view. **There is no browser
viewer to start**; do not launch one.
Live-file writes are telemetry, never a gate: a failed write never blocks a round.
`dreamcontext council demo-live` fakes a live state to preview the panel.

## Red Flags: STOP, you're about to break the chamber

| Thought | Reality |
|---|---|
| "I'll read one full report, just to be sure." | You never read full reports. Board, summaries, timeline. That's it. |
| "I'll add my own take as a seventh voice." | You never debate. Your opinions belong nowhere in the record; add a persona if a lens is missing. |
| "The verdicts are obvious, I'll skip the board." | The board is shown to the user every round. It is the product surface of the debate. |
| "I'll synthesize myself, dispatching is overhead." | The synthesizer is always a clean Agent-tool subagent. You have been staring at summaries for N rounds; you are anchored. |
| "This persona went quiet, I'll write its verdict for it." | Never fabricate a verdict. Resume it, re-fork once, or let `round end` record it missing. |
| "Convergence is 95%, but the plan says 3 rounds, so 3 rounds." | Two rounds at ≥ 90% means offer Call the vote. Grinding a settled debate wastes tokens. |
| "Convergence is 30% but I'll force a confident verdict anyway." | Below 40% after planned rounds you escalate: extra round or split verdict. Fake confidence is worse than a recorded split. |
| "I'll resume the synthesizer from a persona session, it has context." | Never. Inherited framing produces a rubber stamp, not a judgment. |
| "Interludes slow things down, I'll skip offering them." | If the user turned interludes on, the cards are offered every non-final round. |
| "The live file write failed, abort the round." | Live state is telemetry. Swallow it and continue. |

## Rationalization table

| If you think... | The truth is... | So... |
|---|---|---|
| "Personas will converge anyway, why spawn sessions?" | Sessions give personas memory: round 3 reactions to round 1 claims are what make a debate compound. | Spawn once, resume with deltas. |
| "Asking the user about options up front is friction." | Registered options make verdicts comparable and the board readable. | One batched Phase 0 ask, then hands-off. |
| "A repeating persona just has strong convictions." | Verbatim repetition is disengagement, not conviction. | One fresh re-fork with what it must react to. |
| "The minority view lost, it barely needs a mention." | The minority view plus observable revisit conditions is half the report's long-term value. | Make sure the synthesizer states when the minority becomes right. |
| "Skipping `council verdict` saves the persona a call." | Without verdicts there is no board, no timeline, no convergence signal. | Verdict before report, every persona, every round. |

## Hard rules

- **You never debate yourself.** No orchestrator opinions in reports, constraints,
  or synthesis. Missing lens → add a persona.
- **You never read full persona reports.** Only `council summaries`,
  `council board`, `council timeline`, and the `## Verdict` section of the final
  report. Per-debate orchestrator budget stays under ~20K tokens; if it doesn't,
  you are reading full reports somewhere. Stop.
- **Personas are CLI sessions** (spawn round 1, resume with deltas, one re-fork on
  disengagement, parallel via background Bash). **The synthesizer is always a
  clean Agent-tool subagent**, never forked, never resumed. Fallback: Agent-tool
  personas when CLI spawn is unavailable.
- **You are the single writer of `debate.md`** (session registry included).
  Personas touch only their own `<slug>/` folder.
- **Every persona submits `council verdict` before `report append`**, every round.
- **Show `council board` to the user every round.** Run `council live clear` after
  the final report. No browser viewer exists for council; never launch one.
- **Do not skip Phase 0.** One batched ask; autonomous fallback is Standard, open
  options, interludes off, defaults recorded.
- **Persona slugs are unique per debate.**
- **Irreversible decisions force Deep depth.**

## Relationship to other orchestration surfaces

| Surface | Stage | Relationship |
|---|---|---|
| `council` (this) | Decide between options | Owns the debate → verdict lifecycle; produces a decision, not code. |
| `goal-skill` | End-to-end build of a goal | Use *after* council when the decision needs building; council's promoted decision becomes goal-skill's input. |
| `multi-review` | Post-implementation review | Reviews a diff, not a decision. A council may cite review findings as injected facts. |
| `council-synthesizer` agent | Final judgment gate | The only reader of full reports; always clean. |

## Slash command wiring

`/council` invokes this skill. Natural-language triggers in **When to invoke** also
load it. `debate-protocol.md` (sub-skill) holds the exact command table, failure
modes, and file layout; load it when you need the precise sequence.

Files in this skill

  • SKILL.md19.2 KB
  • debate-protocol.md9.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…