Skip to main content

Configuration file reference

All configuration files for uxopian-ai are placed in the ./config/ directory on the host, mounted to /app/config inside the container. The application imports them at startup via application.yaml. This page documents every configuration key in every file.

application.yml

Controls the base URL, server port, Spring profiles, and tool settings.

KeyEnv variableDefaultDescription
app.base-urlAPP_BASE_URL(empty)Public base URL for the application (used in generated links)
server.portUXOPIAN_AI_PORT8080HTTP port uxopian-ai listens on
server.servlet.context-pathCONTEXT_PATH(empty)Optional servlet context path prefix
tools.enabledTOOLS_ENABLEDtrueSet to false to disable all tool execution
plugins.root.pathPLUGINS_ROOT_PATHplugins/Directory scanned at startup for plugin JARs
plugins.tools.enabled-tagsPLUGINS_TOOLS_ENABLED_TAGSflowerdocs,filesSince 2026.0.0-ft5, this no longer gates which tools get registered at startup — every @ToolService in every plugin JAR present in plugins/ is always registered. It now only seeds the default tool-tag whitelist on an auto-created Application (empty = allowAllTools). See Plugin system.
spring.profiles.activeSPRING_PROFILES_ACTIVE(empty)Active Spring profiles. Add dev to disable auth.

Example:

app:
base-url: ${APP_BASE_URL:}

server:
port: ${UXOPIAN_AI_PORT:8080}

tools:
enabled: ${TOOLS_ENABLED:true}

Gateway-signed request authentication

