CortexDB Docs
Docs for CortexDB 0.12.8, the version running on CortexDB Cloud (api.cortexdb.ai).
Self-Hosting

Self-Hosting Quickstart

Run your own CortexDB server with one docker run, then store and recall your first memory against localhost — the recommended way to start.

Self-hosted CortexDB is for customers

Self-hosted releases from 0.9.0 on, including the one these docs describe, are available to customers through the customer portal, with a company license; talk to us to become one. The last public release, 0.8.21, is on cortexdb.ai/download. To use this release today without running a server, start on CortexDB Cloud.

Self-hosting is the recommended way to run CortexDB. You get the same server the cloud runs, your data never leaves your infrastructure, and there's no per-token cost. This page takes you from nothing to a running server with a stored-and-recalled memory in about five minutes.

The quickest path

Not running a server at all is quicker still: CortexDB Cloud is the same release at https://api.cortexdb.ai, free to start. Customers install a server with the installer on the customer portal's Releases page, which also carries their company's license; the steps by hand follow.

The public release is different

cortexdb.ai offers CortexDB 0.8.21, the last public release, as docker run cortexdb/cortexdb:v0.8.21 from Docker Hub, with no license and no portal. Customer releases (0.12.1 and later) come only from customer.cortexdb.ai: the image is a file you docker load, it is tagged with its exact version (there is no :latest to pull), and it needs your company's license (Your license). Never mix the two: a docker pull cortexdb/cortexdb:latest fetches the public release, not yours.

Prerequisites

  • A container runtime — Docker (or Podman). CortexDB ships as a single image, cortexdb/cortexdb.
  • An embedding provider — vector recall needs one. Either an OpenAI-compatible API key (used only for embeddings) or a local Ollama (fully local, no external calls — see Fully local below). Both are equally supported: use the OpenAI key on modest hardware (a laptop, no GPU, limited RAM or disk) or for the simplest setup, and local Ollama on a high-end machine or when vectors must stay on the box. Decide before your first write; the choice is pinned to the data directory and switching later is an offline rebuild. A container with an embedding endpoint configured but no credential refuses to start (FATAL: an explicit CORTEX_EMBEDDING_URL requires CORTEX_EMBEDDING_API_KEY, OPENAI_API_KEY, or LLM_API_KEY) instead of silently serving meaningless mock vectors; the image sets an OpenAI embedding URL by default, so the plain docker run needs a key. CORTEX_EMBEDDING_PROVIDER=mock is the explicit opt-in for control-path tests.
  • ~2 GB RAM and a data volume. A single node handles ~10M events on commodity hardware; everything persists under /data.
  • Optional, only if you want them: an answer lane (CORTEX_ANSWER_*) to enable /v1/answer, and enrichment to populate the Facts/Beliefs/Understanding layers — both off by default. See Self-hosting defaults.

1. Start the server

Load the image from the release page first (its "Run the steps by hand" block downloads it, checks the SHA-256 and runs docker load). docker images cortexdb/cortexdb shows the tag it loaded.

export CORTEX_LICENSE='<your license>'             # in the release page's commands
CORTEXDB_IMAGE=cortexdb/cortexdb:v0.12.8          # the tag docker load printed
docker run -d \
  --name cortexdb \
  --restart unless-stopped \
  --stop-timeout 120 \
  -p 127.0.0.1:3141:3141 \
  -v cortexdb-data:/data \
  -e CORTEX_LICENSE \
  -e CORTEX_INSECURE_NO_AUTH=1 \
  -e CORTEX_EMBEDDING_API_KEY=$OPENAI_API_KEY \
  "$CORTEXDB_IMAGE"

That's the whole install. The container ships with every field at its compiled default: single-node, the v1 API on :3141, data persisted to the cortexdb-data volume. --restart unless-stopped brings the server back after a console restart (which exits with code 75) or a crash, and --stop-timeout 120 gives it the 120 seconds the server needs for a graceful stop (Docker's default is 10 seconds; see Upgrading).

Why an OpenAI key, and why as CORTEX_EMBEDDING_API_KEY?

