Skip to main content
Glama

ask_council

Resolve high-stakes engineering decisions by asking multiple AI models in parallel and receiving one synthesized answer with consensus and disagreement signals.

Instructions

DIRECTIONAL — reserve this for a genuinely contentious or HARD-TO-REVERSE decision (architecture, concurrency, data model, public API, migration) where a single opinion isn't enough and you want several models cross-checked, or for divergent brainstorming where you want independent idea sets merged without losing distinct options. It's slower and heavier than ask, so DON'T reach for it on routine questions — default to ask, and use at most one council call per problem. Check quorum/degraded in the result: a 1-of-N answer is one opinion, not consensus. Ask several models at once the same SOFTWARE/ENGINEERING question, then get back one answer that Fable synthesizes by reconciling all of them (each raw answer is also returned under sources). By default asks Fable (whichever id is newest) + MiniMax (MiniMax-M3), plus DeepSeek (deepseek-flash) when ASK_FABLE_DEEPSEEK_API_KEY is configured — cheap direct models are preferred and consulted first. Pass models to choose from ['fable','fable51','opus','deepseek','minimax','glm','gemini','codex','grok','kimi'] ('fable' tracks the newest Fable automatically and 'fable51' pins claude-fable-5-1 even after it stops being newest — they are the same model today, so naming both buys you nothing; 'opus' is the newest Claude Opus on the same OAuth session as Fable — always available, half the price; 'gemini'/'codex'/'grok'/'kimi' need their local CLIs; 'glm'/'deepseek' need API keys configured on the server). You can also add Ollama Cloud models as 'ollama:' tokens (e.g. 'ollama:qwen3-coder:480b-cloud', 'ollama:nemotron-3-ultra:cloud'); these are reached via a local signed-in ollama daemon by default (reported+skipped if unreachable). The group token 'twin' (aka 'twin flames') expands to BOTH Anthropic reasoners at once — fable + opus — so models=['twin'] is a dual Fable/Opus invocation and models=['twin','minimax'] adds a third voice to it. Both ride the OAuth session, so it needs no provider keys and is the cheapest real second opinion available. Instead of listing models, you can pass a named tier: 'default' (fable+minimax, +deepseek when its key is configured), 'twin' (the twin flames, fable+opus), 'middle' (all of the above +opus+glm+gemini+codex+grok+kimi, cheap models first), or 'full' (+the configured Ollama Cloud models). Instead of models/tier, pass provider ('ollama', 'atlas', 'openrouter', or 'lmstudio') to scope the council to ONE gateway: its configured panel is used by default, its members are that provider's tokens, its adjudicator ladder applies (GPT-first for atlas/openrouter), and 'lmstudio' runs the panel one model at a time (a single GPU). An explicit models is honored within the chosen provider; tier is ignored when provider is set. The result carries a consensus signal ('strong' | 'partial' | 'divergent' | 'unknown') and material_disagreement computed from the panelists' recommendations, and each entry in sources shows that model's recommendation — so you can see WHO endorsed what, not just the merged answer. Panel answers are anonymized to the synthesizer to blunt self-preference bias. Pass synthesizer to have a different model adjudicate the panel (default 'fable'; e.g. 'opus' = newest Claude Opus, 'codex'/'gpt' = GPT-5.6 Sol via the local CLI, or 'atlas:openai/gpt-5.6-sol') — it falls back to Fable when unavailable or failing, and the result's synthesis block reports what actually ran. Same scope as ask: broad and conceptual engineering questions (including brainstorming) are fine; direct offensive-security asks and non-software domain knowledge (biology/medicine refused; neuroscience, cognitive science, AI/ML, and CS are in-scope) are refused.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tierNoNamed council preset (used when `models` is omitted): 'default' = fable+minimax, +deepseek when its API key is configured; 'twin' = the twin flames, fable+opus — a dual Fable/Opus 5 invocation needing no provider keys at all; 'middle' = +opus+glm+gemini+codex+grok+kimi (cheap models first); 'full' = +the configured Ollama Cloud models (ASK_FABLE_OLLAMA_COUNCIL).default
modelsNoExplicit list of models to ask, from ['fable','opus','deepseek','minimax','glm','gemini','codex','grok','kimi'] (aliases: 'm3' = minimax, 'gpt' = codex, 'xai' = grok, 'opus5' = opus), plus any 'ollama:<model>' cloud token (e.g. 'ollama:kimi-k2.7-code:cloud') or 'atlas:<model-id>' token (e.g. 'atlas:zai-org/glm-5.2'). One entry may be the group token 'twin' (aka 'twin flames'), which expands to BOTH Anthropic reasoners — fable + opus — on the one OAuth session, so ['twin'] is a dual Fable/Opus 5 invocation and ['twin','minimax'] adds a third voice to it. Overrides `tier` when given. 'glm'/'deepseek', 'ollama:*' and 'atlas:*' require API keys configured on the server; unconfigured ones are reported and skipped, not fatal.
contextNoOptional code snippets, file paths, or structural context (shared by all models).
sessionNoOptional coordination key for the cross-agent hub (`session_list` / `session_peek`). Reuse the same key across agents working the same decision so turns group together. Defaults to the tool name (`ask_council` / `ask_chain` / `ask_debate` / …) when omitted.
trustedNoOperator-authorized. When true, the prohibited-use denylist runs in log-only mode: security vocabulary in the question AND in `context` is audited but does not block. Use for legitimate security-engineering work (PoC analysis, CVE research, binary hardening review) where the ask genuinely needs security terms. Takes effect ONLY when the operator has set ASK_FABLE_ALLOW_TRUSTED (env or config); otherwise the flag is ignored and the denylist still applies.
providerNoScope the council to ONE gateway: the default panel comes from that provider's configured set (for atlas/openrouter, else a live-catalog shortlist), members are its tokens, and the adjudicator follows that provider's ladder (GPT-first for atlas/openrouter; Fable otherwise). `lmstudio` runs the panel ONE AT A TIME (a single GPU serves one model at a time). An explicit `models` is honored within the chosen provider; `tier` is ignored when `provider` is set. Omit for a mixed council selected by `models`/`tier`.
questionYesA specific software/engineering question to ask the selected models; Fable then synthesizes their answers into one.
context_refNoKey(s) of context saved with `context(op="write", …)` to pull in and prepend to `context` — paste a big context ONCE, reference it by key here. Missing keys are reported, not fatal.
synthesizerNoModel that reconciles the panel answers into one (default 'fable'). Any council token works: 'opus' (Claude Opus 5 — cheaper and faster than Fable), 'codex' (alias 'gpt', GPT-5.6 Sol via the local CLI), 'atlas:openai/gpt-5.6-sol', 'ollama:<model>', … It may also be a panel member — its own answer is anonymized and read last. If it is unavailable or fails, synthesis falls back to Fable (see `synthesis` in the result).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.18.0
    • changedInput schema / properties / context_ref / description
      Previous value: -"Key(s) of context saved with `context_write` to pull in and prepend to `context` — paste a big context ONCE, reference it by key here. Missing keys are reported, not fatal."New value: +"Key(s) of context saved with `context(op=\"write\", …)` to pull in and prepend to `context` — paste a big context ONCE, reference it by key here. Missing keys are reported, not fatal."
    • changedInput schema / properties / models / items / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "fable",
      -      "fable51",
      -      "opus",
      -      "opus48",
      -      "sonnet",
      -      "deepseek",
      -      "minimax",
      -      "glm",
      -      "gemini",
      -      "codex",
      -      "grok",
      -      "kimi",
      -      "claude-fable-5-1",
      -      "claude-opus-4-8",
      -      "claude-opus-5",
      -      "claude-sonnet-5",
      -      "fable-5.1",
      -      "fable-51",
      -      "fable5.1",
      -      "gpt",
      -      "m3",
      -      "opus-4.8",
      -      "opus-48",
      -      "opus-5",
      -      "opus4.8",
      -      "opus5",
      -      "sonnet-5",
      -      "sonnet5",
      -      "xai",
      -      "twin",
      -      "twin flame",
      -      "twin flames",
      -      "twin-flame",
      -      "twin-flames",
      -      "twin_flame",
      -      "twin_flames",
      -      "twinflame",
      -      "twinflames",
      -      "twins"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^ollama:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^atlas:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^openrouter:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^lmstudio:.+",
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "fable",
      +      "fable51",
      +      "opus",
      +      "opus55",
      +      "opus5",
      +      "opus48",
      +      "sonnet",
      +      "deepseek",
      +      "minimax",
      +      "glm",
      +      "gemini",
      +      "codex",
      +      "grok",
      +      "kimi",
      +      "claude-fable-5-1",
      +      "claude-opus-4-8",
      +      "claude-opus-5",
      +      "claude-opus-5-5",
      +      "claude-sonnet-5",
      +      "fable-5.1",
      +      "fable-51",
      +      "fable5.1",
      +      "gpt",
      +      "m3",
      +      "opus-4.8",
      +      "opus-48",
      +      "opus-5",
      +      "opus-5.5",
      +      "opus-55",
      +      "opus4.8",
      +      "opus5.5",
      +      "sonnet-5",
      +      "sonnet5",
      +      "xai",
      +      "twin",
      +      "twin flame",
      +      "twin flames",
      +      "twin-flame",
      +      "twin-flames",
      +      "twin_flame",
      +      "twin_flames",
      +      "twinflame",
      +      "twinflames",
      +      "twins"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^ollama:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^atlas:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^openrouter:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^lmstudio:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^ali:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^[^\\s:]+/[^\\s:]+$",
      +    "type": "string"
      +  }
      +]
    • addedInput schema / properties / provider
      Added value: +{
      +  "description": "Scope the council to ONE gateway: the default panel comes from that provider's configured set (for atlas/openrouter, else a live-catalog shortlist), members are its tokens, and the adjudicator follows that provider's ladder (GPT-first for atlas/openrouter; Fable otherwise). `lmstudio` runs the panel ONE AT A TIME (a single GPU serves one model at a time). An explicit `models` is honored within the chosen provider; `tier` is ignored when `provider` is set. Omit for a mixed council selected by `models`/`tier`.",
      +  "enum": [
      +    "ollama",
      +    "atlas",
      +    "openrouter",
      +    "lmstudio"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / synthesizer / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "fable",
      -      "fable51",
      -      "opus",
      -      "opus48",
      -      "sonnet",
      -      "deepseek",
      -      "minimax",
      -      "glm",
      -      "gemini",
      -      "codex",
      -      "grok",
      -      "kimi",
      -      "claude-fable-5-1",
      -      "claude-opus-4-8",
      -      "claude-opus-5",
      -      "claude-sonnet-5",
      -      "fable-5.1",
      -      "fable-51",
      -      "fable5.1",
      -      "gpt",
      -      "m3",
      -      "opus-4.8",
      -      "opus-48",
      -      "opus-5",
      -      "opus4.8",
      -      "opus5",
      -      "sonnet-5",
      -      "sonnet5",
      -      "xai"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^ollama:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^atlas:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^openrouter:.+",
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "fable",
      +      "fable51",
      +      "opus",
      +      "opus55",
      +      "opus5",
      +      "opus48",
      +      "sonnet",
      +      "deepseek",
      +      "minimax",
      +      "glm",
      +      "gemini",
      +      "codex",
      +      "grok",
      +      "kimi",
      +      "claude-fable-5-1",
      +      "claude-opus-4-8",
      +      "claude-opus-5",
      +      "claude-opus-5-5",
      +      "claude-sonnet-5",
      +      "fable-5.1",
      +      "fable-51",
      +      "fable5.1",
      +      "gpt",
      +      "m3",
      +      "opus-4.8",
      +      "opus-48",
      +      "opus-5",
      +      "opus-5.5",
      +      "opus-55",
      +      "opus4.8",
      +      "opus5.5",
      +      "sonnet-5",
      +      "sonnet5",
      +      "xai"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^ollama:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^atlas:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^openrouter:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^ali:.+",
      +    "type": "string"
      +  }
      +]
  2. Changed3 schema fields changedv0.16.0
    • changedInput schema / properties / models / items / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "fable",
      -      "fable51",
      -      "opus",
      -      "deepseek",
      -      "minimax",
      -      "glm",
      -      "gemini",
      -      "codex",
      -      "grok",
      -      "kimi",
      -      "claude-fable-5-1",
      -      "claude-opus-5",
      -      "fable-5.1",
      -      "fable-51",
      -      "fable5.1",
      -      "gpt",
      -      "m3",
      -      "opus-5",
      -      "opus5",
      -      "xai",
      -      "twin",
      -      "twin flame",
      -      "twin flames",
      -      "twin-flame",
      -      "twin-flames",
      -      "twin_flame",
      -      "twin_flames",
      -      "twinflame",
      -      "twinflames",
      -      "twins"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^ollama:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^atlas:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^openrouter:.+",
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "fable",
      +      "fable51",
      +      "opus",
      +      "opus48",
      +      "sonnet",
      +      "deepseek",
      +      "minimax",
      +      "glm",
      +      "gemini",
      +      "codex",
      +      "grok",
      +      "kimi",
      +      "claude-fable-5-1",
      +      "claude-opus-4-8",
      +      "claude-opus-5",
      +      "claude-sonnet-5",
      +      "fable-5.1",
      +      "fable-51",
      +      "fable5.1",
      +      "gpt",
      +      "m3",
      +      "opus-4.8",
      +      "opus-48",
      +      "opus-5",
      +      "opus4.8",
      +      "opus5",
      +      "sonnet-5",
      +      "sonnet5",
      +      "xai",
      +      "twin",
      +      "twin flame",
      +      "twin flames",
      +      "twin-flame",
      +      "twin-flames",
      +      "twin_flame",
      +      "twin_flames",
      +      "twinflame",
      +      "twinflames",
      +      "twins"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^ollama:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^atlas:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^openrouter:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^lmstudio:.+",
      +    "type": "string"
      +  }
      +]
    • changedInput schema / properties / synthesizer / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "fable",
      -      "fable51",
      -      "opus",
      -      "deepseek",
      -      "minimax",
      -      "glm",
      -      "gemini",
      -      "codex",
      -      "grok",
      -      "kimi",
      -      "claude-fable-5-1",
      -      "claude-opus-5",
      -      "fable-5.1",
      -      "fable-51",
      -      "fable5.1",
      -      "gpt",
      -      "m3",
      -      "opus-5",
      -      "opus5",
      -      "xai"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^ollama:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^atlas:.+",
      -    "type": "string"
      -  },
      -  {
      -    "pattern": "^openrouter:.+",
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "fable",
      +      "fable51",
      +      "opus",
      +      "opus48",
      +      "sonnet",
      +      "deepseek",
      +      "minimax",
      +      "glm",
      +      "gemini",
      +      "codex",
      +      "grok",
      +      "kimi",
      +      "claude-fable-5-1",
      +      "claude-opus-4-8",
      +      "claude-opus-5",
      +      "claude-sonnet-5",
      +      "fable-5.1",
      +      "fable-51",
      +      "fable5.1",
      +      "gpt",
      +      "m3",
      +      "opus-4.8",
      +      "opus-48",
      +      "opus-5",
      +      "opus4.8",
      +      "opus5",
      +      "sonnet-5",
      +      "sonnet5",
      +      "xai"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^ollama:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^atlas:.+",
      +    "type": "string"
      +  },
      +  {
      +    "pattern": "^openrouter:.+",
      +    "type": "string"
      +  }
      +]
    • addedInput schema / properties / trusted
      Added value: +{
      +  "default": false,
      +  "description": "Operator-authorized. When true, the prohibited-use denylist runs in log-only mode: security vocabulary in the question AND in `context` is audited but does not block. Use for legitimate security-engineering work (PoC analysis, CVE research, binary hardening review) where the ask genuinely needs security terms. Takes effect ONLY when the operator has set ASK_FABLE_ALLOW_TRUSTED (env or config); otherwise the flag is ignored and the denylist still applies.",
      +  "type": "boolean"
      +}
  3. First observedv0.12.0

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide only minimal safety flags, so the description carries the full burden, and it delivers: it discloses slowness, one-of-N caveats, result signals (`consensus`, `material_disagreement`, `sources`), anonymization of panel answers, synthesizer fallback, provider-specific behavior, and trusted-mode semantics. No contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is accurate and dense but extremely long and formatted as a single wall of text, which hurts scannability. It front-loads the key usage directive, but it repeats details already present in the schema descriptions (e.g., twin expansion, tier defaults) and would benefit from bullets or section breaks.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates well by explaining what the result contains: `consensus`, `material_disagreement`, `sources` with per-model `recommendation`, and a `synthesis` block. It also covers availability, refusal scope, fallback behavior, and configuration-dependent behavior, so the agent has what it needs to call and interpret the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description goes far beyond field names: it explains the `twin` group token expansion, `tier` meaning relative to `models`, provider-scoped council behavior, synthesizer fallback, and unconfigured-model skipping. This is substantial meaning that the schema alone does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action: ask several models the same software/engineering question and get one Fable-synthesized answer. It distinguishes itself from `ask` by framing itself for contentious or hard-to-reverse decisions, so an agent can tell siblings apart without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is explicitly conditioned: use for hard-to-reverse decisions, divergent brainstorming, or multi-model cross-checking; do NOT use for routine questions, defaulting to `ask`. It even limits to at most one council call per problem and tells the agent to check `quorum`/`degraded`, which is actionable routing guidance beyond any schema field.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.