Council Mode
SkillDev toolsRun a bounded supervisor-mediated advisor council. Use when the user asks for council mode, asks to convene advisors, debate a decision, cross-examine recommendations, or run /council.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Council Mode skill
What this skill tells your AI
The instructions your AI receives, as published by neuron-mr-white/unipi in packages/subagents/skills/council-mode/SKILL.md and read by ahel’s review.
This skill is for the parent supervisor only. Do not inject it into advisors. The parent selects the roster, curates all cross-advisor communication, decides which feedback is valid, and writes the decision memo. Advisors do not talk directly or see peer transcripts by default. This is not free-form agent chat.
Use council mode for a material decision with real tradeoffs. Do not use it for a
trivial or settled question, or for implementation work. Read
skills/pi-subagents/references/execution-controls.md before you launch advisors.
Roster and limits
Roles such as architect, skeptic, operator, and performance reviewer belong to the
/council request. A council-* profile defines only model, tools, context, and
output defaults. Its profile configuration or explicit invocation owns its context
choice.
Create model-based profiles in your user or project agent directory. Do not add
them to this package. This is a valid example; roles still come from /council:
---
name: council-sol
description: Read-only fresh-context advisor for bounded council decisions
tools: read, grep, find, ls
model: openai-codex/gpt-5.6-sol
thinking: high
systemPromptMode: replace
inheritProjectContext: true
inheritSkills: false
defaultContext: fresh
acceptanceRole: read-only
---
Analyze only the assigned council role. Inspect evidence directly. Do not edit,
run mutating commands, commit, push, contact peers, or spawn subagents. Return
concise, cited advice using the report contract in the council task.
After spawn_helper({ action: "list" }), prefer 2–3 executable names that start with
council-. The prefix is a naming convention, not runtime selection. If fewer
than two profiles are available, fill the roster with oracle, then reviewer,
until it has two advisors. Launch fallback oracle with context: "fork" so
global defaults cannot remove its parent-chat context. Let fallback reviewer
use its normal profile context. Note the fallback and known context modes in the
memo. Use the normal single-oracle consultation loop only when a requested roster
or unavailable builtins leaves fewer than two advisors.
Label that result as degraded mode. Never use more than four advisors.
Pass 1 is independent reports. Pass 2 is one cross-exam. The default pass cap is
2. Run pass 3 only when --max-passes 3 was requested and a material dispute can
be settled by evidence an advisor can produce. Never run an unbounded loop.
Protocol
- The parent writes a brief with the question, scope, non-goals, evidence targets, roster, roles, and pass cap.
- Before Pass 1, tell the user the roster, roles, requested or known context
modes, and pass cap. Use a stable key,
phase, and conciselabelfor every workflow child. For example, useadvisor-oracle,phase: "Council pass 1", andlabel: "Oracle — intent and consistency". - Launch one async
workflowScriptwithruns.allfor independent advisor reports. Setcontextwhen the selected advisor has a known profile context or a fallback rule requests one, because a global default can otherwise override that profile. Setcontext: "fork"for fallbackoracle. If no advisor context is known, omitcontextand disclose the unknown runtime default in the memo. Each advisor is read-only and must not spawn children, edit files, run mutating commands, commit, or push. Setoutput: falseunless separate advisor artifacts are explicitly requested or useful for the decision. - Return one aggregate Pass 1 receipt. After it completes, tell the user the completion count, agreement count, dispute count, and whether Pass 2 is needed.
- The parent synthesizes a claim matrix in session. It contains agreements, disputed claims, missing proof, owner decisions, and a relay set of at most five high-impact claims per advisor. Do not delegate this synthesis.
- Before Pass 2, tell the user how many claims are relayed and why each is
material. Launch a second async
workflowScriptwithruns.allresume calls. Each task is a curated challenge packet, not a peer transcript. A resume requires a retained run id and a non-empty task. It excludesagentand rejectsgate. Record the new run id from every resume. Pass 3 resumes those latest ids. Return one aggregate Pass 2 receipt. - After Pass 2, tell the user whether the council converged or which owner decisions remain. The parent writes the final memo. Do not delegate it.
If an advisor is not resumable, run the same profile in fresh context with its own pass-1 report and the challenge packet. Label that response as a fresh-context fallback, not a true cross-exam.
Do not set clarify, worktree, gate, turn budgets, tool budgets, or tight usage
budgets on advisors. Bound work through the roster, pass cap, and report length.
Advisor contracts and pass receipts
Pass-1 reports are at most about 600 words. Give each advisor the same
outputSchema, so reports are comparable without heading cleanup. The following
shape is a contract template. Use the runtime schema syntax supported by the
workflow and keep narrative fields as strings:
const pass1OutputSchema = {
type: "object",
required: [
"recommendation", "evidence", "assumptions", "risks", "confidence",
"challengeClaims", "ownerDecisions", "changeMyMind"
],
properties: {
recommendation: { type: "string" },
evidence: {
type: "array",
items: {
type: "object",
required: ["claim", "sources"],
properties: {
claim: { type: "string" },
sources: { type: "array", items: { type: "string" } }
}
}
},
assumptions: {
type: "array",
items: {
type: "object",
required: ["assumption", "status"],
properties: {
assumption: { type: "string" },
status: { enum: ["verified", "unverified"] }
}
}
},
risks: { type: "array", items: { type: "string" } },
confidence: {
type: "object",
required: ["level", "reason"],
properties: {
level: { enum: ["high", "medium", "low"] },
reason: { type: "string" }
}
},
challengeClaims: { type: "array", items: { type: "string" }, maxItems: 3 },
ownerDecisions: { type: "array", items: { type: "string" } },
changeMyMind: { type: "array", items: { type: "string" } }
}
};
Include this contract in each Pass 1 task: inspect supplied evidence directly; do not see or ask about other advisors; stay read-only; do not spawn children; return only the structured report.
After runs.all, return one aggregate receipt rather than making the parent find
separate artifacts. Preserve the result order or map it by stable key so each row
contains the advisor identity and report:
return {
pass: 1,
advisors: results.map((result, index) => ({
key: result.key,
agent: result.agent,
role: roster[index].role,
requestedContext: roster[index].context ?? "runtime-default-unknown",
runId: result.runId,
report: result.structuredOutput
}))
};
Do not replace runtime-default-unknown with a guessed context. It records that
the launch intentionally omitted context.
A challenge packet contains only disputed claims, strong conflicting evidence, missing proof, owner decisions, and high-impact risks. Attribute peer content as "another advisor". Do not include full peer reports. Use a common Pass 2 contract:
const pass2OutputSchema = {
type: "object",
required: ["responses", "recommendationChanged", "outOfScopeFindings"],
properties: {
responses: {
type: "array",
items: {
type: "object",
required: ["claimId", "disposition", "reason", "sources"],
properties: {
claimId: { type: "string" },
disposition: {
enum: ["accept", "reject", "refine", "owner-decision"]
},
reason: { type: "string" },
sources: { type: "array", items: { type: "string" } }
}
}
},
recommendationChanged: {
type: "object",
required: ["changed", "reason"],
properties: { changed: { type: "boolean" }, reason: { type: "string" } }
},
outOfScopeFindings: { type: "array", items: { type: "string" } }
}
};
Use stable resume keys such as cross-oracle, phase: "Council pass 2", concise
labels, and output: false unless separate artifacts are requested or useful. The
aggregate Pass 2 receipt uses the same row shape as Pass 1, with the new runId
and structuredOutput.
Stop and memo
Converged means no disputed claim remains that both materially affects the recommendation and can plausibly be settled by evidence. Stop at convergence, the pass cap, failed fallback, or user interruption. Put unresolved disputes in owner decisions. Never add a round for polish or symmetry.
The parent memo states the question and scope, recommendation, rationale, accepted
and rejected feedback with reasons, owner decisions, evidence and run ids,
confidence, what would change the decision, and the roster, roles, passes,
fallbacks, and known advisor context modes. State that fallback oracle is
context-aware and forked.
Council mode is not agent-to-agent chat, a transcript dump, mutation authority, auto-escalation to writer lanes, or a council UI. Escalate to a writer only after the parent memo and only when the user explicitly requests it.
Signals
- GitHub stars
- 64
- Forks
- 15
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
council-mode- Source
- github.com/neuron-mr-white/unipi