Skip to content

AI Agent

The AI Agent turns natural language into ClickHouse insights. Ask a question and the agent plans a series of read-only tool calls — querying system tables, inspecting schema, comparing hosts, spotting anomalies — then streams back a concise answer with optional inline charts.

The agent connects through the same ClickHouse host and user as the rest of the dashboard. Its visibility is bounded by the grants on that user. By default it only runs read-only queries. Keep control tools off and use a restricted ClickHouse user for safe exposure.

CategoryWhat the agent covers
Schema explorationList databases, tables, columns; explore tables relevant to a topic
Query analysisRunning, slow, failed, and expensive queries; EXPLAIN plans; optimization advice
System healthServer metrics, disks, errors, anomaly detection
Storage, merges & mutationsPart sizes, active merges, stuck mutations, merge throughput
Replication & clusterReplication lag, queue, ZooKeeper/Keeper status, cluster topology
Schema & data-type adviceORDER BY/keys, codecs, skip indexes, column type right-sizing
Tuning & upgradesHardware-based settings, version-upgrade guidance
Charts & visualizationRun SQL and render an interactive chart inline

A small set of tools delivers this: dedicated primitives for the common reads, and the query tool plus an expert skill recipe for everything else. See Capabilities for the full list.

Skills — when a question needs domain depth, the agent loads a bundled expert guide (a skill) with copy-pasteable SQL recipes before answering. Eighteen skills cover data analysis, anomaly detection, query tuning, schema & data-type design, hardware tuning, version upgrades, concept explanations, incident response, plan-and-verify, and the core domains (replication, cluster, storage, migration, security, best practices, troubleshooting, system tables). Available skills: GET /api/v1/agent/skills.

Plan and verify — for multi-step tasks (incident triage, investigations, find-and-fix) the agent authors a live checklist with update_plan, keeps one step in progress, and verifies each result before stating it. Simple one-step questions skip the plan. See Capabilities for details.

Set at minimum one environment variable:

Terminal window
LLM_API_KEY=your-provider-key

