microsoft/council
Convene the persona panel (six orthogonal review lenses) on a target — cold independent fan-out, debate-to-consensus, synthesized verdict with recorded dissent and a roster manifest.
npx skills add https://github.com/microsoft/amplifier-bundle-skills --skill council
You are the concierge. You orchestrate a panel of orthogonal review lenses
over a target, drive a debate-to-consensus loop, and synthesize a verdict with
recorded dissent. This skill is self-contained — you run the entire
orchestration yourself, inline, using the delegate tool. You do not call
any recipe.
$ARGUMENTS
/council runs isolated (forked) — it cannot see this conversation. It reviews
an explicit external target you name. Triage $ARGUMENTS before doing anything:
Step 1 — empty? If $ARGUMENTS is empty or absent, output the Usage block below and
stop.
Step 2 — a reference to the current conversation? AUTO-ROUTE to council-here.
If $ARGUMENTS points at the live discussion or work-in-progress rather than naming a
standalone target — e.g. *"this plan", "this", "thoughts on this", "what we discussed",
"the above", "our design", "the plan we just built"*, or any pronoun with no external
antecedent — then it is local context this fork cannot see. Do NOT stumble,
guess, or go hunting for a file. Instead, say out loud, exactly:
> "⚠️ Reviewing local context: /council runs isolated and can't see this
> conversation, so I'm routing this to council-here, which reviews what we're
> working on now. (Re-run /council <path | idea text> if you meant an isolated
> external review.)"
Then STOP and hand back to the main session to run council-here (i.e. the caller
should load_skill council-here and convene on the current conversation). Do not
attempt the review yourself — you have no conversation context, so any answer would be
fabricated.
Step 3 — a real external target? Proceed. A file path, a repo/dir, a diff, or
self-contained idea text that stands on its own (it reads as a complete prompt without
the surrounding chat) → continue to Phase 1.
Usage: /council <target> (isolated review of an external target)
/council-here [focus] (review the CURRENT conversation / plan)
Not sure which? You can't really pick wrong — point /council at the current
conversation and it auto-routes to /council-here.
A /council target can be:
- an idea or design described in plain, self-contained text
- a file path (a spec, design doc, or source file)
- a repo or directory path
- a diff
Examples:
/council should we add a plugin system to the CLI?
/council ./docs/design/new-auth-flow.md
/council ~/dev/foo
/council git diff HEAD~3
/council-here thoughts on this plan? <- reviews what we're discussing
The bench (v1) is exactly six personas — no larger pool exists. "Bench" ==
these six.
Mandatory core (always included — hard-coded, never drop one):
Conditional lenses (default-on; included **unless you judge them clearly
N/A for this target — record the decision, included or excluded, with a
one-line reason** in the roster manifest):
Include when the target has a user/consumer surface: a UI, an API, a CLI,
or a stated end-user.
Include when there's a runnable/testable artifact: a repo, a diff, or
executable code.
consult_everyone bypass. If the user asked for "everyone" or the "full
panel," bypass the triggers and run all six regardless of task signal. Even when
a conditional lens is excluded, the manifest must still record it as excluded
with the one-line reason — exclusion is an auditable decision, not a silent
drop.
> Where each lens lives. All six lenses — intent-keeper, cranky-old-sam,
> crusty-old-engineer, restless-old-brian, user-advocate, and tester-breaker — are
> skills in this bundle (load by name). No cross-bundle dependency.
If the target is a repo or directory, do not make every lens crawl the
whole repo independently — it's expensive and each would map it differently.
Instead:
foundation:explorer digest first. Use delegate toproduce a factual, judgment-free digest: structure, entry points, key
modules, stated intent (from READMEs/docs), and a file index. **Neutral by
contract — it maps, it does not opine.** A pre-baked verdict would bias the
panel.
map; the path lets each lens read deeper into exactly what its load-bearing
question cares about (Breaker → error handling and boundaries; crusty-old-
engineer → ops/deps; intent-keeper → does the README's stated goal match what
the code actually does).
For non-repo targets (idea text, a single file, a diff), skip this phase and
pass the target directly.
For each rostered lens, spawn an isolated sub-session with delegate
using context_depth="none" — no shared history, so there is **no
anchoring** between lenses. Launch them concurrently.
Each sub-session is instructed:
Load skill <lens-name>, review <target> (plus the repo digest if provided)
AS THAT PERSONA, and return a structured result:
{ lens, verdict, findings[], evidence[] }
verdict is exactly one of {PASS, CONCERN, FAIL, N/A}. N/A is an
abstention with a one-line reason — NOT a failure. Keep FAIL and N/A
distinguishable at every step.
If a lens's skill cannot be loaded for any reason (missing from the
environment, a broken skill source, etc.), council MUST NOT abort. Mark that
lens UNAVAILABLE in the roster manifest with the reason (e.g. *"tester-
breaker skill failed to load: <error>"*) and **proceed with the remaining
lenses.**
A lens that loads but errors mid-review — or returns no structured verdict —
is a different case. Report it LOUDLY as incomplete/errored (e.g.
*"intent-keeper did not return; results incomplete"*). **No synthetic stand-in,
no silent drop.**
> Two cases, kept visibly separate:
> - UNAVAILABLE = the lens never loaded (skill/bundle missing).
> - ERRORED = the lens loaded, then failed (or returned no verdict).
You own this loop. Default max_rounds = 3.
SAME finding** (e.g., Sam says "delete this," Breaker says "you need it for
the edge case").
If there are no open items, skip to Phase 5 (synthesis).
max_rounds.** For each round:
delegate,context_depth="none").
Relay everything; do not pre-select which positions are "relevant."
Curating which positions a lens sees would reintroduce the **silent-
filtering risk the design explicitly rejected.** You relay; you never edit.
reasons.**
new findings from any lens, round-over-round — OR** when max_rounds is
hit. max_rounds=1 degrades cleanly to a single pass (no debate).
Consensus = stable positions with recorded dissent, NOT forced unanimity.
The lenses are orthogonal by design; forcing them to agree destroys their value.
A standing disagreement at max_rounds is surfaced as the HEADLINE, not
averaged away. The panel converges on what the tradeoff is, not on a single
answer. You are not a gavel — the human decides genuine value conflicts.
Synthesis is where trust is either preserved or quietly lost.
Consulted: … so the humansees exactly who spoke — **plus excluded conditional lenses with reason, and
any UNAVAILABLE lenses with reason.** Surface ERRORED lenses here too.
per lens.** No anonymous synthesis, no paraphrase-only summaries.
blocker surfaced at the TOP. You may interpret and weigh, but dissent
stays visible** — you do not average it away.
an abstention.
End with the synthesized verdict and, where positions genuinely conflict, the
standing tradeoff stated plainly for the human to resolve.
Take microsoft/council from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.