Skip to main content

star-chamber

Multi-LLM council protocol SDK. Fan out code reviews and design questions to multiple LLM providers, then classify findings by consensus.

Installation

pip install star-chamber

Or with uv:

uv add star-chamber

Otari extra

Routing through an Otari gateway needs the otari extra, because the gateway client ships outside the base install:

pip install 'star-chamber[otari]'
uv add 'star-chamber[otari]'
uvx --from 'star-chamber[otari]' star-chamber list-providers

Without the extra, an Otari-mode council still starts, but every non-local provider fails on its first call reporting that the Otari packages are missing. Direct-key councils never need the extra.

Configuration

Create ~/.config/star-chamber/providers.json:

{
  "providers": [
    {"provider": "openai", "model": "gpt-4o", "api_key": "${OPENAI_API_KEY}"},
    {"provider": "anthropic", "model": "claude-sonnet-4-20250514", "api_key": "${ANTHROPIC_API_KEY}"}
  ],
  "timeout_seconds": 90,
  "consensus_threshold": 2
}

API keys can be literal values or ${ENV_VAR} references that are resolved at runtime.

Response token budget

max_tokens is optional. When it is omitted, a member may spend 16384 tokens on its reply.

The field is a budget for the response, not a property of the model. The value is sent to the provider as given, and no limit is ever read back from one, so there is nothing to look up before adding a member.

A budget that is too low makes the member fail rather than return half a review, and the error names the budget that was reached, so raise it from that number or send fewer files. A budget above what the model permits is rejected by the provider. Omit the field until a member reports a cut-off reply.

Provider display names

When several council members share one provider — for example, multiple models behind an OpenAI-compatible gateway such as OpenRouter — give each entry a unique display_name. It becomes that member's identity in council output (consensus classification, flagged_by, quality ratings, individual issues) and is matched by --provider filters. Without it, same-provider members collapse into a single vote and unanimous consensus becomes unreachable:

{
  "providers": [
    {"provider": "openrouter", "display_name": "gpt-5.2", "model": "openai/gpt-5.2", "api_key": "${OPENROUTER_API_KEY}"},
    {"provider": "openrouter", "display_name": "gemini-3.1-pro", "model": "google/gemini-3.1-pro-preview", "api_key": "${OPENROUTER_API_KEY}"},
    {"provider": "openrouter", "display_name": "grok-4.3", "model": "x-ai/grok-4.3", "api_key": "${OPENROUTER_API_KEY}"}
  ],
  "consensus_threshold": 2
}

In the JSON output, each provider response carries both the underlying provider (the routing target) and this display_name, and the display name is the key used throughout the aggregated result — providers_used, providers_responded, quality_ratings, individual_issues, flagged_by, and failed_providers. A member with no display_name falls back to the provider name.

providers_used is the roster that was asked, including members that failed. providers_responded is the roster that answered, and it is the denominator the consensus and majority classifications were computed over. A consensus across two members when three were asked is a weaker signal than the same word across three, so report the answering roster rather than the roster asked.

Otari gateway

Instead of managing API keys per provider, you can route all non-local providers through Otari, Mozilla AI's OpenAI-compatible LLM gateway, by adding a top-level otari object. This mode requires the otari extra:

{
  "providers": [
    {"provider": "openai", "model": "openai:gpt-4o"},
    {"provider": "anthropic", "model": "anthropic:claude-sonnet-4-20250514"}
  ],
  "otari": {
    "api_base": "https://your-gateway.example",
    "api_key": "${OTARI_API_KEY}"
  },
  "timeout_seconds": 90,
  "consensus_threshold": 2
}

In Otari mode, Otari — not the SDK — picks the upstream provider, so the per-provider provider field becomes a label. Otari expects the model field to use a provider:model prefix such as "openai:gpt-4o"; consult Otari's documentation for its model-naming convention.

api_base is the gateway origin with no path, such as https://api.otari.ai, because the client adds the API path itself. Every command rejects a base that ends in an API path, such as /v1, before it calls any provider. The error names the setting that supplied the base, whether the config or OTARI_API_BASE/GATEWAY_API_BASE, and the corrected value to set.

