# CouncilEx v0.1.0 - Table of Contents

Multi-model LLM council workflows. Run LLMs in parallel rounds, aggregate/judge outputs, stream tokens, call tools (parallel exec), observe via telemetry + PubSub. Stock OpenAI/Anthropic/Gemini/Ollama adapters; pluggable Provider.Adapter.

## Pages

- [CouncilEx](readme.md)
- [Changelog](changelog.md)
- [LICENSE](license.md)
- [Council topologies](councils.md)
- [Composition](composition.md)
- [Council Complexity Metric: design sketch](complexity.md)
- [Profiles](profiles.md)
- [Providers](providers.md)
- [Provider Models: Current Catalog](provider_models.md)
- [Per-member capabilities](per_member_capabilities.md)
- [Dynamic Councils: reference](dynamic_councils.md)
- [AutoCouncil: Auto-routing reference](auto_councils.md)
- [Peer Review Patterns](peer_review_patterns.md)
- [Tutorial: Building a Karpathy-Style LLM Council](tutorial_karpathy_council.md)
- [Council Mode (Wu et al.) — Paper-to-CouncilEx Mapping](council_mode_paper.md)
- [Related Work: LLM Council Landscape vs CouncilEx](related_work.md)
- [RAG — retrieval inside a council](rag.md)
- [Diagrams: Visualize Council Topology](diagrams.md)
- [Observability](observability.md)
- [Introspection: Inspect a Council as Data at Runtime](introspection.md)
- [Persistence](persistence.md)
- [Running councils — core API reference](running_councils.md)
- [Running CouncilEx in a Phoenix (or any long-running) app](running_in_phoenix.md)
- [Running CouncilEx from Oban (or any background-job system)](running_with_oban.md)
- [Testing CouncilEx Manually](testing.md)
- [Unit testing councils](unit_testing.md)

## Modules

- [CouncilEx.Config](CouncilEx.Config.md): Central config resolution for CouncilEx.
- [CouncilEx.Context](CouncilEx.Context.md): Context object passed to rounds and members during a run.
Carries the original input, the prior round results, and run metadata.

- [CouncilEx.Diagram.Ascii](CouncilEx.Diagram.Ascii.md): ASCII (box-drawing) renderers for `CouncilEx.Diagram`.
- [CouncilEx.Diagram.IR](CouncilEx.Diagram.IR.md): Canonical intermediate representation of a council topology.
- [CouncilEx.Diagram.Mermaid](CouncilEx.Diagram.Mermaid.md): Mermaid renderers for `CouncilEx.Diagram`.
- [CouncilEx.Diagram.Sequence](CouncilEx.Diagram.Sequence.md): 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.
- [CouncilEx.MemberResult](CouncilEx.MemberResult.md): Per-member execution result.
- [CouncilEx.Members.SubCouncilAdapter](CouncilEx.Members.SubCouncilAdapter.md): 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.
- [CouncilEx.Result](CouncilEx.Result.md): Top-level result of a council run.
- [CouncilEx.RoundResult](CouncilEx.RoundResult.md): Per-round execution result.
- [CouncilEx.Runner](CouncilEx.Runner.md): Synchronous runner. Executes a compiled `CouncilEx.Spec` against an input
and returns a `CouncilEx.Result`.
- [CouncilEx.Runner.RecorderProcess](CouncilEx.Runner.RecorderProcess.md): GenServer that hosts a `CouncilEx.Recorder` callback module for a
single run.
- [CouncilEx.Runner.RoundExec](CouncilEx.Runner.RoundExec.md): Pure round-execution logic shared by the synchronous `CouncilEx.Runner`
and the internal M2b run-server (CouncilEx.RunServer).

- [CouncilEx.Spec](CouncilEx.Spec.md): Compiled council specification produced by the DSL.

