Modules
Multi-model LLM council workflows for Elixir.
Behaviour for round-level aggregators.
Borda count over rankings. Each member output exposes :ordering (a
list, most-preferred first). For N options, position k gets N-k points.
Highest total wins.
Condorcet method. Pairwise comparison of all options across members'
rankings. Returns the option that beats every other option pairwise,
or winner: nil with raw: %{cycle: true} when no Condorcet winner exists.
Median of confidences per option, robust to outliers. Highest median wins.
Borda-count winner plus a "report" suitable for direct UI display: per-judge ballots, average rank position per option, and a vote-count per option.
Most votes wins. Each member output must expose a :choice field.
Weights each option's score by member confidence. For Vote outputs: each option's total = sum of confidences of members who chose it. Highest total wins.
Relabel a map of member_id => content so models cannot identify
whose output is whose during peer review.
A council that picks itself.
Helpers for discovering which providers a council references.
Strategy dispatch for CouncilEx.AutoCouncil.
Try a chain of strategies in order; first success wins.
Stub. Semantic strategy: embed the prompt, cosine-similarity against precomputed catalog vectors, return the top match above a threshold.
Stub. Synthesizer strategy: an LLM designs a fresh DynamicCouncil for
the prompt — picking members, system prompts, rounds, and a chair — then
the resolver runs that synthesized council.
Stub. LLM-classifier strategy: a cheap model picks one catalog id given the prompt and the catalog descriptions. Returns the matching council.
Deterministic rule-based strategy for CouncilEx.AutoCouncil.
Behaviour for CouncilEx.AutoCouncil resolution strategies.
Diagnostic detector for demographic-laden disagreement across member outputs.
Per-member confidence extraction.
Central config resolution for CouncilEx.
Context object passed to rounds and members during a run. Carries the original input, the prior round results, and run metadata.
Topology #2 — independent_analysis → chair.
Topology #9 — independent_analysis → iterate(critique, until: ...) → chair.
K-judge majority topology with confidence-triggered retry.
Topology #1 — independent_analysis → synthesis (chair).
Topology #4 — drafter → critique (reviewers) → peer_review → chair.
Topology #6 — specialist members → peer_review → chair.
Topology #7 — independent_analysis → iterate(pairwise_elimination) → synthesis.
Topology #5 — independent_analysis → vote (with aggregator) → chair.
Topology — independent_analysis → weighted_synthesis (chair).
Static topology diagrams for a CouncilEx council module.
ASCII (box-drawing) renderers for CouncilEx.Diagram.
Canonical intermediate representation of a council topology.
Mermaid renderers for CouncilEx.Diagram.
Renders a council as a Mermaid sequenceDiagram showing interaction over
time: which seat receives what, how each response (R1, R2, …) flows into
later rounds, and where peers are hidden or anonymized.
Data-only council representation. Build at runtime, edit, persist to storage, restore, run — all without defining an Elixir module.
Data-only representation of a council member for runtime / DB-driven
councils. Module-form members (the static DSL) keep their module()
shape; dynamic councils use this struct everywhere a module would
appear.
Data-only round spec for dynamic councils. Maps a string round type
(e.g. "independent_analysis", "iterate") plus an opts map to one
of the built-in round modules (or a user-registered round).
Structured error captured during a council run.
Public catalog of PubSub events emitted on the run-scoped topic
"council_ex:run:#{run_id}". Stable extension surface as of v0.7.
Behaviour and DSL helpers for council members.
Per-member execution result.
Dispatch helpers that abstract over the two member representations
Compile-time generator for sub-council member shims. A council member declared
with member :id, council: SubCouncil produces a shim module satisfying
CouncilEx.Member plus a __sub_council__/0 callback that
CouncilEx.Runner.RoundExec uses to branch into sub-council execution.
Versioned schema migrations for CouncilEx's opt-in Ecto-backed
features (Registry, Reliability, Recorder). Modeled after
Oban.Migration.
Boot-time reconciliation for orphaned run rows.
Ecto schema for the <prefix>runs table.
Ecto schema for the <prefix>run_events table.
Reusable bundle of runtime/execution options for council members.
Prebaked profile: Anthropic Claude Sonnet at moderate temperature.
Prebaked profile: Google gemini-2.5-flash at moderate temperature.
Prebaked profile: locally-pulled Ollama llama3.1 at moderate temperature.
Prebaked profile: OpenAI gpt-4o with moderate temperature.
Prebaked profile: OpenAI gpt-4o tuned for divergent / creative output.
Prebaked profile: OpenAI gpt-4o with temperature: 0.0 for
reproducible / judging-style work.
Prebaked profile: OpenAI gpt-4o-mini at moderate temperature. Cheap
workhorse — good fit for member panels where the chair runs on a
larger model (e.g. OpenAIBalanced chair + OpenAIMini members).
Prebaked profile: OpenRouter openrouter/auto. OpenRouter picks the
best-fit model per request based on prompt characteristics. Useful as
a sensible default when you don't want to commit to one provider.
Prebaked profile: Anthropic Claude Sonnet served via OpenRouter
(anthropic/claude-sonnet-4-6). Useful when you want Claude quality
without managing a separate Anthropic provider entry.
Behaviour implemented by provider adapters.
Behaviour for provider-specific request/response handling.
Provider.Adapter for Anthropic Messages API.
Provider.Adapter for Google Gemini's Generative Language API.
Config preset for routing the OpenAI-compatible adapter at a local Ollama
server. NOT a separate Provider.Adapter implementation — uses
CouncilEx.Provider.Adapters.OpenAI underneath.
Provider.Adapter for OpenAI-compatible APIs (OpenAI, OpenRouter, Groq).
Provider.Adapter for OpenRouter (https://openrouter.ai).
Adapter-dispatching provider. Reads :adapter from config opts to
select the per-provider request/response handling module (e.g.,
CouncilEx.Provider.Adapters.OpenAI or Anthropic).
Raised by resolve_api_key/1 when an {:system, var} references an
unset environment variable. Kept for v0.1 back-compat; new code should
let the underlying adapter raise its own System.EnvError.
In-process mock provider for tests and demos.
Facade for the configured PubSub adapter.
Behaviour for CouncilEx.PubSub backends.
:pg-backed PubSub adapter. Default backend for CouncilEx.PubSub.
Phoenix.PubSub-backed adapter. Delegates to a user-supplied Phoenix.PubSub
server name configured via
Behaviour for run lifecycle event recorders.
Default CouncilEx.Recorder implementation backed by Ecto + Postgres.
Lookup table for the building blocks dynamic councils reference by string name: profiles, tools, output schemas, routers, custom rounds.
Pluggable storage backend for CouncilEx.Registry runtime registrations.
In-memory CouncilEx.Registry backend backed by ETS. Default.
Ecto-backed CouncilEx.Registry runtime registrations. Multi-replica safe.
Redis-backed CouncilEx.Registry runtime registrations. Multi-replica safe.
Per-member historical reliability tracking for adaptive weighting.
In-memory ETS-backed CouncilEx.Reliability store.
Ecto-backed CouncilEx.Reliability store. Multi-replica safe.
No-op CouncilEx.Reliability store. score/2 always returns nil.
Redis-backed CouncilEx.Reliability store. Multi-replica safe.
A normalized LLM request passed from the runner to a provider adapter.
A normalized provider response.
Top-level result of a council run.
Behaviour for round implementations.
Per-round execution result.
Like CouncilEx.Rounds.PeerReview but each judge sees the prior
round's outputs under anonymous labels ("Response A", "Response B",
…) instead of original member ids.
Like PeerReview but expects member outputs to match
CouncilEx.Schemas.Critique (strengths / weaknesses /
suggested_changes). Members typically declare
output_schema CouncilEx.Schemas.Critique.
Each member sees only the council's original input, with no awareness of other members. Ideal for the first round of any council.
Wraps another round, repeats until a convergence callback returns true
or max_iterations is reached.
One bracket level of a tournament. Pairs surviving members from the most recent bracket level (or all members on first invocation) and runs a pairwise judgment per pair, in parallel.
Each member sees the original input plus the previous round's outputs from the OTHER members, keyed by original member id. Members run in parallel.
Each member returns a %CouncilEx.Schemas.Ranking{} (or a map with
:ordering and :rationale). Round-level aggregate/2 delegates to
the configured aggregator (default CouncilEx.Aggregators.Borda).
Runs the chair sequentially with full visibility into prior rounds.
Each member returns a %CouncilEx.Schemas.Vote{} (or a map with
:choice, :rationale, :confidence). Round-level aggregate/2
delegates to the configured aggregator (default
CouncilEx.Aggregators.Plurality).
Chair synthesis round that exposes per-member weights to the chair prompt.
Optional behaviour for adaptive member subsetting.
GenServer that drives a single council run from start to finish.
Synchronous runner. Executes a compiled CouncilEx.Spec against an input
and returns a CouncilEx.Result.
GenServer that hosts a CouncilEx.Recorder callback module for a
single run.
Pure round-execution logic shared by the synchronous CouncilEx.Runner
and the internal M2b run-server (CouncilEx.RunServer).
Convert an Ecto embedded schema to a JSON Schema map.
Standard Ecto embedded schema for Critique-round member outputs.
Standard Ecto embedded schema for Ranking-round member outputs.
Standard Ecto embedded schema for Vote-round member outputs.
Compiled council specification produced by the DSL.
A single token chunk emitted during streaming.
Optional DynamicSupervisor wrapper for grouping council runs.
Helpers for emitting CouncilEx telemetry events.
Helpers for testing councils. Add import CouncilEx.Test in your test files.
Behaviour for tools an LLM member can call mid-completion.
A tool-call request emitted by an LLM mid-completion.
Result of executing a %CouncilEx.ToolCall{}.
Build a CouncilEx.Tool that retrieves passages from an in-memory
document corpus via BM25 ranking.
Per-run verbose tracer. Subscribes to a single run's PubSub topic and
prints a human-readable timeline to an IO device until the run reaches
a terminal event (:run_completed or :run_failed).
Oban worker that wraps a CouncilEx run in a durable, retry-safe
job.
Mix Tasks
Print a diagram of a council module's static topology.