Skip to Content
Polyant is open source under AGPL-3.0 — star us on GitHub.
ReferenceEnvironment Variables

Environment Variables

On this page

Note. This page is generated from the managed-services build’s sample configuration. The open-source build differs in four ways: it has no GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, AUTH_MODE, AUTH_ALB_PLATFORM_ADMIN_GROUP, REMOVE_AUTHORIZATION_FILTER_FOR_TESTING, LOG_LEVEL_TAG_PREFIX, POSTGRES_CONNECT_RETRIES or POSTGRES_CONNECT_RETRY_DELAY_MS; its sample database name and user are polyant; its sample also lists the admin panel’s NEXT_PUBLIC_API_URL and INTERNAL_ENGINE_URL, described in Deployment; and the settings this page places under Admin Console → Installation policies are under Settings → General.

Many product settings are no longer environment variables. The variables that used to carry them are listed under Retired variables with the place each value is set now.

Database

VariableDefaultDescription
DATABASE_URL--
POSTGRES_HOSTlocalhostIndividual PostgreSQL settings are an alternative to DATABASE_URL. The defaults match the local Docker setup. Replace POSTGRES_PASSWORD before deploying.
POSTGRES_PORT5432-
POSTGRES_DBpolyant_enterprise-
POSTGRES_USERpolyant_enterprise-
POSTGRES_PASSWORDlocal-development-password-
POSTGRES_SSL-Set to “true” only when the DB enforces TLS (e.g. AWS Aurora). Leave empty or unset for local Docker PostgreSQL. The only accepted values are “true” and “false” (empty = unset = off); anything else - “1”, “yes”, “require”, “TRUE” - fails validation at boot rather than silently meaning OFF. UPGRADING: this used to accept any string and treat everything but the literal “true” as off. If you carry POSTGRES_SSL=1 (or “require”) against Aurora, TLS was OFF and the value is now rejected - set it to “true”. See docs/UPGRADING.md. CAVEAT: “true” gives TLS WITHOUT certificate verification - the client passes rejectUnauthorized: false (see database/client.ts), so it defeats a passive listener but not an active MITM. Verifying the chain needs a CA bundle this configuration does not take yet.
POSTGRES_CONNECT_RETRIES- (example: 60)Boot-time DB readiness gate (migrate step waits for the DB before migrating). Covers the Aurora-writer warm-up on a fresh deploy. Defaults: 60 retries × 2000ms.
POSTGRES_CONNECT_RETRY_DELAY_MS- (example: 2000)-
POSTGRES_POOL_MAX-Connection pools. The main pool serves the message pipeline, the API and the jobs (10 is postgres.js’s own default). Analytics and dashboard reads get a separate, smaller pool, so heavy aggregates queue among themselves instead of taking the connections a conversation turn waits for; each statement on it is capped at the timeout below (milliseconds).
POSTGRES_ANALYTICS_POOL_MAX--
POSTGRES_ANALYTICS_STATEMENT_TIMEOUT_MS--

HTTP Server (NestJS)

VariableDefaultDescription
API_PORT4000-

Encryption

VariableDefaultDescription
ENCRYPTION_KEY-32-byte hex-encoded key for AES-256-GCM encryption of instance secrets. Generate with: node -e “console.log(require(‘crypto’).randomBytes(32).toString(‘hex’))“

Authentication

VariableDefaultDescription
AUTH_SECRET-Shared secret between engine and web for JWT verification (Auth.js JWE). Must be identical in both packages. Generate with: openssl rand -hex 32
AUTH_TRUST_HOSTtrueAuth.js host trust. Required for any self-hosted deployment - including local development on http://localhost  - and when running behind a reverse proxy (Render, Railway, nginx, etc.). Leave at true unless you run on a platform (e.g. Vercel) that sets the host automatically. Used by the web package, so it must also be present in packages/web/.env.local.

Google OAuth (web only)

