Quickstart

Containerized Service

Run MemexAI as a separate service, then connect over TypeScript, Python, or MCP.

The containerized service path is the recommended default. Your application does not need database credentials; it connects to MemexAI over HTTP with the TypeScript SDK, Python SDK, or through MCP over SSE/stdio.

Fastest path

If you want a coding agent to do the integration inside your app, paste this into the agent:

Setup MemexAI by following https://memexai.space/setup.md

That public setup file tells the agent to inspect your app, choose the right adapter, start the local service, wire memory tools, add the MemexAI prompt block, and run a two-turn memory proof. See Coding Agent Onboarding for the human-readable version.

If you want to wire it manually, follow this page:

  1. Start the Docker Compose service.
  2. Connect your app with the TypeScript SDK, Python SDK, or MCP.
  3. Use one stable userId per end user.
  4. Pass both the MemexAI tools and memory.getSystemPrompt(...) into every model call.
  5. Verify that one turn writes memory and a later turn recalls it.

What you are starting

TLDR: Docker runs Postgres plus a MemexAI HTTP service. Your app calls the service with MEMEX_API_KEY; operators use the admin UI with MEMEX_ADMIN_SECRET.

Under the hood:

  • the service creates the mx_* Postgres tables on startup
  • agent routes execute memory tools and write revisions/access logs
  • admin routes let you inspect and correct memory files
  • memory.getSystemPrompt(...) fetches the prompt block that makes stored memory affect the next answer
  • optional model configuration powers memory_memorize, answer synthesis in memory_search, hybrid search embeddings, and background dreaming

Compose file

services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: memexai
      POSTGRES_PASSWORD: memexai
      POSTGRES_DB: memexai
    volumes:
      - memexai_postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U memexai"]
      interval: 5s
      timeout: 5s
      retries: 5

  memexai:
    image: soorajshankar/memexai:latest
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      DATABASE_URL: postgresql://memexai:memexai@postgres:5432/memexai
      MEMEX_API_KEY: dev-agent-key
      MEMEX_ADMIN_SECRET: dev-admin-secret
      GEMINI_API_KEY: ...
      MEMEX_DREAM_ENABLED: "false"
      # MEMEX_SHARED_WRITE_MODE: rw # optional: let agent tools write shared/**
      # MEMEX_TELEMETRY_DISABLED: "true" # optional opt-out
    ports:
      - "8080:8080"

volumes:
  memexai_postgres_data:

Start it:

docker compose up -d

Verify it:

curl -fsS http://localhost:8080/health

The API and admin UI are available at http://localhost:8080. For local defaults, open:

http://localhost:8080/admin?defaultAdminSecret=1&defaultApiKey=1&onboarding=1

If your build does not support the default-login query params, open http://localhost:8080/admin and enter:

Admin secret: dev-admin-secret
Agent API key: dev-agent-key

Connect with the TypeScript SDK

npm install @memexai/sdk ai @ai-sdk/google
import { MemexAI } from '@memexai/sdk'
import { generateText, stepCountIs } from 'ai'
import { createGoogleGenerativeAI } from '@ai-sdk/google'

const memex = new MemexAI({
  url: 'http://localhost:8080',
  apiKey: process.env.MEMEX_API_KEY ?? 'dev-agent-key',
})

const memory = memex.forUser({ userId: 'user_123', actor: 'assistant' })
const system = await memory.getSystemPrompt('You are a helpful assistant with durable user memory.')

const result = await generateText({
  model: createGoogleGenerativeAI()('gemini-2.5-flash'),
  system,
  prompt: 'Remember that I prefer quiet neighborhoods near good schools.',
  tools: memory.createAgenticToolset(),
  stopWhen: stepCountIs(5),
})

console.log(result.text)

memory.getSystemPrompt(...) adds the MemexAI prompt block to your base prompt. Without that prompt block or an equivalent system section, the tools can store memory, but the next response may not be conditioned on it.

Verify the memory loop

Run two separate calls for the same userId.

Turn one:

