Configuration
All environment variables for configuring the AI Agent — LLM provider, model picker, access control, and conversation persistence.
Configure the agent entirely through environment variables. Start with the core LLM settings, then add provider keys, access control, and persistence as you need them.
Core LLM settings
These three variables cover most deployments.
| Variable | Default | Purpose |
|---|---|---|
LLM_API_KEY | — | Provider API key. Required to enable the agent. |
LLM_API_BASE | https://openrouter.ai/api/v1 | OpenAI-compatible base URL. |
LLM_MODEL | openrouter:openrouter/free | Model identifier (provider:modelId). |
LLM_API_KEY=sk-or-...
LLM_API_BASE=https://openrouter.ai/api/v1
LLM_MODEL=openrouter:openrouter/autoProvider-specific keys
Set the key for each provider you want to use. Only providers with a key configured appear as selectable in the model picker.
| Variable | Provider | Notes |
|---|---|---|
OPENROUTER_API_KEY | OpenRouter | Alias for LLM_API_KEY when using OpenRouter. |
OPENROUTER_API_BASE | OpenRouter | Override base URL. |
OPENROUTER_REFERER | OpenRouter | HTTP referer sent with requests (for leaderboard attribution). |
OPENROUTER_APP_NAME | OpenRouter | App name sent with requests. |
OPENROUTER_MODELS_API | OpenRouter | Override models list URL. |
NVIDIA_API_KEY | NVIDIA NIM | NIM API key. |
NVIDIA_API_BASE | NVIDIA NIM | NIM base URL (defaults to NVIDIA's hosted endpoint). |
ANYROUTER_API_KEY | AnyRouter | AnyRouter API key. |
ANYROUTER_API_BASE | AnyRouter | AnyRouter base URL. |
Extra models
LLM_EXTRA_MODELS adds entries to the model picker without touching code. Format:
provider:modelId[|contextLength][|description]provider— one ofopenrouter,nvidia,anyroutermodelId— model ID passed to the provider (may contain colons)contextLength— optional integer token count; defaults to128000description— optional display label; defaults tomodelId
Comma-separate multiple models:
LLM_EXTRA_MODELS="nvidia:meta/llama-3.3-70b|131072|Llama 3.3 70B,openrouter:x-ai/grok-2"Extra models are appended after the built-in registry. If an extra entry shares a provider:modelId key with a built-in, the built-in wins.
Access & safety
| Variable | Default | Purpose |
|---|---|---|
CHM_FEATURE_AGENT_ACCESS | public | Set to authenticated to require login before using the agent. |
AGENT_API_TOKEN | — | Shared Bearer token accepted by POST /api/v1/agent. |
AGENT_ENABLE_CONTROL_TOOLS | false | When true, enables optimize_table, kill_query, and kill_mutation. Keep off unless the ClickHouse user is trusted. |
RATE_LIMIT_AGENT_PER_MIN | 10 | Max POST /api/v1/agent requests per minute, applied per signed-in identity and per IP for anonymous callers. |
AGENT_DEBUG | false | When truthy (1/true/yes/on), logs verbose agent request/usage details. Leave off in production — it prints message keys, resolved user ids, and token usage. |
Require auth on public deployments:
CHM_FEATURE_AGENT_ACCESS=authenticatedProtect the API endpoint with a bearer token:
AGENT_API_TOKEN=your-secret-tokencurl -H "Authorization: Bearer $AGENT_API_TOKEN" \
-d '{"message":"...","hostId":0}' \
https://your-host/api/v1/agentCross-source Postgres tools
Set CHM_FEATURE_POSTGRES_SOURCE=true to expose the agent's read-only Postgres
tools (run_postgres_select_query, get_postgres_metrics,
list_postgres_slow_query_patterns, get_postgres_table_stats). They resolve a per-call pgHostId against
the POSTGRES_* env lists below — a flat positional index, exactly like a
ClickHouse hostId indexes the CLICKHOUSE_* lists. All lists are
comma-separated and index-aligned with POSTGRES_HOST; a single POSTGRES_USER
/ POSTGRES_PASSWORD broadcasts to every host.
| Variable | Default | Purpose |
|---|---|---|
CHM_FEATURE_POSTGRES_SOURCE | false | Master gate. When true, the three Postgres tools are added to the agent. Pure env gate (no Clerk) so self-hosted has equal support. |
POSTGRES_HOST | — | Comma-separated Postgres hosts (host or host:port). Defines the pgHostId id space. |
POSTGRES_PORT | 5432 | Ports (used when a host has no inline :port). |
POSTGRES_USER | postgres | Users; a single value applies to all hosts. |
POSTGRES_PASSWORD | — | Passwords; a single value applies to all hosts. |
POSTGRES_DATABASE | postgres | Database names. |
POSTGRES_SSLMODE | — | libpq sslmode (disable | require | verify-full). |
POSTGRES_NAME | — | Display names for the sources. |
Env hosts only, for now
The agent's Postgres tools read env-configured hosts (POSTGRES_*), like the
ClickHouse tools read CLICKHOUSE_*. Per-user (D1) Postgres connections managed
in the UI are not yet visible to the agent — the same limitation the ClickHouse
agent tools already have. Env Postgres hosts are operator-supplied and trusted
(no SSRF re-guard), matching the CLICKHOUSE_HOST precedent.
Point the Postgres user at a read-only role. The tools pin the session read-only and gate the SQL, but a least-privilege user is defense in depth.
CHM_FEATURE_POSTGRES_SOURCE=true
POSTGRES_HOST=db.internal:5432
POSTGRES_USER=readonly
POSTGRES_PASSWORD=secret
POSTGRES_DATABASE=appdbLeast-privilege ClickHouse user
The agent's query tool (and the MCP server) run
read-only SELECTs that the model composes. Because the model can read any
table the connection user can, point it at a dedicated, restricted user —
not default or an admin account. Two concerns in particular:
system.query_logcan contain credentials embedded in query text (e.g. aCREATE ... IDENTIFIED BYor ans3(...)call another client ran).system.users,system.grants, andsystem.quotasexpose your access model.
Create a monitoring user restricted to the system tables the dashboard needs and deny the sensitive ones:
CREATE USER chmonitor_agent IDENTIFIED BY 'a-strong-password'
SETTINGS readonly = 1;
-- Read-only access to the metrics/monitoring tables the dashboard reads.
GRANT SELECT ON system.* TO chmonitor_agent;
-- Revoke the tables that leak secrets or your access model.
REVOKE SELECT ON system.query_log FROM chmonitor_agent;
REVOKE SELECT ON system.users FROM chmonitor_agent;
REVOKE SELECT ON system.grants FROM chmonitor_agent;
REVOKE SELECT ON system.quotas FROM chmonitor_agent;Keep control tools off by default
Leave AGENT_ENABLE_CONTROL_TOOLS=false unless the ClickHouse user is trusted —
it enables mutating tools (optimize_table, kill_query, kill_mutation). A
readonly = 1 user is a second line of defense even if it is ever turned on.
Conversation persistence
| Variable | Type | Default | Purpose |
|---|---|---|---|
VITE_FEATURE_CONVERSATION_DB | Build-time | false | Enable server-side conversation storage. Derived from canonical CHM_FEATURE_CONVERSATION_DB — set that one before pnpm run build. Requires Clerk. |
CONVERSATION_STORE_BACKEND | Runtime | (auto) | Backend: agentstate, d1, postgres, or memory. Auto-selects when unset. |
For per-backend env vars and setup, see Conversation history and Store backends.
Where to set these
- Cloudflare Workers —
wrangler secret put LLM_API_KEYfor secrets;[vars]inwrangler.tomlfor non-secret values in your own worker. (In this repo's hosted deploy, non-secret config lives inapps/dashboard/.env.productionand there is no[vars]block.) See Deploy to Cloudflare. - Docker —
environment:block indocker-compose.ymlor--env-file .env. See Deploy with Docker. - Kubernetes —
Secretfor keys,ConfigMapfor non-secret values. See Deploy to Kubernetes. - Vercel / self-hosted — environment variables in the project dashboard or
.env.local.
Keep LLM keys server-side
Never put LLM API keys in VITE_* variables. Anything prefixed VITE_ is baked into browser JavaScript at build time and is visible to anyone who opens DevTools. Use plain (non-VITE) variables for all keys — they stay on the server.