VariableDefaultDescription
GOOGLE_CLIENT_ID-Create credentials at https://console.cloud.google.com  → APIs & Services → Credentials
GOOGLE_CLIENT_SECRET--
AUTH_MODEsessionAuth source for the engine’s global AuthGuard. session (default) - Auth.js JWT (cookie/Bearer) + per-instance API key. session is the only value that boots. alb-oidc is REFUSED at startup (config.ts exits): a gateway-forwarded identity carries no organization and holds no role bindings, so it was denied on every management route - a mode that only worked under a condition nobody declared. Re-enabling it means mapping the gateway identity onto a local user, not deleting the check.
AUTH_ALB_PLATFORM_ADMIN_GROUP- (example: polyant-platform-admins)In alb-oidc mode, members of this Cognito group receive the platform_admin role. Change this sample value to the group configured in your identity provider.
REMOVE_AUTHORIZATION_FILTER_FOR_TESTING- (example: true)RBAC PermissionGuard. Always ENFORCED here: undeclared routes and failed permission checks are denied with 403. There is no variable to turn that off in production - NODE_ENV=production ignores the escape hatch below. REMOVE_AUTHORIZATION_FILTER_FOR_TESTING=true drops the guard to SHADOW mode (every would-be denial logged as [authz] shadow: would deny …, nothing denied) and works ONLY outside production. It is a local-debugging aid: with it set every @RequirePermission is a no-op and cross-organization isolation is off, so any authenticated user reaches the whole management plane. NOTE: this deployment does NOT read AUTHZ_ENFORCE - that is the OSS knob for the same posture. Setting it here does nothing, which has already sent someone down the wrong path while diagnosing a 403.
CORS_ORIGINS-Comma-separated list of origins allowed to call the engine API (CORS). Leave empty in development if engine and web run on the same origin (rewrites). In production, set this to the public origin of your web app. Example: CORS_ORIGINS=https://app.example.com,https://admin.example.com  A credentialed wildcard (*) is refused at startup - list explicit origins.

Reverse proxy

VariableDefaultDescription
TRUST_PROXY0Number of trusted proxy hops between the engine and the public internet (e.g. set to 1 if a single reverse proxy like Render/Railway/nginx sits in front of the engine). Controls whether X-Forwarded-Host / X-Forwarded-Proto headers are honored when reconstructing the request URL for the Twilio webhook signature check. Accepts an integer hop count or true/false. Leave at 0 (default) if the engine is exposed directly - otherwise attackers could spoof Host/Proto and bypass the Twilio HMAC. It also decides the client address rate limiting sees: behind a proxy left at 0, every request comes from the proxy’s address and shares its limits. For the URL, it matters for a WhatsApp channel in authToken mode, whose inbound authentication is the Twilio HMAC over the reconstructed URL. A channel in apiKey mode is gated by a secret in the webhook path, which no forwarded header can influence.

API rate limiting (@nestjs/throttler)

VariableDefaultDescription
THROTTLE_ENABLED- (example: false)Per-IP throttling on the HTTP API, and the only part of it that is a variable: whether it runs at all. Only the literal false disables ALL throttling - the global default and every per-route @Throttle override - which is what parallel dev/eval runs firing from one IP want. Default on. The WINDOW and the LIMIT are platform policies, edited at Admin Console → Installation policies, so a limit that turns out to be too tight is a form rather than a redeploy. They are not here on purpose: a rate limiter that could be turned off from inside the product is no use to a locked-out administrator.

Web → Engine URL

VariableDefaultDescription
NEXT_PUBLIC_API_URLhttp://localhost:4000URL the Next.js frontend uses to reach the engine API (server-side rewrites).
INTERNAL_ENGINE_URLhttp://localhost:4000Internal URL the web’s Credentials provider uses to call the engine’s /api/auth/credentials/verify endpoint (server-side only). Defaults to http://localhost:4000 . In production, point this at the engine’s internal address (e.g. http://engine:4000  inside a private network).

Auth

VariableDefaultDescription
AUTH_INTERNAL_SECRET- (example: replace-with-a-generated-credentials-secret)Shared secret used by the web’s Credentials provider to call the engine’s /api/auth/credentials/verify endpoint. Must be identical in engine and web .env files. Leave this optional setting unset to disable email/password login. Generate with: node -e “console.log(require(‘crypto’).randomBytes(48).toString(‘base64url’))“
INITIAL_ADMIN_EMAIL- (example: [email protected])Initial admin user - created on first boot if the users table is empty. INITIAL_ADMIN_PASSWORD is REQUIRED to seed the admin: if unset, seeding is skipped (no auto-generation) to avoid writing the secret to the engine logs. INITIAL_ADMIN_EMAIL is optional (defaults to administrator@local); set on a non-empty database it also creates or unlocks that account as platform admin.
INITIAL_ADMIN_PASSWORD- (example: choose-a-strong-password)-

External plugins