Remember that I prefer quiet neighborhoods near good schools.

Turn two:

What kind of neighborhood do I prefer?

A successful setup answers from stored memory on turn two. In the admin UI, the Files tab should show the user memory file, Revisions should show the write, and Access Logs should show the later read or search.

If turn one writes memory but turn two stays generic, check that the second model call uses the same userId and includes await memory.getSystemPrompt(...).

Connect with the Python SDK

python3 -m pip install memexai
from memexai import MemexAI

memex = MemexAI(
    url="http://localhost:8080",
    api_key="dev-agent-key",
)

memory = memex.for_user("user_123", actor="assistant")

result = await memory.search("What does this user prefer?")
print(result.get("answer") or result["results"])

await memex.close()

Connect with MCP

MCP clients can connect to the same service over SSE:

http://localhost:8080/v1/mcp/sse?userId=user_123&actor=claude&apiKey=dev-agent-key

Or through stdio after building the service:

bun run build:service

DATABASE_URL=postgresql://memexai:memexai@localhost:5433/memexai \
MEMEX_API_KEY=dev-agent-key \
node apps/service/dist/index.js --stdio --user-id user_123 --actor claude-desktop

See MCP Clients for details.

Model configuration

LLM-backed memory_memorize and agentic memory_search are configured on the service, not in the SDK.

GEMINI_API_KEY=...
GEMINI_MODEL=gemini-2.5-flash

# or
OPENAI_API_KEY=...
OPENAI_MODEL=gpt-4.1-mini

Without a service model, memory_search still works through Postgres full-text search, or hybrid pgvector search when embeddings are configured. memory_memorize returns MODEL_NOT_CONFIGURED.

For the smoothest first run, set GEMINI_API_KEY on the service so the agentic memory_memorize tool can decide what should become durable memory.

Shared writable mode

By default, agents can read shared/** but can write only user/**. To let agent tools contribute durable global knowledge, project canon, policies, style guides, or learned procedures to shared/**, set:

MEMEX_SHARED_WRITE_MODE=rw

Keep this disabled for untrusted public-user agents. When enabled, prefer memory_patch over full rewrites and keep private user facts, secrets, raw transcripts, and untrusted external content out of shared/**.

Search configuration

MemexAI uses BM25 Postgres full-text search by default. With MEMEX_SEARCH_MODE=auto and a Gemini API key, the service also stores pgvector embeddings for memory files and runs hybrid BM25 + vector search with reciprocal rank fusion.

MEMEX_SEARCH_MODE=auto
GEMINI_API_KEY=...

Set MEMEX_SEARCH_MODE=bm25 to force full-text search only.

Anonymous telemetry

MemexAI service telemetry is enabled by default for the OSS Docker image and service process. It sends anonymous product usage events to PostHog so the project can understand whether installs reach first memory, use MCP, enable dreaming, and hit service errors.

Telemetry never sends memory content, prompts, file paths, tool arguments, user IDs, API keys, admin secrets, or database URLs.

Disable service telemetry with:

MEMEX_TELEMETRY_DISABLED=true

To use a different PostHog project or a self-hosted collector, set MEMEX_TELEMETRY_POSTHOG_KEY and MEMEX_TELEMETRY_POSTHOG_HOST.

Background dreaming

Dreaming is optional background memory consolidation for long-horizon agents. Use it when user memory keeps growing across sessions and you want MemexAI to clean the durable record between conversations: merge duplicate facts, compact fragmented notes, resolve direct corrections, refresh stale indexes, and keep files readable for the next agent trajectory.

Turn on the scheduler with:

MEMEX_DREAM_ENABLED=true

The database dream_enabled config key is the runtime master switch. The admin Dreams panel and endpoints under /v1/admin/dream/* let operators read and update dream config, list user dream status, pause all dreaming, and pause or resume specific users.

Dreaming skips users with no qualifying memory changes, waits for the configured grace period after the latest write, excludes log files from consolidation, and avoids writing user/dream-log.md when there was nothing to update.

See Background Dreaming for the full operating model.

On this page