Ai council review
Convene a council of ~4 frontier models via the OpenRouter API for independent parallel reviews of a PR, plan doc, or files, then synthesize agreements and dissents in-session. Use for high-stakes or contested changes, before irreversible decisions, or when one extra model's opinion is not enough — costs real money per run. Triggers on /ai-council-review, "council review", "panel review", "multi-model review", "review with multiple models", "ask several models", "get a third opinion", "high-stakes review", "openrouter review". For a quick single-model second opinion, use ai-review instead.From its SKILL.md
npx -y skills add eins78/agent-skills --skill ai-council-reviewAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- reads credentialsReads from 1 credential source: `OPENROUTER_API_KEY`.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 4 commands, including `node ${CLAUDE_SKILL_DIR}/scripts/council.mjs review <flags> --dry-run` and 3 more.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.7 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it
AI Council Review
Several frontier models review the same material in parallel — blind to each other — via one API (OpenRouter). A dispatch script handles fan-out, cost gating, and clustering; you synthesize, because you can do the one thing the council cannot: verify findings against the actual repository.
This is the heavyweight sibling of ai-review (single model, $0.03). A
council run costs real money ($0.30–0.90 with default presets). Use it for
high-stakes decisions, not routine diffs.
Data leaves the machine — confirm before first dispatch
Everything submitted (diffs, plan docs, file contents) is sent to the OpenRouter API and forwarded to multiple third-party model providers (different companies, different data-retention policies). For private or proprietary code this means unreleased source leaves the machine.
- Before the FIRST council run in a session, confirm with your human partner that sending this content to external providers is acceptable — especially in private repos or anything under NDA. Consent given for this repo earlier in this session carries over; do not re-ask per run.
- Reduce exposure: review the diff, not the whole tree; never include
.envfiles, credentials, or customer data in the input. - Account-wide tightening: OpenRouter privacy settings (disable logging, restrict to ZDR-eligible providers).
Prerequisites
- Node.js >= 20 (
node --version) OPENROUTER_API_KEYexported (get one: https://openrouter.ai/keys). The script reads it from the environment only and never prints it. If it is missing, dispatch exits with code 4 — ask your human partner; do NOT hunt for keys in keychains, dotfiles, or session archives.
CRITICAL rules
- Never fabricate or substitute a council opinion. If members fail or
quorum is not met, report that and offer the
ai-reviewfallback — do not write "what the model would probably say", and do not pass your own review off as a member's. - Never pass
--yeson your own.--yesasserts that your human partner saw the printed cost estimate and approved it in this session. Budget gate refusals (exit 3) are a stop, not an obstacle to route around. - Never skip the synthesis protocol. Raw per-model output is not the deliverable; the verified, dissent-preserving report is.
Workflow
Script: ${CLAUDE_SKILL_DIR}/scripts/council.mjs (always via this absolute
path — never a relative ./scripts/...).
1. Classify
| Input | Flags | Rubric |
|---|---|---|
| GitHub PR | --pr <N> | --rubric code |
| Unstaged / staged / branch diff | (default) / --staged / --branch [base] | --rubric code |
| Plan or design doc | <file> or --plan <file> | --rubric plan |
| Any other document/files | <file...> or --input-file <f> | --rubric doc |
Preset: code rubric → --preset code; otherwise the default preset is
already right. --models a,b,c overrides for custom councils.
--personas runs the council in coverage mode: each member gets a
distinct focus lens (correctness, security, design, testing, operations)
on top of the shared rubric. This trades consensus signal for breadth —
agreement counting is invalid across different assignments, and the
synthesis protocol switches to coverage mode. Prefer it for broad material
(a large plan, a many-concern diff); prefer the identical-rubric default
when the question is "is this correct?" and agreement should mean
something.
2. Estimate (spend-free)
node ${CLAUDE_SKILL_DIR}/scripts/council.mjs review <flags> --dry-run
Show the user the per-model table and total. If the estimate exceeds the confirmation threshold (default $1), you MUST get an explicit go-ahead in this session before step 3.
3. Dispatch (1–4 minutes — run in background)
node ${CLAUDE_SKILL_DIR}/scripts/council.mjs review <same flags> [--yes]
The script fans out in parallel, retries once on 429/5xx, aborts hung
members at the timeout, persists everything, and prints RUN_DIR=<path> as
its last line.
| Exit | Meaning | Your move |
|---|---|---|
| 0 | Quorum met (check degraded in manifest) | Synthesize (step 4) |
| 1 | Usage/input error (bad slug, empty diff, oversized payload) | Fix per the message; slug errors include suggestions — update roster, retry |
| 2 | Quorum failed | Report which members failed and why; offer ai-review fallback; do NOT synthesize or self-substitute |
| 3 | Budget gate blocked (nothing sent) | Relay the estimate to your human partner; only proceed how they decide |
| 4 | API key missing/rejected | Ask your human partner to set OPENROUTER_API_KEY |
4. Synthesize
Follow ${CLAUDE_SKILL_DIR}/references/synthesis.md step by step. Core
moves: members are anonymized (member-A…) — do not open
roster-key.json until the report step; agreement is counted over
delivered members; parse-failed members' raw text is read and included; top
findings are verified against the actual repo before being reported;
dissent is preserved as contested items and minority reports; ranking is
verified > severity > agreement > confidence.
5. Report
Write report.md into the run dir per
${CLAUDE_SKILL_DIR}/references/report-template.md; give the user the
condensed version in chat with actual vs estimated cost. Then record the
verification outcomes (outcomes record, synthesis protocol step 8) — the
archive is what makes future rosters evidence-based.
6. Optional: post to the PR
Only on explicit user request, post findings with gh pr comment (or a
formal review via gh api). The script never posts anywhere.
Cost pattern: two-stage triage (optional)
A suggestion for material that may not need a frontier council — nothing enforces it:
- Run
--preset budget(3 cheaper members) first. - Escalate to
default/maxonly if the budget run produced majors/blockers or contested clusters — objective properties ofclusters.json, not a feeling. - A clean budget run (approvals + nits) is a result: report it and stop.
Each stage passes the same estimate and consent gates; escalation is a second run with its own estimate. Prior art: cascade cost controls (cheap-first with objective escalation triggers).
Re-reviewing after fixes
Each cluster in clusters.json has a fingerprint stable across runs
(built from files + title tokens, not member labels or line numbers). When
a council run follows an earlier run of the same material:
- Compare fingerprints against the previous run's
clusters.json; classify clusters as new / persisting / resolved. Fingerprints are a hint — confirm matches semantically before reporting them. - Stuck rule: if the same blocking findings (by fingerprint) survive two consecutive runs, do not propose a third run — the council has said what it has to say. Recommend human judgment on the persisting blockers instead. (Cost/termination gate from prior art; see README provenance.)
Configuration
Precedence: flags > AI_COUNCIL_* env > repo .ai-council.json >
~/.config/ai-council-review/config.json > bundled
references/presets.json (presets: default, code, budget, max,
smoke; scalars: budgetUsd, confirmThresholdUsd, timeoutMs,
quorum, preset).
Useful env: OPENROUTER_BASE_URL (testing), COUNCIL_TIMEOUT_MS,
REVIEW_BASE_BRANCH (for --branch).
Run artifacts live under ~/.local/state/ai-council-review/<repo>/<run-id>/
(override: --out). They contain the reviewed source — treat as sensitive;
never commit them.
Inspecting the roster
node ${CLAUDE_SKILL_DIR}/scripts/council.mjs models # current council + live pricing
node ${CLAUDE_SKILL_DIR}/scripts/council.mjs models --verify a,b # diagnose slugs
Model slugs churn. When dispatch exits 1 with "Unknown model slug", the fix
is a roster update (config override or a patch to references/presets.json)
— pick the suggested replacement closest in capability.
What ships with it: 29 files
154.8 KB alongside SKILL.md, 16 of them executable
references/
- presets.json1.1 KB
- prompts/code-review.md1.6 KB
- prompts/document-review.md1.5 KB
- prompts/plan-review.md1.7 KB
- report-template.md1.9 KB
- synthesis.md8.3 KB
scripts/
- council.mjsruns22.4 KB
- lib/budget.mjsruns4.7 KB
- lib/cluster.mjsruns5.3 KB
- lib/config.mjsruns6.2 KB
- lib/input.mjsruns9.3 KB
- lib/openrouter.mjsruns7.7 KB
- lib/outcomes.mjsruns6.3 KB
- lib/prompts.mjsruns2.5 KB
- lib/schema.mjsruns8.5 KB
tests/
- budget.test.mjsruns3.5 KB
- cluster.test.mjsruns5.6 KB
- dispatch.test.mjsruns23.7 KB
- extract.test.mjsruns4.8 KB
- fixtures/sample-responses/chatty.txt613 B
- fixtures/sample-responses/clean.json586 B
- fixtures/sample-responses/fenced.txt431 B
- fixtures/sample-responses/malformed.txt44 B
- fixtures/tiny-diff.patch259 B
- input.test.mjsruns2.4 KB
- live-smoke.test.mjsruns2.4 KB
- outcomes.test.mjsruns7.7 KB
- jsconfig.json302 B
- README.md13.5 KB
Gives 0 of the 12 instructions most review quality skills give in ~2.0k tokens
Counted across 1,273 of the 2,403 authors here whose files we hold, read 2026-09-06
- Ask one question at a timein 63 of 1273, across 62 files
- Provide a recommended answer for each questionin 47 of 1273, across 45 files
- Rank findings by severityin 44 of 1273
- Use parameterized queries for database accessin 38 of 1273, across 20 files
- Validate all user input with schemasin 33 of 1273, across 15 files
- Store secrets in environment variablesin 32 of 1273, across 14 files
- Explore the codebase to answer questionsin 31 of 1273, across 29 files
- Store tokens in httpOnly cookiesin 30 of 1273, across 12 files
- Implement rate limiting on API endpointsin 30 of 1273, across 12 files
- Sanitize user-provided HTMLin 29 of 1273, across 11 files
- Return generic error messages to usersin 28 of 1273, across 10 files
- Cite file and line for every findingin 28 of 1273, across 25 files
Said here and by no other author read
- Confirm external data sharing with human partner first
- Review only the diff to reduce data exposure
- Run dry-run estimate before dispatching
- Get explicit human approval for costs exceeding threshold
- Verify council findings against the actual repository
- Preserve dissent as contested items in reports
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.