OmniRoute Chat CLI
diegosouzapw/OmniRoute
Sends chat completions, streams responses, and opens an interactive REPL against any OmniRoute-routed model provider.
Has several open-weight models answer a question, rank each other's anonymized answers, then lets a chairman model write the final response through Fireworks AI.
$ npx skills add dair-ai/dair-academy-plugins --skill llm-council -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install dair-ai/dair-academy-plugins llm-council --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/dair-ai/dair-academy-plugins.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/llm-council/skills/llm-council .claude/skills/llm-council && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "llm-council" agent skill from https://github.com/dair-ai/dair-academy-plugins/tree/main/plugins/llm-council/skills/llm-council into .claude/skills/llm-council/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "llm-council", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/dair-ai/dair-academy-plugins/tree/main/plugins/llm-council/skills/llm-councilType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add dair-ai/dair-academy-plugins --skill llm-council -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install dair-ai/dair-academy-plugins llm-council --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dair-ai/dair-academy-plugins.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/llm-council/skills/llm-council .agents/skills/llm-council && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "llm-council" agent skill from https://github.com/dair-ai/dair-academy-plugins/tree/main/plugins/llm-council/skills/llm-council into .agents/skills/llm-council/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "llm-council", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dair-ai/dair-academy-plugins --skill llm-council -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install dair-ai/dair-academy-plugins llm-council --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dair-ai/dair-academy-plugins.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/llm-council/skills/llm-council .cursor/skills/llm-council && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "llm-council" agent skill from https://github.com/dair-ai/dair-academy-plugins/tree/main/plugins/llm-council/skills/llm-council into .cursor/skills/llm-council/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "llm-council", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/dair-ai/dair-academy-plugins.git --path plugins/llm-council/skills/llm-council--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add dair-ai/dair-academy-plugins --skill llm-council -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install dair-ai/dair-academy-plugins llm-council --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dair-ai/dair-academy-plugins.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/llm-council/skills/llm-council .gemini/skills/llm-council && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "llm-council" agent skill from https://github.com/dair-ai/dair-academy-plugins/tree/main/plugins/llm-council/skills/llm-council into .gemini/skills/llm-council/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "llm-council", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install dair-ai/dair-academy-plugins llm-councilInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add dair-ai/dair-academy-plugins --skill llm-council -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/dair-ai/dair-academy-plugins.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/llm-council/skills/llm-council .github/skills/llm-council && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "llm-council" agent skill from https://github.com/dair-ai/dair-academy-plugins/tree/main/plugins/llm-council/skills/llm-council into .github/skills/llm-council/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "llm-council", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dair-ai/dair-academy-plugins --skill llm-council -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install dair-ai/dair-academy-plugins llm-council --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dair-ai/dair-academy-plugins.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/llm-council/skills/llm-council .opencode/skills/llm-council && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "llm-council" agent skill from https://github.com/dair-ai/dair-academy-plugins/tree/main/plugins/llm-council/skills/llm-council into .opencode/skills/llm-council/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "llm-council", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
llm-councilHas several open-weight models answer a question, rank each other's anonymized answers, then lets a chairman model write the final response through Fireworks AI.
This skill implements the LLM Council idea attributed to Karpathy, running every model call through Fireworks AI. Phase one sends your question to each selected model independently and in parallel. Phase two has the models rank each other's anonymized responses, and phase three has a chairman model synthesize the final answer. Before any run it checks that FIREWORKS_API_KEY is set, then uses AskUserQuestion to let you pick the council models and the chairman. The menu includes GLM 5, two DeepSeek V3 versions, MiniMax M2.1, Kimi K2.5, Qwen3 235B and Llama 4 Maverick, and three to five models are recommended.
The rules stress transparency. Raw API responses are saved to files and never summarized or truncated, the ranking phase is never skipped, and all individual responses, all rankings and the final synthesis are shown to you, read back from the files so nothing is altered. The skill's allowed tools are Read, Write, Bash and AskUserQuestion, and the folder includes a .env.example file.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 0abffdc. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadWriteBashAskUserQuestionFrom allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
python3From the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
fireworks.aiapi.fireworks.aiFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
FIREWORKS_API_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
LLM Council on Fireworks AI loads about 5k tokens when it runs. Until then it costs about 98 tokens; SKILL.md has 574 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Read, Write, Bash, AskUserQuestionAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from dair-ai/dair-academy-plugins at commit 0abffdc, republished under its MIT licence (© dair-ai). 574 words, ~4,968 tokens.
.claude/skills/llm-council/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.This skill implements Karpathy's LLM Council concept where multiple open-weight LLMs deliberate on a query, powered entirely by Fireworks AI:
All inference runs through Fireworks AI using open-weight models. The speed and pricing of Fireworks makes it practical to run multi-model deliberation that would be slow or expensive on other providers.
Before running any phase, verify the Fireworks API key is set:
if [ -z "$FIREWORKS_API_KEY" ]; then
echo "ERROR: FIREWORKS_API_KEY is not set."
echo "Create a Fireworks AI account at: https://fireworks.ai/"
echo "Then export it in your shell profile (~/.zshrc or ~/.bashrc):"
echo ' export FIREWORKS_API_KEY="your_api_key_here"'
exit 1
fi
echo "FIREWORKS_API_KEY is set."Present these options to the user via AskUserQuestion (multiselect):
| Model | Fireworks ID | Provider |
|---|---|---|
| GLM 5 | accounts/fireworks/models/glm-5 | Z.ai |
| DeepSeek V3.1 | accounts/fireworks/models/deepseek-v3p1 | DeepSeek |
| DeepSeek V3.2 | accounts/fireworks/models/deepseek-v3p2 | DeepSeek |
| MiniMax M2.1 | accounts/fireworks/models/minimax-m2p1 | MiniMax |
| Kimi K2.5 | accounts/fireworks/models/kimi-k2p5 | Moonshot |
| Qwen3 235B | accounts/fireworks/models/qwen3-235b-a22b | Alibaba |
| Llama 4 Maverick | accounts/fireworks/models/llama4-maverick-instruct-basic | Meta |
Use AskUserQuestion to get:
Note: AskUserQuestion supports max 4 options per question. Since there are 7 models, split model selection across two questions, or show the most popular 4 and let the user type "Other" for the rest. A good default is to show 4 models in the first question and note the others are available via "Other". Rotate which models are shown based on variety.
Example AskUserQuestion for model selection (show 4, mention others):
question: "Which models should participate in the LLM Council? (Also available via Other: Llama 4 Maverick, Qwen3 235B, GLM 5)"
header: "Models"
multiSelect: true
options:
- label: "DeepSeek V3.2"
description: "DeepSeek's newest and most capable model"
- label: "MiniMax M2.1"
description: "MiniMax's strong open-weight model"
- label: "Kimi K2.5"
description: "Moonshot's strong open-weight model"
- label: "DeepSeek V3.1"
description: "DeepSeek's proven reasoning model"Example AskUserQuestion for chairman:
question: "Which model should be the Chairman (synthesizes the final answer)?"
header: "Chairman"
multiSelect: false
options:
- label: "DeepSeek V3.2 (Recommended)"
description: "Newest DeepSeek, strong at comprehensive analysis"
- label: "GLM 5"
description: "Strong reasoning for synthesis"
- label: "Kimi K2.5"
description: "Strong at structured synthesis"
- label: "MiniMax M2.1"
description: "Strong open-weight model for synthesis"Use this mapping to convert user selections to Fireworks model IDs:
MODEL_MAP = {
"GLM 5": "accounts/fireworks/models/glm-5",
"DeepSeek V3.1": "accounts/fireworks/models/deepseek-v3p1",
"DeepSeek V3.2": "accounts/fireworks/models/deepseek-v3p2",
"MiniMax M2.1": "accounts/fireworks/models/minimax-m2p1",
"Kimi K2.5": "accounts/fireworks/models/kimi-k2p5",
"Qwen3 235B": "accounts/fireworks/models/qwen3-235b-a22b",
"Llama 4 Maverick": "accounts/fireworks/models/llama4-maverick-instruct-basic",
}After gathering input, run this script to get responses from all selected models in parallel:
QUERY="USER_QUERY_HERE"
MODELS='["accounts/fireworks/models/glm-5", "accounts/fireworks/models/deepseek-v3p1"]'
python3 << 'PYEOF'
import os
import json
import requests
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
FIREWORKS_API_KEY = os.environ.get("FIREWORKS_API_KEY")
API_URL = "https://api.fireworks.ai/inference/v1/chat/completions"
QUERY = os.environ.get("QUERY", "")
MODELS = json.loads(os.environ.get("MODELS", "[]"))
# Create session directory
timestamp = time.strftime("%Y%m%d-%H%M%S")
SESSION_DIR = f"/tmp/llm-council/{timestamp}"
os.makedirs(SESSION_DIR, exist_ok=True)
# Save config
config = {"query": QUERY, "models": MODELS, "timestamp": timestamp}
with open(f"{SESSION_DIR}/config.json", "w") as f:
json.dump(config, f, indent=2)
def call_model(model_id, query):
"""Call a single model via Fireworks AI"""
try:
start = time.time()
response = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {FIREWORKS_API_KEY}",
"Content-Type": "application/json"
},
json={
"model": model_id,
"messages": [
{"role": "system", "content": "You are participating in an LLM council deliberation. Provide your best, most thoughtful response to the query. Be comprehensive but focused."},
{"role": "user", "content": query}
],
"max_tokens": 4000,
"temperature": 1
},
timeout=120
)
response.raise_for_status()
elapsed = time.time() - start
data = response.json()
usage = data.get("usage", {})
return {
"success": True,
"content": data["choices"][0]["message"]["content"],
"model": model_id,
"latency_seconds": round(elapsed, 2),
"tokens": {
"prompt": usage.get("prompt_tokens", 0),
"completion": usage.get("completion_tokens", 0),
"total": usage.get("total_tokens", 0)
}
}
except Exception as e:
return {
"success": False,
"content": f"[ERROR: {str(e)}]",
"model": model_id,
"latency_seconds": 0,
"tokens": {"prompt": 0, "completion": 0, "total": 0}
}
print(f"\n{'='*60}")
print("PHASE 1: Collecting Individual Responses")
print(f"{'='*60}")
print(f"Query: {QUERY[:200]}...")
print(f"Models: {', '.join([m.split('/')[-1] for m in MODELS])}")
print(f"Session: {SESSION_DIR}")
print()
# Parallel execution
results = {}
with ThreadPoolExecutor(max_workers=len(MODELS)) as executor:
futures = {executor.submit(call_model, m, QUERY): m for m in MODELS}
for future in as_completed(futures):
model = futures[future]
result = future.result()
results[model] = result
status = "OK" if result["success"] else "FAILED"
latency = f"{result['latency_seconds']}s" if result["success"] else "N/A"
print(f" [{status}] {model.split('/')[-1]} ({latency})")
# Save raw results
with open(f"{SESSION_DIR}/phase1_responses.json", "w") as f:
json.dump(results, f, indent=2)
print(f"\nPhase 1 complete. Results saved to: {SESSION_DIR}/phase1_responses.json")
print(f"SESSION_DIR={SESSION_DIR}")
PYEOFEach model reviews and ranks the anonymized responses from Phase 1:
SESSION_DIR="/tmp/llm-council/TIMESTAMP_HERE"
python3 << 'PYEOF'
import os
import json
import requests
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
FIREWORKS_API_KEY = os.environ.get("FIREWORKS_API_KEY")
API_URL = "https://api.fireworks.ai/inference/v1/chat/completions"
SESSION_DIR = os.environ.get("SESSION_DIR")
# Load Phase 1 results
with open(f"{SESSION_DIR}/config.json") as f:
config = json.load(f)
with open(f"{SESSION_DIR}/phase1_responses.json") as f:
phase1_results = json.load(f)
QUERY = config["query"]
MODELS = config["models"]
# Create anonymized mapping
labels = ["A", "B", "C", "D", "E", "F", "G"][:len(MODELS)]
model_to_label = dict(zip(MODELS, labels))
label_to_model = {v: k for k, v in model_to_label.items()}
# Format anonymized responses
anonymized_responses = []
for model_id in MODELS:
label = model_to_label[model_id]
content = phase1_results[model_id]["content"]
anonymized_responses.append(f"=== Response {label} ===\n{content}")
anonymized_text = "\n\n".join(anonymized_responses)
def get_rankings(model_id, query, anonymized, own_label):
"""Get rankings from a single model"""
ranking_prompt = f"""You are evaluating responses from multiple AI models to this query:
QUERY: {query}
Here are the anonymized responses:
{anonymized}
Please rank these responses from BEST to WORST. For each ranking:
1. State the response letter (A, B, C, etc.)
2. Give a brief reason (1-2 sentences)
3. You may skip ranking your own response (labeled {own_label}) or rank it fairly
Format your response EXACTLY as:
RANKINGS:
1. [Letter] - [Brief reason]
2. [Letter] - [Brief reason]
3. [Letter] - [Brief reason]
..."""
try:
start = time.time()
response = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {FIREWORKS_API_KEY}",
"Content-Type": "application/json"
},
json={
"model": model_id,
"messages": [
{"role": "system", "content": f"You are ranking AI responses objectively. Your own response is labeled '{own_label}'."},
{"role": "user", "content": ranking_prompt}
],
"max_tokens": 1000,
"temperature": 1
},
timeout=90
)
response.raise_for_status()
elapsed = time.time() - start
return {
"success": True,
"content": response.json()["choices"][0]["message"]["content"],
"model": model_id,
"latency_seconds": round(elapsed, 2)
}
except Exception as e:
return {
"success": False,
"content": f"[ERROR: {str(e)}]",
"model": model_id,
"latency_seconds": 0
}
print(f"\n{'='*60}")
print("PHASE 2: Cross-Model Ranking")
print(f"{'='*60}")
print(f"Label mapping: {json.dumps({v: k.split('/')[-1] for k, v in model_to_label.items()})}")
print()
# Collect rankings from all models in parallel
rankings = {}
with ThreadPoolExecutor(max_workers=len(MODELS)) as executor:
futures = {
executor.submit(get_rankings, mid, QUERY, anonymized_text, model_to_label[mid]): mid
for mid in MODELS
}
for future in as_completed(futures):
model = futures[future]
result = future.result()
rankings[model] = result
status = "OK" if result["success"] else "FAILED"
latency = f"{result['latency_seconds']}s" if result["success"] else "N/A"
print(f" [{status}] {model.split('/')[-1]} ({latency})")
# Save rankings
output = {
"label_mapping": label_to_model,
"model_to_label": model_to_label,
"rankings": rankings
}
with open(f"{SESSION_DIR}/phase2_rankings.json", "w") as f:
json.dump(output, f, indent=2)
print(f"\nPhase 2 complete. Rankings saved to: {SESSION_DIR}/phase2_rankings.json")
PYEOFThe Chairman model receives all responses and rankings, then produces the final synthesis:
SESSION_DIR="/tmp/llm-council/TIMESTAMP_HERE"
CHAIRMAN_MODEL="accounts/fireworks/models/glm-5"
python3 << 'PYEOF'
import os
import json
import requests
import time
FIREWORKS_API_KEY = os.environ.get("FIREWORKS_API_KEY")
API_URL = "https://api.fireworks.ai/inference/v1/chat/completions"
SESSION_DIR = os.environ.get("SESSION_DIR")
CHAIRMAN_MODEL = os.environ.get("CHAIRMAN_MODEL")
# Load all previous results
with open(f"{SESSION_DIR}/config.json") as f:
config = json.load(f)
with open(f"{SESSION_DIR}/phase1_responses.json") as f:
phase1 = json.load(f)
with open(f"{SESSION_DIR}/phase2_rankings.json") as f:
phase2 = json.load(f)
QUERY = config["query"]
label_to_model = phase2["label_mapping"]
model_to_label = phase2["model_to_label"]
# Format responses with model names revealed
responses_text = []
for model_id, result in phase1.items():
label = model_to_label.get(model_id, "?")
model_name = model_id.split("/")[-1]
responses_text.append(f"=== {label}: {model_name} ===\n{result['content']}")
# Format rankings
rankings_text = []
for model_id, result in phase2["rankings"].items():
model_name = model_id.split("/")[-1]
rankings_text.append(f"[{model_name}'s Rankings]\n{result['content']}")
synthesis_prompt = f"""You are the Chairman of an LLM Council. Your task is to synthesize the best possible answer from multiple AI responses.
ORIGINAL QUERY:
{QUERY}
INDIVIDUAL RESPONSES:
{chr(10).join(responses_text)}
MODEL RANKINGS:
{chr(10).join(rankings_text)}
As Chairman, produce a FINAL SYNTHESIS that:
1. Incorporates the strongest elements from the best-ranked responses
2. Resolves any contradictions between responses
3. Addresses aspects that multiple models agreed on
4. Corrects any errors identified through cross-ranking
5. Provides the most complete, accurate, and helpful answer
Begin your synthesis:"""
print(f"\n{'='*60}")
print("PHASE 3: Chairman Synthesis")
print(f"{'='*60}")
print(f"Chairman: {CHAIRMAN_MODEL.split('/')[-1]}")
print()
try:
start = time.time()
response = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {FIREWORKS_API_KEY}",
"Content-Type": "application/json"
},
json={
"model": CHAIRMAN_MODEL,
"messages": [
{"role": "system", "content": "You are the Chairman of an LLM Council. Synthesize multiple AI perspectives into a definitive, comprehensive response."},
{"role": "user", "content": synthesis_prompt}
],
"max_tokens": 4000,
"temperature": 1
},
timeout=180
)
response.raise_for_status()
elapsed = time.time() - start
synthesis = response.json()["choices"][0]["message"]["content"]
with open(f"{SESSION_DIR}/phase3_synthesis.txt", "w") as f:
f.write(synthesis)
print(f"Phase 3 complete ({elapsed:.2f}s). Synthesis saved to: {SESSION_DIR}/phase3_synthesis.txt")
except Exception as e:
print(f"ERROR: {e}")
synthesis = f"[ERROR: {str(e)}]"
with open(f"{SESSION_DIR}/phase3_synthesis.txt", "w") as f:
f.write(synthesis)
# Update config with chairman
config["chairman"] = CHAIRMAN_MODEL
with open(f"{SESSION_DIR}/config.json", "w") as f:
json.dump(config, f, indent=2)
PYEOFRead all saved files and display the complete council deliberation:
SESSION_DIR="/tmp/llm-council/TIMESTAMP_HERE"
python3 << 'PYEOF'
import os
import json
SESSION_DIR = os.environ.get("SESSION_DIR")
# Load all data
with open(f"{SESSION_DIR}/config.json") as f:
config = json.load(f)
with open(f"{SESSION_DIR}/phase1_responses.json") as f:
phase1 = json.load(f)
with open(f"{SESSION_DIR}/phase2_rankings.json") as f:
phase2 = json.load(f)
with open(f"{SESSION_DIR}/phase3_synthesis.txt") as f:
synthesis = f.read()
model_to_label = phase2["model_to_label"]
label_to_model = phase2["label_mapping"]
# Build formatted output
output = []
output.append("=" * 70)
output.append(" LLM COUNCIL DELIBERATION")
output.append(" Powered by Fireworks AI")
output.append("=" * 70)
output.append("")
output.append(f"QUERY: {config['query']}")
output.append(f"COUNCIL: {', '.join([m.split('/')[-1] for m in config['models']])}")
output.append(f"CHAIRMAN: {config.get('chairman', 'N/A').split('/')[-1]}")
output.append("")
# Phase 1: Individual Responses
output.append("-" * 70)
output.append(" PHASE 1: INDIVIDUAL RESPONSES")
output.append("-" * 70)
output.append("")
for model_id, result in phase1.items():
model_name = model_id.split("/")[-1]
label = model_to_label.get(model_id, "?")
latency = result.get("latency_seconds", "N/A")
tokens = result.get("tokens", {})
output.append(f"[{label}] {model_name} (latency: {latency}s, tokens: {tokens.get('total', 'N/A')})")
output.append("-" * 40)
output.append(result["content"])
output.append("")
# Phase 2: Cross-Model Rankings
output.append("-" * 70)
output.append(" PHASE 2: CROSS-MODEL RANKINGS")
output.append("-" * 70)
output.append("")
output.append(f"Label mapping: {json.dumps({v: k.split('/')[-1] for k, v in model_to_label.items()}, indent=2)}")
output.append("")
for model_id, result in phase2["rankings"].items():
model_name = model_id.split("/")[-1]
output.append(f"[{model_name}'s Rankings]")
output.append(result["content"])
output.append("")
# Phase 3: Chairman Synthesis
output.append("-" * 70)
output.append(" PHASE 3: CHAIRMAN'S SYNTHESIS")
output.append("-" * 70)
output.append("")
chairman_name = config.get("chairman", "Chairman").split("/")[-1]
output.append(f"[{chairman_name} - Chairman]")
output.append("")
output.append(synthesis)
output.append("")
output.append("=" * 70)
output.append(f"Session files: {SESSION_DIR}/")
# Save formatted output
final_output = "\n".join(output)
with open(f"{SESSION_DIR}/final_output.md", "w") as f:
f.write(final_output)
print(final_output)
print(f"\nFull output saved to: {SESSION_DIR}/final_output.md")
PYEOF/tmp/llm-council/{timestamp}/export FIREWORKS_API_KEY="your_api_key_here"source ~/.zshrc© dair-ai, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in plugins/llm-council/skills/llm-council of dair-ai/dair-academy-plugins.
Open the folder on GitHubat commit 0abffdc
LLM Council on Fireworks AI next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| LLM Council on Fireworks AI this skilldair-ai/dair-academy-plugins | 614 | — | ~5k | Automated safety check: Notes | MIT | |
| OmniRoute Chat CLIdiegosouzapw/OmniRoute | 75k | — | ~345 | Automated safety check: Pass | MIT | |
| Model Architecture Diagram FinderBBuf/AI-Infra-Auto-Driven-SKILLS | 938 | — | ~1.2k | Automated safety check: Pass | None | |
| Quota Axikunchenguid/quota-axi | 147 | — | ~547 | Automated safety check: Pass | MIT | |
| Update Ollama Cloud Modelsheypinchy/pinchy | 182 | — | ~3.9k | Automated safety check: Notes | AGPL-3.0 | |
| Model Routingalinaqi/maggy | 707 | — | ~1.5k | Automated safety check: Pass | MIT |
diegosouzapw/OmniRoute
Sends chat completions, streams responses, and opens an interactive REPL against any OmniRoute-routed model provider.
BBuf/AI-Infra-Auto-Driven-SKILLS
Looks up public original architecture diagrams for named LLM, vision-language, MoE, diffusion and OCR models and returns the image with its source attribution.
kunchenguid/quota-axi
Report local Claude, Codex, Cursor, GitHub Copilot, Grok, Kimi, Z.AI, Alibaba, OpenCode Go, Antigravity, Command Code, MiniMax, MiMo, DeepSeek, OpenRouter, ElevenLabs, Devin, Muse, and Higgsfield…
heypinchy/pinchy
A skill your agent uses when a new Ollama Cloud model is announced or available (e.g.
alinaqi/maggy
9-tier model routing system with cascading classifier fallback and result auto-evaluation
ascend-ai-coding/awesome-ascend-skills
Track daily PRs and Issues from vllm-project/vllm and vllm-project/vllm-ascend, filter by model (DeepSeek/Qwen/GLM/MiniMax/Kimi) and tech topics (PD disaggregation, MTP, quantization, graph mode…
dair-ai/dair-academy-plugins
Creates and maintains configurable research wikis: scaffold a folder, add sources, compile pages and indexes, and file query answers back.
dair-ai/dair-academy-plugins
Generates and edits images with Google's Gemini Nano Banana Pro model through the Gemini API, including photo edits and multi-image composition.
dair-ai/dair-academy-plugins
Builds a single-file HTML survey paper on an AI or ML topic from a research bundle the agent curates, with prose and SVG figures written by Kimi K2.6.
dair-ai/dair-academy-plugins
Converts a YouTube talk into a markdown study note with slide images, a timestamped transcript and editable notes, browsable through a small local server.
dair-ai/dair-academy-plugins
Help a user learn a topic through adaptive tutoring, lesson planning, practice, retrieval checks, explanations, study guides, or exercises.
dair-ai/dair-academy-plugins
Builds a self-contained HTML digest of AI and agent news pulled from chosen X accounts through the official X MCP server, grouped into categories like Coding Agents and Agent Research.
Categories
Has several open-weight models answer a question, rank each other's anonymized answers, then lets a chairman model write the final response through Fireworks AI. This skill implements the LLM Council idea attributed to Karpathy, running every model call through Fireworks AI. Phase one sends your question to each selected model independently and in parallel.
LLM Council on Fireworks AI fits situations like: comparing how several open-weight models answer the same question; building a consensus answer from multiple model perspectives; having models rank each other's answers before a final synthesis.
Run `npx skills add dair-ai/dair-academy-plugins --skill llm-council -a claude-code`. Or copy the skill folder (plugins/llm-council/skills/llm-council in dair-ai/dair-academy-plugins) into .claude/skills/llm-council in your project. Claude Code loads it when a task matches its description.
Run `npx skills add dair-ai/dair-academy-plugins --skill llm-council -a codex`. Or copy the skill folder (plugins/llm-council/skills/llm-council in dair-ai/dair-academy-plugins) into .agents/skills/llm-council in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add dair-ai/dair-academy-plugins --skill llm-council -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/llm-council, .gemini/skills/llm-council, .github/skills/llm-council and .opencode/skills/llm-council in your project.
Going by SKILL.md and its folder, LLM Council on Fireworks AI needs the command-line tools its instructions call (python3) and credentials named FIREWORKS_API_KEY. Our summary lists: A Fireworks AI account and a FIREWORKS_API_KEY. Its frontmatter pre-approves these tools: Read, Write, Bash, AskUserQuestion.
SKILL.md names 2 domains. In commands or code: fireworks.ai and api.fireworks.ai; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
LLM Council on Fireworks AI is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with LLM Council on Fireworks AI: OmniRoute Chat CLI (diegosouzapw/OmniRoute, 75k stars), Model Architecture Diagram Finder (BBuf/AI-Infra-Auto-Driven-SKILLS, 938 stars), Quota Axi (kunchenguid/quota-axi, 147 stars) and Update Ollama Cloud Models (heypinchy/pinchy, 182 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
dair-ai (a GitHub organization) maintains it in dair-ai/dair-academy-plugins, which has 614 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on July 21, 2026.
Source: dair-ai/dair-academy-plugins on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.