Since 2026.0.0-ft5, requests can carry a gateway-issued X-Gateway-Auth assertion instead of bare X-User-* headers. Verification is inactive until a secret is set (matches the gateway's own opt-in behavior — see gateway-application.yaml), but the official Helm chart makes the secret mandatory (the chart fails to render without appConfig.internalAuth.secret).

KeyEnv variableDefaultDescription
internal-auth.jwt.secretINTERNAL_AUTH_JWT_SECRET(empty, verification off)HS256 shared secret, at least 32 bytes, must be byte-for-byte identical to the gateway's own internal-auth.jwt.secret. Generate with openssl rand -base64 48.
internal-auth.jwt.issuerINTERNAL_AUTH_JWT_ISSUERuxopian-gateway-internalExpected iss claim on the incoming assertion.
internal-auth.jwt.clock-skew-secondsINTERNAL_AUTH_JWT_CLOCK_SKEW_SECONDS5Allowed clock drift when validating the assertion's expiry.

Rotating the secret requires rolling both services close together — expect 401 responses between the two rollouts until both are running the new value.

opensearch.yml

OpenSearch connection settings.

KeyEnv variableDefaultDescription
opensearch.hostOPENSEARCH_HOSTlocalhostOpenSearch host
opensearch.portOPENSEARCH_PORT9200OpenSearch port
opensearch.schemeOPENSEARCH_SCHEMEhttpConnection scheme (http or https)
opensearch.usernameOPENSEARCH_USERNAME(empty)Username for authenticated OpenSearch
opensearch.passwordOPENSEARCH_PASSWORD(empty)Password for authenticated OpenSearch
opensearch.force-refresh-indexOPENSEARCH_FORCE_REFRESH_INDEXfalseForce index refresh after each write (slow; for testing only)
opensearch.index-prefixOPENSEARCH_INDEX_PREFIXuxopian-aiPrefix used in index names: {tenant}-{prefix}-{base}

Example:

opensearch:
host: ${OPENSEARCH_HOST:localhost}
port: ${OPENSEARCH_PORT:9200}
scheme: ${OPENSEARCH_SCHEME:http}
username: ${OPENSEARCH_USERNAME:}
password: ${OPENSEARCH_PASSWORD:}
force-refresh-index: ${OPENSEARCH_FORCE_REFRESH_INDEX:false}

llm-clients-config.yml

LLM provider configurations, default provider/model, and context size.

Default LLM settings

KeyEnv variableDefaultDescription
llm.default.providerLLM_DEFAULT_PROVIDERopenaiDefault LLM provider identifier
llm.default.modelLLM_DEFAULT_MODELgpt-5.1Default model name
llm.default.base-promptLLM_DEFAULT_PROMPTbasePromptDefault base prompt ID
llm.contextLLM_CONTEXT_SIZE10Number of previous requests included in each LLM call
llm.debug.enabledLLM_DEBUGfalseEnable verbose LLM request/response logging

Provider configuration structure

llm:
provider:
globals:
- provider: <provider-id>
defaultLlmModelConfName: <model-conf-name>
globalConf:
apiSecret: <api-key>
endpointUrl: <provider-url>
temperature: <float>
timeout: <duration>
maxRetries: <int>
extras:
<provider-specific-key>: <value>
llModelConfs:
- llmModelConfName: <name>
modelName: <actual-model-name>
multiModalSupported: <bool>
functionCallSupported: <bool>

Supported provider identifiers

openai, anthropic, azure-openai, bedrock, gemini, mistral-ai, huggingface, ollama, nu-extract

Provider-specific extras

ProviderExtra keysDescription
bedrockAwsRegion, AwsAccessKey, AwsSessionTokenAWS credentials and region
nu-extractmodelIdModel ID override (defaults to modelName if absent)

Azure OpenAI (azure-openai) does not use extras. The modelName field is passed as the deployment name.

Tenant overrides

llm:
provider:
tenants:
- tenantId: <tenant-id>
mergeStrategy: MERGE # MERGE | OVERWRITE | CREATE_IF_MISSING
providers:
- provider: <provider-id>
globalConf:
apiSecret: <tenant-specific-key>

prompts.yml

Prompt template definitions.

note

Prompts live only as versioned documents in OpenSearch (see Managing prompts); base prompts are seeded once, at tenant creation, from prompts.globals below.

KeyDescription
prompts.globalsList of global prompt definitions (see structure below)

Prompt definition structure

- id: <unique-id>
role: SYSTEM | USER | ASSISTANT
content: |
Thymeleaf template content...
[[${variable}]]
requiresMultiModalModel: false
requiresFunctionCallingModel: false
reasoningDisabled: false
defaultLlmProvider: "" # optional: override provider for this prompt
defaultLlmModel: "" # optional: override model for this prompt

metrics.yml

Micrometer metrics and actuator configuration.

KeyDescription
management.elastic.metrics.export.enabledEnable/disable OpenSearch metrics export (default: true)
management.elastic.metrics.export.hostOpenSearch URL for metrics. Default reads from opensearch.* properties.
management.elastic.metrics.export.indexIndex name for metrics (default: micrometer-metrics)
management.elastic.metrics.export.auto-create-indexAuto-create metrics index (default: true)
management.endpoints.web.exposure.includeExposed actuator endpoints. Default: health,info/actuator/loggers was removed from exposure in 2026.0.0-ft5, and management.endpoint.loggers.enabled is false as defense-in-depth. See Upgrade notes.
management.metrics.uxopian-ai.enableEnable custom uxopian-ai metrics (default: true)
management.metrics.enable.*Standard metric groups disabled by default: application, tomcat, logback, jvm, system, http, process, disk, executor

hazelcast.yml

Hazelcast cluster configuration. Used by the gateway for session caching.

KeyEnv variableDefaultDescription
hazelcast.cluster-nameuxopian-ai-clusterHazelcast cluster name
hazelcast.kubernetes.enabledHAZELCAST_KUBERNETES_ENABLEDfalseEnable Kubernetes service discovery
hazelcast.kubernetes.service-dnsHAZELCAST_KUBERNETES_SERVICE_DNSai-standalone-headlessKubernetes headless service DNS name
hazelcast.kubernetes.namespaceHAZELCAST_KUBERNETES_NAMESPACEdefaultKubernetes namespace for discovery

alfresco

Configuration for the Alfresco plugin. Since 2026.0.0-ft5, its tools are always registered when the JAR is present in plugins/; whether they're exposed to a given caller is controlled by that caller's Application tool/tag whitelist, not by plugins.tools.enabled-tags.

KeyEnv variableDefaultDescription
alfresco.base-urlALFRESCO_BASE_URL(empty)Alfresco REST API v1 base URL. Required when the plugin is enabled.
alfresco.legacy-base-urlALFRESCO_LEGACY_BASE_URL(auto-derived)Base URL for Alfresco legacy Web Script endpoints (/alfresco/s/…). Auto-derived from base-url when not set: if base-url contains /alfresco-api, it is replaced with /alfresco; if base-url ends with /api, the suffix becomes /s; otherwise /s is appended. Override only if the auto-derivation does not match your deployment layout.
alfresco.cmm-enabledALFRESCO_CMM_ENABLEDfalseEnable Alfresco Custom Content Model lookup. When disabled, the LLM sees only the fallback cm:* system properties.
alfresco.common-system-propertiescm:name, cm:title, cm:description, cm:created, cm:modified, cm:creator, cm:modifierList of system properties (name, label, description, indexable, allowed values) surfaced to the LLM when CMM is disabled. Override if your tenant uses a different default schema.

Example:

alfresco:
base-url: ${ALFRESCO_BASE_URL:}
# legacy-base-url is auto-derived from base-url — set only if the derivation is wrong
# legacy-base-url: ${ALFRESCO_LEGACY_BASE_URL:}
cmm-enabled: ${ALFRESCO_CMM_ENABLED:false}
# common-system-properties: (defaults shipped with the plugin)

See Integrate with Alfresco for deployment steps.

filenet

Configuration for the FileNet plugin. Since 2026.0.0-ft5, its tools are always registered when the JAR is present in plugins/; whether they're exposed to a given caller is controlled by that caller's Application tool/tag whitelist, not by plugins.tools.enabled-tags.

There is no object store setting: the object store is the tenant, resolved per request by the ICN plugin and carried in its JWT — see How the tenant is resolved.

KeyEnv variableDefaultDescription
filenet.ce-api-url(empty)Content Engine Web Services (CEWS) endpoint, e.g. http://<ce-host>:<port>/wsi/FNCEWS40MTOM/. Required when the plugin is enabled.
filenet.oidc-realmFILENET_OIDC_REALM(empty)Name of the OIDC/OAuth provider trust registered on the Content Platform Engine via ACCE. Every CE call is authenticated as the current caller (via OpenTokenCredentials), not a shared service account — see Integrate with FileNet. Required.
filenet.common-system-propertiesDocumentTitle, DateCreated, DateLastModified, Creator, LastModifier, MajorVersionNumber, MimeTypeList of properties (name, title, dataType, multiValued, allowedValues) surfaced to the LLM as the searchable/readable data model. Override if your object store uses a different default schema.
filenet.writable-properties(empty)List of properties (same structure as above) intended to be writable by the LLM. Configured but not yet wired to a callable tool — there is currently no LLM-callable way to update a FileNet document property.

Example:

filenet:
ce-api-url: ${FILENET_CE_API_URL:}
oidc-realm: ${FILENET_OIDC_REALM:}
# common-system-properties: (defaults shipped with the plugin)
# writable-properties:
# - name: DocumentTitle
# title: Document Title
# dataType: "xs:string"
# multiValued: false

The IBM Content Engine Java API dependencies (com.filenet:jace, com.filenet:p8cel10n) required to build this plugin are proprietary and resolved from the Arondor Artifactory, not Maven Central.

See Integrate with FileNet for deployment steps, including the ICN plugin and the gateway's FileNetProvider JWT settings.

mcp-server.yml

MCP (Model Context Protocol) boot-time configuration. Starting with 2026.0.0-ft3, MCP connections are typically managed through the admin UI (Managing MCP servers) rather than this file; the shipped mcp-server.yml is commented out.

# mcp:
# client:
# name: uxopian-ai-mcp-server
# log-requests: true
# sse:
# url: ${MCP_SSE_URL:http://localhost:8081/uxopian/ai/sse}
KeyEnv variableDescription
mcp.sse.urlMCP_SSE_URLLegacy boot-time MCP SSE endpoint URL. Prefer the admin UI for runtime management.
mcp.client.nameMCP client name presented to the server.

script-scan.yml

Configuration for the LLM-based security scan applied to admin-managed scripts (see Managing scripts). Added in 2026.0.0-ft4. The file is imported optionally, so its absence is non-fatal; without a configured provider, scripts can still be created, edited, and force-published, but the Scan & publish action is unavailable.

KeyEnv variableDefaultDescription
script.scan.llm-provider-idSCRIPT_SCAN_LLM_PROVIDER(empty)ID of a configured LLM provider used to run the scan. Required to enable scanning.
script.scan.llm-modelSCRIPT_SCAN_LLM_MODEL(empty)Model used for the scan; falls back to the provider's default model when blank.
script.scan.prompt(built-in)The security-review prompt sent to the model. Override to customize the scan policy.

Example:

script:
scan:
llm-provider-id: ${SCRIPT_SCAN_LLM_PROVIDER:}
llm-model: ${SCRIPT_SCAN_LLM_MODEL:}
# prompt: (built-in security-review prompt; override to customize)

gateway-application.yaml

Gateway (uxopian-gateway) configuration.

KeyDescription
server.portGateway listening port (default: 8085)
app.gateway.provider-headerHeader carrying the provider ID for multi-provider setups
app.routes[].idRoute identifier (used in logs)
app.routes[].uriBackend service URI (e.g., http://uxopian-ai:8080)
app.routes[].pathAnt path pattern — incoming requests must match this to activate the route
app.routes[].prefixBase prefix prepended to all security rule paths for matching against incoming requests
app.routes[].rewritePathComma-separated regex, replacement — rewrites the request path before forwarding to the backend. Uses Java named capture groups ((?<name>...)), referenced as $\{name} in the replacement.
app.routes[].providerAuthProvider bean name — either a built-in singleton (DevProvider, FlowerDocsProvider, Fast2Provider, AlfrescoProvider, FileNetProvider) or a name declared under app.providers below
app.routes[].security[].pathPath pattern for security rule (relative — combined with prefix at startup)
app.routes[].security[].publicIf true, no authentication required for this path
app.routes[].security[].rolesList of required roles for this path

YAML anchors (&ANCHOR / *alias) can be used to share URI and security rule definitions across multiple routes. Define anchors at the root level (before app:).

See Configure gateway routes for a step-by-step guide to deriving path, prefix, and rewritePath values, debug logging instructions, and a full FlowerDocs example.

The gateway's own endpoints (app.security)

app.routes[].security[] rules only apply within their own route's path — they never cover paths the gateway serves itself (/actuator/**, and nothing else, since routes are the only other traffic). A top-level app.security list configures those gateway-owned paths:

KeyDescription
app.security[].pathPath pattern, matched as-is (no route prefix involved)
app.security[].publicIf true, no authentication required
app.security[].rolesList of required roles

Without this, /actuator/health falls through to "authenticated" by default — which 401s the Kubernetes liveness/readiness probe and crash-loops the pod. The shipped application.yml sets:

app:
security:
- path: "/actuator/health"
public: true
- path: "/actuator/**"
roles: ["ADMIN"]

Named provider instances (app.providers)

Since 2026.0.0-ft5, a provider type that ships an AuthProviderFactory (currently Fast2Provider, AlfrescoProvider, and FileNetProvider) can be instantiated more than once, under an operator-chosen name — for example, to serve two separate FileNet tenants from one gateway. Omitting app.providers entirely keeps the previous single-instance-per-type behavior; this is purely additive.

KeyDescription
app.providers.<name>.typeOne of the provider types above that supports named instances
app.providers.<name>.config.*Arbitrary key/value configuration passed to that provider type's factory (same keys as the type's own dedicated config block)

Config keys mirror each provider's own dedicated block, kebab-cased: public-key / issuer / tenant-id / clock-skew-seconds for FileNetProvider, share-url / tenant-id / cache-ttl-minutes for AlfrescoProvider, public-key-url / tenant-id for Fast2Provider. These are the gateway's JWT-validation settings — not to be confused with uxopian-ai's own FileNet connector settings (filenet.ce-api-url, filenet.oidc-realm, configured on the ai-standalone side, see Integrate with FileNet).

app:
providers:
filenet-tenant-a:
type: FileNetProvider
config:
public-key: /path/to/tenant-a-icn-plugin-public-key.pem
issuer: icn-plugin
tenant-id: tenant-a-fallback
filenet-tenant-b:
type: FileNetProvider
config:
public-key: /path/to/tenant-b-icn-plugin-public-key.pem
issuer: icn-plugin
tenant-id: tenant-b-fallback
routes:
- id: filenet-a
provider: filenet-tenant-a
# ...
- id: filenet-b
provider: filenet-tenant-b
# ...

The instance name must not collide with a built-in provider bean name. Failing to declare type, referencing a type with no AuthProviderFactory, or a factory error at startup all fail fast with a clear message.

CORS (app.cors)

Since 2026.0.0-ft5, cross-origin access is controlled by the gateway itself.

KeyDescription
app.cors.allowed-originsList of allowed origins for cross-origin requests. Empty (the default) allows none — set this explicitly if a browser client on a different origin must reach the gateway.

Gateway-signed internal auth (internal-auth.jwt)

Since 2026.0.0-ft5, the gateway can sign every proxied request so uxopian-ai no longer has to trust bare X-User-* headers from whatever reaches it — see uxopian-ai's internal-auth.jwt.secret, which must match exactly.

KeyEnv variableDefaultDescription
internal-auth.jwt.secretINTERNAL_AUTH_JWT_SECRET(empty, signing off)HS256 shared secret, at least 32 bytes. Signing is simply inactive when unset — no error.
internal-auth.jwt.issuerINTERNAL_AUTH_JWT_ISSUERuxopian-gateway-internaliss claim stamped on the issued assertion.
internal-auth.jwt.ttl-secondsINTERNAL_AUTH_JWT_TTL_SECONDS30Assertion lifetime.

Public paths get signed too, not just authenticated ones: any request the gateway forwards for a path marked public in app.security/app.routes[].security[] still carries a signed X-Gateway-Auth assertion when a secret is configured — an anonymous one (no sub/tenantId, just the provider claim). Any X-Gateway-Auth the client itself supplied is stripped and replaced first, never appended to.