MemClaw / docs
Concepts

Architecture

Every service, resident, and topic in Caura — the core tier that ships in OSS, the platform tier that ships managed, how a write flows through the event bus, and what differs between self-host and managed deployments.

Four core services, one event bus, scheduled residents, Postgres + pgvector underneath. Synchronous on the response path, async on the heavy work. Two tiers: the core tier (core-* services) is the OSS product; the platform tier (the gateway and platform-* services) is the managed and enterprise control plane — structurally separate, not just commercially.

Memories enter through one of exactly three ingest paths — realtime (an agent chose to write), reflective (the Interviewer), and bulk (imports and documents). The memory pipeline page follows one write through the stages; this page maps the machinery.

Core tier

core-api

FastAPI service and the hot node. Handles HTTP and MCP requests — the MCP server is mounted at /mcp on the same app, so a single deployment serves both surfaces. It applies auth, trust, quotas, and keystones; writes raw memories; serves recall reads (vector + full-text + entity-graph, blended); and hosts the Interviewer submit endpoint, the Skills Inbox routes, and the admin lifecycle-fanout endpoints the residents fire into.

After a successful write, what happens next depends on the deployment (see the variance table): on self-host (deployment_mode=inline, the OSS default) core-api embeds and enriches inline on the write path; on managed (deferred) it publishes embed-requested / enrich-requested to the event bus for core-worker. Contradiction detection runs post-commit, fire-and-forget via an async track_task (see services/contradiction_detector.py's detect_contradictions_async) — the write itself does not block on it.

core-api is also a consumer: it subscribes to memclaw.memory.embedded / .enriched (the return edge on the diagram — how contradiction detection fires on the deferred path), to the crystallize / entity-link / insights lifecycle topics (their pipeline machinery lives here), and to memclaw.org.settings-changed as a broadcast so every process drops its settings cache when governance controls change.

core-worker

Async worker, managed deployments only — the OSS compose stack does not include it, and doesn't need it: OSS runs inline. On managed it subscribes to embed-requested and enrich-requested, calls the configured embedding + entity-extraction providers, writes structured rows back through core-storage-api, and also carries the archive/purge lifecycle consumers (per-tenant concurrency, retry + DLQ).

core-storage-api

Thin Postgres gateway used by every other service for memory CRUD and pgvector ops. Runs two uvicorn workers by default (its Dockerfile CMD); raising that means overriding the container command — measure against your own workload before backfills rather than assuming a throughput number.

core-operations

The scheduler service — a fourth core service that fires nine registered cron ticks (see core-operations/src/core_operations/app.py). Each tick calls a core-api admin endpoint, which fans out one event per active tenant; tenants that haven't opted in to a feature never appear in its fanout and pay zero cost.

TickCadenceDrives
lifecycle-archive-expireddailyarchive memories past their expiry
lifecycle-archive-staledailyarchive long-untouched memories
lifecycle-purge-soft-deleteddailyhard-delete soft-deleted rows past retention
lifecycle-crystallizedailyCrystallizer consolidation
lifecycle-entity-linkdailyentity-link discovery
lifecycle-insightsdailyinsights discovery
agent-digestdailyper-agent activity digests (opt-in)
agent-digest-weeklyweeklyweekly digest window
interviewer-schedulehourlyqueues due interview_request fleet commands

One deliberate exception: Forge distillation is not a core-operations tick. Its cadence comes from an external scheduler hitting POST /admin/lifecycle/fanout/forge-distill — on self-host you provide that cron; on managed the platform fires it. This is the only feature whose schedule is operator-supplied.

Redis

In both compose files and required: backs the cache and per-tenant rate limits, and is health-probed by /api/v1/health. Without it, caching and rate limiting fail — it is not an optional accelerator.

TEI local embedder (optional)

A supported local-embedding deployment (--profile embed-local in compose): Text Embeddings Inference serving BAAI/bge-m3 (1024-dim), for self-hosters who want no external embedding API. Without it, embedding uses the configured remote provider.

Residents

A resident is a scheduled server-side job that operates on stored data rather than serving a request: the six lifecycle jobs, Agent Digests, the Interviewer scheduler, and Forge. core-operations provides the clock; the work itself runs where each consumer is registered:

  • embed / enrich and archive / purge — core-worker on managed; core-api on OSS (no worker process).
  • crystallize / entity-link / insights — always core-api, in both deployments (the pipeline machinery lives there).
  • Forge distill — consumed via the Skill Factory service code in core-api; cadence operator-supplied on self-host (above).

Every lifecycle tick writes one lifecycle_audit row per tenant, so a silent failure is visible in data, not just logs.

Event bus

OSS default is an in-process bus; the managed deployment uses Google Pub/Sub. The /api/v1/health route's event_bus field reports the current backend's status. Five topic families (common/events/topics.py):

FamilyTopics
memclaw.memory.*created · embed-requested · embedded · enrich-requested · enriched
memclaw.lifecycle.*archive-expired-requested · archive-stale-requested · purge-soft-deleted-requested · crystallize-requested · entity-link-requested · insights-requested · forge-distill-requested
memclaw.pipeline.*entity-extract-requested · entity-extracted
memclaw.org.*settings-changed (broadcast — every process drops its settings cache) · suppression-changed (tenant suppress / restore mirroring)
memclaw.audit.*event-recorded

The write flow is a loop, not a line: embedded / enriched flow back to core-api (green arrow on the diagram), which is how contradiction detection fires on the deferred path — the worker announces completion, core-api reacts.

Platform tier (managed / enterprise)

Self-hosters can skip this section — none of it runs in the OSS stack. On managed deployments an nginx gateway fronts everything, and six platform-* services form the control plane: platform-auth-api (identity — API keys, Broker installs), platform-audit-api (the tamper-evident audit log), platform-admin-api (tenant administration), platform-storage-api, platform-operations (platform-side scheduled jobs), and an internal devops bot.

The Broker's place in the system

The Caura Broker is the local daemon (memclawd) on a developer machine that connects coding agents to Caura and enforces policy, redaction, and audit before anything leaves the machine. Architecturally it is a producer (lane 0) with its own identity plane:

  • Frozen wire contract. The install endpoints (installs/register, claim, heartbeat, policy/stream) plus audit-log are a frozen v1 contract, enforced by oasdiff breaking-change gates in CI in both repos (platform-auth-api/openapi.broker.json, platform-audit-api/openapi.broker.json; the OSS core-api baseline landed with its own gate). A breaking change to what deployed Brokers depend on fails the PR.
  • Verified identity. The gateway plumbs X-Caura-Credential-Kind: install_credential and X-Install-UUID into core-api, which namespaces Broker-owned agents as broker:<install> — cross-install attribution can't be forged, and bulk writes carry per-item attribution.
  • Two modes. Personal mode (an unjoined install) works self-contained; Fleet mode joins the install to a Broker Fleet for heartbeats, policy streaming, and dashboard governance.

How install credentials differ from user API keys, and what broker:<install> ownership means for reads, is covered under trust levels.

Deployment variance

Say it once: what actually differs between the stacks.

ConcernSelf-host (OSS)Managed / enterprise
Embed + enrichInline in core-api (deployment_mode=inline)Deferred to core-worker
core-worker processNot in composeSeparate service
Event busInProcessEventBusGoogle Pub/Sub
Archive / purge consumersRegistered in core-apiSubscribed by core-worker
Crystallize / entity-link / insightscore-apicore-api (same)
Forge cadenceOperator-provided external cronFired by managed infra
Broker governancePersonal modeFleet mode: heartbeat, policy stream, audit
EmbeddingsOpenAI-compatible provider or TEI localPlatform-tier provider (Vertex)
Platform tier + gatewayAbsentPresent

OpenClaw plugin (optional)

Lives inside an OpenClaw gateway and claims the memory slot, replacing memory-core and exposing the memclaw_* tools to every agent that runs through the gateway. It is also the push-delivery path for Skill Factory active skills and hosts the plugin-buffer Interviewer collector. See OpenClaw integration.