- Core
  - [CouncilEx](CouncilEx.md): Multi-model LLM council workflows for Elixir.
  - [CouncilEx.Error](CouncilEx.Error.md): Structured error captured during a council run.
  - [CouncilEx.Member](CouncilEx.Member.md): Behaviour and DSL helpers for council members.
  - [CouncilEx.Profile](CouncilEx.Profile.md): Reusable bundle of runtime/execution options for council members.
  - [CouncilEx.Request](CouncilEx.Request.md): A normalized LLM request passed from the runner to a provider adapter.

  - [CouncilEx.Response](CouncilEx.Response.md): A normalized provider response.

  - [CouncilEx.Round](CouncilEx.Round.md): Behaviour for round implementations.
  - [CouncilEx.Router](CouncilEx.Router.md): Optional behaviour for adaptive member subsetting.
  - [CouncilEx.RunServer](CouncilEx.RunServer.md): GenServer that drives a single council run from start to finish.
  - [CouncilEx.StreamChunk](CouncilEx.StreamChunk.md): A single token chunk emitted during streaming.

  - [CouncilEx.Supervisor](CouncilEx.Supervisor.md): Optional `DynamicSupervisor` wrapper for grouping council runs.
  - [CouncilEx.Tool](CouncilEx.Tool.md): Behaviour for tools an LLM member can call mid-completion.
  - [CouncilEx.ToolCall](CouncilEx.ToolCall.md): A tool-call request emitted by an LLM mid-completion.
  - [CouncilEx.ToolCallResult](CouncilEx.ToolCallResult.md): Result of executing a `%CouncilEx.ToolCall{}`.

- Dynamic Councils
  - [CouncilEx.DynamicCouncil](CouncilEx.DynamicCouncil.md): Data-only council representation. Build at runtime, edit, persist to
storage, restore, run — all without defining an Elixir module.
  - [CouncilEx.DynamicMember](CouncilEx.DynamicMember.md): 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.
  - [CouncilEx.DynamicRound](CouncilEx.DynamicRound.md): 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).
  - [CouncilEx.MemberSpec](CouncilEx.MemberSpec.md): Dispatch helpers that abstract over the two member representations
  - [CouncilEx.Registry](CouncilEx.Registry.md): Lookup table for the building blocks dynamic councils reference by string
name: profiles, tools, output schemas, routers, custom rounds.
  - [CouncilEx.Registry.Backend](CouncilEx.Registry.Backend.md): Pluggable storage backend for `CouncilEx.Registry` runtime registrations.
  - [CouncilEx.Registry.ETS](CouncilEx.Registry.ETS.md): In-memory `CouncilEx.Registry` backend backed by ETS. Default.
  - [CouncilEx.Registry.Ecto](CouncilEx.Registry.Ecto.md): Ecto-backed `CouncilEx.Registry` runtime registrations. Multi-replica safe.
  - [CouncilEx.Registry.Redis](CouncilEx.Registry.Redis.md): Redis-backed `CouncilEx.Registry` runtime registrations. Multi-replica safe.

- AutoCouncil
  - [CouncilEx.AutoCouncil](CouncilEx.AutoCouncil.md): A council that picks itself.
  - [CouncilEx.AutoCouncil.Providers](CouncilEx.AutoCouncil.Providers.md): Helpers for discovering which providers a council references.
  - [CouncilEx.AutoCouncil.Resolver](CouncilEx.AutoCouncil.Resolver.md): Strategy dispatch for `CouncilEx.AutoCouncil`.
  - [CouncilEx.AutoCouncil.Strategies.Cascade](CouncilEx.AutoCouncil.Strategies.Cascade.md): Try a chain of strategies in order; first success wins.
  - [CouncilEx.AutoCouncil.Strategies.Embedding](CouncilEx.AutoCouncil.Strategies.Embedding.md): *Stub.* Semantic strategy: embed the prompt, cosine-similarity against
precomputed catalog vectors, return the top match above a threshold.
  - [CouncilEx.AutoCouncil.Strategies.LLMBuild](CouncilEx.AutoCouncil.Strategies.LLMBuild.md): *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.
  - [CouncilEx.AutoCouncil.Strategies.LLMClassify](CouncilEx.AutoCouncil.Strategies.LLMClassify.md): *Stub.* LLM-classifier strategy: a cheap model picks one catalog id given
the prompt and the catalog descriptions. Returns the matching council.
  - [CouncilEx.AutoCouncil.Strategies.Rules](CouncilEx.AutoCouncil.Strategies.Rules.md): Deterministic rule-based strategy for `CouncilEx.AutoCouncil`.
  - [CouncilEx.AutoCouncil.Strategy](CouncilEx.AutoCouncil.Strategy.md): Behaviour for `CouncilEx.AutoCouncil` resolution strategies.