Then open /agents in the dashboard, pick a host, and start asking questions. The agent uses OpenRouter by default (https://openrouter.ai/api/v1) with the free model tier.

For full configuration options see Configuration.

  • Configuration — all env vars, providers, access control
  • Capabilities — tools, skills, plan & verify, examples
  • Conversation History — how history works, how to enable server persistence
    • Store Backends — per-backend setup (D1, ClickHouse, Postgres, …)
    • AgentState — managed/self-hosted persistence with AI enrichment (auto-titles, follow-ups)

Agent chat history is persisted by a server-side ConversationStore chosen at deploy time by environment variables. Four backends are available:

BackendSelected whenNotes
Browserconversation-DB feature flag offlocalStorage only; history is per-browser, no server setup
AgentStateAGENTSTATE_API_KEY is setManaged or self-hosted conversation-history service; optional AI enrichment
D1a Cloudflare D1 binding is presentCloudflare-native SQLite
PostgresDATABASE_URL is setAny PostgreSQL-compatible database

Selection priority when persistence is enabled: AgentState (if AGENTSTATE_API_KEY) → D1 (Cloudflare binding) → Postgres (DATABASE_URL) → Memory (last-resort, non-persistent). With the feature flag off, history stays in the Browser.

Server persistence requires VITE_FEATURE_CONVERSATION_DB=true and an authenticated user — configure Clerk (VITE_AUTH_PROVIDER=clerk + CLERK_SECRET_KEY) so history can be scoped per user. Unauthenticated sessions always fall back to browser history. See Authentication.

AgentState is a conversation-history database-as-a-service for AI agents. Use it when you want managed (or self-hosted) persistence that survives browser clears and is shared across devices, plus optional AI enrichment — auto-generated conversation titles and follow-up question suggestions — and per-project analytics. It is self-hostable as a single Cloudflare Worker (see duyet/agentstate) and ships an npm SDK (@agentstate/sdk).

Per-user isolation is built in: each thread is namespaced by AgentState external_id as <userId>:<conversationId> and tagged user:<userId>, so one project key safely holds every user’s history without cross-talk.

Environment variables (all server-side):

VariableRequiredDefaultPurpose
AGENTSTATE_API_KEYto enableas_live_... project key; its presence activates the AgentState backend
AGENTSTATE_BASE_URLnohttps://agentstate.app/apiendpoint; override to point at a self-hosted instance
AGENTSTATE_AI_ENRICHnofalseenable auto-title + follow-up suggestions
CONVERSATION_STORE_BACKENDnoautoforce agentstate when a Cloudflare D1 binding is also present

Still requires VITE_FEATURE_CONVERSATION_DB=true and a Clerk auth provider (VITE_AUTH_PROVIDER=clerk + CLERK_SECRET_KEY).

  1. Sign in at agentstate.app and create a project.
  2. Create an API key — it is prefixed as_live_ and shown once, so copy it immediately.
  3. Set it server-side:
Terminal window
VITE_FEATURE_CONVERSATION_DB=true
AGENTSTATE_API_KEY=as_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
## Optional: turn on auto-titles + follow-up suggestions
AGENTSTATE_AI_ENRICH=true

Run your own AgentState Worker per duyet/agentstate, then point the dashboard at it:

Terminal window
VITE_FEATURE_CONVERSATION_DB=true
AGENTSTATE_API_KEY=as_live_your_self_hosted_key
AGENTSTATE_BASE_URL=https://your-agentstate-host/api

Against a locally running AgentState instance, use the seed test key:

Terminal window
VITE_FEATURE_CONVERSATION_DB=true
AGENTSTATE_BASE_URL=http://localhost:8787
AGENTSTATE_API_KEY=as_live_TEST_KEY_FOR_LOCAL_DEV_ONLY_1234567890ab
  • Settings sidebar — the agent settings sidebar shows a read-only Conversation History section naming the active backend (e.g. AgentState).
  • EndpointGET /api/v1/conversations/backend reports the active backend and whether enrichment is available:
Terminal window
curl https://your-host/api/v1/conversations/backend
## => { "backend": "agentstate", "supportsAiEnrichment": true }

When AgentState is active and AGENTSTATE_AI_ENRICH=true:

  • Auto-title — new conversations get a concise generated title instead of a placeholder.
  • Follow-ups — the chat suggests follow-up questions after a turn. The dashboard reads them from GET /api/v1/conversations/$id/follow-ups.

With enrichment off, conversations persist normally but titles and follow-up suggestions are not generated.

Separate from chat history, the AI Insights panel on /overview persists the short observations it generates through its own pluggable store, mirroring the conversation backends above. It is additive opt-in via one env var and defaults to ClickHouse, so existing deployments are unaffected.

Terminal window
INSIGHTS_STORE_BACKEND=auto # auto | clickhouse | d1 | postgres | agentstate | memory
ValueBackendPrerequisite
auto (default)ClickHouse monitoring_findings tablewritable monitoring connection
clickhousesame as autowritable monitoring connection
d1Cloudflare D1 insights_findings tableINSIGHTS_D1 binding, else CONVERSATIONS_D1
postgresPostgres insights_findings tableDATABASE_URL
agentstateAgentState State storeAGENTSTATE_API_KEY (+ optional AGENTSTATE_BASE_URL)
memoryin-process (ephemeral)

The D1, Postgres, and AgentState backends reuse the same env / bindings as the conversation store. auto resolves to ClickHouse and never silently follows other env; if an explicitly selected backend is missing its prerequisite, the engine logs a warning and falls back to ClickHouse. GET /api/v1/insights/backend reports the active backend ({ "backend": "d1" }), and the overview panel shows a read-only “Stored in <backend>” footer.

Terminal window
curl -X POST https://your-host/api/v1/agent \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AGENT_API_TOKEN" \
-d '{"message": "Which queries are running right now?", "hostId": 0}'

hostId is a zero-based numeric index; defaults to 0.

The dashboard exposes an MCP (Model Context Protocol) endpoint at /api/mcp. The same implementation runs in the standalone Cloudflare MCP Worker (apps/mcp). All tools are read-only by design — write and DDL statements are rejected.

The MCP Servers section of the agent settings sidebar shows the built-in clickhouse-monitor server with its live connection status, tool count, resource count, and version — fetched from GET /api/v1/mcp/info. Click a server row to see the full tool and resource list. The built-in server is always enabled and cannot be toggled off. Custom server registration (“Connect new server”) is not yet available.

ToolPurpose
queryExecute a read-only SQL query (SELECT / WITH / DESCRIBE / EXPLAIN only)
list_databasesList all databases with their engines and comments
list_tablesList tables in a database with row counts and sizes
get_table_schemaGet column definitions for a table including types, defaults, and comments
get_metricsKey server metrics: version, uptime, active connections, memory usage
get_running_queriesCurrently running queries ordered by elapsed time
get_slow_queriesSlowest completed queries from the query log
get_merge_statusCurrently running merge operations with progress and elapsed time
explore_table_schemaThree-mode schema exploration: databases → tables → full schema with relationships

The query tool — the only tool that accepts arbitrary SQL — validates every statement before execution via validateSqlQuery (@chm/sql-builder). It throws on any write or DDL statement and on dangerous ClickHouse commands. Allowed prefixes: SELECT, WITH (CTE), DESCRIBE, EXPLAIN. Rejected: INSERT, ALTER, DROP, CREATE, TRUNCATE, RENAME, DELETE, UPDATE, SYSTEM RELOAD/FLUSH/KILL/SHUTDOWN, GRANT, REVOKE, ATTACH, DETACH, KILL, SET, multi-statement payloads (; chaining), and dangerous table functions (remote(), url(), s3(), etc.).

All other MCP tools run fixed SELECT queries and pass readonly: '1' to the ClickHouse connection — they cannot issue writes regardless of the validator.

  • Use a read-only ClickHouse user scoped to the system tables the dashboard needs.
  • Keep control tools off (AGENT_ENABLE_CONTROL_TOOLS=false, the default) unless you trust the user and need kill/optimize.
  • On public deployments, require authentication: CHM_FEATURE_AGENT_ACCESS=authenticated.
  • Keep LLM keys server-side — never in VITE_* variables (those are baked into browser JS at build time).