skills/agent-council/SKILL.md
Use when facing trade-offs, subjective judgments, uncertain decisions, or when diverse viewpoints would improve judgment quality. Triggers include "council", "다른 의견", "perspectives", "what do others think".
npx skillsauth add toongri/oh-my-toong-playground agent-councilInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Advisory body providing multiple AI perspectives on uncertain decisions. When all members are unavailable, falls back to in-session single-voice advisory using the in-session fallback framework.
</Role>Council provides opinions. The caller makes the final decision.
| 상황 | Council 필요? | 이유 | |------|---------------|------| | 아키텍처 트레이드오프 | ✅ Yes | 다양한 관점 필요 | | 주관적 코드 품질 판단 | ✅ Yes | 명확한 정답 없음 | | 리스크 평가 불일치 | ✅ Yes | 관점에 따라 달라짐 | | 컴파일/문법 에러 | ❌ No | 객관적 해결책 존재 | | 코드 스타일 | ❌ No | ktlint가 처리 | | 명확한 스펙 요구사항 | ❌ No | 구현만 하면 됨 |
digraph council_decision {
rankdir=TB;
node [shape=box, style=rounded];
start [label="Decision needed?", shape=diamond];
objective [label="Objective answer exists?", shape=diamond];
skip [label="Skip council\nDecide directly"];
use [label="Use council"];
start -> objective [label="yes"];
start -> skip [label="no decision"];
objective -> skip [label="yes (compile error, lint)"];
objective -> use [label="no (trade-offs, judgment)"];
}
Use Council:
Skip Council:
bun "${CLAUDE_SKILL_DIR}/scripts/job.ts" collect JOB_DIR — polls internally; re-call if not "done"done does NOT mean semantically complete. A member can exit cleanly yet return a non-answer — a plan, framing, or "I'll answer once X arrives" response. Read each member's content and judge: did it actually answer the asked question? Also check: is any member in awaiting_resume state? For any member that is awaiting_resume OR whose content is a non-answer (narrative-only / incomplete / waiting pattern), call resume-member BEFORE proceeding. clean is destructive (it deletes the jobDir, and resume-member <jobDir> requires that jobDir) — so clean is ALWAYS the last step, only after completeness is confirmed.bun "${CLAUDE_SKILL_DIR}/scripts/job.ts" clean JOB_DIRCouncil members do not share the caller's session context. The caller must explicitly provide:
Include context richly. Council members should judge with the same context as the caller.
Execute bun "${CLAUDE_SKILL_DIR}/scripts/job.ts" from the project root:
Note: Always write the council prompt in English for consistent cross-model communication.
For programmatic use within Claude Code sessions:
CRITICAL: Always set timeout: 180000 on every Bash tool call.
Hard Constraints:
0. Each Bash call MUST run in FOREGROUND. All subcommands (start, collect) run synchronously. No background execution. No run_in_background.
sleep. The collect subcommand polls internally (5-second intervals, 150-second default timeout). External sleep is redundant and wastes time.start subcommand runs ONCE. Polling (collect) may repeat. No job re-creation.1. Start council (Bash, timeout: 180000)
PROMPT_FILE=$(mktemp)
cat > "$PROMPT_FILE" << 'PROMPT_EOF'
## Evaluation Criteria
[Key principles - in English]
## Project Context
[Conventions and patterns - in English]
## Target
[Code or content under review]
## Question
[Specific points needing judgment - in English]
PROMPT_EOF
JOB_DIR=$(bun "${CLAUDE_SKILL_DIR}/scripts/job.ts" start --stdin < "$PROMPT_FILE")
Output: JOB_DIR path (one line on stdout).
Important: Write prompts in English for consistent cross-model communication.
2. Collect results (Bash, timeout: 180000)
collect polls internally every 5 seconds until all members complete or its internal timeout (default 150s) expires. No external sleep needed.
bun "${CLAUDE_SKILL_DIR}/scripts/job.ts" collect "$JOB_DIR"
"overallState": "done" → proceed to Step 3."running", "queued", etc.) → call collect again (same command, foreground, timeout: 180000).3. Read raw outputs
Use the Read tool to read each member's outputFilePath from the manifest.
Only read entries where outputFilePath is non-null (null = infrastructure failure; see Degradation Policy).
4. Completeness gate — resume-member if needed (Chairman judgment)
done does NOT mean semantically complete. Read each member's content. If any member is in awaiting_resume state OR returned a non-answer (narrative-only / incomplete / waiting pattern / "I'll answer once X arrives"), call resume-member before proceeding:
bun "${CLAUDE_SKILL_DIR}/scripts/job.ts" resume-member "$JOB_DIR" <name> "Please answer the question directly."
The prompt is written by the Chairman LLM for the specific situation. The example above is illustrative only.
Cap: max 3 resumes per member. After cap exhaustion — partial-accept (include what was received) OR escalate the entire job. The Chairman judges which applies based on the situation.
WARNING: clean is destructive — it deletes the jobDir permanently, and resume-member <jobDir> ... requires that jobDir to exist. clean is ALWAYS the last step, called only after completeness is confirmed for all members.
5. Synthesize (caller responsibility)
You as the Chairman must synthesize raw outputs into the Advisory Format (see below). The council does NOT produce a synthesized advisory automatically.
6. Cleanup (Bash, timeout: 180000)
bun "${CLAUDE_SKILL_DIR}/scripts/job.ts" clean "$JOB_DIR"
--include-chairman / --include-chairman=true: Force-include the chairman as a member regardless of config.--exclude-chairman / --exclude-chairman=true: Force-exclude the chairman from members.--exclude-chairman=false: Explicitly request the chairman BE included (value-respecting).exclude_chairman_from_members in config. The semantic default is true (chairman excluded) when the config key is absent; shipped configs override this to false to include the chairman as a member.Flag values are respected (value-respecting parsing).
--exclude-chairman=falsedoes NOT exclude the chairman — it explicitly keeps them.
When both
--include-chairmanand--exclude-chairmanare passed simultaneously,--exclude-chairmanwins (override precedence).
When synthesizing raw outputs:
Last verified: 2026-02 (review quarterly as models update)
When synthesizing, weight each model's opinion based on the question domain:
| Member | Primary Strengths | Weight Higher When | |--------|-------------------|-------------------| | claude | Nuanced trade-off reasoning, instruction coherence across long context, risk/impact assessment | Architecture decisions, requirement ambiguity resolution, risk evaluation | | codex | Code-level feasibility analysis, implementation cost/complexity estimation, API contract design | "Is this buildable?" questions, implementation approach choices, technical debt evaluation | | gemini | Broad factual grounding, alternative solution discovery, edge case identification | Technology comparisons, "what are we missing?" questions, assumption challenges |
Application rules:
<Output_Format>
Chairman synthesizes council opinions into:
## Council Advisory
### Consensus
[Points where council members agree]
### Divergence
[Points where opinions differ + summary of each position]
### Recommendation
[Synthesized advice. When model opinions diverge, note which model's expertise is most relevant to this domain and why — referencing Model Characteristics table]
</Output_Format>
Strong Consensus → Adopt recommendation with confidence
Clear Divergence → Options:
Mixed Signals → Weigh perspectives based on relevance
Partial Results → Apply Degradation Policy. Synthesize from available responses, note missing perspectives.
| Mistake | Why It's Wrong | Fix | |---------|----------------|-----| | 컴파일 에러에 council 호출 | 객관적 해결책 있음, 시간 낭비 | 직접 수정 | | context 없이 질문만 전달 | 맥락 없이 판단 불가 | 평가 기준, 프로젝트 컨텍스트 포함 | | council 결정을 그대로 수용 | council은 자문, 결정은 호출자 | 의견 참고 후 직접 결정 | | 모든 결정에 council 호출 | 불필요한 오버헤드 | 트레이드오프/주관적 판단에만 사용 | | 한국어로 council 호출 | 모델 간 일관성 저하 | 영어로 프롬프트 작성 |
| Red Flag | Reality | |----------|---------| | "빨리 결정해야 해서 council 생략" | 중요한 결정일수록 다양한 관점 필요 | | "내 판단이 맞으니까 확인만" | 확인 편향 - council은 반론을 들으려고 쓰는 것 | | "에러 메시지가 뭔지 모르겠어서" | 객관적 문제는 council 대상 아님 | | "council이 결정해줄 거야" | Council은 조언, 결정 책임은 호출자 |
Council members may fail due to CLI unavailability, timeout, or errors. This is NOT the same as quorum logic.
Critical distinction:
Decision tree:
overallState === 'done' AND all members have terminal states?missing_cli → CLI not installed. Degradation applies (infra failure — unrecoverable).timed_out → CLI exceeded timeout. Degradation applies (infra failure — unrecoverable).error (non-zero exit) → CLI failed. Degradation applies (infra failure — unrecoverable).canceled → Manually stopped. Degradation applies (infra failure — unrecoverable).awaiting_resume → Member paused mid-turn waiting for continuation. Recoverable — call resume-member (see completeness gate above). This is distinct from infra failure; the member is alive and can continue.done but content is a non-answer → Member exited cleanly but returned framing / a plan / a waiting pattern instead of actually answering the question. Recoverable — call resume-member. The runner marks it done based on exit reason, not semantic completeness; the Chairman judges semantic completeness by reading the content.If start exits non-zero or returns an empty $JOB_DIR, skip Steps 2–4 (no collect/clean) and fall back to in-session advisory: READ prompts/default.md and apply the framework defined there IN-SESSION. You become the in-session advisor for the remainder of this skill invocation — no manifest exists to read. When the cause is the no-members guard — stderr contains to dispatch — enter the fallback silently (expected path: empty/all-filtered members config). For any other non-zero exit (an unexpected failure — disk/permission, spawn error, a bug), first surface the failure reason (include the stderr line) in your output, then proceed with the in-session fallback.
Synthesis by response count:
| Responses | Action | Output Modification |
|-----------|--------|---------------------|
| 3/3 | Full synthesis | Standard advisory format |
| 2/3 | Partial synthesis | Prepend: "⚠️ Partial advisory (2/3 respondents). [failed_member] unavailable: [state]. The following synthesis lacks [failed_member]'s perspective ([see Model Characteristics for what this model typically contributes])." |
| 1/3 | Single response report | Prepend: "⚠️ Limited advisory (1/3 respondents). [failed_members] unavailable. Presenting single response from [available_member] without synthesis. Treat as individual opinion, not council advisory." |
| 0/3 | In-session fallback | READ prompts/default.md and deliver in-session advisory. When all members failed due to infrastructure errors (not the no-members guard), surface a one-line failure summary before proceeding. |
Partial synthesis rules:
tools
Use at the end of a work session to review the WHOLE session and record entities worth pinning. This is the manual, deliberate complete-sweep review — NOT an automated nudge. Triggers on "wrap up", "wrap-up", "session wrap", "end of session", "what should I pin".
documentation
Use when initializing the pins knowledge graph for the first time in a project. Guides the user through creating pins.yaml (the storage manifest). Triggers on "setup pins", "initialize pins", "create pins.yaml", "first-run pins".
testing
Use when you need to record a single pin entity to the knowledge graph. Invokes lib/pins record() to validate and write a canonical .md file. Triggers on "record pin", "pin this", "save this as a pin".
databases
Use when looking up pins by type, tags, or source. Drives lib/pins/query.ts to retrieve matching pin entries from the knowledge graph. Supersedes the legacy manual ls+frontmatter procedure.