- Tools
  - [CouncilEx.Tools.InMemoryDocs](CouncilEx.Tools.InMemoryDocs.md): Build a `CouncilEx.Tool` that retrieves passages from an in-memory
document corpus via BM25 ranking.

- Prebaked Profiles
  - [CouncilEx.Profiles.AnthropicBalanced](CouncilEx.Profiles.AnthropicBalanced.md): Prebaked profile: Anthropic Claude Sonnet at moderate temperature.
  - [CouncilEx.Profiles.GeminiBalanced](CouncilEx.Profiles.GeminiBalanced.md): Prebaked profile: Google `gemini-2.5-flash` at moderate temperature.
  - [CouncilEx.Profiles.OllamaLocal](CouncilEx.Profiles.OllamaLocal.md): Prebaked profile: locally-pulled Ollama `llama3.1` at moderate temperature.
  - [CouncilEx.Profiles.OpenAIBalanced](CouncilEx.Profiles.OpenAIBalanced.md): Prebaked profile: OpenAI `gpt-4o` with moderate temperature.
  - [CouncilEx.Profiles.OpenAICreative](CouncilEx.Profiles.OpenAICreative.md): Prebaked profile: OpenAI `gpt-4o` tuned for divergent / creative output.

  - [CouncilEx.Profiles.OpenAIDeterministic](CouncilEx.Profiles.OpenAIDeterministic.md): Prebaked profile: OpenAI `gpt-4o` with `temperature: 0.0` for
reproducible / judging-style work.

  - [CouncilEx.Profiles.OpenAIMini](CouncilEx.Profiles.OpenAIMini.md): 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).
  - [CouncilEx.Profiles.OpenRouterAuto](CouncilEx.Profiles.OpenRouterAuto.md): 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.
  - [CouncilEx.Profiles.OpenRouterClaudeSonnet](CouncilEx.Profiles.OpenRouterClaudeSonnet.md): 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.

- Built-in Rounds
  - [CouncilEx.Rounds.AnonymizedPeerReview](CouncilEx.Rounds.AnonymizedPeerReview.md): 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.
  - [CouncilEx.Rounds.Critique](CouncilEx.Rounds.Critique.md): Like PeerReview but expects member outputs to match
`CouncilEx.Schemas.Critique` (`strengths` / `weaknesses` /
`suggested_changes`). Members typically declare
`output_schema CouncilEx.Schemas.Critique`.

  - [CouncilEx.Rounds.IndependentAnalysis](CouncilEx.Rounds.IndependentAnalysis.md): Each member sees only the council's original input, with no awareness of
other members. Ideal for the first round of any council.

  - [CouncilEx.Rounds.Iterate](CouncilEx.Rounds.Iterate.md): Wraps another round, repeats until a convergence callback returns true
or `max_iterations` is reached.
  - [CouncilEx.Rounds.PairwiseElimination](CouncilEx.Rounds.PairwiseElimination.md): 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.
  - [CouncilEx.Rounds.PeerReview](CouncilEx.Rounds.PeerReview.md): 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.
  - [CouncilEx.Rounds.Ranking](CouncilEx.Rounds.Ranking.md): 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`).

  - [CouncilEx.Rounds.Synthesis](CouncilEx.Rounds.Synthesis.md): Runs the chair sequentially with full visibility into prior rounds.
  - [CouncilEx.Rounds.Vote](CouncilEx.Rounds.Vote.md): 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`).

  - [CouncilEx.Rounds.WeightedSynthesis](CouncilEx.Rounds.WeightedSynthesis.md): Chair synthesis round that exposes per-member weights to the chair prompt.

