Environment Variables
AEGIS uses a single .env file at the repository root. All services load it at startup using python-dotenv. Copy .env.example to get started:
cp .env.example .envComplete Variable Reference
Database
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL | Yes | postgresql://aegis:aegis_local@localhost:5432/aegis | PostgreSQL connection string. Used by all Python services that need database access (orchestration engine, memory service, knowledge graph service, approval service, compliance monitor, flaring monitor). |
Redis
| Variable | Required | Default | Description |
|---|---|---|---|
REDIS_URL | Yes | redis://localhost:6379 | Redis connection URL. Used by the memory service for working memory (Redis Hash) and the injection ledger (Redis Hash at skill:ledger:{conversation_id}). |
Kafka
| Variable | Required | Default | Description |
|---|---|---|---|
KAFKA_BOOTSTRAP_SERVERS | Yes | localhost:9092 | Kafka broker address. Used by the ingestion service for publishing entity extraction events. |
LLM Providers
| Variable | Required | Default | Description |
|---|---|---|---|
OPENAI_API_KEY | For embeddings | None | OpenAI API key. Used for episodic-memory embeddings (text-embedding-3-small). On the dev box the OpenAI key is dead and LLM calls route to Anthropic (below), so agent execution does not need it; embeddings degrade gracefully without it. |
ANTHROPIC_API_KEY | Yes (box) | None | Anthropic API key. The dev box routes all agent LLM calls to Claude via LiteLLM (DEFAULT_LLM_MODEL=anthropic/claude-sonnet-5), so this is required for agent execution there. |
LITELLM_LOG_LEVEL | No | DEBUG | Log verbosity for the LiteLLM library. Set to INFO or WARNING to reduce noise. |
You must supply at least one LLM provider key. The default model is
anthropic/claude-sonnet-5 (LiteLLM → Anthropic), so ANTHROPIC_API_KEY is what
agent execution needs; OPENAI_API_KEY is used for episodic-memory embeddings and
degrades gracefully when absent. All other variables have working defaults for
local development.
Service Ports
These variables configure which port each service listens on. The defaults match the standard AEGIS port assignments.
| Variable | Required | Default | Description |
|---|---|---|---|
API_GATEWAY_PORT | No | 8000 | Go API gateway listen port |
ORCHESTRATION_PORT | No | 8001 | Orchestration engine listen port |
MEMORY_PORT | No | 8002 | Memory service listen port |
KNOWLEDGE_GRAPH_PORT | No | 8003 | Knowledge graph service listen port |
APPROVAL_PORT | No | 8004 | Approval service listen port |
INGESTION_PORT | No | 8005 | Ingestion service listen port |
COMPLIANCE_PORT | No | 8006 | Compliance monitor listen port |
FLARING_PORT | No | 8007 | Flaring monitor listen port |
The auth service always runs on port 8009. Its port is not configurable via environment variable in the current implementation.
Authentication
| Variable | Required | Default | Description |
|---|---|---|---|
JWT_SECRET | Yes | aegis-local-dev-secret-change-in-production | Secret key for signing and verifying JWT tokens (HS256 algorithm). The auth service uses this to generate tokens, and the gateway uses it to validate them. Must be changed for production. |
BOOTSTRAP_ADMIN_EMAIL | Yes | admin@aegis.local | Email of the initial admin user seeded by the auth service on startup (if no user with that email exists). |
BOOTSTRAP_ADMIN_PASSWORD | Yes | aegis-dev-admin | Password for the seeded bootstrap admin. Must be changed for production. |
AEGIS_COOKIE_HTTPONLY | No | 0 | R42a: adds HttpOnly to the server-set aegis_token cookie. Keep 0 until the R42b client cutover — the pre-R42b frontend still writes the cookie via document.cookie, which browsers silently reject once an HttpOnly cookie of the same name exists. |
AEGIS_COOKIE_SECURE | No | 0 | R42a: adds Secure to the server-set aegis_token cookie (HTTPS only). Flipped on the box in R42b. |
AEGIS_PUBLIC_BASE_URL | No | (empty) | Base URL prefixed onto the one-time invite/reset links returned by POST /auth/admin/users and .../reset-password (e.g. https://aegis.reddyvarun.com). |
AEGIS_AUTH_MODE | No | log | R42d: service-side identity enforcement mode for aegis_shared.auth (log | enforce). In log, a missing identity or failed role/permission check on a protected route emits one structured warning (aegis.auth ...) and passes; in enforce it returns 401/403. Deploy in log, soak until the warning volume is zero for 24h, then flip to enforce and restart the Python services. Rollback = flip back to log. |
HMAC_SIGNING_KEY | Yes | aegis-local-hmac-key-change-in-production | HMAC key used to sign entries in the append-only audit trail. Each audit log row includes an HMAC signature for tamper detection. Must be changed for production. In production, this is managed by HashiCorp Vault. |
Observability
| Variable | Required | Default | Description |
|---|---|---|---|
LANGFUSE_PUBLIC_KEY | No | None | Langfuse public key for LLM observability tracing. |
LANGFUSE_SECRET_KEY | No | None | Langfuse secret key. |
LANGFUSE_HOST | No | https://cloud.langfuse.com | Langfuse server URL. |
Eval Capture (R40a)
| Variable | Required | Default | Description |
|---|---|---|---|
TURN_SNAPSHOTS_ENABLED | No | true | Publish a frozen context snapshot at every turn end (fire-and-forget; the turn path never waits on it). |
SNAPSHOT_STREAM_MAXLEN | No | 10000 | Approximate MAXLEN of the snapshots:pending Redis stream — generous so trimming only happens if the writer has been dead a long time. |
SNAPSHOT_MAX_PAYLOAD_BYTES | No | 1048576 | Payload cap; oversized snapshots truncate messages tail-first with a marker instead of failing. |
SNAPSHOT_RETENTION_DAYS | No | 30 | Boot-time sweep age for snapshots not referenced by an eval case (promoted snapshots are permanent). |
SNAPSHOT_RECLAIM_IDLE_MS | No | 60000 | R41 A6: idle time before another orchestration replica reclaims a stranded pending snapshot entry via XAUTOCLAIM. The writer uses a per-replica consumer name, so running >1 replica is safe. Must exceed the writer’s own ≤10s transient-retry backoff. |
Connector Service (R44a)
Configuration for the connector service (port 8011) — external data source catalog, credential custody, egress policy, probes, and discovery. See Connector Service for the full security model.
| Variable | Required | Default | Description |
|---|---|---|---|
AEGIS_SECRET_BACKEND | No | dev | Credential secret store backend: gcp (GCP Secret Manager, secret id aegis-conn-{tenant_id}-{connector_key}) or dev (Fernet-encrypted file store under .aegis-secrets/). The dev store refuses to start with AEGIS_ENV=production. |
CONNECTOR_EGRESS_ALLOW_CIDRS | No | (empty) | Comma-separated CIDRs exempted from the default-deny egress policy (loopback, link-local/metadata, RFC1918, CGNAT, …). A deployment decision, never tenant-reachable; malformed entries fail loudly. Local dev probing of the operator-demo sidecar needs 127.0.0.0/8. |
CONNECTOR_DEV_STORE_DIR | No | .aegis-secrets | Directory for the dev Fernet file store. |
CONNECTOR_DEV_STORE_KEY | No | (auto-generated) | Fernet key for the dev store. Generated once and persisted beside the store (.store-key) when unset. |
CONNECTOR_CRED_CACHE_TTL_S | No | 600 | In-memory credential read-cache TTL (seconds); invalidated on rotation. |
CONNECTOR_STATEMENT_TIMEOUT_S | No | 30 | Statement timeout applied to probe/discovery sessions on the external source. |
CONNECTOR_DISCOVERY_MAX_SCHEMAS | No | 50 | Schema-count cap; above it, discovery degrades loudly to a schema-name-only snapshot (truncated: true). |
CONNECTOR_DISCOVERY_MAX_BYTES | No | 2000000 | Snapshot byte cap; above it, column detail is dropped (truncated: true). |
CONNECTOR_SKIP_DB | No | (unset) | 1 skips the DB pool and boot migrations (unit tests only). |
GOOGLE_CLOUD_PROJECT | For gcp backend | (ADC default) | GCP project for the Secret Manager backend; falls back to application-default credentials. |
Internal Service URLs
These are used by the orchestration engine to call other services. You typically do not need to change these unless running services on non-default ports.
| Variable | Default | Used By |
|---|---|---|
MEMORY_SERVICE_URL | http://localhost:8002 | Orchestration engine |
KNOWLEDGE_GRAPH_SERVICE_URL | http://localhost:8003 | Orchestration engine, ingestion service |
APPROVAL_SERVICE_URL | http://localhost:8004 | Orchestration engine |
CONNECTOR_SERVICE_URL | http://localhost:8011 | Orchestration engine (registry status + exposure execute, R44c), agent-config (bind-time validation) |
CONNECTOR_STATUS_CACHE_TTL_S | 30 | Orchestration engine — in-process TTL for the connector-status registry cache (R44c) |
Orchestration Engine Tuning
| Variable | Default | Description |
|---|---|---|
DEFAULT_LLM_MODEL | gpt-4o (code fallback) | Default model for LLM calls when not specified in the request. Fallback floor under tenant Platform Settings (see below). The dev box sets this to anthropic/claude-sonnet-5 (LiteLLM → Anthropic; the box OpenAI key is dead) |
DEFAULT_MAX_TOKENS_PER_EXECUTION | 100000 | Per-conversation token budget (cumulative across every turn; fallback floor under Platform Settings) |
DEFAULT_MAX_COST_PER_EXECUTION | 5.0 | Per-conversation dollar cost budget (fallback floor under Platform Settings) |
DEFAULT_MAX_TOKENS_PER_TURN | = per-execution | Per-turn token budget (R41 A8): bounds a single runaway turn. Defaults to the per-conversation ceiling so the tier is dormant until lowered |
DEFAULT_MAX_COST_PER_TURN | = per-execution | Per-turn dollar cost budget (R41 A8) |
DEFAULT_MAX_OUTPUT_TOKENS_PER_CALL | 16384 | max_tokens ceiling for a single LLM call (thinking + visible output — distinct from the cumulative per-execution budget above). Keep ≥ 8000: Claude Sonnet 5 runs adaptive thinking by default and thinking tokens bill against max_tokens, so a low ceiling can be consumed entirely by a thinking block and return an empty assistant message (fallback floor under Platform Settings) |
DEFAULT_THINKING_MODE | adaptive | Thinking mode sent explicitly to Anthropic models (adaptive | disabled) so provider default changes can’t silently flip behavior. Omitted for models that don’t accept the parameter (Haiku tier, non-Anthropic) (fallback floor under Platform Settings) |
MAX_GRAPH_ITERATIONS | 20 | Maximum number of tool-call loop iterations before forcing output |
EPISODIC_TOP_K | 3 | Number of episodic memories to retrieve per query |
R35_INTEGRITY_FAIL_LOUD | true | R35 startup integrity check mode. When true (default since R35 P2), an unresolved agent_definitions.root_skill_key / persona_key fails loudly at deploy rather than at a tester’s first message. The default was false in R35 P1 (warn-not-fail) while the rrc_rule37 / rrc_rule32 skills did not yet exist; R35 P2 seeds those skills and flips the default to true. Override to false only for an environment that has not yet run the P2 seeders. |
HITL_BREAK_GLASS | false | R41 A2: true restores the legacy fail-open approval behavior (proceed with a warning when the approval service can’t record a mandatory checkpoint). Default false fails closed — the turn pauses awaiting_hitl and is retryable. Use only for a documented operational emergency; every use is logged loudly. |
SANDBOX_UNKNOWN_CLASSIFICATION_BEARING | false | R41 A9: default classification posture for code with no explicit classification. true treats unclassified code as classification-bearing, so the trusted exact sandbox path fails closed when the rule gate is unevaluable. Default false preserves the exact-path availability decoupling. Explicitly-classified blocks always override this. |
The DEFAULT_* variables still exist, but they are now the fallback floor under tenant-level Platform Settings (admin page at /configuration/platform-settings, backed by the agent-config-service /settings API). At every turn start the orchestration engine resolves request override → tenant setting → env default; the env values apply only when the tenant has no value set or the settings fetch fails. Changing runtime LLM config no longer requires editing env vars on the box.
Packs & Horizontalization
AEGIS is a domain-neutral compliance runtime: compliance domains are installable packs rather than hardcoded verticals. These variables control pack discovery and the config-driven runtime.
| Variable | Default | Description |
|---|---|---|
PACKS_DIR | (empty) | R41 B2 pack-discovery scan root. Empty = the built-in orchestration/packs/ directory (currently the RRC packs: rule_37, rule_32, form_pr, flaring_monitor, epa_oooob). Set an absolute path to load out-of-tree packs — adding a domain needs no core code edits |
R41_CONFIG_ASSESSORS | false | R41 B3: use the config-driven deterministic assessors (a five-verb DSL sourced from pack manifests + rule_versions thresholds) instead of the legacy imperative RRC assessors. Flip after the parity soak |
AUDIT_CHAIN_ENABLED | true | R41 C5: per-tenant tamper-evident HMAC hash chain over turn_snapshots (verifier: orchestration.audit_chain.verify_chain). Uses HMAC_SIGNING_KEY |
KG_GRAPH_AUTO_REPAIR | false | Knowledge-graph startup auto-repairs a detected AGE catalog-OID drift (drop + create + reseed — destructive to graph data). Leave false anywhere the graph holds non-seed data; set true only on dev/demo boxes with reproducible seed data |
COMPLIANCE_MOCK_RULE_CHANGES | false | Optional (E0.5): serve compliance-monitor’s simulated rule-change registry instead of the rule_versions table (demo/tests only) |
FLARING_RENEWAL_CHECKLIST_DOMAIN | (unset) | Optional (E0.5): checklist workspace domain that flaring-monitor’s initiate_renewal predictive alerts route to (emitted as action_domain) |
Example .env File
# Database
DATABASE_URL=postgresql://aegis:aegis_local@localhost:5432/aegis
# Redis
REDIS_URL=redis://localhost:6379
# Kafka
KAFKA_BOOTSTRAP_SERVERS=localhost:9092
# LLM Providers (add your keys)
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
LITELLM_LOG_LEVEL=DEBUG
# Service Ports
API_GATEWAY_PORT=8000
ORCHESTRATION_PORT=8001
MEMORY_PORT=8002
KNOWLEDGE_GRAPH_PORT=8003
APPROVAL_PORT=8004
INGESTION_PORT=8005
COMPLIANCE_PORT=8006
FLARING_PORT=8007
# Auth (local dev)
JWT_SECRET=aegis-local-dev-secret-change-in-production
BOOTSTRAP_ADMIN_EMAIL=admin@aegis.local
BOOTSTRAP_ADMIN_PASSWORD=aegis-dev-admin
AEGIS_COOKIE_HTTPONLY=0
AEGIS_COOKIE_SECURE=0
AEGIS_PUBLIC_BASE_URL=http://localhost:3000
AEGIS_AUTH_MODE=log
HMAC_SIGNING_KEY=aegis-local-hmac-key-change-in-production
# Observability
LANGFUSE_PUBLIC_KEY=
LANGFUSE_SECRET_KEY=
LANGFUSE_HOST=https://cloud.langfuse.comSecurity Notes
Never commit your .env file. The repository .gitignore excludes it. For production deployments, secrets are managed by HashiCorp Vault — never store production keys in environment files.
The following variables contain sensitive values that must be rotated for production:
JWT_SECRET— compromised value allows forging authentication tokensBOOTSTRAP_ADMIN_PASSWORD— the default seeds an admin account; set a strong value before deployingHMAC_SIGNING_KEY— compromised value allows forging audit trail signaturesOPENAI_API_KEY— compromised value allows unauthorized LLM usage at your cost