VariableDefaultDescription
PLUGIN_DIRS-Comma-separated absolute paths scanned for external plugins in addition to the built-in plugin directory. Leave empty unless self-hosting and loading a local plugin. Example: /opt/polyant/plugins,/srv/acme-plugin
PLUGIN_MARKETPLACE_OFFICIAL_ENABLED- (example: true)Plugin marketplaces. The official Exelab marketplace is on by default and its signing keys ship with the engine; set these only to point a deployment at a different official origin, rotate keys ahead of a release, or switch it off. Other marketplaces (signed or not) are added at runtime by a Platform Admin in Platform → Plugins. Every origin must use HTTPS.
PLUGIN_MARKETPLACE_ORIGIN- (example: https://marketplace.polyant.ai)-
PLUGIN_MARKETPLACE_TRUSTED_KEYS_JSON- (example: [{"keyId":"exelab-2026-10","publicKey":"-----BEGIN PUBLIC KEY-----\\n...\\n-----END PUBLIC KEY-----"}])-
PLUGIN_MARKETPLACE_ALLOW_LOOPBACK_HTTP- (example: false)Plain HTTP to a loopback host (localhost, 127.x, [::1]) for local fixtures and tests. Refused at boot when NODE_ENV=production.
PLUGIN_MARKETPLACE_ALLOW_UNSIGNED- (example: false)Whether a Platform Admin may add a marketplace without signature checks. Defaults to false in production and true elsewhere; an existing unsigned marketplace is not read while this is false.
PLUGIN_MATERIALIZATION_ROOT- (example: /tmp/polyant-plugins)Downloaded bundles are verified and extracted here (created owner-only); the directory is ephemeral runtime state and can be rebuilt from PostgreSQL desired state after restart.
PLUGIN_CATALOG_POLL_MS300000-
PLUGIN_MAX_WORKERS8-
PLUGIN_WORKER_IDLE_MS300000-
PLUGIN_WORKER_HEAP_MB128-
PLUGIN_WORKER_LOAD_TIMEOUT_MS15000A plugin module that has not finished importing by then fails and its worker is terminated.
PLUGIN_CALL_TIMEOUT_MS60000Deadline of a plugin tool call; a hook call uses the hook’s own timeout.
PLUGIN_ABORT_GRACE_MS5000An aborted call still running after this is treated as stuck: its worker is terminated and the call counts towards the plugin’s circuit.
PLUGIN_CIRCUIT_FAILURES3-
PLUGIN_CIRCUIT_WINDOW_MS300000-
PLUGIN_CIRCUIT_COOLDOWN_MS60000-
PLUGIN_MAX_COMPRESSED_BYTES26214400-
PLUGIN_MAX_EXPANDED_BYTES104857600-
PLUGIN_MAX_FILES2000-
PLUGIN_SYNC_RPC_BYTES1048576-

Panel build (packages/web, build time)

VariableDefaultDescription
NEXT_PUBLIC_APP_VERSION-Next reads .env only from packages/web/, never this file: these belong in packages/web/.env.local (or the build environment), and they are baked into the bundle at build time - changing one needs a rebuild, not a restart. - NEXT_PUBLIC_APP_VERSION: version shown in the panel’s About. Defaults to the version in packages/web/package.json. - NEXT_PUBLIC_APP_REVISION: commit shown beside it. Falls back to GITHUB_SHA (set by GitHub Actions), then to empty. Dockerfile.web takes it as a build argument.
NEXT_PUBLIC_APP_REVISION--

Logging verbosity

VariableDefaultDescription
LOG_LEVELinfoControls how much the structured/pipeline loggers emit (console + daily log files at logs/engine-YYYY-MM-DD.log under the Polyant project root, or /app/logs/engine-YYYY-MM-DD.log in Docker). One of: debug | info | warn | error | silent. Default: info. - debug: verbose per-step pipeline tracing (LLM call lines, tool-call args, system-prompt length, context load) on top of info - info: high-value skeleton - request, LLM token/latency, tool results, supervisor + response timing - warn: suppress info-level lines, keep warnings + errors - error: errors only - silent: disable all structured logging Note: the full system prompt is never logged here. Full-payload inspection is the per-instance debug_enabled flag, which persists the prompt, the messages and the tool definitions for analysis instead of dumping them to stdout.
LOG_LEVEL_TAG_PREFIX- (example: EXELAB)Prefix on the level tag every log record carries (_DEBUG, _INFO, _WARN, _ERROR). It exists so a log aggregator can isolate this engine’s records from the noise of NestJS and the AWS SDK, which keep their own level names. Letters, digits and underscore, up to 32 chars; defaults to EXELAB.
VOICE_DEBUG_TIMELINE- (example: true)Telephone voice channel: every call’s timeline event and per-turn line in the log (names, timings and counts, never words), for following a call step by step. Call start/end, failures and refusals are logged without it.
VOICE_SHUTDOWN_DRAIN_MS- (example: 15000)On shutdown, how long phone calls in progress may continue before they are ended (milliseconds, 0-110000, default 15000); new calls are refused meanwhile. Keep it plus the 10 s HTTP grace period under the container’s stop timeout.

Base URL

VariableDefaultDescription
BASE_URLhttp://localhost:4000Public base URL of the engine: the origin an external service must use to reach it, and what every webhook URL, OAuth redirect and agent card is built from. This is the BOOTSTRAP value. A platform admin can set the public address at Admin Console → Installation policies and that wins, which is how a wrong address is corrected without a redeploy. It cannot be derived from the incoming request: the panel reaches the engine through its own rewrite, so the host on that request is the internal one, and an OAuth redirect URI that varied per request would never match the one registered with the provider.

Retired variables and where they are set now

The engine no longer reads these. A deployment that still sets one keeps booting, the engine logs a warning at boot naming where the value is set now, and the value has no effect. Before removing a variable you had set to something other than its default, enter the same value in its new place. See Upgrading.

VariableWhere the value is set now
DATETIME_TIMEZONE, DATETIME_LOCALEThe agent’s Advanced → Behaviour overrides. A deployment-wide time zone is TZ.
DEDUP_SIMILARITY_THRESHOLDThe agent’s Advanced → Behaviour overrides (Memory dedup threshold, default 0.90).
MESSAGE_SOFT_DEBOUNCE_MS, MESSAGE_TYPING_DELAY_MS, MESSAGE_MAX_RESTARTSThe agent’s Advanced → Behaviour overrides (defaults 2000 ms, 1500 ms and 3).
KNOWLEDGE_MAX_DOCS_PER_INSTANCEThe organization’s knowledge-document cap, default 500 per agent. The managed-services build sets it in the database column organizations.knowledge_max_docs_per_agent; there is no console field yet.
ANALYTICS_RETENTION_DAYS, SSE_MAX_CONNECTIONS, SSE_MAX_CONNECTIONS_PER_USER, THROTTLE_TTL_MS, THROTTLE_LIMIT, AGENT_CALL_TIMEOUT_MS, MCP_CONNECT_TIMEOUT_MS, SCHEDULER_ORPHAN_GRACE_MS, SCHEDULER_DEFAULT_MAX_RUN_MSInstallation policies, with the same defaults. THROTTLE_ENABLED stays an environment variable.
CONVERSATION_LIST_TIMEOUT_MSInstallation policies (managed services).
SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASSWORD, MAIL_FROM, PANEL_URLThe mailer in Installation policies (managed services). The old values are not read as a fallback.
AUTH_ALLOWED_DOMAIN, AUTH_ALLOWED_DOMAINSEach organization’s SSO domains (managed services).
DEFAULT_ORG_NAMEThe organization’s name, edited in the console (managed services).
RETENTION_DEFAULT_DAYSEach retention policy states its own window (managed services).
PLATFORM_S3_BUCKET, PLATFORM_S3_REGION, PLATFORM_S3_ACCESS_KEY_ID, PLATFORM_S3_SECRET_ACCESS_KEYEach agent’s own storage secrets. See Attachment storage.
AWS_REGIONNo longer a Polyant fallback. Set the AWS region on each agent, or on its organization (managed services). The AWS SDK may still read the variable for its own purposes.
PLATFORM_ADMIN_EMAILNothing. The first platform admin is the account INITIAL_ADMIN_EMAIL names; promote others from Platform members.
DEBUG_LLM_PAYLOADThe agent’s own debug capture.
LANGSMITH_API_KEY, LANGSMITH_PROJECT, LANGSMITH_TRACINGNothing: tracing is configured per agent.
DEFAULT_INSTANCE_ID, WORKSPACES_ROOTNothing.
PDF_CONCURRENCYThe Markdown-to-PDF plugin’s own configuration.
Last updated on