Skip to content
kazma.
ع Star 7 Get Started

Environment Variables

Complete env reference for local, Docker, and production. Prefer strong secrets; never commit .env with real keys. Also see Configuration for kazma.yaml and ConfigStore.

VariableDefaultPurpose
KAZMA_COMPUTER_USE10 disables the computer_use tool
KAZMA_LANGFUSE(unset)0 forces console tracing even when Langfuse keys exist
LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEYWith logging.langfuse.enabled: auto, both set → Langfuse backend
KAZMA_EMBED_FLEET(unset)1 + OpenAI/Voyage key → hosted embeddings (issue #78)
KAZMA_DOCLING10 skips Docling salvage on weak PDF extracts
KAZMA_REMOTE_PARSE10 skips LlamaParse/Reducto salvage
LLAMAPARSE_API_KEY / REDUCTO_API_KEYHard-PDF remote extract (parent process; not the parser sandbox)
KAZMA_SILERO_VAD(unset)1 tries Silero VAD (falls back to energy)
KAZMA_LITELLM_URL(unset)LiteLLM proxy for OpenAI-compatible providers only (e.g. http://127.0.0.1:4000)
KAZMA_LITELLM10 disables the LiteLLM proxy even if a URL is set
KAZMA_LITELLM_LOCAL(unset)1 also routes loopback Ollama/LM Studio through the proxy
KAZMA_LITELLM_FALLBACK_DIRECT(unset)1 retries the original provider URL if the proxy is unreachable
LITELLM_MASTER_KEY / LITELLM_API_KEY / KAZMA_LITELLM_KEYBearer key sent to the proxy (else the provider key is reused)
LIVEKIT_URL(unset)LiveKit WebRTC URL for web duplex voice (e.g. wss://…livekit.cloud)
LIVEKIT_API_KEY / LIVEKIT_API_SECRETLiveKit API credentials (room tokens). All three required to enable duplex
KAZMA_VOICE_DUPLEX10 disables LiveKit duplex even if credentials are set
KAZMA_CUA_PLANNER10 keeps computer_use on vision-JSON (no Anthropic CUA / Gemini mapping)
KAZMA_MCP_SAMPLING01 allows MCP sampling/createMessage after a HITL card (no tools on that LLM call)
KAZMA_MCP_SAMPLING_TIMEOUT60Seconds to wait for the sampling HITL card
KAZMA_REALTIME_CODEC01 uses REST STT/TTS as the audio codec. OpenAI Realtime / Gemini Live are skipped
  1. Specific helpers may read env first (KAZMA_SECRET, vault, disclosure).
  2. ConfigStore DB wins for most runtime settings.
  3. kazma.yaml seeds missing DB keys.
  4. Hardcoded defaults last.

Generic ConfigStore.get() does not automatically overlay every env var — only documented keys below that code explicitly reads.

Document platform limits, OCR, workers, retention, capacity, and rollout flags are ConfigStore / kazma.yaml keys (live-read), not a parallel env matrix. Primary keys are nested, for example:

  • documents.enabled / documents.shadow / documents.default_authoritative
  • documents.intake.max_bytes, documents.limits.max_pages
  • documents.ocr.*, documents.workers.*, documents.capacity.*
  • documents.retention.*, documents.gc.*, documents.security.*

See Document Intelligence — live configuration and kazma_core.documents.config.DocumentConfig. Optional cert soak size: KAZMA_DOCUMENT_SOAK_ITERATIONS (used by scripts/certify_documents.py --soak).

VariableDefaultPurpose
KAZMA_DOCUMENTS_JOBS_BACKENDautoForce sqlite for job queue (else follow Postgres when configured)
KAZMA_DOCUMENTS_METADATA_BACKENDautosqlite / postgres / auto (auto follows jobs backend). Postgres metadata enables multi-replica CRUD; GC mark/sweep is backend-agnostic (repository.gc_mark)
KAZMA_DOCUMENT_SOAK_ITERATIONS100Soak iteration count for certify_documents.py --soak

VariableDefaultProd required?Purpose
KAZMA_HOST127.0.0.1Set deliberatelyBind address. Non-loopback requires KAZMA_SECRET.
KAZMA_PORT / serve arg9090 (CLI)NoHTTP port (kazma serve [port]). Docker images may differ — check compose.
KAZMA_SECRETgenerated on loopbackYes on public bindAuth shared secret / session material. Known-bad default refused.
KAZMA_PRODUCTIONunsetYes for prodEnables vault-required, workspace root, code_exec policy, YOLO hard-block, etc.
KAZMA_ENVunsetOptionalSome paths treat production specially.
KAZMA_PUBLIC_URLunsetRecommended behind proxyPublic origin for OAuth/OIDC redirects.
KAZMA_CORS_ORIGINSunsetIf browser cross-originComma-separated origins.
KAZMA_ENV_FILEunsetNoAbsolute path to an extra .env, loaded last so it wins. The .env ladder is: <kazma home>/.env<cwd>/.env → this. Nothing outside the installation is read unless you name it here.
KAZMA_TRUSTED_PROXIESunsetYes behind any proxyComma-separated addresses the reverse proxy connects from (127.0.0.1 for same-host nginx/Caddy, the bridge IP under Docker). Only these peers may set X-Forwarded-For / X-Forwarded-Proto. See the warning below.
KAZMA_LOOPBACK_AUTOLOGIN0Keep 0Re-enables credential-less loopback login even with a proxy declared. Only for a host where 127.0.0.1 really is just you.
KAZMA_TRUST_LAN0Keep 0 unless neededLAN trust for auth middleware.
KAZMA_AUTH_DISABLEDunsetNever in prodDisables auth helpers — dev only.
KAZMA_ALLOW_YOLOunsetAvoidOnly way to re-enable YOLO when KAZMA_PRODUCTION=1.
KAZMA_VERBOSE_ERRORS0Keep 0Appends the real exception message to API errors (still redacted for paths and credentials). Dev only — production returns a code plus a correlation id.

:::danger KAZMA_TRUSTED_PROXIES is required behind a reverse proxy

Kazma treats a loopback client as the local operator and auto-issues an admin session to it — that is what makes single-operator localhost use work with no login.

Behind a same-host nginx/Caddy, request.client.host is 127.0.0.1 for every internet visitor. Without KAZMA_TRUSTED_PROXIES, each of them is therefore treated as the operator and handed an admin session on the first page load, over HTTP and WebSocket. This was audit finding F-01 (2026-08-29).

Set it to the proxy’s address and Kazma reads the real client from X-Forwarded-For instead, and stops treating peer address as a credential:

Terminal window
KAZMA_TRUSTED_PROXIES=127.0.0.1

Your proxy must send the forwarded headers and must overwrite rather than append a client-supplied value; the shipped deploy/nginx-ha.conf already does. serve.py passes --proxy-headers --forwarded-allow-ips to uvicorn from this variable automatically.

Under Docker this is the proxy container’s bridge address (often 172.17.0.1 or the compose network gateway), not 127.0.0.1. Getting it wrong no longer fails open: a forwarded header from an undeclared peer disables peer-address trust for the process and logs the address to set.

Verify after deployauthenticated must read false before login, and proxy.state should read declared (direct behind a proxy means the variable did not take; undeclared_proxy means it is set to the wrong address, and proxy.hint names the right one):

Terminal window
curl -s https://your.domain/api/auth/status

:::


VariableDefaultProd required?Purpose
KAZMA_VAULT_KEYunsetYes if productionAES vault master material.
KAZMA_JWT_SECRETunsetIf JWT paths usedJWT signing for tenant/API tokens.
KAZMA_DISCLOSURE_KEYunsetOptionalVulnerability disclosure crypto helper.

VariableDefaultProd required?Purpose
KAZMA_DATABASE_URLunset (SQLite)Multi-replica YesPostgres DSN → dual-backend stores + LangGraph checkpointer.
DATABASE_URLunsetAltAccepted by migrate script as alias.
KAZMA_DB_BACKENDautoOptionalForce postgres / sqlite.
KAZMA_DB_CONTAINERkazma-dbMigrationDocker container name for pg_dump / pg_restore discovery during kazma migrate. See Migration.
KAZMA_DB_INTERNAL_PORT5432MigrationContainer-internal Postgres port when pg_dump / pg_restore run via docker exec (the host’s forwarded port is unreachable from inside the container).
KAZMA_PG_POOL_RETRIES5OptionalConnection-pool creation retry count. Handles transient failures (Windows Docker-bridge, container mid-startup).
KAZMA_PG_POOL_RETRY_DELAY1.0OptionalSeconds between pool-creation retries.
KAZMA_PG_POOL_MIN1OptionalMinimum connections in the psycopg pool.
KAZMA_PG_POOL_MAX10OptionalMaximum connections in the psycopg pool.
KAZMA_PG_POOL_TIMEOUT5OptionalSeconds a caller waits for a free pool connection. A hang here used to freeze /health/ready on the event loop.

Default remains Docker/local python_exec and in-process swarm. These are opt-in for untrusted code and multi-hour work. See Architecture and extras kazma[sandbox] / kazma[durable].

VariableDefaultProd required?Purpose
KAZMA_E2B_API_KEY / E2B_API_KEYunsetUntrusted / multi-user codeE2B Firecracker for HITL-approved python_exec.
KAZMA_E2Bauto if key setNo0 keeps Docker/local even with a key.
KAZMA_CODE_EXEC_DOCKERautoSingle-operator jail1/force Docker; 0 local (ignored when production forbids local). force also blocks host shell_exec unless KAZMA_HOST_SHELL=1.
KAZMA_HOST_SHELLunsetEscape hatch1 allows host shell_exec even when KAZMA_CODE_EXEC_DOCKER=force.
KAZMA_LIVE_EVALunsetNo1 runs the opt-in live-model eval (tests/test_hands_live.py). CI skips.
KAZMA_TEMPORAL_HOST / TEMPORAL_ADDRESSunsetMulti-hour swarmTemporal frontend (localhost:7233). Wraps swarm _dispatch_inner.
KAZMA_TEMPORALauto if host setNo0 keeps in-process swarm.
KAZMA_TEMPORAL_REQUIREDunsetStrict HA1 = fail the task if Temporal/SDK is down (no in-process fallback).
KAZMA_TEMPORAL_NAMESPACEdefaultNoTemporal namespace.
KAZMA_TEMPORAL_QUEUEkazma-swarmNoTask queue for the in-process Temporal worker.
KAZMA_CODE_INDEXonNo0 disables the workspace symbol index + codebase_search.
KAZMA_IDE_LSPonNo0 disables the /api/ide/lsp backend. The Web /ide editor is CodeMirror 5 (syntax only); hover/complete UI is not bound.

VariableDefaultProd required?Purpose
OPENAI_API_KEYunsetOne provider keyOpenAI-compatible key; also used for the dall-e image-gen backend.
KAZMA_API_KEYunsetFallbackGeneric API key fallback.
KAZMA_PROVIDERunsetOptional bootProvider id at startup.
KAZMA_MODELunsetOptional bootModel id at startup.
ANTHROPIC_API_KEYunsetFor ClaudeNative Anthropic Messages API (anthropic_llm.py).
AZURE_OPENAI_ENDPOINT / AZURE_OPENAI_API_KEY / AZURE_OPENAI_DEPLOYMENT / AZURE_OPENAI_API_VERSIONunsetFor AzureAzure OpenAI (azure_llm.py).
AWS_REGION / AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEYunsetFor BedrockAWS Bedrock via standard boto3 credential chain (bedrock_llm.py).
STABILITY_API_KEYunsetOptionalStability SDXL image-gen backend.
FAL_KEYunsetOptionalFlux image-gen backend (FAL.ai).
KAZMA_IMAGE_PROVIDERunsetOptionalForce an image backend (pollinations/dall-e/stability/flux); default auto.
KAZMA_STRICT_TOOLSunset (off)No1 stamps OpenAI function.strict: true on closed tool schemas (all properties required; optionals are T | null). Default is closed objects with additionalProperties: false only — local / Anthropic / Gemini often 400 on strict.
KAZMA_LLM_STREAMonNo0 falls back to blocking chat() (no token SSE).
KAZMA_TOOL_HOOKSonNo0 disables PreToolUse / PostToolUse (in-process and command). Empty agent.hooks.* lists are a no-op. Hooks cannot skip HITL.
KAZMA_PLAN_MODEonNo0 disables /plan enter/execute. Plan mode is not a HITL bypass.
GOOGLE_CALENDAR_TOKEN / MS_CALENDAR_TOKENunsetOptionalOverride only. Calendar tokens normally live in the vault (calendar.google.* / calendar.microsoft.*) via Settings → Email → Connect Calendar / Connect with Microsoft.
Provider-specificAs usede.g. DeepSeek, Groq, xAI, OpenRouter, Mistral, Together, Cohere, Fireworks, Perplexity, AI21, Google ADC — see Configuration.

VariableDefaultProd required?Purpose
KAZMA_WORKSPACEactive WorkspaceStore / data dirProd root policyAgent filesystem workspace root.
KAZMA_VECTOR_COLLECTIONagent_memoryNoChroma collection name.
KAZMA_VECTOR_MODELBAAI/bge-m3NoLegacy alias for the embedding model id (prefer KAZMA_EMBED_MODEL).
KAZMA_EMBED_PROVIDERlocalNoEmbedding provider (local or openai-compatible).
KAZMA_EMBED_MODELBAAI/bge-m3NoEmbedding model id (overrides memory.embedding.model).
KAZMA_EMBED_DIM1024NoEmbedding dimension (must match the model’s output).
KAZMA_EMBED_BASE_URLunsetRemote only/embeddings endpoint base URL for openai-compatible.
KAZMA_EMBED_API_KEYunsetRemote onlyAPI key for the remote /embeddings endpoint.
KAZMA_DEMO_MODEunsetNoDemo fixtures — never enable in real prod.
KAZMA_MEMORY_ENFORCE_TENANTunsetMulti-tenant onlyWhen 1/true, the /memory operator endpoints scope reads, id-keyed mutations, undo tokens, and graph-clear by the request-scoped tenant (set by the auth middleware from verified JWT/opaque-session claims). Unset = single-tenant default. Flip on only when you add a second tenant.
KAZMA_MEMORY_STATE_ROLEunset (mirror)Multi-replica onlyprimary makes the Postgres state backend the recall SoT (fail-closed if down — no silent SQLite). Dense search is pgvector fused with ILIKE. Do not enable until python scripts/reconcile_memory_mirror.py --dry-run reports no dead-in-mirror / only-in-mirror rows.
KAZMA_PGVECTORauto when a Postgres DSN is setNo0 keeps sqlite-vec even if Postgres is on. Unset = pgvector auto-select from KAZMA_DATABASE_URL / memory.backends.state.url. Explicit Qdrant in Settings still wins.

See Web research for playbooks. Tools are used from chat (no /research slash command).

VariableDefaultPurpose
KAZMA_SEARXNG_URLmulti-base auto-discoveryPreferred search backend for web_search (also ConfigStore search.searxng_url).
KAZMA_READ_URL_MAX_CHARS16000Default window size for one read_url / crawl_page response.
KAZMA_TOOL_RESULT_MAX_CHARS4000Graph truncate cap for ordinary tools.
KAZMA_TOOL_RESULT_RESEARCH_MAX_CHARS16000Higher graph truncate for research tools (read_url, digests, crawl_site, …).
KAZMA_RESEARCH_DIRresearchDefault workspace subfolder for auto-named read_url_to_file / crawl saves.
KAZMA_RESEARCH_DIGEST_MAX12000Max output size of digest_research_file.
KAZMA_CRAWL_MAX_PAGES50Hard ceiling for crawl_site max_pages.
KAZMA_CRAWL_MAX_DEPTH5Hard ceiling for crawl_site max_depth.
KAZMA_FETCH_BACKENDautoauto | httpx | jina | firecrawl.
KAZMA_FIRECRAWL_API_KEYunsetOptional Firecrawl scrape API (used in pre-fetch + hard-page recovery).
KAZMA_FIRECRAWL_URLhttps://api.firecrawl.devFirecrawl API base (self-host OK).
KAZMA_JINA_READERunset (recovery-on)1 = always try first; unset = last-resort recovery; 0/off = never use Jina.
JINA_API_KEY / KAZMA_JINA_API_KEYunsetOptional Jina Bearer token for higher rate limits.

Optional package: Playwright via pip install 'kazma[web]' then playwright install chromium (bot walls / thin JS shells).

SearXNG ops: docker compose --profile search up -d searxnghttp://127.0.0.1:8088 (JSON enabled in deploy/searxng/settings.yml).


VariableDefaultProd required?Purpose
KAZMA_OIDC_ISSUERunsetIf SSOOIDC issuer URL.
KAZMA_OIDC_CLIENT_IDunsetIf SSOClient id.
KAZMA_OIDC_CLIENT_SECRETunsetIf SSOClient secret (required for HS* id_token).
KAZMA_WS_GRAPHunsetNo1 restores WS send_prompt / approve_tool as a second graph client (debug). Default: SSE only.

See OIDC IdP Setup and Multi-user SaaS.


Native skill email-manager. Default provider auto: real account if configured, else sandbox.

VariablePurpose
EMAIL_DEFAULT_PROVIDERauto | sandbox | gmail | microsoft | imap | pop
EMAIL_GMAIL_ADDRESSGmail address (filled by OAuth or IMAP/POP)
EMAIL_GMAIL_APP_PASSWORDApp password for IMAP/POP (often blocked on Workspace)
EMAIL_GMAIL_AUTHoauth | imap | pop (set by Settings / OAuth)
EMAIL_GMAIL_CLIENT_ID / EMAIL_GMAIL_CLIENT_SECRETGoogle OAuth web client (recommended)
EMAIL_GMAIL_ACCESS_TOKEN / EMAIL_GMAIL_REFRESH_TOKENSet by OAuth callback / refresh
EMAIL_GMAIL_REDIRECT_URIOverride callback (default {public}/api/email/oauth/gmail/callback)
EMAIL_MS_ACCESS_TOKENGraph bearer token (short-lived)
EMAIL_MS_REFRESH_TOKENGraph refresh token
EMAIL_MS_CLIENT_IDAzure app client id
EMAIL_MS_CLIENT_SECRETAzure app secret (confidential clients)
EMAIL_MS_TENANT_IDTenant (common default)
EMAIL_MS_REDIRECT_URIOverride callback (default {public}/api/email/oauth/microsoft/callback)
EMAIL_MS_AUTHoauth | imap | pop
EMAIL_MS_ADDRESS / EMAIL_MS_PASSWORDMicrosoft IMAP/POP login
EMAIL_MS_IMAP_HOST / EMAIL_MS_POP_HOST / EMAIL_MS_SMTP_HOSTOverride M365 protocol hosts
KAZMA_PUBLIC_URLPublic origin for OAuth redirects behind proxy
EMAIL_ADDRESS / EMAIL_PASSWORDGeneric IMAP/POP user
EMAIL_PROTOCOLimap | pop for generic account
EMAIL_IMAP_HOST / EMAIL_IMAP_PORTIMAP (default 993)
EMAIL_POP_HOST / EMAIL_POP_PORTPOP3 SSL (default 995)
EMAIL_SMTP_HOST / EMAIL_SMTP_PORTSMTP (default 587 STARTTLS)
EMAIL_ACCOUNTSComma-separated multi-account aliases
EMAIL_ACCOUNT_{ALIAS}_TYPEgmail | microsoft | imap | pop
EMAIL_ACCOUNT_{ALIAS}_ADDRESS / _PASSWORDPer-account credentials
EMAIL_ACCOUNT_{ALIAS}_*IMAP_HOST, POP_HOST, REFRESH_TOKEN, CLIENT_ID, …

API: GET /api/email/status, GET /api/email/presets, POST /api/email/protocol/connect\|disconnect, OAuth start/callback routes.
HITL: email_send, email_delete, email_categorize. Guide: Email integration.


Native skill x-publisher. Credentials live in Settings → X (vaulted ConfigStore keys) or env. Compose and plan on X Studio (/x). Guide: X publisher.

VariableDefaultPurpose
KAZMA_X_POSTunset (on if Settings enabled)0 hard-disables posting (Studio, chat, and scheduled fire).
KAZMA_X_SCHEDULEunset (on)0 disables scheduling only (book_x_post / Studio Schedule).
X_API_KEYunsetOAuth 1.0a consumer key (else connectors.x.api_key).
X_API_KEY_SECRETunsetConsumer secret.
X_ACCESS_TOKENunsetUser access token.
X_ACCESS_TOKEN_SECRETunsetUser access token secret.

Do not use the app-only Bearer token. User authentication must be Read and write.


Safety guards & embedder downloads (2026-08-19)

Section titled “Safety guards & embedder downloads (2026-08-19)”

Opt-in hardening from the deep-structure audit (docs/audits/AUDIT_DEEP_STRUCTURE_2026-08-19.md) — all default OFF (current behavior preserved) unless noted.

VariableDefaultPurpose
KAZMA_HITL_CANONICAL_FLOORunset (off)Union the canonical danger-tool list back into the effective require_approval_for, so Settings/YAML cannot narrow below it. Strict multi-operator deployments should set 1. The drift warning repeats every 15 min regardless.
KAZMA_GATEWAY_STRICT_ALLOWLISTunset (compat)Stop forcing _allow_all on the Telegram/Discord/Slack adapters — an empty allowlist then fails closed (no messages). Without it, forced allow-all logs a WARNING naming both remediations when no allowlist is configured.
KAZMA_MCP_SCOPE_GUARD1 (on)Fail-close MCP tool calls when a per-task workspace_scope targets a different root than the process-bound MCP root (prevents silent wrong-repo operations). Set 0 only if the guard blocks a legitimate flow.
KAZMA_EMBED_ALLOW_DOWNLOADunset (contextual)Force-allow the local embedder to download its model from HuggingFace. Fallback embedders (unknown provider / broken remote config) never download — they check the local HF cache and degrade to no embeddings with an actionable warning instead of stalling on a ~2GB download. Deliberate local configs keep first-run download rights.

VariableDefaultPurpose
KAZMA_MAX_COSTcost breaker defaultUSD budget ceiling.
KAZMA_SILENCE_WINDOWcost breaker defaultSilence window seconds.
KAZMA_CHAOS_ENABLEDunsetChaos routes (must stay off in prod).
KAZMA_SMOKE_BASEhttp://127.0.0.1:9090Smoke test base URL.
KAZMA_TEST_FORCE_OUTPUT_ROUTINGunsetTest-only gateway output routing.
KAZMA_CODE_EXEC_DOCKERpolicyforce in hardened Docker compose for code_exec jail.
KAZMA_MARKET_STUB0Example skill market data stub.

VariablePurpose
GITHUB_TOKEN / OAuth pathNative git tools & GitHub client (prefer OAuth→PAT chain in app).

Terminal window
# Loopback; secret auto-generated if missing
KAZMA_HOST=127.0.0.1
# optional OPENAI_API_KEY=...
kazma serve 9090
Terminal window
KAZMA_HOST=0.0.0.0
KAZMA_SECRET=<strong-random>
KAZMA_PRODUCTION=1
KAZMA_VAULT_KEY=<strong-random>
KAZMA_PUBLIC_URL=https://your.domain
KAZMA_TRUSTED_PROXIES=127.0.0.1 # REQUIRED — the proxy's address, not the client's
KAZMA_TRUST_LAN=0
KAZMA_CODE_EXEC_DOCKER=force

Under Docker, KAZMA_TRUSTED_PROXIES is the proxy container’s address on the bridge network (often 172.17.0.1 or the compose network’s gateway), not 127.0.0.1.

Terminal window
KAZMA_DATABASE_URL=postgresql://…
KAZMA_PRODUCTION=1
KAZMA_SECRET=
KAZMA_VAULT_KEY=
KAZMA_PUBLIC_URL=https://…
KAZMA_TRUSTED_PROXIES=<load-balancer / ingress address>
# optional OIDC_*