chmonitor
AI Agent

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.

VariableDefaultPurpose
LLM_API_KEYProvider API key. Required to enable the agent.
LLM_API_BASEhttps://openrouter.ai/api/v1OpenAI-compatible base URL.
LLM_MODELopenrouter:openrouter/freeModel identifier (provider:modelId).
LLM_API_KEY=sk-or-...
LLM_API_BASE=https://openrouter.ai/api/v1
LLM_MODEL=openrouter:openrouter/auto

Provider-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.

VariableProviderNotes
OPENROUTER_API_KEYOpenRouterAlias for LLM_API_KEY when using OpenRouter.
OPENROUTER_API_BASEOpenRouterOverride base URL.
OPENROUTER_REFEREROpenRouterHTTP referer sent with requests (for leaderboard attribution).
OPENROUTER_APP_NAMEOpenRouterApp name sent with requests.
OPENROUTER_MODELS_APIOpenRouterOverride models list URL.
NVIDIA_API_KEYNVIDIA NIMNIM API key.
NVIDIA_API_BASENVIDIA NIMNIM base URL (defaults to NVIDIA's hosted endpoint).
ANYROUTER_API_KEYAnyRouterAnyRouter API key.
ANYROUTER_API_BASEAnyRouterAnyRouter base URL.

Extra models

LLM_EXTRA_MODELS adds entries to the model picker without touching code. Format:

provider:modelId[|contextLength][|description]
  • provider — one of openrouter, nvidia, anyrouter
  • modelId — model ID passed to the provider (may contain colons)
  • contextLength — optional integer token count; defaults to 128000
  • description — optional display label; defaults to modelId

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

VariableDefaultPurpose
CHM_FEATURE_AGENT_ACCESSpublicSet to authenticated to require login before using the agent.
AGENT_API_TOKENShared Bearer token accepted by POST /api/v1/agent.
AGENT_ENABLE_CONTROL_TOOLSfalseWhen true, enables optimize_table, kill_query, and kill_mutation. Keep off unless the ClickHouse user is trusted.
RATE_LIMIT_AGENT_PER_MIN10Max POST /api/v1/agent requests per minute, applied per signed-in identity and per IP for anonymous callers.
AGENT_DEBUGfalseWhen 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=authenticated

Protect the API endpoint with a bearer token:

AGENT_API_TOKEN=your-secret-token
curl -H "Authorization: Bearer $AGENT_API_TOKEN" \
     -d '{"message":"...","hostId":0}' \
     https://your-host/api/v1/agent

Least-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_log can contain credentials embedded in query text (e.g. a CREATE ... IDENTIFIED BY or an s3(...) call another client ran).
  • system.users, system.grants, and system.quotas expose 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

VariableTypeDefaultPurpose
VITE_FEATURE_CONVERSATION_DBBuild-timefalseEnable server-side conversation storage. Derived from canonical CHM_FEATURE_CONVERSATION_DB — set that one before bun run build. Requires Clerk.
CONVERSATION_STORE_BACKENDRuntime(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 Workerswrangler secret put LLM_API_KEY for secrets; [vars] in wrangler.toml for non-secret values in your own worker. (In this repo's hosted deploy, non-secret config lives in apps/dashboard/.env.production and there is no [vars] block.) See Deploy to Cloudflare.
  • Dockerenvironment: block in docker-compose.yml or --env-file .env. See Deploy with Docker.
  • KubernetesSecret for keys, ConfigMap for 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.

On this page