It's used only for embeddings (vector recall needs a real embedding provider; the server exits at startup rather than run on meaningless mock vectors). Passing it as CORTEX_EMBEDDING_API_KEY keeps it embeddings-only. Passed as plain OPENAI_API_KEY, the image's baked defaults also switch on entity extraction (a gpt-4o-mini call per write) and the gpt-4.1 verifier lane, which you may not want on a first run. Prefer to keep everything local? Point embeddings at a local Ollama instead — see Fully local, no external keys below.

Auth: CORTEX_INSECURE_NO_AUTH is dev-only

CORTEX_INSECURE_NO_AUTH=1 makes the server serve requests with no token (as user:local, or as the named X-Cortex-Actor) — the frictionless path for local development. The flag does not restrict the bind; the -p 127.0.0.1:... mapping is what keeps it on loopback only. Before exposing the port, drop that flag and set -e CORTEX_API_KEY=<a strong secret> instead; the value itself becomes your bearer credential (Authorization: Bearer <secret>). Note: if you set neither on a network-exposed bind, the server refuses to serve open — it auto-generates a key and prints it in the boot log, and every request needs it. See Security & Compliance.

On a network, send the key with every request

Every deployment preset requires the key: a request carrying only an X-Cortex-Actor header gets 401 MISSING_TOKEN.

2. Confirm it's healthy

curl http://localhost:3141/v1/admin/health
# {"status":"healthy","version":"vX.Y.Z"}   <- the release you installed, e.g. the one on your Download page

curl http://localhost:3141/v1/admin/ready
# ... "degraded": false  →  real embeddings are working (not mock)

If ready reports "degraded": true, the embedding provider is failing (for example a dead key returning 401) or you opted into mock embeddings — check the embeddings block for the provider's error text. A container with no embedding credential at all does not get this far: it exits at startup (see Prerequisites).

Readiness is outcome-based — gate deploys on it, not health

/v1/admin/ready reports what real provider calls actually did. Its embeddings check distinguishes mock, failing (a configured key returning 401 on every call), and healthy — so a dead key marks the server degraded and surfaces the provider's error text instead of silently returning empty recall. health only tells you the process is up; always gate container healthchecks and deploys on ready.

3. Store and recall your first memory

No token is needed because the server was started with CORTEX_INSECURE_NO_AUTH=1 (dev mode). Pick your surface — on a keyed server, add -H "Authorization: Bearer $CORTEX_API_KEY" (curl) or bearer=… (SDK):

curl

# Capture. ?wait=indexed returns once the event is searchable, so the recall below can't race the write.
# Keep the "id" in the answer: it is the original event ID.
curl -sfS -X POST "http://localhost:3141/v1/experience?wait=indexed" \
  -H "X-Cortex-Actor: user:local" -H "Content-Type: application/json" \
  -d '{
    "scope": "org:demo/user:local",
    "modality": "conversation",
    "content": { "kind": "message", "role": "user",
                 "text": "We migrated the payments service to CockroachDB. Timeline is Q2 2026." },
    "context": { "observed_at": "2026-05-16T10:42:00Z" },
    "idempotency_key": "decision-payments-001"
  }'

# Recall
curl -sfS -X POST http://localhost:3141/v1/recall \
  -H "X-Cortex-Actor: user:local" -H "Content-Type: application/json" \
  -d '{ "scope": "org:demo/user:local", "view": "holistic",
        "query": "What database are we using for payments?", "diagnostics": "none" }'

Python

pip install cortexdbai
from cortexdb.v1 import V1Client

# Point at your self-hosted server. In local no-auth mode, no bearer token is needed.
client = V1Client(api_url="http://localhost:3141", actor="user:local")

scope = "org:demo/user:local"

client.experience(
    scope=scope,
    text="We migrated the payments service to CockroachDB. Timeline is Q2 2026.",
    observed_at="2026-05-16T10:42:00Z",
    idempotency_key="decision-payments-001",
    wait="indexed",           # block until it's searchable, for a clean first recall
)

pack = client.recall(scope=scope, view="holistic",
                     query="What database are we using for payments?", diagnostics="none")
print(pack.get("context_block", ""))

TypeScript

npm install cortexdbai
import { V1Client } from "cortexdbai/v1";

const client = new V1Client({ apiUrl: "http://localhost:3141", actor: "user:local" });
const scope = "org:demo/user:local";