api_base and api_key may be omitted from the config; when omitted, the SDK's OtariProvider auto-detects credentials from its own env vars: OTARI_API_KEY for the hosted otari.ai platform (Authorization: Bearer, matching otari.ai's docs), or GATEWAY_API_KEY for a self-hosted gateway (Otari-Key header). OTARI_AI_TOKEN is also accepted as a platform-token alias. Both fields also support ${ENV_VAR} references.

Providers marked "local": true always bypass Otari and continue to use their own api_base.

Override the config path with the STAR_CHAMBER_CONFIG environment variable.

CLI

Code review

star-chamber review src/auth.py src/db.py

Design question

star-chamber ask "Should we use Redis or Memcached for session storage?"

Options

--provider, -p    Provider to include (repeatable)
--config          Path to providers.json
--timeout         Per-provider timeout in seconds
--context-file    File containing project context to include in the prompt
--council-context File containing prior council round feedback (debate mode)
--format          Output format: text or json
--output          Write JSON result to file

List providers

star-chamber list-providers

Protocol schemas

The SDK ships the council protocol specification as package data.

# List available schemas.
star-chamber schema list

# Print a specific schema.
star-chamber schema code-review-result

Python API

from star_chamber import run_council_sync, CouncilConfig, ProviderConfig

config = CouncilConfig(
    providers=(
        ProviderConfig(provider="openai", model="gpt-4o"),
        ProviderConfig(provider="anthropic", model="claude-sonnet-4-20250514"),
    ),
    timeout_seconds=90,
    consensus_threshold=2,
)

# Code review.
result = run_council_sync(
    files={"auth.py": open("auth.py").read()},
    config=config,
    mode="code-review",
)

print(result.summary)
for issue in result.consensus_issues:
    print(f"  [{issue.severity}] {issue.location}: {issue.description}")

# Design question.
result = run_council_sync(
    prompt="Should we use a monorepo or polyrepo?",
    config=config,
    mode="design-question",
)

print(result.consensus_recommendation)

Async

import asyncio
from star_chamber import run_council

result = asyncio.run(run_council(
    files={"auth.py": open("auth.py").read()},
    mode="code-review",
))

Schema access

from star_chamber import get_schema, list_schemas

# List available schema names.
names = list_schemas()

# Get a specific schema as a JSON string.
schema_json = get_schema("code-review-result")

Consensus classification

Issues from multiple providers are grouped by file, line proximity (within 5 lines), and category, then classified as:

  • Consensus -- all providers agree.
  • Majority -- two or more providers agree, but not all.
  • Individual -- flagged by a single provider.

Results are sorted by severity within each bucket.

License

Apache-2.0

Metadata

Release files for star-chamber 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for star-chamber 0.7.0
File Size Uploaded Provenance
star_chamber-0.7.0.tar.gz 132.9 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for star-chamber 0.7.0
File Interpreter ABI Platform
star_chamber-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 196.0 kB

Release files / star_chamber-0.7.0.tar.gz

Download URL star_chamber-0.7.0.tar.gz
Size 132.9 kB
Tags Source
SHA-256 checksum
How to use checksums
71801a59021b107b6ff8cb55873d0482780aa19c34a494d13141bd25b8aa29bc
BLAKE2b-256 checksum
How to use checksums
789bb8f5df586e1779c6681a07632f6b273c3d6da2d2f00aee90e9006570d2cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / star_chamber-0.7.0-py3-none-any.whl

Download URL star_chamber-0.7.0-py3-none-any.whl
Size 63.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
170bad8f8a822f987e0516ff1d07bbae650aaf7a1a2d7835acd97d2f3979dbe6
BLAKE2b-256 checksum
How to use checksums
1ed569d168ab515b1d8209baf707d8f0be6027fe9a2b86d9703fe25b39045085
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for star-chamber 0.7.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for star_chamber-0.7.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page