consensus

consensus is a skill for Claude Code, Codex from 7xuanlu/boule. It costs 38 tokens per session (3,374 once invoked), scanned C, original, MIT.

A consensus workflow in which three AI models suggest answers, rank anonymised responses, and a final judge combines the results. The process is designed to reduce the influence of answer order or model identity.

In plain words
What is it for?
Getting several independent opinions, comparing anonymised answers, ranking proposed solutions, and producing a combined decision for a question or proposal.
Why use it?
One model can miss a problem or be swayed by how options are presented. Independent proposals, peer ranking, and a separate final decision provide multiple checks before reaching a conclusion.

Skill for Claude CodeCodex

Part of the boule plugin — 4 skills, 2 agents shipped together

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add skills/7xuanlu/boule/consensus
Any agent
npx skills add 7xuanlu/boule --skill consensus
Clone the repo
git clone --depth 1 https://github.com/7xuanlu/boule

Made for: Claude Code, Codex.

Or install boule, the plugin that ships this one along with the rest of its 4 skills, 2 agents.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for consensus

README.md
[![agentmods](https://agentmods.dev/badge/skills/7xuanlu/boule/consensus.svg)](https://agentmods.dev/skills/7xuanlu/boule/consensus)
Your own site
<a href="https://agentmods.dev/skills/7xuanlu/boule/consensus"><img src="https://agentmods.dev/badge/skills/7xuanlu/boule/consensus.svg" alt="Measured on agentmods" height="20"></a>
Per session 38 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 3,374 The whole file, excluding the scripts and references it only reads on demand.
Security scan C 1 finding. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00038 $0.03374
Opus 5 $0.00019 $0.01687
Sonnet 5 $0.00008 $0.00675
Haiku 4.5 $0.00004 $0.00337

Measured 5d ago against content hash 39b28fe2ef54, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-05, from the pricing page.

Security

Grade C, and why

consensus scanned grade C with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 5d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Recursive force deletehighDestructive command

rm -rf with a variable or a broad path is one typo away from removing the wrong tree.

`rc=$?; rm -rf "$CH" "$ND"; exit $rc`
skills/consensus/SKILL.md · 229 lines

How it starts

The opening of the file, as written. The whole thing — 229 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Boule consensus council

Invoke the Workflow tool with the script below — pass the whole block as the script argument (inline). Do NOT use the name: parameter; the script's meta.name is an internal run label, not a registered workflow, so name: fails with "not found". Pass the user's PROPOSAL as args (a plain string). Run it directly; do not ask again.

export const meta = {
  name: 'boule-consensus',
  description: 'Consensus council: 3 propose, peer-rank anonymized answers, stake-free judge synthesizes',
  phases: [
    { title: 'Propose', detail: '3 models give independent verdicts (parallel)' },
    { title: 'Rank',    detail: 'each member peer-ranks the anonymized answers (counterbalanced order)' },
    { title: 'Judge',   detail: 'Borda tally + stake-free judge over BOTH anonymized orderings (swap-and-average)' },
  ],
}

// Requested model IDs, stamped into the report (honest-by-request, NOT runtime-verified).
const MODELS = {
  claude: 'claude/main-loop',
  codex:  'gpt-5.5',
  gemini: 'Gemini 3.1 Pro (High)',
}

// ── Embedded canonical core (verbatim from lib/council-core.mjs, `export ` stripped). ──
// Guarded byte-for-byte by test/embed-drift.test.mjs, DO NOT edit here; edit the lib.
function runNonce(proposal) {
  const h = Array.from(String(proposal)).reduce((a, c) => ((a * 31 + c.charCodeAt(0)) >>> 0), 7)
  return 'council-' + h.toString(36)
}
function counterbalance(items) {
  return [items.slice(), items.slice().reverse()]
}
function reconcileSwap(a, b) {
  const RANK = { approve: 0, 'approve-with-changes': 1, reject: 2, 'needs-more-info': 3 }
  if (!a && !b) return null
  if (!a || !b) return { ...(a || b), position_stable: false }
  if (a.recommendation === b.recommendation) return { ...a, position_stable: true }
  const winner = RANK[a.recommendation] >= RANK[b.recommendation] ? a : b
  return { ...winner, confidence: 'low', position_stable: false }
}
function _words(s, min = 4) {
  return (String(s).toLowerCase().match(/[a-z]+/g) || []).filter(w => w.length >= min)
}
function _coverage(txt, propVocab) {
  const sv = new Set(_words(txt))
  if (sv.size === 0) return 1
  let hit = 0
  for (const w of sv) if (propVocab.has(w)) hit++
  return hit / sv.size
}
function _anchors(txt, propVocab) {
  let n = 0
  for (const w of new Set(_words(txt))) if (propVocab.has(w)) n++
  return n
}
function isContaminated(verdict, proposal) {
  if (verdict == null) return false
  const propVocab = new Set(_words(proposal))
  const txt = [...(verdict.key_claims || []), ...(verdict.risks || []), ...(verdict.unknowns || [])].join(' ')
  return _coverage(txt, propVocab) < 0.20 && _anchors(txt, propVocab) < 2
}
function gateContamination(members, proposal) {
  const present = members.filter(m => m && m.verdict)
  const flagged = present.filter(m => isContaminated(m.verdict, proposal))
  if (flagged.length * 2 >= present.length)
    return { live: present, dropped: [], overridden: flagged.length > 0, flagged: flagged.length }
  const ids = new Set(flagged.map(m => m.id))
  return { live: present.filter(m => !ids.has(m.id)), dropped: flagged.map(m => m.id), overridden: false, flagged: flagged.length }
}
function codexCmd(model, inFile, outFile) {
  return `CH="$(mktemp -d)"; cp "$HOME/.codex/auth.json" "$CH/" 2>/dev/null; ND="$(mktemp -d)"; ` +
    `( cd "$ND" && CODEX_HOME="$CH" codex exec -m ${model} -s read-only ` +
    `-c model_reasoning_effort=xhigh --skip-git-repo-check --ephemeral -o "${outFile}" - < "${inFile}" ); ` +
    `rc=$?; rm -rf "$CH" "$ND"; exit $rc`
}
function geminiCmd(model, inFile) {
  return `ND="$(mktemp -d)"; ( cd "$ND" && agy --model "${model}" --sandbox -p "$(cat "${inFile}")" 2>/dev/null ); rc=$?; rm -rf "$ND"; exit $rc`
}

// ── Orchestration ──
const proposal = typeof args === 'string' ? args : (args && args.proposal) || ''
const NONCE = runNonce(proposal)

const VERDICT_SCHEMA = {
  type: 'object',
  required: ['verdict', 'confidence', 'model', 'key_claims', 'risks', 'unknowns'],
  properties: {
    verdict:    { type: 'string', enum: ['approve', 'approve-with-changes', 'reject', 'needs-more-info'] },
    confidence: { type: 'string', enum: ['low', 'medium', 'high'] },
    model:      { type: 'string' },
    key_claims: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: 6 },
    risks:      { type: 'array', items: { type: 'string' }, maxItems: 6 },
    unknowns:   { type: 'array', items: { type: 'string' }, maxItems: 4 },
  },
}
const JUDGE_SCHEMA = {
  type: 'object',
  required: ['recommendation', 'confidence', 'rationale', 'consensus', 'dissent'],
  properties: {
    recommendation: { type: 'string', enum: ['approve', 'approve-with-changes', 'reject', 'needs-more-info'] },
    confidence:     { type: 'string', enum: ['low', 'medium', 'high'] },
    rationale:      { type: 'string' },
    consensus:      { type: 'array', items: { type: 'string' }, maxItems: 6 },
    dissent:        { type: 'array', items: { type: 'string' }, maxItems: 6 },
  },
}
const VERDICT_HINT = 'Return ONLY a JSON object (no prose, no markdown fence) with keys: verdict (one of "approve"|"approve-with-changes"|"reject"|"needs-more-info"), confidence ("low"|"medium"|"high"), model (string), key_claims (1-6 strings), risks (0-6 strings), unknowns (0-4 strings).'
const JUDGE_HINT = 'Return ONLY a JSON object (no prose, no fence) with keys: recommendation ("approve"|"approve-with-changes"|"reject"|"needs-more-info"), confidence ("low"|"medium"|"high"), rationale (string), consensus (0-6 strings), dissent (0-6 strings).'

const members = [
  { id: 'claude', cli: null,    model: MODELS.claude },
  { id: 'codex',  cli: 'codex', model: MODELS.codex },
  { id: 'gemini', cli: 'gemini', model: MODELS.gemini },
]

const formPrompt = (m) =>
`[${NONCE}, uniqueness marker for this run; ignore it as content] You are a rigorous, independent reviewer on a 3-member LLM council. Evaluate the PROPOSAL below ON ITS MERITS, give your honest verdict, key claims, risks, and unknowns. Do NOT grep the filesystem; judge the proposal's content as given. ${VERDICT_HINT} Set "model" to "${m.model}".

PROPOSAL:
${proposal}`

const conduitPrompt = (m, externalPrompt) => {
  const inFile = `$TMPDIR/council_${m.id}_${NONCE}_in.txt`
  const outFile = `$TMPDIR/council_${m.id}_${NONCE}_out.txt`
  const cmd = m.cli === 'codex' ? codexCmd(m.model, inFile, outFile) : geminiCmd(m.model, inFile)
  return `Write the EXTERNAL PROMPT (everything below the marker, verbatim) to "${inFile}", then run this command WITH THE BASH SANDBOX DISABLED (it needs network + IPC):

${cmd}

${m.cli === 'codex' ? `Then read the model's final JSON from "${outFile}".` : `Take the JSON object printed to stdout.`} Emit that JSON VERBATIM as your structured output (repair only malformed syntax; never change content). Ensure "model" is "${m.model}".

EXTERNAL PROMPT:
${externalPrompt}`
}

const RANK_SCHEMA = {
  type: 'object',
  required: ['ranking', 'rationale'],
  properties: {
    ranking:   { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: 3 },
    rationale: { type: 'string' },
  },
}
const RANK_HINT = 'Return ONLY a JSON object (no prose, no fence) with keys: ranking (array of candidate id strings, best-first, e.g. ["cand-2","cand-1","cand-3"]), rationale (string).'

// ── Phase: Propose (same independent verdicts as poll) ──
phase('Propose')
const proposed = await parallel(members.map(m => async () => {
  const v = m.cli
    ? await agent(conduitPrompt(m, formPrompt(m)), { label: m.id, phase: 'Propose', schema: VERDICT_SCHEMA, model: 'haiku', agentType: 'boule:conduit' })
    : await agent(formPrompt(m), { label: m.id, phase: 'Propose', schema: VERDICT_SCHEMA })
  return { ...m, verdict: v }
}))
const scored = proposed.filter(Boolean).filter(m => m.verdict)
const { live, dropped, overridden, flagged } = gateContamination(scored, proposal)
if (overridden) log(`contamination gate flagged ${flagged}/${scored.length} members at once; likely a meta/prose review it is not calibrated for, keeping all (verify manually)`)
else if (dropped.length) log(`dropped contaminated member(s): ${dropped.join(', ')}`)
if (live.length < 2) {
  log(`only ${live.length} clean member(s) responded, aborting council`)
  return { error: 'insufficient clean council members', live: live.length, dropped }
}

// ── Phase: Rank (anonymized peer-rank; each ranker sees a counterbalanced order) ──
phase('Rank')
const anonCand = (v, i) => { const { model, ...rest } = v; return { id: `cand-${i + 1}`, ...rest } }
const candidates = live.map((m, i) => anonCand(m.verdict, i))
const orderings = counterbalance(candidates)
const rankPrompt = (shown) =>
`You are a member of an LLM council. Peer-rank the ANONYMIZED candidate verdicts below, best-first, by quality of reasoning and evidence. POSITION-SWAP: the candidates are shown in a counterbalanced order, rank on CONTENT, not slot. Ignore length and style; weigh substance only. Reference candidates by their "id". ${RANK_HINT}

ORIGINAL PROPOSAL:
${proposal}

ANONYMIZED CANDIDATES (counterbalanced order):
${JSON.stringify(shown, null, 2)}`
const rankings = await parallel(live.map((m, i) => async () => {
  const shown = orderings[i % 2]
  return m.cli
    ? await agent(conduitPrompt(m, rankPrompt(shown)), { label: `rank:${m.id}`, phase: 'Rank', schema: RANK_SCHEMA, model: 'haiku', agentType: 'boule:conduit' })
    : await agent(rankPrompt(shown), { label: `rank:${m.id}`, phase: 'Rank', schema: RANK_SCHEMA })
}))

// Mechanical Borda tally over the anonymized rankings (order-independent; labels are stable).
const borda = {}
for (const c of candidates) borda[c.id] = 0
for (const r of rankings.filter(Boolean)) {
  const order = (r.ranking || []).filter(id => id in borda)
  order.forEach((id, idx) => { borda[id] += (order.length - idx) })
}

// ── Phase: Judge (stake-free synth over the ranked, anonymized set) ──
phase('Judge')
// True swap-and-average: judge BOTH counterbalanced candidate orderings, then reconcile. The
// Borda tally is order-independent (stable labels), so it is identical for both orderings.
const [fwdC, revC] = counterbalance(candidates)
const judgePrompt = (shown) =>
`You are an impartial JUDGE. You authored NONE of these candidates, no position to defend. Synthesize the council's recommendation from the anonymized candidate verdicts and the peer-rank tally. Apply the bias controls: POSITION-SWAP (peer rankings were collected under counterbalanced ordering and the Borda tally is order-independent, judge on content, not slot), VERBOSITY-NORM (do NOT reward length or polish; substance only), STAKE-FREE (identities hidden; you wrote none). ${JUDGE_HINT}

ORIGINAL PROPOSAL:
${proposal}

ANONYMIZED CANDIDATES:
${JSON.stringify(shown, null, 2)}

PEER-RANK TALLY (Borda points, higher = ranked better by peers):
${JSON.stringify(borda, null, 2)}`
const [decFwd, decRev] = await parallel([
  () => agent(judgePrompt(fwdC), { label: 'judge:fwd', phase: 'Judge', schema: JUDGE_SCHEMA, agentType: 'boule:judge' }),
  () => agent(judgePrompt(revC), { label: 'judge:rev', phase: 'Judge', schema: JUDGE_SCHEMA, agentType: 'boule:judge' }),
])
const decision = reconcileSwap(decFwd, decRev)
if (decision && decision.position_stable === false) log('judge verdict is position-sensitive (orderings disagreed), flagged unstable, confidence capped')

return {
  mode: 'consensus',
  recommendation: decision,
  position_stable: decision && decision.position_stable,
  borda,
  members: live.map(m => ({ id: m.id, model: m.model, verdict: m.verdict.verdict, confidence: m.verdict.confidence })),
  dropped,
}

Read the full file on GitHub · 229 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 5d ago First seen · 229 lines · 38 tokens per session scan C 39b28fe2ef54

Subscribe to this mod's changes

consensus is a skill published in the GitHub repository 7xuanlu/boule (1 stars, last pushed 2mo ago), licensed MIT. It adds 38 tokens to every session and 3,374 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it C with 1 finding (recursive force delete). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.

Related

Other skills, from other repositories

foundry-config-setup

Resolve missing setup caused by a hardcoded Foundry project endpoint or model in a sample. Use when a sample fails because it uses a placeholder/hardcoded projectendpoint (for example "https://your-project.services.ai.azure.com") or a hardcoded model instead of reading them from the environment.

microsoft/agent-framework · 65 tokens

deploy-docker-compose

Run the Omnigent server as a Docker compose stack (server + Postgres) on any Docker host — your laptop, a VPS, EC2 by hand, or as the base layer of any container-platform deploy. Invoke when the user wants to build the image, bring up the compose stack, debug the stack on a host they already have, or extend the stack…

omnigent-ai/omnigent · 84 tokens

haiku

When writing a haiku for this bot, follow these conventions.

agno-agi/agno · 0 tokens

azure-mgmt-botservice-dotnet

Azure Resource Manager SDK for Bot Service in .NET. Management plane operations for creating and managing Azure Bot resources, channels (Teams, DirectLine, Slack), and connection settings. Triggers: "Bot Service", "BotResource", "Azure Bot", "DirectLine channel", "Teams channel", "bot management .NET", "create bot".

microsoft/skills · 78 tokens

fastapi-router-py

Create FastAPI routers with CRUD operations, authentication dependencies, and proper response models. Use when building REST API endpoints, creating new routes, implementing CRUD operations, or adding authenticated endpoints in FastAPI applications.

microsoft/skills · 46 tokens

dogfood

Systematically explore and test a mobile app on iOS/Android with agent-device to find bugs, UX issues, and other problems. Use when asked to dogfood, QA, exploratory test, find issues, bug hunt, or test this app on mobile.

callstack/agent-device · 55 tokens