consilium-py
GitHub ↗
PYTHON PACKAGE consilium · Latin, “council” Generator · Conservator · Control

Don’t ship on
one opinion.

consilium-py runs a dialectical review of a proposed change through independent AI voices — one proposes, one weighs the risk, one audits — then returns a single graded verdict with a confidence score. From any terminal, script, or HTTP endpoint.

View on GitHub →

one deliberation, start to verdict

Generator

Proposes

3–5 approaches
+ a preferred one

Conservator

Weighs risk

reversibility,
regression

Control

Audits

correctness,
disagreements

Verdict GO
confidence 0.82

The pipeline

One proposal, three lenses, one verdict.

Every deliberation passes through three AI voices in sequence. The Generator runs first, blind to any risk framing — so the ideas aren’t anchored by caution before they exist.

Generator · first

Proposes the options

Lays out 3–5 approaches with their trade-offs and picks a preferred one. Sees the change on its own terms, with no risk framing to anchor it.

Conservator

Weighs the risk

Scores each candidate for risk, reversibility, and regression potential. An irreversibility flag is a hard veto — it can block the whole change.

Control · last

Audits the record

Checks correctness and glossary compliance, and surfaces where the voices disagree — the signal that a change needs a second look.

then · aggregator

A veto cascade turns the three voices into one Report: an unparseable voice, a failed audit, or an irreversible flag each force a block; otherwise the verdict and a confidence score fall out of how much the voices agree.

Get started

Run it anywhere you already work.

A terminal command, a Python call, or an HTTP endpoint — the same engine behind each.

Command line

# install, then point it at a change
pip install consilium-py
export OPENROUTER_API_KEY=sk-or-...

consilium deliberate "Add Redis caching to the API"
consilium check                  # review your staged git diff
consilium serve                  # open the web UI
consilium ingest docs/           # feed reference docs into RAG

Python

from consilium import deliberate

report = deliberate(
    "Add rate limiting",
    mode="dialectic",
)
print(report.verdict)      # GO
print(report.confidence)  # 0.82

HTTP

# pip install 'consilium-py[server]'
curl -X POST localhost:8123/deliberate \
  -H "Content-Type: application/json" \
  -d '{"proposal": "Add a /health route"}'

# → {"verdict":"GO","confidence":0.82,...}

Four modes

Scale the scrutiny to the stakes.

Start fast and cheap; escalate to a full council when a change is worth it.

sequentialdefault
The core chain — Generator → Conservator → Control in one pass. Fast, and the right call for most changes.
1× cost
dialectic
Adds a fourth Skeptic voice that challenges the chosen approach. With --skeptic-can-override it can downgrade the verdict.
+1 voice
trias
One neutral Generator sets a shared candidate set; three personalities — Pioneer, Architect, Steward — each run a full review and vote. A categorical block can’t be out-voted.
3 personalities
langgraphextra
The same sequential pipeline expressed as a LangGraph StateGraph — for teams already standardized on LangGraph orchestration.
[langgraph]

The verdict

Six outcomes, no ambiguity.

Every deliberation resolves to exactly one verdict and a confidence score — a decision you can act on or route.

GO

The approach is sound. Proceed.

MODIFY

Proceed, with the noted changes applied first.

STOP

Don’t proceed as proposed — the risks outweigh it.

BLOCK

A hard gate tripped: an unparseable voice, a failed audit, or an irreversible risk.

ESCALATE

The voices disagree enough that a human should decide.

ANSWER

Not a change proposal — a question, answered directly.

Under the hood

Batteries, opt-in.

The core is small and dependency-light. Everything below is an optional extra that guards its own imports.

Provider-agnosticany model via LiteLLM
Runs on Anthropic, OpenAI, Gemini, or anything LiteLLM reaches — pass provider/model. Or use --model claude-cli with no API key at all, just a Claude subscription.
RAG memory[rag] · ChromaDB
Past deliberations and ingested reference docs come back as context. consilium ingest <path> chunks your docs into the index; retrieval cites its source in the report.
HTTP server[server] · FastAPI
A POST /deliberate endpoint plus a self-contained web UI. consilium serve picks a free port and opens a browser.
Traceable by designrequirement map
Every capability carries a # implements: tag linked to a requirement doc; a drift gate fails the build when code and spec diverge — so the docs can’t quietly rot away from the code.

Ship it

From git push to Cloud Run.

The package ships with the infrastructure to run it — containerized, provisioned as code, and gated by CI. Not an afterthought: the whole path is in the repo.

Dockerfile

Container

python:3.12-slim
→ uvicorn

Artifact Registry

Image

build & push
to GCP

Terraform

Provision

infra/ as code
terraform apply

Cloud Run v2

Serve

scales to zero,
private by default

Stack

Docker Terraform GCP Cloud Run Artifact Registry Secret Manager GitHub Actions GHCR PyPI (OIDC) Dependabot
CI/CD on every change.github/workflows
GitHub Actions runs the full pytest suite (3.11 + 3.12) and the requirement-drift gate on every push, and validates the Terraform on every infra/ change. On a version tag it publishes the package to PyPI via OIDC trusted publishing and pushes a container image to GHCR. Every action is pinned to a commit SHA and kept current by Dependabot — closing the supply-chain gap that floating version tags leave open.
Secrets, done rightSecret Manager
The API key lives in Secret Manager and the service reads it by reference — never a plaintext environment variable, never in the Terraform state as a literal. Public access is opt-in behind a variable; the service is private by default.
Infrastructure as codeinfra/*.tf
Artifact Registry, the Cloud Run service, Secret Manager, and IAM are all declared in Terraform, with state kept in a versioned GCS bucket rather than a local file — reproducible, reviewable, and destroyable in one command. The apply is a documented step today; wiring it to CI via Workload Identity Federation is the next increment.