Every setting NeelAI reads, what it does, and what happens if you leave it alone. Settings are read from the environment, normally through .env next to docker-compose.yml. Anything not listed here is not read by the application.
Note: Values are read at the point of use rather than cached at import, so a setting changed in
.env takes effect on the next container restart — no image rebuild.1Database connection
NeelAI connects to your SAP Business One HANA database as a read-only user and to its own Postgres instance for platform data. The two are unrelated: losing the platform database stops logins, losing HANA stops answers.
| Setting | Type | Default | Effect |
|---|---|---|---|
HANA_HOST | hostname | — | HANA host. A name your Docker network can resolve, or an IP. localhost here means the container, not your laptop. |
HANA_PORT | int | 30015 | SQL port of the tenant database. Port 3<instance>15 for a tenant, 3<instance>13 for a single-container system. |
HANA_USER | string | — | Database user. Needs SELECT and nothing else — see §3. |
HANA_PASSWORD | string | — | Password for that user. |
HANA_SCHEMA | string | — | Company schema, e.g. SBODEMOIN. One deployment reads one schema. |
HANA_POOL_SIZE | int | 5 | Maximum concurrent HANA connections. Raising this does not make one answer faster; it lets more people ask at once. |
HANA_IDLE_TTL_SECONDS | int | 300 | Idle connections are closed after this. Set it below any firewall idle timeout between you and HANA, or you will see connections that look alive and are not. |
PLATFORM_DB_URL | url | — | Postgres URL for users, roles, grants and chat history. Not your ERP data. |
Warning: If
HANA_USER has write privileges, NeelAI will not use them — but you have removed your own last line of defence. Grant SELECT only, and let the grant be the guarantee rather than our good intentions.2Model and retrieval
| Setting | Type | Default | Effect |
|---|---|---|---|
MODEL_API_KEY | string | — | Required. Without it the product starts and every question fails at the retrieval step. |
NEELAI_MODEL | string | pinned | Model used for Ask Anything. Pinned deliberately; see the note below. |
MAX_RETRIEVAL_STEPS | int | 12 | How many tool calls the retrieval loop may make before it must answer. Raising it costs latency on hard questions and changes nothing on easy ones. |
EXTENDED_THINKING | bool | true | Extra reasoning budget during retrieval planning. Turn it off to cut latency at some cost to multi-table questions. |
SCHEMA_SNAPSHOT_DIR | path | /app/schema | Where the introspected schema snapshot is written. Must be writable by the container user. |
SCHEMA_REFRESH_HOURS | int | 24 | How often the snapshot is rebuilt. Refresh manually after adding user-defined fields rather than waiting. |
Note: The model is pinned rather than tracking "latest" on purpose. An answer that changes shape because a model was silently upgraded underneath you is indistinguishable, from the finance team's side, from a bug.
3Features
| Setting | Type | Default | Effect |
|---|---|---|---|
ACTIVITY_LOGGING_ENABLED | bool | true | Append every question, answer and failure to activity.jsonl. Set false to stop recording question text entirely. |
ACTIVITY_LOG_DIR | path | backend/logs | Where that file is written. |
CHAT_HISTORY_ENABLED | bool | true | Keep conversation threads so follow-up questions have context. Disabling makes every question standalone. |
EXTERNAL_MCP_ENABLED | bool | false | Enable the external MCP bridge. |
EXTERNAL_MCP_URL | url | — | Bridge endpoint. Required when the above is on. |
EXTERNAL_MCP_KEY | string | — | Bearer key, 32 characters or more. |
4Observability
Optional, and entirely separable — the stack starts and runs without any of it.
| Setting | Type | Default | Effect |
|---|---|---|---|
GRAFANA_ADMIN_USER | string | admin | Grafana login. Change before exposing beyond localhost. |
GRAFANA_ADMIN_PASSWORD | string | admin | As above, and more so. |
To run the application without the observability containers at all, name the services explicitly: docker compose up postgres valkey backend frontend.
Tip: Loki rejects unknown configuration keys and exits rather than ignoring them, so a typo takes the container down and shows up elsewhere as a DNS error. Validate before restarting:
docker run --rm -v "$PWD/observability/loki:/c" grafana/loki:2.9.8 -config.file=/c/loki-config.yaml -verify-config.