- Built-in Councils
  - [CouncilEx.Councils.Chairman](CouncilEx.Councils.Chairman.md): Topology #2 — independent_analysis → chair.
  - [CouncilEx.Councils.Consensus](CouncilEx.Councils.Consensus.md): Topology #9 — independent_analysis → iterate(critique, until: ...) → chair.
  - [CouncilEx.Councils.JuryWithRetry](CouncilEx.Councils.JuryWithRetry.md): K-judge majority topology with confidence-triggered retry.
  - [CouncilEx.Councils.ParallelPanel](CouncilEx.Councils.ParallelPanel.md): Topology #1 — independent_analysis → synthesis (chair).
  - [CouncilEx.Councils.PeerReview](CouncilEx.Councils.PeerReview.md): Topology #4 — drafter → critique (reviewers) → peer_review → chair.
  - [CouncilEx.Councils.Specialist](CouncilEx.Councils.Specialist.md): Topology #6 — specialist members → peer_review → chair.
  - [CouncilEx.Councils.Tournament](CouncilEx.Councils.Tournament.md): Topology #7 — independent_analysis → iterate(pairwise_elimination) → synthesis.
  - [CouncilEx.Councils.Voting](CouncilEx.Councils.Voting.md): Topology #5 — independent_analysis → vote (with aggregator) → chair.
  - [CouncilEx.Councils.WeightedConsensus](CouncilEx.Councils.WeightedConsensus.md): Topology — independent_analysis → weighted_synthesis (chair).

- Aggregators
  - [CouncilEx.Aggregator](CouncilEx.Aggregator.md): Behaviour for round-level aggregators.
  - [CouncilEx.Aggregators.Borda](CouncilEx.Aggregators.Borda.md): 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.

  - [CouncilEx.Aggregators.Condorcet](CouncilEx.Aggregators.Condorcet.md): 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.

  - [CouncilEx.Aggregators.Median](CouncilEx.Aggregators.Median.md): Median of confidences per option, robust to outliers. Highest median wins.

  - [CouncilEx.Aggregators.PeerRanking](CouncilEx.Aggregators.PeerRanking.md): 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.
  - [CouncilEx.Aggregators.Plurality](CouncilEx.Aggregators.Plurality.md): Most votes wins. Each member output must expose a `:choice` field.
  - [CouncilEx.Aggregators.WeightedMean](CouncilEx.Aggregators.WeightedMean.md): 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.

- Reliability
  - [CouncilEx.BiasDetector](CouncilEx.BiasDetector.md): Diagnostic detector for demographic-laden disagreement across member outputs.
  - [CouncilEx.Confidence](CouncilEx.Confidence.md): Per-member confidence extraction.
  - [CouncilEx.Reliability](CouncilEx.Reliability.md): Per-member historical reliability tracking for adaptive weighting.
  - [CouncilEx.Reliability.ETS](CouncilEx.Reliability.ETS.md): In-memory ETS-backed `CouncilEx.Reliability` store.
  - [CouncilEx.Reliability.Ecto](CouncilEx.Reliability.Ecto.md): Ecto-backed `CouncilEx.Reliability` store. Multi-replica safe.
  - [CouncilEx.Reliability.Null](CouncilEx.Reliability.Null.md): No-op `CouncilEx.Reliability` store. `score/2` always returns `nil`.
  - [CouncilEx.Reliability.Redis](CouncilEx.Reliability.Redis.md): Redis-backed `CouncilEx.Reliability` store. Multi-replica safe.

- Persistence
  - [CouncilEx.Persistence.Migration](CouncilEx.Persistence.Migration.md): Versioned schema migrations for CouncilEx's opt-in Ecto-backed
features (Registry, Reliability, Recorder). Modeled after
`Oban.Migration`.
  - [CouncilEx.Persistence.Recovery](CouncilEx.Persistence.Recovery.md): Boot-time reconciliation for orphaned run rows.
  - [CouncilEx.Persistence.Schema.Run](CouncilEx.Persistence.Schema.Run.md): Ecto schema for the `<prefix>runs` table.
  - [CouncilEx.Persistence.Schema.RunEvent](CouncilEx.Persistence.Schema.RunEvent.md): Ecto schema for the `<prefix>run_events` table.
  - [CouncilEx.Recorder](CouncilEx.Recorder.md): Behaviour for run lifecycle event recorders.
  - [CouncilEx.Recorder.Ecto](CouncilEx.Recorder.Ecto.md): Default `CouncilEx.Recorder` implementation backed by Ecto + Postgres.
  - [CouncilEx.Workers.Oban](CouncilEx.Workers.Oban.md): Oban worker that wraps a `CouncilEx` run in a durable, retry-safe
