chmonitor
AI Agent

Conversation history

How agent chat history works, how to enable server-side persistence, and which authentication is required.

Agent chat history is stored in browser localStorage by default — no server setup needed. Enable server-side persistence when you want history shared across devices, preserved after a browser clear, or visible to multiple users.

How persistence works

  • Persistence off — every conversation is local to the browser. Clearing browser data loses history.
  • Persistence on, unauthenticated user — falls back to localStorage. Server stores require a user identity to scope history correctly.
  • Persistence on, authenticated user — history is read and written to the configured server store.

Enable server persistence

Server-side persistence requires two things:

  1. CHM_FEATURE_CONVERSATION_DB=true must be set at build time (before bun run build). The client VITE_FEATURE_CONVERSATION_DB value is derived from it and baked into the bundle, so it cannot be changed at runtime. It also requires Clerk auth to be active (CHM_AUTH_PROVIDER=clerk).
  2. A backend must be reachable at runtime.
CHM_FEATURE_CONVERSATION_DB=true
CHM_AUTH_PROVIDER=clerk
CHM_CLERK_PUBLISHABLE_KEY=pk_live_...
# Runtime — select or force a backend:
CONVERSATION_STORE_BACKEND=postgres   # or: agentstate, d1, memory
DATABASE_URL=postgresql://user:pass@host:5432/db

When CONVERSATION_STORE_BACKEND is not set, the server auto-selects the first available backend in the order described below.

Backend resolution order

When CONVERSATION_STORE_BACKEND is not set (or set to an unrecognized value), the server picks the first available backend in this order:

AgentState

Selected when AGENTSTATE_API_KEY is set and CONVERSATION_STORE_BACKEND is not d1, postgres, or memory.

Cloudflare D1

Selected when the CHM_CLOUD_D1 binding is present (Cloudflare Workers only).

Postgres

Selected when DATABASE_URL is set.

Memory

Fallback in development/CI. Conversations are lost on process restart.

You can force a specific backend by setting CONVERSATION_STORE_BACKEND to agentstate, d1, postgres, or memory.

AgentState self-host quickstart

AgentState is a cloud-hosted conversation store. It works on any deployment target (Cloudflare Workers, Docker, Kubernetes, Vercel).

Get an API key

Get an API key at agentstate.app.

Set build-time variables

The client VITE_* values are derived from these:

CHM_FEATURE_CONVERSATION_DB=true
CHM_AUTH_PROVIDER=clerk
CHM_CLERK_PUBLISHABLE_KEY=pk_live_...

Set runtime variables

AGENTSTATE_API_KEY=as_live_...
# CONVERSATION_STORE_BACKEND=agentstate  # optional — auto-selected when key is present

Optional: enable AI enrichment

Enrich stored conversation titles:

AGENTSTATE_AI_ENRICH=true

Deploy

No migrations needed — AgentState manages the schema.

Per-platform wiring:

Add the key via wrangler secret put:

wrangler secret put AGENTSTATE_API_KEY
# wrangler.toml [vars]
CONVERSATION_STORE_BACKEND = "agentstate"
docker run -d --name chmonitor -p 3000:3000 \
  -e AGENTSTATE_API_KEY='as_live_...' \
  -e CONVERSATION_STORE_BACKEND='agentstate' \
  ghcr.io/chmonitor/chmonitor:vX.Y.Z
kubectl create secret generic chmonitor-agentstate \
  --from-literal=AGENTSTATE_API_KEY='as_live_...'
# in ConfigMap
CONVERSATION_STORE_BACKEND: "agentstate"

Request / response flow

On each request the server loads the thread from the store, runs the agent, then writes the updated thread back before streaming the response to the browser.

Auth requirement

Server stores require an authenticated user identity to namespace threads. If the request is unauthenticated, the server skips persistence and the browser keeps local history. To enable server persistence, configure an auth provider — see Authentication.

Deprecated alias

NEXT_PUBLIC_FEATURE_CONVERSATION_DB=true is accepted as an alias for VITE_FEATURE_CONVERSATION_DB=true but is deprecated. Do not use it for new deployments.

On this page