# ============================================================================ # MemClaw OSS — Environment Configuration # ============================================================================ # Copy to .env and fill in your provider + API key. The stack starts with # dummy (fake) providers by default — set at least one real provider below # for meaningful semantic search and LLM enrichment. # # Supported provider combinations (pick one row): # # Provider | EMBEDDING_PROVIDER | ENTITY_EXTRACTION_PROVIDER | Key to set # ------------|--------------------| ---------------------------|------------------- # OpenAI | openai | openai | OPENAI_API_KEY # Anthropic | openai * | anthropic | ANTHROPIC_API_KEY (+ OPENAI_API_KEY for embeddings) # Gemini | openai * | gemini | GEMINI_API_KEY (+ OPENAI_API_KEY for embeddings) # OpenRouter | openai * | openrouter | OPENROUTER_API_KEY (+ OPENAI_API_KEY for embeddings) # # * Anthropic, Gemini, and OpenRouter don't offer embedding APIs here, so pair # them with OpenAI for embeddings. # # Note: Vertex AI is reserved for platform-tier deployments (enterprise) and is # not available as a tenant-facing provider. # -- Mode ------------------------------------------------------------------- IS_STANDALONE=true # Also the default environment identity for the Pub/Sub event bus: when # EVENT_BUS_BACKEND=pubsub, the bus stamps each message with this value and # drops messages published by a sibling environment that shares the same GCP # project's topics. Override independently with EVENT_BUS_ENV if the bus # identity must differ from ENVIRONMENT. Irrelevant for the default # in-process bus (single environment per process). ENVIRONMENT=development # -- Image version (docker-compose only) ------------------------------------ # Pin the published image tag pulled from ghcr.io on first ``up``. # Defaults to ``latest`` (the most recent stable release). Subsequent # ``up`` commands re-use the cached image (``pull_policy: missing`` # in docker-compose.yml) — to fetch a newer image at the same tag, run: # # docker compose pull && docker compose up -d # # Set to a specific version like ``v1.0.0`` for reproducibility. To # build from local source instead, run # ``docker compose up --build --no-pull``. # # MEMCLAW_VERSION is tag-only (it expands inline into ``image:`` for # both core-api and core-storage-api). For *digest pinning* — strict # supply-chain reproducibility — a single MEMCLAW_VERSION is not # enough: the two services have different images and therefore # different sha256 digests, so a shared digest would fail to pull on # whichever service it doesn't belong to. Pin per-service via a # docker-compose.override.yml that hardcodes each ``image:`` to its # own ``name:tag@sha256:``. Look up each service's digest with: # docker buildx imagetools inspect ghcr.io/caura-ai/caura-memclaw-core-api:v1.2.3 # docker buildx imagetools inspect ghcr.io/caura-ai/caura-memclaw-core-storage-api:v1.2.3 # MEMCLAW_VERSION=latest # -- Database (PostgreSQL + pgvector) ---------------------------------------- POSTGRES_HOST=127.0.0.1 POSTGRES_PORT=5432 POSTGRES_USER=memclaw # REQUIRED: change in production POSTGRES_PASSWORD=changeme POSTGRES_DB=memclaw # Set true in production POSTGRES_REQUIRE_SSL=false # -- Auth ------------------------------------------------------------------- # Admin API key — gates /api/admin/* routes. REQUIRED in production. ADMIN_API_KEY= # Optional: when set, ALL non-admin requests must include this key via X-API-Key. # Useful when exposing the API to a network (not just localhost). MEMCLAW_API_KEY= # -- Embedding provider ----------------------------------------------------- # Options: openai | local | fake EMBEDDING_PROVIDER=openai # Required if EMBEDDING_PROVIDER=openai or ENTITY_EXTRACTION_PROVIDER=openai OPENAI_API_KEY= # -- Local embedder (opt-in: BAAI/bge-m3 via TEI sidecar) ------------------- # When you bring up the stack with ``--profile embed-local``, the # ``tei`` service runs HuggingFace Text Embeddings Inference with # ``BAAI/bge-m3`` (1024-dim, MIT, multilingual). It speaks the same # OpenAI-compatible API, so the existing ``EMBEDDING_PROVIDER=openai`` # path is reused — point it at the sidecar with ``OPENAI_EMBEDDING_BASE_URL``. # # Quickstart: # docker compose --profile embed-local up -d # # core-api transparently embeds via tei:80 instead of api.openai.com. # # All four envs are unset by default — leave them empty to keep using # OpenAI's hosted embeddings. Schema is at 1024-dim (alembic 010), so a # matching 1024-dim model is required when self-hosting. See # ``docs/local-embedder.md`` for the full story (model swaps, GPU image # tag, instruction-aware models like Qwen3-Embedding, etc.). # # OPENAI_EMBEDDING_BASE_URL=http://tei:80/v1 # OPENAI_EMBEDDING_MODEL=BAAI/bge-m3 # TEI rejects the ``dimensions=`` SDK kwarg — must be false when talking to TEI. # OPENAI_EMBEDDING_SEND_DIMENSIONS=false # Optional: only set when running an instruction-aware model (Qwen3-Embedding, # e5-instruct). bge-m3 is symmetric — leave empty. # EMBEDDING_QUERY_INSTRUCTION= # Optional: Matryoshka truncation for native >1024-dim models against the # 1024 schema. bge-m3 is native 1024 — leave empty. # OPENAI_EMBEDDING_TRUNCATE_TO_DIM= # Compose-only knobs (read by docker-compose.yml's ``tei`` service): # Default CPU build; switch to ``89-1.7`` for an L4-class GPU host. # TEI_IMAGE_TAG=cpu-1.7 # Default model. Change requires a re-embed when changing dim or pooling. # TEI_MODEL_ID=BAAI/bge-m3 # -- LLM enrichment --------------------------------------------------------- USE_LLM_FOR_MEMORY_CREATION=true # Options: openai | anthropic | openrouter | gemini | fake | none ENTITY_EXTRACTION_PROVIDER=openai ENTITY_EXTRACTION_MODEL=gpt-5.4-nano # Outer cap on the inline embed+enrich gather (ParallelEmbedEnrich). # Must stay below REQUEST_TIMEOUT_SECONDS so this fires first. # ENRICHMENT_INLINE_TIMEOUT_SECONDS=35.0 # Per-call timeout passed to AsyncOpenAI (covers LLM + embedding). # OPENAI_REQUEST_TIMEOUT_SECONDS=25.0 # -- Provider API keys (set the ones matching your chosen providers) --------- ANTHROPIC_API_KEY= OPENROUTER_API_KEY= # Gemini Developer API (key-auth, no GCP project / ADC required) GEMINI_API_KEY= # -- Provider model overrides (optional) ------------------------------------ # Override the default model for each provider. Defaults shown. # ANTHROPIC_DEFAULT_MODEL=claude-haiku-4-5-20251001 # GEMINI_DEFAULT_MODEL=gemini-3.1-flash-lite-preview # OPENROUTER_DEFAULT_MODEL=openai/gpt-5.4-nano # LLM_FALLBACK_MODEL_OPENAI=gpt-5.4-nano # OPENAI_EMBEDDING_MODEL=text-embedding-3-small # Embeddings: only OpenAI is supported in-tree. Other providers (Vertex, # self-hosted, etc.) require a custom EmbeddingProvider implementation; the # pgvector schema requires output dim == VECTOR_DIM (default 1024). # -- Platform-tier providers (enterprise only) ------------------------------ # Operator-managed singleton providers used when a tenant has no own credentials. # Leave empty for OSS self-hosted — tenants then use their own API keys above # or fall back to fake providers. Platform keys NEVER enter tenant-configurable # code paths. # # PLATFORM_LLM_PROVIDER= # vertex | openai | "" (disabled) # PLATFORM_LLM_MODEL= # e.g. gemini-3.1-flash-lite-preview, gpt-5.4-nano # PLATFORM_LLM_API_KEY= # OpenAI API key (when PLATFORM_LLM_PROVIDER=openai) # PLATFORM_LLM_GCP_PROJECT_ID= # GCP project (when PLATFORM_LLM_PROVIDER=vertex) # PLATFORM_LLM_GCP_LOCATION=us-central1 # GCP region (Vertex) # # PLATFORM_EMBEDDING_PROVIDER= # openai | "" (disabled) # PLATFORM_EMBEDDING_MODEL= # e.g. text-embedding-3-small # PLATFORM_EMBEDDING_API_KEY= # OpenAI API key for platform embeddings # -- Core Storage API ------------------------------------------------------- CORE_STORAGE_API_URL=http://localhost:8002 # -- Redis (optional) ------------------------------------------------------- # Empty = in-memory fallback. Set for production / multi-replica deployments. REDIS_URL= # -- Short-Term Memory (STM) ------------------------------------------------ USE_STM=false # memory | redis STM_BACKEND=memory # 24h STM_NOTES_TTL=86400 # 48h STM_BULLETIN_TTL=172800 # -- Crystallizer ----------------------------------------------------------- CRYSTALLIZER_ENABLED=true CRYSTALLIZER_STALE_DAYS=180 CRYSTALLIZER_DEDUP_THRESHOLD=0.95 # -- CORS ------------------------------------------------------------------- CORS_ORIGINS=http://localhost:3000 # -- Sentry (optional error tracking) --------------------------------------- SENTRY_DSN= # -- Database pool ----------------------------------------------------------- DB_POOL_SIZE=50 DB_MAX_OVERFLOW=50