job.

- Output Schemas
  - [CouncilEx.Schema.JSONSchema](CouncilEx.Schema.JSONSchema.md): Convert an Ecto embedded schema to a JSON Schema map.
  - [CouncilEx.Schemas.Critique](CouncilEx.Schemas.Critique.md): Standard Ecto embedded schema for Critique-round member outputs.

  - [CouncilEx.Schemas.Ranking](CouncilEx.Schemas.Ranking.md): Standard Ecto embedded schema for Ranking-round member outputs.
  - [CouncilEx.Schemas.Vote](CouncilEx.Schemas.Vote.md): Standard Ecto embedded schema for Vote-round member outputs.

- Providers
  - [CouncilEx.Provider](CouncilEx.Provider.md): Behaviour implemented by provider adapters.
  - [CouncilEx.Provider.Adapter](CouncilEx.Provider.Adapter.md): Behaviour for provider-specific request/response handling.
  - [CouncilEx.Provider.Adapters.Anthropic](CouncilEx.Provider.Adapters.Anthropic.md): Provider.Adapter for Anthropic Messages API.
  - [CouncilEx.Provider.Adapters.Gemini](CouncilEx.Provider.Adapters.Gemini.md): Provider.Adapter for Google Gemini's Generative Language API.
  - [CouncilEx.Provider.Adapters.Ollama](CouncilEx.Provider.Adapters.Ollama.md): 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.
  - [CouncilEx.Provider.Adapters.OpenAI](CouncilEx.Provider.Adapters.OpenAI.md): Provider.Adapter for OpenAI-compatible APIs (OpenAI, OpenRouter, Groq).
  - [CouncilEx.Provider.Adapters.OpenRouter](CouncilEx.Provider.Adapters.OpenRouter.md): Provider.Adapter for OpenRouter (<https://openrouter.ai>).
  - [CouncilEx.Providers.Instructor](CouncilEx.Providers.Instructor.md): 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`).
  - [CouncilEx.Providers.Mock](CouncilEx.Providers.Mock.md): In-process mock provider for tests and demos.

- Observability
  - [CouncilEx.Anonymize](CouncilEx.Anonymize.md): Relabel a map of `member_id => content` so models cannot identify
whose output is whose during peer review.
  - [CouncilEx.Diagram](CouncilEx.Diagram.md): Static topology diagrams for a `CouncilEx` council module.
  - [CouncilEx.Events](CouncilEx.Events.md): Public catalog of PubSub events emitted on the run-scoped topic
`"council_ex:run:#{run_id}"`. Stable extension surface as of v0.7.
  - [CouncilEx.PubSub](CouncilEx.PubSub.md): Facade for the configured PubSub adapter.
  - [CouncilEx.PubSub.Adapter](CouncilEx.PubSub.Adapter.md): Behaviour for `CouncilEx.PubSub` backends.
  - [CouncilEx.PubSub.PG](CouncilEx.PubSub.PG.md): `:pg`-backed PubSub adapter. Default backend for `CouncilEx.PubSub`.
  - [CouncilEx.PubSub.Phoenix](CouncilEx.PubSub.Phoenix.md): `Phoenix.PubSub`-backed adapter. Delegates to a user-supplied Phoenix.PubSub
server name configured via
  - [CouncilEx.Telemetry](CouncilEx.Telemetry.md): Helpers for emitting CouncilEx telemetry events.
  - [CouncilEx.Verbose](CouncilEx.Verbose.md): 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`).

- Testing
  - [CouncilEx.Test](CouncilEx.Test.md): Helpers for testing councils. Add `import CouncilEx.Test` in your test files.

- Exceptions
  - [CouncilEx.Providers.Instructor.MissingEnvError](CouncilEx.Providers.Instructor.MissingEnvError.md): 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`.

  - [CouncilEx.Schema.JSONSchema.UnsupportedTypeError](CouncilEx.Schema.JSONSchema.UnsupportedTypeError.md)

## Mix Tasks

- [mix council.diagram](Mix.Tasks.Council.Diagram.md): Print a diagram of a council module's static topology.