await client.experience(scope, {
  text: "We migrated the payments service to CockroachDB. Timeline is Q2 2026.",
  role: "user",
  observedAt: "2026-05-16T10:42:00Z",
  idempotencyKey: "decision-payments-001",
}, { wait: "indexed" });

const pack = await client.recall(scope, { view: "holistic",
  query: "What database are we using for payments?", diagnostics: "none" });
console.log(pack.context_block);

4. Verify it — and where things live

A quick "did it actually work?" checklist:

  1. Readiness, not liveness. curl http://localhost:3141/v1/admin/ready → "degraded": false. If it's true, the embedding provider is failing or mocked — fix it before trusting recall.
  2. Read-your-writes. The recall in step 3 should return your text in context_block. (It used wait="indexed", so the event is searchable by the time the write returns.)
  3. Where your data lives. Everything — WAL, RocksDB, indexes, blobs — is under /data, persisted to the cortexdb-data Docker volume. Back it up with a verified cold backup.
  4. Boot diagnostics / logs. docker logs cortexdb shows the pinned embedding provider, the auth posture, and the config_lint dump (what actually loaded). Grep it when something's off:
    docker logs cortexdb 2>&1 | grep -iE "embedding|auth|answer|degraded"
  5. The Admin Console. Open http://localhost:3141/ in a browser — CortexDB ships a built-in operator UI (Overview, Memories, Observability, Logs, Settings, …). See Admin Console.

Common first-run issues

degraded: true → no real embedding provider (set a key or point at Ollama). 401 MISSING_TOKEN on a write → the server isn't in no-auth mode; start it with CORTEX_INSECURE_NO_AUTH=1 (dev) or send Authorization: Bearer $CORTEX_API_KEY. Empty facts() / no /v1/answer → expected on a content-only instance; enable enrichment / the answer lane (defaults).

What you get by default

Your instance runs in content-only mode out of the box: event capture, episodes, and BM25 + vector + RRF recall are on. Blob extraction (it needs content processors configured), the LLM-derived layers (Facts, Beliefs, Understanding), the knowledge graph, cross-encoder rerank, and /v1/answer are opt-in — see Self-hosting defaults for exactly what's on and how to enable the rest.

Fully local, no external keys

To run with no external API calls at all, point embeddings at a local Ollama. This is the right choice on a high-end machine (spare CPU and RAM, ideally a GPU) or when the text you store must never leave the box; on a modest machine the OpenAI key above is the lighter option, and the two are otherwise equivalent. Start Ollama and pull the model before the first write, because the provider is pinned to the data directory on first boot:

# On the host: ollama pull nomic-embed-text
docker run -d --name cortexdb --restart unless-stopped --stop-timeout 120 \
  --network host -e CORTEX_V1_API_ADDR=127.0.0.1:3141 -v cortexdb-data:/data \
  -e CORTEX_LICENSE \
  -e CORTEX_INSECURE_NO_AUTH=1 \
  -e CORTEX_EMBEDDING_PROVIDER=ollama \
  -e CORTEX_EMBEDDING_URL=http://127.0.0.1:11434 \
  -e CORTEX_EMBEDDING_MODEL=nomic-embed-text \
  -e CORTEX_EMBEDDING_DIMS=768 \
  -e CORTEX_EMBEDDING_API_KEY=ollama \
  "$CORTEXDB_IMAGE"

Ollama listens on 127.0.0.1 by default, which a container on Docker's own network can't reach, so the container shares the host's network (--network host, Linux) and CORTEX_V1_API_ADDR keeps CortexDB on this machine only. CORTEX_INSECURE_NO_AUTH=1 is the same local-only choice as above: without it, or an API key, the first write is refused. The installer's "Local Ollama" option sets all of this and checks the model is pulled.

To also get natural-language answers (/v1/answer) and the Facts/Beliefs layers locally, wire the answer lane and enrichment to Ollama too — see LLM & Answer and Self-hosting defaults.

Upgrading

CortexDB upgrades are a container image swap against the same data volume: stop the server with a 120-second grace (docker stop -t 120 cortexdb), then start the new image with the same flags and volume. The full procedure, what each release changes for an existing deployment, and how to roll back are on Upgrading.

Next steps

On this page