- Python 3.11+
- OpenAI API key (required)
Before installing, please create a virtual environment and activate it.
python -m venv venv
source venv/bin/activateOne-command (recommended):
python scripts/install.pyInstalls the package in editable mode with all extras (dev, ui). Registers moralstack and moralstack-ui CLI entry
points.
Manual (equivalent to install.py):
pip install -e ".[dev,ui]"Development only (pytest, pytest-cov, ruff, black, mypy):
pip install -e .[dev]With Web UI (FastAPI, uvicorn, jinja2):
pip install -e .[ui]Alternative (legacy):
pip install -r requirements.txtNote: requirements.txt installs dependencies only; it does not register the moralstack CLI. Use pip install -e .
or install.py for that.
The Python SDK (govern()) is included in the base package — no extra install step needed. All required dependencies (openai, pydantic, ruamel.yaml, etc.) are already in [project.dependencies].
pip install -e .The [ui] extra is only needed for the web dashboard (moralstack-ui). The [dev] extra is only needed for running tests and linting.
from moralstack import govern
from openai import OpenAI
# Minimum: OPENAI_API_KEY must be set in the environment
client = govern(OpenAI())
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Explain recursion in programming."}],
)
print(response.content) # generated text (or refusal)
print(response.governance_metadata.final_action) # NORMAL_COMPLETE | SAFE_COMPLETE | REFUSE
print(response.governance_metadata.risk_score) # 0.0–1.0All SDK parameters are optional and can be overridden programmatically:
from moralstack import govern, GovernanceConfig
from openai import OpenAI
client = govern(
OpenAI(),
config=GovernanceConfig(
# Pipeline credentials (default: from env)
api_key="sk-...", # OPENAI_API_KEY
model="gpt-4o", # OPENAI_MODEL
base_url=None, # OPENAI_BASE_URL
# Domain-specific governance
domain_overlay="healthcare", # enforce a named domain overlay
# Failure handling
failure_policy="refuse", # "refuse" (default) | "passthrough"
# Observability
observability_mode="file_only", # "off" | "file_only" | "db_only" | "dual"
jsonl_dir="logs/audit",
# Session tracking (multi-turn)
enable_session_tracking=True,
),
)The pipeline uses its own internal LLM client for deliberation (configured via GovernanceConfig). The OpenAI() client you pass to govern() is used only for final text generation. SDK bootstrap calls load_env() before building modules, so MORALSTACK_* and OPENAI_* values are loaded from .env first. Runtime tuning (deliberation cycles, risk thresholds, module temperatures, etc.) is controlled exclusively via MORALSTACK_* environment variables — see .env.template for the full list.
All configuration can be managed via a .env file in the project root.
Copy .env.minimal to .env end configure your API key in OPENAI_API_KEY
- Copy the template:
cp .env.template .env(Linux/macOS) orcopy .env.template .env(Windows) - Edit
.envand set your values (at minimumOPENAI_API_KEY) - Run
moralstack,moralstack-ui, orpython scripts/benchmark_moralstack.py— they load.envautomatically at startup
Non-empty values from .env override pre-existing environment variables (load_dotenv(..., override=True)).
Optional variables left empty are purged after loading to avoid invalid empty-string settings in third-party libraries.
Newer OpenAI models (gpt-5.x, o1, o3, o4) require max_completion_tokens instead of max_tokens. MoralStack
automatically selects the correct parameter based on the model name — no configuration needed.
See docs/modules/openai_params.md for details and how to add support for future models.
| Variable | Default | Description |
|---|---|---|
| OPENAI_API_KEY | - | OpenAI API key (required) |
| OPENAI_MODEL | gpt-4o | Primary internal governance model. In SDK mode, this does not override the model= passed to chat.completions.create(...) for final response generation (see README SDK model resolution section). |
| MORALSTACK_POLICY_REWRITE_MODEL | - (same as OPENAI_MODEL) | Internal policy rewrite() model at cycle 2+; SDK final response model is still controlled by chat.completions.create(model=...). .env.template uses gpt-4.1-nano; set any lighter model to reduce latency (see policy.md) |
| OPENAI_BASE_URL | - | Base URL (proxy/enterprise) |
| OPENAI_TIMEOUT_MS | 60000 | Timeout in milliseconds |
| OPENAI_MAX_RETRIES | 3 | Retries on 429/503 |
| OPENAI_TEMPERATURE | 0.7 (fallback) | Generation temperature (.env.template starter: 0.1) |
| OPENAI_TOP_P | 0.9 (fallback) | Nucleus sampling parameter (.env.template starter: 0.8) |
| MORALSTACK_OBSERVABILITY_DB_PATH | - | SQLite DB path (enables persistence) |
| MORALSTACK_OBSERVABILITY_MODE | db_only if DB set | db_only | dual | file_only |
| MORALSTACK_OBSERVABILITY_JSONL_DIR | logs/observability | JSONL output directory (file_only and dual modes) |
| MORALSTACK_DB_PATH | - | Deprecated alias for MORALSTACK_OBSERVABILITY_DB_PATH |
| MORALSTACK_PERSIST_MODE | - | Deprecated alias for MORALSTACK_OBSERVABILITY_MODE |
| MORALSTACK_UI_PORT | 8765 | Web UI port |
| MORALSTACK_UI_USERNAME | - | Basic Auth for UI (required when running moralstack-ui) |
| MORALSTACK_UI_PASSWORD | - | Basic Auth for UI |
| MORALSTACK_CONSTITUTION_MAX_PARALLEL_AGENTS | 2 | Parallel domain agents for constitution retrieval |
| MORALSTACK_VERBOSE | - | Set to 1 for verbose output |
Risk Estimator: Optional overrides (e.g. MORALSTACK_RISK_MODEL, MORALSTACK_RISK_LOW_THRESHOLD,
MORALSTACK_RISK_MEDIUM_THRESHOLD, MORALSTACK_RISK_MAX_RETRIES, …) are listed in .env.template and fully documented
in docs/modules/risk_estimator.md. Leave them commented to use
built-in defaults (risk estimator uses the same model as OPENAI_MODEL when MORALSTACK_RISK_MODEL is not set). In
both CLI run and benchmark, risk configuration is read only from the environment (.env); there is no CLI override —
env is the single source of configuration.
Perspective: Optional overrides (e.g. MORALSTACK_PERSPECTIVES_MODEL, MORALSTACK_PERSPECTIVES_MAX_RETRIES,
MORALSTACK_PERSPECTIVES_MAX_TOKENS, …) are listed in .env.template and fully documented
in docs/modules/perspectives.md. Leave them commented to use
built-in defaults (perspectives use the same model as OPENAI_MODEL when MORALSTACK_PERSPECTIVES_MODEL is not set). *
In both CLI run and benchmark, perspective configuration is read only from the environment (.env); there is no CLI
override — env is the single source of configuration.*
Critic: Optional overrides (e.g. MORALSTACK_CRITIC_MODEL, MORALSTACK_CRITIC_MAX_RETRIES,
MORALSTACK_CRITIC_MAX_TOKENS, …) are listed in .env.template and fully documented
in docs/modules/critic.md. Leave them commented to use built-in
defaults (critic uses the same model as OPENAI_MODEL when MORALSTACK_CRITIC_MODEL is not set). In both CLI run and
benchmark, critic configuration and model are read only from the environment (.env); there is no CLI override — env is
the single source of configuration.
Simulator: Optional overrides (e.g. MORALSTACK_SIMULATOR_MODEL, MORALSTACK_SIMULATOR_MAX_RETRIES,
MORALSTACK_SIMULATOR_MAX_TOKENS, …) are listed in .env.template and fully documented
in docs/modules/simulator.md. Leave them commented to use built-in
defaults (simulator uses the same model as OPENAI_MODEL when MORALSTACK_SIMULATOR_MODEL is not set). In both CLI
run and benchmark, simulator configuration and model are read only from the environment (.env); there is no CLI
override — env is the single source of configuration.
Hindsight: Optional overrides (e.g. MORALSTACK_HINDSIGHT_MODEL, MORALSTACK_HINDSIGHT_MAX_RETRIES,
MORALSTACK_HINDSIGHT_MAX_TOKENS, …) are listed in .env.template and fully documented
in docs/modules/hindsight.md. Leave them commented to use built-in
defaults (hindsight evaluator uses the same model as OPENAI_MODEL when MORALSTACK_HINDSIGHT_MODEL is not set). In
both CLI run and benchmark, hindsight configuration and model are read only from the environment (.env); there is no
CLI override — env is the single source of configuration.
Orchestrator: Optional overrides (e.g. MORALSTACK_ORCHESTRATOR_MAX_DELIBERATION_CYCLES,
MORALSTACK_ORCHESTRATOR_TIMEOUT_MS, MORALSTACK_ORCHESTRATOR_ENABLE_PERSPECTIVES,
MORALSTACK_ORCHESTRATOR_PARALLEL_MODULE_CALLS, MORALSTACK_ORCHESTRATOR_PARALLEL_CRITIC_WITH_MODULES,
MORALSTACK_ORCHESTRATOR_ENABLE_DYNAMIC_PARALLEL_SCHEDULER, MORALSTACK_ORCHESTRATOR_ENABLE_SPECULATIVE_GENERATION,
MORALSTACK_ORCHESTRATOR_CYCLE1_EARLY_CONVERGENCE_MIN_WEIGHTED_APPROVAL,
MORALSTACK_ORCHESTRATOR_CYCLE1_EARLY_CONVERGENCE_MAX_SEMANTIC_HARM,
MORALSTACK_ORCHESTRATOR_CYCLE1_EARLY_CONVERGENCE_MIN_PER_PERSPECTIVE_APPROVAL,
MORALSTACK_ORCHESTRATOR_ENABLE_SIMULATOR_GATING, MORALSTACK_ORCHESTRATOR_SIMULATOR_GATE_SKIP_MAX_PRIOR_SEMANTIC_HARM, …)
are listed in .env.template and fully documented in
docs/modules/orchestrator.md. Leave them commented to use built-in
defaults. In both CLI run and benchmark, orchestrator configuration is read only from the environment (.env); there
is no CLI override — env is the single source of configuration.
Benchmark: Optional overrides (e.g. MORALSTACK_BENCHMARK_OUTPUTS, MORALSTACK_BENCHMARK_BASELINE_MODEL,
MORALSTACK_BENCHMARK_JUDGE_MODEL) are listed in .env.template and fully documented
in docs/modules/benchmark.md. MORALSTACK_BENCHMARK_BASELINE_MODEL
is the single source for the baseline only (raw GPT): when set, it overrides CLI --model for baseline; when unset,
uses gpt-4o. MoralStack modules use their own env vars. MORALSTACK_BENCHMARK_JUDGE_MODEL configures the LLM used for
evaluation: when set, it overrides the CLI --judge-model option; when not set, the judge uses the same model as
MoralStack policy. When the judge model differs from the generation model, the judge is independent; otherwise the
judge is not independent. Reports and the UI display this distinction explicitly.
You can still set variables directly:
# Linux / macOS
export OPENAI_API_KEY=sk-...
# Windows (PowerShell)
$env:OPENAI_API_KEY = "sk-..."# With .env configured:
moralstack --mock # Test with mock modules (no API)
moralstack # Real launch (requires OPENAI_API_KEY in .env)
# Or with env var:
export OPENAI_API_KEY=sk-...
moralstackcp .env.template .env
# Edit .env and set OPENAI_API_KEY=sk-...
moralstackType a prompt in the interactive shell; the system will evaluate the risk and respond accordingly.
Note: You can also use
python scripts/mstack_run.pyas a legacy wrapper, but the preferred method ismoralstack. Runmoralstack --verbosefor detailed deliberation output. WithMORALSTACK_OBSERVABILITY_DB_PATHset, usemoralstack-uito browse runs and export markdown reports on demand.
With pip install -e .[ui] and MORALSTACK_OBSERVABILITY_DB_PATH set, run:
moralstack-uiThen open in your browser:
You will be redirected to the login page. Enter MORALSTACK_UI_USERNAME and MORALSTACK_UI_PASSWORD from your .env.
After login you will access the dashboard at /runs.
Troubleshooting 401: Ensure .env is in the project root and moralstack-ui is run from the project directory (or
the package-based fallback will load it). If the password contains # or =, wrap it in quotes:
MORALSTACK_UI_PASSWORD="pass#word".