> ## Documentation Index
> Fetch the complete documentation index at: https://astron-bb4261fd.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Complete environment variable reference for z3rno-server, organized by feature. Every flag below maps to a pydantic-settings field in z3rno_server.config.

# Configuration reference

Every Z3rno surface beyond the **always-on** base (`store` / `recall` / `forget` / `audit` / sessions / api-keys / conversations / limits / graph) is **opt-in via a gating flag**. Default values produce a working local-dev stack against `docker-compose.dev.yml`; flip the gates as you light up Forge / Ingest / Refine / forget-proof / OpenTelemetry / etc.

<Note>
  Source of truth: [`z3rno-server/src/z3rno_server/config.py`](https://github.com/the-ai-project-co/z3rno-server/blob/main/src/z3rno_server/config.py). Variables names are case-insensitive; values are read from environment or `.env` file. **As of v0.20.0.**
</Note>

## Database

| Variable                             | Default                                                              | Notes                                                                                                                                                                             |
| ------------------------------------ | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DATABASE_URL`                       | `postgresql+asyncpg://z3rno:z3rno_dev_password@localhost:5432/z3rno` | Async driver required (`asyncpg`).                                                                                                                                                |
| `DATABASE_POOL_SIZE`                 | `20`                                                                 | SQLAlchemy connection pool.                                                                                                                                                       |
| `DATABASE_MAX_OVERFLOW`              | `10`                                                                 | Pool overflow above `DATABASE_POOL_SIZE`.                                                                                                                                         |
| `DATABASE_READ_URL`                  | `""`                                                                 | **Opt-in (Phase G slice 1).** When set, pure-read GET endpoints route SELECTs to the replica. WAL replay lag is checked at session acquire; over-threshold falls back to primary. |
| `READ_REPLICA_LAG_CHECK_ENABLED`     | `true`                                                               | Honoured only when `DATABASE_READ_URL` is set.                                                                                                                                    |
| `READ_REPLICA_LAG_THRESHOLD_SECONDS` | `5.0`                                                                | Replica skipped when lag exceeds this.                                                                                                                                            |

## Valkey / Redis

| Variable     | Default                    | Notes                                            |
| ------------ | -------------------------- | ------------------------------------------------ |
| `VALKEY_URL` | `""`                       | Preferred. Falls back to `REDIS_URL` when empty. |
| `REDIS_URL`  | `redis://localhost:6379/0` | Back-compat alias.                               |

## Embedding

| Variable             | Default                  | Notes                                                                                         |
| -------------------- | ------------------------ | --------------------------------------------------------------------------------------------- |
| `EMBEDDING_PROVIDER` | `litellm`                | Routes embedding calls through LiteLLM.                                                       |
| `EMBEDDING_MODEL`    | `text-embedding-3-small` | OpenAI default. Output dim is hard-coded at 1536 (ADR-001).                                   |
| `OPENAI_API_KEY`     | `""`                     | Required for OpenAI embeddings. Also the fallback for `LLM_API_KEY` and `MULTIMODAL_API_KEY`. |

## Authentication

| Variable             | Default     | Notes                                                                                                                                                                                                                             |
| -------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Z3RNO_API_KEY`      | `""`        | **Dev bypass.** When set, this key authenticates without a DB lookup. The fresh-local-server default is `z3rno_sk_test_localdev` — rotate it for any non-localhost deploy. Production keys are generated via `POST /v1/api-keys`. |
| `Z3RNO_DEV_ORG_ID`   | `""`        | Org id stamped on requests authenticated by `Z3RNO_API_KEY`.                                                                                                                                                                      |
| `API_KEY_HEADER`     | `X-API-Key` | Alternative to `Authorization: Bearer`.                                                                                                                                                                                           |
| `API_KEY_CACHE_TTL`  | `60`        | Valkey cache TTL (seconds) for verified API keys.                                                                                                                                                                                 |
| `JWT_SECRET_KEY`     | `""`        | HMAC secret for dashboard JWT auth. Required when JWT auth is in use.                                                                                                                                                             |
| `JWT_ALGORITHM`      | `HS256`     |                                                                                                                                                                                                                                   |
| `JWT_EXPIRY_MINUTES` | `60`        |                                                                                                                                                                                                                                   |

## Rate limiting

| Variable                | Default | Notes                                  |
| ----------------------- | ------- | -------------------------------------- |
| `RATE_LIMIT_ENABLED`    | `true`  | Toggles the entire middleware.         |
| `RATE_LIMIT_PER_MINUTE` | `60`    | Per-API-key request budget.            |
| `RATE_LIMIT_BURST`      | `10`    | Burst allowance above the steady rate. |

## Server / CORS / logging

| Variable       | Default                                       | Notes                                                |
| -------------- | --------------------------------------------- | ---------------------------------------------------- |
| `SERVER_HOST`  | `0.0.0.0`                                     |                                                      |
| `SERVER_PORT`  | `8000`                                        |                                                      |
| `DEBUG`        | `false`                                       |                                                      |
| `CORS_ORIGINS` | `http://localhost:3000,http://localhost:8000` | Comma-separated.                                     |
| `LOG_LEVEL`    | `INFO`                                        | `DEBUG` / `INFO` / `WARNING` / `ERROR` / `CRITICAL`. |
| `LOG_FORMAT`   | `json`                                        | `json` or `text`.                                    |

## Celery backpressure

| Variable                                 | Default | Notes                                                                                                |
| ---------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- |
| `CELERY_QUEUE_DEPTH_THRESHOLD`           | `1000`  | When broker depth exceeds this, `/v1/ingest*` returns 503 with `Retry-After`. Set to `0` to disable. |
| `CELERY_QUEUE_DEPTH_RETRY_AFTER_SECONDS` | `30`    | Value of the `Retry-After` header on backpressure 503s.                                              |

***

# Phase A — Forge (`DISTILL_ENABLED`)

The Forge pipeline is dormant unless `DISTILL_ENABLED=true`. With the flag off, `/v1/distill` is not registered and `z3rno.forge_distill` self-rejects.

| Variable                      | Default              | Notes                                                                                                                       |
| ----------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `DISTILL_ENABLED`             | `false`              | Master gate.                                                                                                                |
| `LLM_PROVIDER`                | `openai`             | `openai` / `anthropic` / `gemini` / `bedrock` / `ollama`.                                                                   |
| `LLM_MODEL`                   | `openai/gpt-4o-mini` | LiteLLM-namespaced model id.                                                                                                |
| `LLM_API_KEY`                 | `""`                 | Falls back to `OPENAI_API_KEY` when provider is `openai`.                                                                   |
| `LLM_TIMEOUT_SECONDS`         | `30.0`               | Per-call timeout.                                                                                                           |
| `LLM_MAX_RETRIES`             | `3`                  | Tenacity retry budget.                                                                                                      |
| `STRUCTURED_OUTPUT_FRAMEWORK` | `instructor`         | Only `instructor` is shipped.                                                                                               |
| `DISTILL_CHUNK_SIZE`          | `1024`               | tokens                                                                                                                      |
| `DISTILL_CHUNK_OVERLAP`       | `128`                | tokens                                                                                                                      |
| `DISTILL_MAX_CONCURRENCY`     | `4`                  | Per-job LLM fan-out semaphore.                                                                                              |
| `DISTILL_SUMMARY_STYLE`       | `concise`            | `concise` / `bullet` / `abstractive`.                                                                                       |
| `DISTILL_PROVENANCE_REQUIRED` | `false`              | **Phase F slice 1.** When true, aborts the Forge transaction if any Memo's provenance + audit chain entry can't be written. |

# Phase B.1 — Ingestion (`INGEST_ENABLED`)

`/v1/ingest`, `/v1/ingest/file`, `/v1/datasets` and the `z3rno.ingest_run` worker register only when `INGEST_ENABLED=true`.

| Variable                    | Default                    | Notes                                                             |
| --------------------------- | -------------------------- | ----------------------------------------------------------------- |
| `INGEST_ENABLED`            | `false`                    | Master gate.                                                      |
| `STORAGE_BACKEND`           | `local`                    | `local` (filesystem) or `s3` (Phase B.2).                         |
| `STORAGE_LOCAL_DIR`         | `/var/lib/z3rno/artifacts` |                                                                   |
| `INGEST_MAX_FILE_BYTES`     | `52428800` (50 MB)         | Hard cap on uploads + URL responses.                              |
| `INGEST_MAX_CSV_ROWS`       | `10000`                    |                                                                   |
| `INGEST_DEFAULT_CHUNK_SIZE` | `1024`                     | Per-request override allowed.                                     |
| `INGEST_AUTO_DISTILL`       | `true`                     | Chain ingest → `z3rno.forge_distill` when `DISTILL_ENABLED=true`. |
| `URL_FETCH_TIMEOUT_SECONDS` | `15.0`                     |                                                                   |
| `URL_ALLOWED_SCHEMES`       | `http,https`               |                                                                   |

# Phase B.2 — Multimodal / S3 / Tavily / Playwright

Each capability flips on independently — multimodal doesn't require S3, Tavily doesn't require multimodal, etc.

### Multimodal (image + audio)

| Variable                     | Default              | Notes                                                                                                                    |
| ---------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `MULTIMODAL_ENABLED`         | `false`              | Registers image/audio loaders with the registry on worker startup.                                                       |
| `MULTIMODAL_PROVIDER`        | `litellm`            | `litellm` (OpenAI vision + Whisper) / `local` (CLIP + openai-whisper, requires `z3rno-core[multimodal-local]`) / `stub`. |
| `MULTIMODAL_VISION_MODEL`    | `openai/gpt-4o-mini` |                                                                                                                          |
| `MULTIMODAL_AUDIO_MODEL`     | `whisper-1`          |                                                                                                                          |
| `MULTIMODAL_API_KEY`         | `""`                 | Falls back to `OPENAI_API_KEY`.                                                                                          |
| `MULTIMODAL_MAX_AUDIO_BYTES` | `26214400` (25 MB)   | OpenAI Whisper cap.                                                                                                      |
| `MULTIMODAL_MAX_IMAGE_BYTES` | `20971520` (20 MB)   |                                                                                                                          |

### S3 storage backend (`STORAGE_BACKEND=s3`)

| Variable               | Default     | Notes                                                               |
| ---------------------- | ----------- | ------------------------------------------------------------------- |
| `S3_BUCKET`            | `""`        | Required when `STORAGE_BACKEND=s3`.                                 |
| `S3_REGION`            | `us-east-1` |                                                                     |
| `S3_ENDPOINT_URL`      | `""`        | Empty for AWS; set for MinIO / Cloudflare R2 / DigitalOcean Spaces. |
| `S3_PREFIX`            | `z3rno`     | Bucket-key prefix sandbox.                                          |
| `S3_ACCESS_KEY_ID`     | `""`        | Empty → default AWS credential chain (IRSA / IAM role).             |
| `S3_SECRET_ACCESS_KEY` | `""`        |                                                                     |

### Tavily web search (registers `/v1/ingest/search`)

| Variable              | Default | Notes                             |
| --------------------- | ------- | --------------------------------- |
| `TAVILY_API_KEY`      | `""`    | Set to register the search route. |
| `TAVILY_SEARCH_DEPTH` | `basic` | `basic` / `advanced`.             |
| `TAVILY_MAX_RESULTS`  | `5`     |                                   |

### URL loader Playwright fallback

| Variable                         | Default | Notes                                            |
| -------------------------------- | ------- | ------------------------------------------------ |
| `URL_PLAYWRIGHT_ENABLED`         | `false` | Requires `pip install 'z3rno-core[playwright]'`. |
| `URL_PLAYWRIGHT_MIN_CHARS`       | `200`   | Below this, fall back to Playwright.             |
| `URL_PLAYWRIGHT_TIMEOUT_SECONDS` | `30.0`  |                                                  |

# Phase C — Retrieval

| Variable             | Default | Notes                                                                                                                         |
| -------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `ALLOW_CYPHER_QUERY` | `false` | Gates `strategy="CYPHER"` on recall. Off by default — the strategy exists but is hidden behind 403 until an operator opts in. |

# Phase D — Refine / Ontology / Codegraph (`REFINE_ENABLED`)

`/v1/feedback`, `/v1/refine`, and the `z3rno.refine_run` worker register only when `REFINE_ENABLED=true`.

### Refine

| Variable                       | Default            | Notes                                                                                                                          |
| ------------------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| `REFINE_ENABLED`               | `false`            | Master gate.                                                                                                                   |
| `REFINE_SCHEDULE`              | `cron:0 */6 * * *` | Per-cron-tab format; consumed by the legacy schedule wiring. Multi-tenant scheduler uses `REFINE_BEAT_INTERVAL_SECONDS` below. |
| `FEEDBACK_WEIGHT_DECAY`        | `0.95`             | EMA blend factor per refine cycle.                                                                                             |
| `REFINE_MAX_PER_TICK`          | `10`               | **v0.19.4.** Tenants picked per scheduler tick.                                                                                |
| `REFINE_BEAT_INTERVAL_SECONDS` | `0`                | **v0.19.4.** Set `> 0` to enable multi-tenant beat scheduler. `0` keeps the scheduler dormant (on-demand only).                |
| `REFINE_INFER_ENABLED`         | `false`            | LLM stage: propose edges for under-connected Memos.                                                                            |
| `REFINE_SUMMARIZE_ENABLED`     | `false`            | LLM stage: per-cluster SUMMARY Memos.                                                                                          |
| `REFINE_INFER_MAX_CANDIDATES`  | `50`               | Per-cycle LLM call cap.                                                                                                        |

### Ontology grounding (Forge integration)

| Variable                     | Default | Notes                                                                       |
| ---------------------------- | ------- | --------------------------------------------------------------------------- |
| `ONTOLOGY_RESOLVER`          | `none`  | `none` or `rdflib`. Set `rdflib` to resolve distilled entities to OWL URIs. |
| `ONTOLOGY_FILE_PATH`         | `""`    | Required when `ONTOLOGY_RESOLVER=rdflib`. Path to OWL/TTL/RDF file.         |
| `ONTOLOGY_MATCHING_STRATEGY` | `fuzzy` | `exact` or `fuzzy`.                                                         |
| `ONTOLOGY_FUZZY_THRESHOLD`   | `0.80`  | Minimum score for fuzzy match (`0`-`1`).                                    |

### Codegraph (Ingest integration)

| Variable              | Default             | Notes                                                                                                                  |
| --------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `CODEGRAPH_ENABLED`   | `false`             | When true, ingest of code sources also runs the tree-sitter extractor. Requires `pip install 'z3rno-core[codegraph]'`. |
| `CODEGRAPH_LANGUAGES` | `python,typescript` | Allow-list. **v0.19.5** added `go` and `rust`.                                                                         |

# Phase F — Differentiation

### Memory-tier routing

| Variable                 | Default | Notes                                                                                                                                                 |
| ------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MEMORY_TIER_AUTO_ROUTE` | `false` | When true, the AUTO strategy asks the `MemoryTierRouter` for tiers and fans out across them. Per-request `tier_route` in the recall body always wins. |

### Compliance-graded retrieval (PII redaction)

| Variable                         | Default | Notes                                                                              |
| -------------------------------- | ------- | ---------------------------------------------------------------------------------- |
| `RETRIEVAL_REDACTION_ENABLED`    | `false` | Role-aware regex scrubbing on recall results.                                      |
| `RETRIEVAL_REDACTION_RULES_PATH` | `""`    | YAML rules file. Empty → built-in defaults (email / SSN / credit card / US phone). |

### Forget-with-proof

| Variable                        | Default   | Notes                                                                                                                    |
| ------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------ |
| `FORGET_PROOF_ENABLED`          | `false`   | When true, every `forget()` emits a Merkle-rooted, ed25519-signed certificate; `GET /v1/forget/{cert_id}` is registered. |
| `FORGET_PROOF_SIGNING_KEY_PATH` | `""`      | PEM-encoded unencrypted Ed25519 private key.                                                                             |
| `FORGET_PROOF_SIGNER_KEY_ID`    | `default` | Rotation-friendly label stamped on each cert.                                                                            |

### Distributed worker backends

| Variable              | Default  | Notes                                                                                                                  |
| --------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `DISTRIBUTED_BACKEND` | `celery` | `celery` / `modal` / `k8s_jobs`. Off-default backends lazy-import — missing SDK raises `JobBackendError`, not a crash. |
| `MODAL_APP_NAME`      | `z3rno`  |                                                                                                                        |
| `K8S_JOBS_NAMESPACE`  | `z3rno`  |                                                                                                                        |
| `K8S_JOBS_IMAGE`      | `""`     | Image used when `DISTRIBUTED_BACKEND=k8s_jobs`.                                                                        |

# Phase G — Agent-native

### Usage telemetry + budgets

Zero = no cap (default). Non-zero values trip `BudgetExceededError` on Forge / refine pre-flight; the job is rejected before any LLM/embedding work.

| Variable                          | Default |
| --------------------------------- | ------- |
| `USAGE_BUDGET_DAILY_TOKENS`       | `0`     |
| `USAGE_BUDGET_DAILY_LLM_CALLS`    | `0`     |
| `USAGE_BUDGET_DAILY_EMBEDDINGS`   | `0`     |
| `USAGE_BUDGET_MONTHLY_TOKENS`     | `0`     |
| `USAGE_BUDGET_MONTHLY_LLM_CALLS`  | `0`     |
| `USAGE_BUDGET_MONTHLY_EMBEDDINGS` | `0`     |

Per-tenant overrides land via `PUT /v1/tenants/me/budgets` (v0.20.3). See [Components → z3rno-server](/components/server) for the endpoint.

### Cross-tenant admin (v0.22.1, managed-hosting)

| Variable             | Default | Notes                                                                                                                                                              |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `SUPERADMIN_ENABLED` | `false` | Gates `/v1/tenants/{org_id}/budgets`. Both this **and** `SUPERADMIN_API_KEY` must be set for the routes to register.                                               |
| `SUPERADMIN_API_KEY` | `""`    | Deploy-time secret. The bearer presented on a request is matched against this directly — there is no DB lookup. Treat like a root password; rotate by config push. |

The cross-tenant surface is off by default and stays invisible (not
in the OpenAPI spec) until both vars are set. See the
[Managed-hosting guide](/guides/managed-hosting) for the ops playbook.

### Recall counter batching (v0.22.0)

| Variable                       | Default | Notes                                                                                                  |
| ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------ |
| `RECALL_COUNT_BATCH_ENABLED`   | `false` | Coalesce `recall_count` bumps into one UPDATE per org per window. Per-process.                         |
| `RECALL_COUNT_BATCH_WINDOW_MS` | `50`    | Flush cadence. Smaller = fresher counters + more writes; larger = staler counters + better coalescing. |

Off by default; flip on once your deployment's benchmark numbers
ratify the win. The single-process laptop bench delta is +2-4%
ops/sec at high concurrency with a -19 to -25% p99 reduction at
20-30 concurrent recalls.

### OpenTelemetry tracing

| Variable                      | Default        | Notes                                                                  |
| ----------------------------- | -------------- | ---------------------------------------------------------------------- |
| `OTEL_ENABLED`                | `false`        | When true, instruments FastAPI; W3C `traceparent` propagates outbound. |
| `OTEL_SERVICE_NAME`           | `z3rno-server` |                                                                        |
| `OTEL_ENVIRONMENT`            | `production`   | Stamped as `deployment.environment` on every span.                     |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | `""`           | OTLP/gRPC endpoint.                                                    |

# v0.20 — Operator polish

### NOTIFY/LISTEN audit drain (v0.20.2)

| Variable                     | Default | Notes                                                                                                                                                                                                                                                                                        |
| ---------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Z3RNO_AUDIT_LISTEN_ENABLED` | `false` | Gate read by the `z3rno-audit-listener` console-script (the singleton pod deployed by the chart's `auditListener.enabled` block). When true, the listener opens `LISTEN z3rno_audit_pending` and fires `z3rno.audit_drain` on every notification (\~50 ms wake instead of waiting for beat). |

### Audit-drain tunables (read by the engine; surface them through chart `beat.audit.*`)

| Variable                        | Default | Notes                                                                                    |
| ------------------------------- | ------- | ---------------------------------------------------------------------------------------- |
| `AUDIT_DRAIN_BATCH_SIZE`        | `500`   | Rows per drain transaction.                                                              |
| `AUDIT_DRAIN_INTERVAL_SECONDS`  | `1.0`   | Beat tick interval. Recommended `60.0` when listener is enabled (poll becomes fallback). |
| `AUDIT_DRAIN_MAX_ORGS_PER_TICK` | `100`   | Bounds per-tick fan-out.                                                                 |

***

## Reference

* **Source:** [`z3rno-server/src/z3rno_server/config.py`](https://github.com/the-ai-project-co/z3rno-server/blob/main/src/z3rno_server/config.py)
* **Helm surface:** [Components → z3rno-helm](/components/helm) — these env vars all surface as values keys.
* **Server reference:** [Components → z3rno-server](/components/server) — endpoint × gating-flag matrix.
* **Per-release detail:** [`changelogs/`](https://github.com/the-ai-project-co/z3rno-process-docs/tree/main/improvements/changelogs)
