Skip to main content

Component configuration

All control plane settings use the EAI_ prefix and are defined in services/control-plane/src/eai/config.py or read by an integration adapter (see platform-integration.md). Non secret values live in controlPlane.config (ConfigMap); secrets in OpenBao kv/eai/<env>/<service>. Lists (EAI_CORS_ORIGINS) are written as JSON.

ComponentFileKey points
Control Planedeploy/helm/enterprise-ai/values.yaml (controlPlane)EAI_AUTH_DEV=0 in prod, EAI_AUTH_SPIFFE=1, integration URLs (EAI_OPENBAO_URL, EAI_TEMPORAL_URL, ...), pre-upgrade migration job, GET /metrics scraped by the ServiceMonitor
Background workervalues.yaml (worker)python -m eai.worker, one replica, same image, ConfigMap and secrets as the API, dedicated NetworkPolicy
Portalvalues.yaml (portal)NEXT_PUBLIC_EAI_API_URL, public OIDC client portal (PKCE S256)
LiteLLMdeploy/litellm/config.example.yaml, litellm.configkeys through os.environ/..., router fallbacks; generated in prod by GET /v1/litellm/config and POST /v1/litellm/sync
vLLMvllm.modelsone entry per model: gpus, args, minReplicas/maxReplicas, KEDA threshold
Multimodal workersworkers.itemsSTT/TTS/video, KEDA nats-jetstream on consumer lag (stream and consumer passed as arguments)
Keycloakdeploy/keycloak/realm-enterprise-ai.jsonclients portal (PKCE S256), control-plane (bearer, audience), cli (device flow), realm roles, sub, tenant, clearance, roles claims
OpenFGAdeploy/policies/openfga/model.fgaowner, editor, viewer, can_use, member on every type, objects prefixed by the tenant
OPAdeploy/policies/opaeai.model_invocation, eai.tool_invocation, eai.gateway_access, eai.data_access, eai.agent_autonomy on the Policy Contract input, kill switch and thresholds in data.json
Kyvernodeploy/policies/kyverno/cluster-policies.yamlcosign signatures, non-root, read-only rootfs, limits, no latest, sandbox RuntimeClass, tenant/owner labels
SPIREdeploy/spiretrust domain enterprise-ai.internal, k8s_psat, OpenBao UpstreamAuthority
OpenBaodeploy/openbaoHCL policies per service (kv/data/tenants/*, transit keys tenant-<uuid>), kubernetes auth roles
cert-managerdeploy/cert-managerinternal CA, OpenBao PKI issuer, ACME for the gateway
Ciliumdeploy/ciliumdefault deny, FQDN egress per provider (label eai.io/provider-<name>=enabled on LiteLLM)
APISIXdeploy/apisix/apisix.yaml/v1 routes, OIDC, Redis rate limits, strips X-Dev-* and X-SPIFFE-ID; /metrics not published
KEDAdeploy/kedaLiteLLM, agent workers
Observabilitydeploy/observabilityOTel PII filtering, SLO and cost rules on the eai_* metrics, OpenSearch logs and SIEM, Jaeger traces, Opik AI traces; no dashboard server (Navin Manager and portal, ADR-0169)
PostgreSQLdeploy/data/postgres/cluster.yamlCNPG 3 instances, zone anti-affinity, WAL to S3
Velerodeploy/velero/schedules.yamldaily + hourly, PostgreSQL, Qdrant, OpenBao hooks
Wazuhdeploy/wazuhaudit JSON decoder, rules 100800-100808

Enabling an external provider​

  1. Store the key: bao kv put kv/eai/prod/providers/openai OPENAI_API_KEY=....
  2. Add it to litellm.secrets.keys and the model to the generated config.
  3. Label LiteLLM pods eai.io/provider-openai=enabled to open FQDN egress.
  4. Allow provider, model and region in the tenant policy (OPA eai.model_invocation, overrides in data.eai.config.tenants.<uuid>.model_invocation).

Monitoring​

SIEM, mutation audit, signed WORM export and erasure in Opik and ClickHouse: see siem-audit.md (EAI_SIEM_*, EAI_AUDIT_SIGNING, EAI_AUDIT_WORM_RETENTION_DAYS).

VariableDefaultPurpose
EAI_OPIK_URLemptyOpik backend (AI traces, OTLP /v1/private/otel, erasure and retention through the REST API). In prod: https, or plain http to a *.svc Service only, never credentials in the URL (startup refused otherwise)
EAI_OPIK_UI_URLemptyOpik frontend for the trace links of GET /v1/telemetry/traces/{id}; https required in prod
EAI_GRAFANA_URLemptyGrafana console run by the client (bring your own, never deployed by the platform because of its AGPL licence, ADR-0101), deep link of the portal operations space (GET /v1/platform-manager/console); https without credentials, otherwise the link is not shown
EAI_KEYCLOAK_CONSOLE_URLemptyKeycloak administration console, deep link of the portal; https without credentials
EAI_LITELLM_UI_URLemptyLiteLLM proxy administration UI, deep link of the portal; https without credentials
EAI_OPENSEARCH_DASHBOARDS_URLemptyOpenSearch Dashboards, deep link of the portal; https without credentials
EAI_PLATFORM_MANAGER_CONSOLE_URLempty (then EAI_PLATFORM_MANAGER_URL)Platform Manager console targeted by the deep links of the Platform Manager space (ADR-0162)
EAI_OPIK_WORKSPACEdefaultOpik workspace (Comet-Workspace header)
EAI_OPIK_PROJECTeai-platformOpik project of the platform spans
EAI_OPIK_API_KEYemptyAPI key, only when the Opik deployment authenticates its API (OpenBao secret)
EAI_METRICS_TOKENemptybearer token of GET /metrics, required outside dev and test (32 characters minimum)
EAI_WORKER_METRICS_PORT9464metrics port of python -m eai.worker (0 disables)
EAI_MEDIA_WORKER_METRICS_PORT9465metrics port of python -m eai.media_worker (0 disables)
EAI_WORKER_GAUGES_INTERVAL_SECONDS30interval of the gauges job (global gauges computed from the database)
EAI_WORKER_VERIFY_CHAIN_INTERVAL_SECONDS3600interval of the verify_chain job (audit chain of every tenant)

Traces and logs:

VariableRole
EAI_OTEL_ENABLEDEnables OpenTelemetry traces. A missing OpenTelemetry package refuses the API start.
EAI_SLO_AVAILABILITY_TARGETSAvailability target per service, comma separated service=value, values in [0.5, 1). Default control_plane_api=0.995,model_gateway=0.995,tool_gateway=0.995,realtime=0.995. An invalid value is refused at production startup.
EAI_SLO_LATENCY_TARGETS_SECONDSLatency threshold per service in seconds, in (0, 300]. Default 1 for every service.
EAI_SLO_LATENCY_OBJECTIVEShare of requests that must stay under the latency threshold, in [0.5, 1). Default 0.95.
EAI_SLO_RETENTION_MINUTESHow long each replica keeps its in memory measurements for GET /v1/telemetry/slo, between 60 and 10080. Default 1440.
EAI_TELEMETRY_SPAN_MAX_DAYSLongest retention of the span summaries (eai.telemetry_spans, ADR-0157) for every tenant, applied by the retention worker job, between 1 and 3650 days. The telemetry retention policy of a tenant can be shorter. Default 90.
EAI_OTEL_EXPORTER_OTLP_ENDPOINTOTLP/HTTP collector, port 4318 (/v1/traces is appended).
EAI_OTEL_EXPORTER_OTLP_CERTIFICATEInternal CA of an https collector (defaults to SSL_CERT_FILE).
EAI_LOG_LEVELDEBUG, INFO, WARNING, ERROR or CRITICAL; JSON logs on stdout with trace_id, span_id and request_id.

The AI path clients (LiteLLM, vLLM, multimodal adapters, collector) only reach the hosts declared in the EAI_*_URL and EAI_*_ENDPOINT settings.

See Monitoring and alerting.

LiteLLM gateway, model versions and isolation​

SettingRole
EAI_LITELLM_URLAddress of the LiteLLM OSS proxy (1.106.5); empty, the gateway calls the providers itself.
EAI_LITELLM_MASTER_KEYProxy master key, injected from OpenBao, never exposed to agents.
EAI_LITELLM_VENVTest tooling only: venv of the real proxy created by bash tools/litellm/setup.sh (default /tmp/toolchains/litellm-venv). Without it tests/test_llm_litellm_proxy_real.py fails with a clear message.

The isolated mode (local_only, air_gapped) is not an environment variable: it is set per tenant or per project with PUT /v1/llm/isolation and refuses every external route before any outbound call. Model versions, their progressive rollout and the rollback are driven by the API (see B-04); no setting activates a model without an approval.

RAG and embeddings​

SettingDefaultPurpose
EAI_RAG_EMBEDDING_MODELlocal-hash-256registry embedding model (capability embeddings) of a new knowledge base; bge-m3-vllm in prod (values-prod.yaml, values-onprem-gpu.yaml)
EAI_MEMORY_EMBEDDING_MODELlocal-hash-256embedding model of the agent memory; after a change the worker re-embeds the items
EAI_RAG_RERANK_MODELemptyrerank model (capability rerank) used by rerank: true without rerank_model
EAI_PADDLEOCR_URLemptyPaddleOCR serving endpoint (POST /ocr) for scans; otherwise Docling, otherwise tesseract
EAI_EMBEDDINGS_BATCH_SIZE64texts per Model Gateway call (ingestion, reindex)
EAI_QDRANT_SHARD_NUMBER, EAI_QDRANT_REPLICATION_FACTOR, EAI_QDRANT_WRITE_CONSISTENCY_FACTORempty (Qdrant defaults)shards, replicas per shard and write acknowledgements of every new Qdrant collection; 3, 2 and 1 on the 3 node Qdrant cluster (values.yaml, values-prod.yaml): losing one node loses no vector
EAI_WORKER_EMBEDDINGS_REINDEX_INTERVAL_SECONDS60interval of the embeddings_reindex job (knowledge base reindex, memory re-embedding)

Every embedding goes through the Model Gateway with the controls of the chosen model; EAI_EMBEDDINGS_URL no longer exists. local-hash-256 is a hashing of words, not a semantic model: it is accepted in dev and test only. In prod the startup refuses it for EAI_RAG_EMBEDDING_MODEL and EAI_MEMORY_EMBEDDING_MODEL, and outside dev and test creating a knowledge base with it returns 422 embedding_model_invalid.

Realtime and streaming DLP​

SettingDefaultPurpose
EAI_REALTIME_WS_TOKEN_TTL_SECONDS300Lifetime of a single use ws_token
EAI_REALTIME_WS_MAX_MESSAGE_BYTES1048576Maximum WebSocket message size (uvicorn ws_max_size and handler check, close 1009)
EAI_REALTIME_WS_MAX_EVENTS_PER_SECOND50Sustained client event rate (close 4429)
EAI_REALTIME_WS_BURST100Burst allowed above the rate
EAI_REALTIME_WS_MAX_SESSION_SECONDS3600Maximum connection duration (close 4408)
EAI_REALTIME_WS_IDLE_TIMEOUT_SECONDS120Idle timeout (close 4408)
EAI_REALTIME_CONSENT_REQUIREDunset (required outside dev and test)Realtime transcription refused without an active participant consent (consent_required); false is refused at production startup. Recording always needs consent
EAI_VAD_URLunsetHTTP voice worker (route /vad, Silero VAD) called by the http-vad adapter through the egress guard
EAI_SILERO_VAD_MODELunsetSilero VAD (MIT) ONNX file for the in process silero-onnx adapter (onnxruntime)
EAI_KOKORO_MODEL, EAI_KOKORO_VOICES, EAI_KOKORO_VOICEunset, af_heartKokoro v1.0 files (Apache-2.0 weights) of the reference TTS adapter kokoro (kokoro-onnx)
EAI_STREAM_DLP_HOLDBACK_CHARS128Characters held back by the sliding streaming DLP buffer

Redis (cache and coordination)​

See redis.md. Redis is only a cache and a coordination aid: permissions, suspensions, quotas and evidence are always read from PostgreSQL.

SettingDefaultPurpose
EAI_REDIS_URLemptyrediss://host:port/0 (TLS). Empty: in-memory rate limit counters, per replica. In prod the startup refuses redis:// without TLS
EAI_REDIS_USERNAMEemptyRedis ACL user
EAI_REDIS_PASSWORD_FILEemptyFile holding the ACL password (never the password itself). Required in prod when EAI_REDIS_URL is set
EAI_REDIS_TLS_CA_FILEemptyCA bundle verifying the rediss:// server certificate

Licences​

See licensing.md. None of these settings limits users, agents, applications, use cases or plugins.

SettingDefaultPurpose
EAI_LICENSE_PUBLIC_KEYSemptyPublisher Ed25519 public keys, comma separated kid:x (several for a rotation). In prod the startup refuses a malformed value, a duplicate kid or a test-* kid
EAI_LICENSE_EXPIRING_SOON_DAYS30Days before valid_until when the state becomes expiring_soon (1 to 365, checked at startup in prod)
EAI_LICENSE_WARNING_DAYS30,7,1Warning thresholds of the license_check job (days before valid_until)
EAI_WORKER_LICENSE_CHECK_SECONDS3600Interval of the license_check worker job

Context Authority, delegations, mandates and break glass​

See ../../security/en/identity-context-delegation.md. The private key of the Context Authority is never logged, never returned and never stored in the database: only its public key (JWK) is registered.

SettingDefaultPurpose
EAI_CONTEXT_SIGNING_KEY_REFemptyOpenBao reference of the private key, openbao:<kv path>#<field> (Ed25519 or ECDSA P-256 PEM). Required in prod; changing the key is a rotation (the previous one still verifies for EAI_CONTEXT_MAX_TTL_SECONDS)
EAI_CONTEXT_SIGNING_KEYemptyPEM key in the environment, dev and test only: refused at startup in prod
EAI_CONTEXT_ISSUERurn:eai:context-authorityIssuer (iss) of signed contexts, checked by every verify
EAI_CONTEXT_AUDIENCESeai-control-planeAccepted audiences, comma separated; the first one is the default audience
EAI_CONTEXT_TTL_SECONDS900Default lifetime of a context
EAI_CONTEXT_MAX_TTL_SECONDS3600Maximum lifetime of a context and verification window of a retired key
EAI_CONTEXT_LEEWAY_SECONDS30Clock tolerance on iat and exp
EAI_CONTEXT_REQUIRED0Every run gets a signed context; without a key the run is refused (503). Must be 1 in prod (checked at startup)
EAI_DELEGATION_DEFAULT_TTL_SECONDS28800Lifetime of the implicit delegation of a run
EAI_DELEGATION_MAX_TTL_SECONDS86400Maximum lifetime of a delegation
EAI_MANDATE_MAX_TTL_DAYS365Maximum lifetime of a scheduled agent mandate
EAI_BREAK_GLASS_MAX_SECONDS3600Maximum duration of a break glass grant
EAI_WORKLOAD_SERVICE_IDeai-control-planeTechnical identity of this workload carried by runs
EAI_WORKLOAD_SPIFFE_IDemptySPIFFE ID of this workload when SPIRE issues one

SOC, AI-SDR and Kill Switch​

See ../../security/en/soc-runbook.md. The proportionality guard limits (confidence, blast radius, reactions needing an approval) live in deploy/policies/opa/data.json (soc_response), not in settings.

SettingDefaultPurpose
EAI_SOC_WEBHOOK_SECRETemptyHMAC secret of POST /v1/soc/webhooks/{source} (Falco, Tetragon, OpenSearch) and POST /v1/soc/receipts (empty: every delivery refused with 401). 32 characters minimum in prod (checked at startup)
EAI_SOC_CORRELATION_WINDOW_SECONDS900Window of the event correlator (same user, agent or tenant); 60 to 86400, checked at startup in prod
EAI_WORKER_SOC_SCAN_SECONDS30Interval of the soc_scan worker job (audit chain to detections, policy baselines)
EAI_WORKER_SOC_VERIFY_SECONDS120Interval of the soc_verify worker job (Containment Verifier, receipts, drift re-applied)
EAI_MCP_RUNTIME_REAPER_SECONDS60Interval of the MCP Runtime controller loop, in the API pods (sleep, failures, probes, cleanups)
EAI_MCP_INTERNAL_HOSTSemptyInternal hosts of the MCP servers the gateway may call (host, host:port, *.suffix, CIDR); every public host is refused
EAI_MCP_CATALOG_STORAGE_PROFILEemptyPlatform storage profile (SeaweedFS) of the company MCP catalogue; required in production
EAI_MCP_CATALOG_KEYmcp-runtime/templates.yamlObject key of the MCP catalogue in that profile
EAI_MCP_CATALOG_REFRESH_SECONDS300Refresh period of the MCP catalogue
EAI_MCP_RUNTIME_IMAGE_REGISTRIES<harbor-host>Internal registries a template image may come from
EAI_MCP_RUNTIME_WAKE_TIMEOUT_SECONDS90How long a call waits for a sleeping or recreated instance
EAI_MCP_RUNTIME_FAILURE_LIMIT3Failures within the window before the failed state (explicit start)
EAI_MCP_RUNTIME_FAILURE_WINDOW_SECONDS900Window in which the failures of an instance are counted
EAI_MCP_RUNTIME_HEALTH_TIMEOUT_SECONDS3.0Timeout of the GET /health probe of a ToolHive proxy
EAI_MCP_RUNTIME_OTEL_ENDPOINTotel-collector.observability.svc.cluster.local:4318OTLP/HTTP collector (TLS) of the ToolHive proxies, host:port without scheme
EAI_MCP_RUNTIME_OTEL_SAMPLING_RATE1.0Trace sampling of the ToolHive proxies
EAI_MCP_RUNTIME_OTEL_CA_FILE/etc/eai/ca/ca.crtInternal CA copied to every MCP Runtime namespace; required outside dev and test

Client object storage (brick E-13)​

See ../../en/guides/storage-administration.md. The client chooses its storage (AWS S3, Azure Blob, Google Cloud Storage, IBM COS, SeaweedFS or another S3 compatible service) with a storage profile; secrets stay in OpenBao (tenant profiles) or in EAI_CRED_<NAME> variables (platform profiles), never in the profile. Private endpoints (on premises SeaweedFS or IBM COS appliance) must be listed in EAI_EGRESS_PRIVATE_ALLOWLIST.

SettingDefaultPurpose
EAI_AUDIT_WORM_STORAGE_PROFILEemptyName of the platform profile that receives the WORM audit exports of the tenants without an audit_worm profile; empty: legacy EAI_S3_* store (manifest worm.qualified: false)
EAI_STORAGE_CA_BUNDLEemptyPEM file of the certificate authority of an on premises endpoint; TLS verification stays on. In prod an unreadable file is refused at startup
EAI_STORAGE_REQUEST_TIMEOUT_SECONDS30Timeout of a storage call (connection capped at 5 s)
EAI_STORAGE_PRESIGN_MAX_SECONDS3600Longest presigned URL issued; 1 to 86400, checked at startup in prod (a presigned URL is a bearer credential)
EAI_STORAGE_CAPABILITY_MAX_AGE_SECONDS86400Maximum age of a capability verification; older, the usage is refused (409 storage_capability_missing, reason stale) until the profile is verified again; 60 to 604800, checked at startup in prod

Outside the dev and test environments, storage endpoints, token endpoints (IBM IAM, Microsoft Entra ID, Google OAuth2) and presigned URLs must be https (422 storage_tls_required).

gVisor sandbox​

VariableDefaultPurpose
EAI_SANDBOX_RUNSC/tmp/toolchains/runscrunsc (gVisor) binary for untrusted tool code; when missing or unusable the code is refused (fail closed)

Audit Gateway and Evidence Service (kit section 11)​

See siem-audit.md. The prod startup checks refuse a missing EAI_AUDIT_SEAL_SIGNING_KEY_REF and any EAI_AUDIT_PAYLOAD_KEK other than openbao-transit.

VariableDefaultPurpose
EAI_AUDIT_GATEWAY_HTTP_URLemptySIEM HTTP collector: one POST per event, Idempotency-Key header equal to the event id, through the operator egress client
EAI_AUDIT_GATEWAY_NATS_SUBJECTaudit.eventsJetStream subject eai.<tenant>.<subject> (when EAI_NATS_URL is set), Nats-Msg-Id header for dedup
EAI_AUDIT_GATEWAY_NATS_STREAMEAI_AUDITJetStream stream created when missing (subjects eai.*.audit.>)
EAI_AUDIT_GATEWAY_BATCH500Outbox rows handled per tenant and per run
EAI_AUDIT_GATEWAY_MAX_ATTEMPTS12After that the row stays pending and an outbox_missing integrity alert is opened
EAI_AUDIT_GATEWAY_BACKOFF_SECONDS2.0Base of the exponential backoff (base × 2^(attempts-1), capped at 900 s)
EAI_WORKER_AUDIT_GATEWAY_SECONDS10Period of the audit_gateway job
EAI_AUDIT_SEAL_SIGNING_KEY_REFemptyOpenBao reference openbao:<kv path>#<field> of the Ed25519 seal private key (required in prod)
EAI_AUDIT_SEAL_SIGNING_KEYemptyPlain Ed25519 PEM key, dev and test only
EAI_WORKER_AUDIT_SEAL_SECONDS300Period of the audit_seal job
EAI_AUDIT_SEAL_MAX_EVENTS10000Most events per seal
EAI_WORKER_AUDIT_INTEGRITY_SECONDS900Period of the audit_integrity job (chains, seals, signatures, timestamps, outbox coverage)
EAI_AUDIT_CLOCK_SKEW_SECONDS300Largest accepted lead of event_time over the database clock; 0 to 3600, checked at startup in prod
EAI_AUDIT_PAYLOAD_KEKemptyKey encryption key of the sensitive payloads: openbao-transit (prod) or a base64 32 byte key (dev and test); empty: sensitive payloads are refused
EAI_AUDIT_PAYLOAD_RETENTION_DAYS365Age after which the audit_retention job purges encrypted payloads outside legal holds
EAI_WORKER_AUDIT_RETENTION_SECONDS86400Period of the audit_retention job
EAI_OPA_DELIVERYpushpush: engine=opa policies are pushed to OPA on write; bundle: OPA loads the signed bundles published by POST /v1/policies/bundles (prod: signing key required)
EAI_POLICY_BUNDLE_SIGNING_KEY_FILEemptyPEM file of the RSA private key signing the bundles (RS256); required with EAI_OPA_DELIVERY=bundle, publication refused in prod without it
EAI_POLICY_BUNDLE_KEY_IDeai-policykeyid of the signatures, same as the keys entry of the OPA configuration
EAI_KMS_PROVIDERnoneKey management eai.crypto.kms: openbao (Transit), pkcs11 (client HSM) or none
EAI_KMS_PKCS11_MODULEemptyPath of the PKCS#11 library provided by the client (required with pkcs11)
EAI_KMS_PKCS11_TOKEN_LABELemptyHSM token label (required with pkcs11)
EAI_KMS_PKCS11_PIN_FILEemptyMounted file holding the user PIN, never the PIN in the environment (required with pkcs11)