Caura (formerly MemClaw) — the shared governed memory layer for AI agent fleets
Caura — formerly MemClaw — is open-source memory for multi-tenant, multi-agent AI fleets. Your agents store what they learn, find what the fleet knows, and get smarter with every interaction — learning from each other instead of repeating mistakes.
Agents write plain text. Caura turns it into searchable, governed, self-improving memory.
One loop, three pillars: write, recall, compound — every interaction makes the next one smarter.
Built for fleets, not single agents. Public agent-memory benchmarks (LoCoMo, LongMemEval) measure one agent, one user, one long conversation — the single-chatbot shape. The deployment shape we see in production is the opposite: dozens or thousands of agents working on behalf of a company, sharing what they learn under governance. Caura is architected around that shape from day one — scoped memory, cross-agent outcome propagation, fleet-wide trust tiers — and competes on the axes that compound with agent count: latency, token efficiency, and governance. See Performance for the numbers, or read the benchmarks write-up.
In production at eToro (NASDAQ: ETOR): 300+ AI agents on one governed memory — 26,500+ memories, 1,372 shared skills, 23 ms p50 search. Architecture deep-dive →
Quick Start
Try it locally — no API key, no signup
The fastest way to see Caura work. Standalone mode runs single-tenant with auth bypassed — write and recall a memory in four commands. (It boots with dummy embeddings so there's nothing to configure; add an AI provider key for semantic search — see Self-Hosted below.)
git clone https://github.com/caura-ai/caura.git
cd caura-memclaw
cp .env.example .env && echo "IS_STANDALONE=true" >> .env # single-tenant, no API key
docker compose up -d # Postgres + pgvector + Redis + API (~30s)
# Write a memory — no API key needed
curl -X POST http://localhost:8000/api/v1/memories \
-H "X-API-Key: standalone" -H "Content-Type: application/json" \
-d '{"tenant_id": "default", "content": "Our auth service uses JWT with 15-minute expiry."}'
# Search for it
curl -X POST http://localhost:8000/api/v1/search \
-H "X-API-Key: standalone" -H "Content-Type: application/json" \
-d '{"tenant_id": "default", "query": "authentication token lifetime"}'
The write response comes back enriched with an LLM-inferred memory_type, title, summary, tags, status, and weight — all from a single content field.
Ready for semantic recall, multi-tenant, a managed host, or an OpenClaw fleet? Pick a path below.
Three paths — pick the one that matches your setup:
| Path | When | Time to first memory |
|---|---|---|
| Managed platform | Quickest. We host the DB + scaling. | ~2 min |
| Self-hosted (Docker) | Privacy / on-prem / air-gapped. | ~5 min |
| OpenClaw plugin | You already run an OpenClaw fleet — install Caura as a plugin against any of the above. | ~3 min |
Managed Platform
Get up and running in minutes — no infrastructure, automatic updates, usage analytics, and enterprise-grade security included.
- Sign up free on caura.ai
- Grab your API key from the dashboard
- Connect via MCP or REST:
{
"mcpServers": {
"caura": {
"url": "https://caura.ai/mcp",
"headers": { "X-API-Key": "mc_your_api_key_here" }
}
}
}
Production / team use: the quickstart key above is a tenant-scoped credential — fine for personal use, but a fleet of agents should bind each one to its own agent-scoped credential for trust gating, fleet membership, and per-agent keystones. Provision agent-scoped credentials atomically via
POST /api/v1/admin/agent-keys/provision, or through the dashboard at/settings/organization/api-credentials. Both kinds use themc_prefix on the wire — scope is bound at mint time on the credential itself. The MCP server accepts the credential on eitherX-API-Key: mc_…orAuthorization: Bearer mc_…. (Pre-existingmca_…andmci_…keys continue to authenticate via back-compat.)Using a tenant-scoped credential? Pass an explicit
agent_idon every MCP tool call — the gateway refuses the reserved default (mcp-agent) on the tenant-scoped path.
Self-Hosted (Open Source)
The fastest path is Docker Compose — one command brings up Postgres + pgvector + Redis + the API.
Prefer not to use Docker? Skip to Manual deployment (Python + Postgres) below for the bare-Python path.
No cloud API key, no external calls? v2.0+ supports a self-hosted local embedder (
BAAI/bge-m3via HuggingFace TEI) — seedocs/local-embedder.md. The setup below walks through the OpenAI default; the local-embedder doc walks through the alternative.
Prerequisites
- Docker Engine 24+ (Linux) or Docker Desktop (macOS / Windows). Confirm with
docker --version. - Docker Compose v2 (built into modern Docker). Confirm with
docker compose version. - Git for cloning.
- ~2 GB free disk for images + Postgres data volume.
1. Clone and configure
git clone https://github.com/caura-ai/caura.git
cd caura-memclaw
cp .env.example .env
Set your AI provider in .env — minimal setup with OpenAI:
EMBEDDING_PROVIDER=openai
ENTITY_EXTRACTION_PROVIDER=openai
USE_LLM_FOR_MEMORY_CREATION=true
OPENAI_API_KEY=sk-...
Without any AI keys the stack still starts — dummy providers return non-semantic embeddings, useful for testing the API surface.
💡 Want zero cloud API calls? v2.0+ ships a self-hosted embedder profile (
BAAI/bge-m3on a HuggingFace TEI sidecar). Bring up the stack withdocker compose --profile embed-local up -dand set the fourOPENAI_EMBEDDING_*envs from.env.example— seedocs/local-embedder.mdfor the full setup. Combined withIS_STANDALONE=true(below) this is a fully self-contained deployment with no external API calls.
| Provider | .env settings |
Required key |
|---|---|---|
| OpenAI (default) | EMBEDDING_PROVIDER=openaiENTITY_EXTRACTION_PROVIDER=openai |
OPENAI_API_KEY |
| Google Gemini | EMBEDDING_PROVIDER=openaiENTITY_EXTRACTION_PROVIDER=gemini |
GEMINI_API_KEY + OPENAI_API_KEY |
| Anthropic | EMBEDDING_PROVIDER=openaiENTITY_EXTRACTION_PROVIDER=anthropic |
ANTHROPIC_API_KEY + OPENAI_API_KEY |
| OpenRouter | EMBEDDING_PROVIDER=openaiENTITY_EXTRACTION_PROVIDER=openrouter |
OPENROUTER_API_KEY + OPENAI_API_KEY |
| Self-hosted (TEI / bge-m3) | --profile embed-local + OPENAI_EMBEDDING_BASE_URL=http://tei:80/v1+ OPENAI_EMBEDDING_MODEL=BAAI/bge-m3+ OPENAI_EMBEDDING_SEND_DIMENSIONS=false |
none — runs locally |
Anthropic, Gemini, and OpenRouter don't offer embedding APIs here — pair them with OpenAI (or with TEI) for embeddings. You can mix providers freely. Gemini uses the Google AI Studio key-auth Developer API (no GCP project/ADC required). The self-hosted TEI row keeps EMBEDDING_PROVIDER=openai because TEI speaks the same OpenAI-compatible API; see docs/local-embedder.md for hardware sizing, GPU setup, and model swapping.
2. Start the stack
docker compose up -d
By default this pulls the multi-arch images from ghcr.io (linux/amd64 + linux/arm64) on first run — takes ~30 seconds. Subsequent up commands re-use the cached image (no registry round-trip, works offline). To pin a specific version, set MEMCLAW_VERSION=v1.2.3 in your .env. To build from local source instead (e.g. when iterating on a fork), run docker compose up --build --no-pull.
To upgrade to a newer image at the same tag (e.g. :latest after we cut a new release), run docker compose pull && docker compose up -d. Without an explicit pull, the local cache wins — there's no silent version drift.
Offline / air-gapped operation: depending on whether the image is already cached locally:
- Image cached, no network:
docker compose up -dworks as-is —pull_policy: missingdoesn't try to pull when the image is present. Usedocker compose up --no-pullif you want to be explicit.- No local image, no network:
docker compose up --build --no-pull(build from source, don't try to pull).- Strict no-network guarantee (e.g. an air-gapped pipeline that should never reach
ghcr.io): drop adocker-compose.override.ymlsettingpull_policy: neverfor both services — Compose then fails fast if the image is absent rather than attempting a pull.
| Service | URL |
|---|---|
| Core API (REST + MCP) | http://localhost:8000 |
| Core Storage API | http://localhost:8002 |
| PostgreSQL (pgvector) | localhost:5432 |
| Redis | localhost:6379 |
What the stack contains — and what it doesn't
docker compose up starts exactly four containers:
| Container | Role |
|---|---|
db |
PostgreSQL 16 + pgvector |
redis |
Cache and rate limiting |
core-storage-api |
Storage service (SQL + vector search) |
core-api |
REST + MCP surface; embedding and enrichment run in-process (deployment_mode=inline, the default) |
A fifth service, tei (the local embedder), is defined in the compose file but only starts with --profile embed-local. Components you may see referenced elsewhere in this repo — core-worker, the platform-tier services, the Google Pub/Sub event bus — run only in managed/enterprise deployments. The OSS stack uses the in-process event bus, and inline mode embeds and enriches inside core-api itself, so no worker service is needed.
3. Verify
curl http://localhost:8000/api/v1/health
# {"status":"ok","storage":"connected","redis":"connected","event_bus":"ok"}
4. Write and search
# Write a memory (standalone mode — no API key needed)
curl -X POST http://localhost:8000/api/v1/memories \
-H "X-API-Key: standalone" \
-H "Content-Type: application/json" \
-d '{"tenant_id": "default", "content": "Our auth service uses JWT with 15-minute expiry."}'
# Search for it
curl -X POST http://localhost:8000/api/v1/search \
-H "X-API-Key: standalone" \
-H "Content-Type: application/json" \
-d '{"tenant_id": "default", "query": "authentication token lifetime"}'
The write response carries an LLM-inferred memory_type, title, summary, tags, status, and a weight (the importance score) — all derived from a single content field. On the default fast-write path, enrichment is applied asynchronously: the immediate response is marked enrichment_pending and the inferred fields populate within moments.
POST /search returns matches under an items array, each entry the full memory plus a similarity score:
{
"items": [
{
"id": "…",
"agent_id": "mcp-agent",
"memory_type": "fact",
"title": "Auth service uses JWT with 15-minute expiry",
"similarity": 0.47,
"visibility": "scope_team",
"status": "active"
}
]
}
Embedding is asynchronous too, so a just-written memory may not surface in
semantic search right after the write returns. The write response says so:
metadata.embedding_pending: true means the row was stored without an embedding
and a background backfill is scheduled. Until it lands the memory is already
reachable by keyword and in the non-semantic GET /memories list — it just
doesn't compete on semantic similarity yet. Budget ~15–20s in production; a
slower backfill (staging, or a saturated worker) can take minutes, so treat the
flag as the signal rather than assuming a fixed delay.
If a caller has to search for what it just wrote, pass write_mode: "strong" on
the write. That embeds inline — the response comes back with no
embedding_pending and the memory is immediately searchable. The trade is an
embedding provider call on the request path, which is precisely what fast mode's
sub-2s p99 visibility target exists to avoid, so it's worth choosing per write
rather than switching on globally. (A deployment configured to embed inline, the
default for a local OSS install, never sets the flag at all.)
⭐ If Caura just worked for you, star the repo — it's how other fleet builders find us, and it shapes how much time we can invest in the OSS edition.
OSS supports three auth paths. Pick one and add it to your .env, then docker compose up -d to restart.
Standalone — single-tenant (tenant_id="default"), simplest for local / self-install:
IS_STANDALONE=true
No API key required for REST. MCP still expects a non-empty X-API-Key header — any value works.
Pair Standalone mode with
--profile embed-local(seedocs/local-embedder.md) for a fully self-contained deployment: no admin keys, no external API calls, all embeddings computed locally. Useful for offline / air-gapped environments and personal-laptop installs.
Admin key — multi-tenant with full access:
ADMIN_API_KEY=your-long-random-admin-key
Pass X-API-Key: your-long-random-admin-key and include tenant_id in request bodies / query params.
Shared gate — for network-exposed OSS deployments:
MEMCLAW_API_KEY=your-shared-key
Clients send X-API-Key: your-shared-key plus X-Tenant-ID: <tenant>.
See AGENT-INSTALL.md for the full agent self-install walkthrough.
# Unit tests (no DB needed)
pytest tests/ -m "unit"
# All tests (requires PostgreSQL)
docker compose up -d db
pytest tests/ -m "not benchmark"
# Smoke test against live API (~30s, auto-cleanup)
python scripts/smoke_test.py --url http://localhost:8000 --api-key <admin-key>
OpenClaw Plugin
Already running an OpenClaw fleet? Install Caura as a plugin against either the managed platform or your self-hosted stack:
# Point at whichever URL hosts your Caura API
export CAURA_URL=https://caura.ai # managed
# or: export CAURA_URL=http://localhost:8000 # self-hosted
export CAURA_KEY=your-key # `standalone` works in self-hosted standalone mode
export CAURA_FLEET=my-fleet
curl -sf -H "X-API-Key: $CAURA_KEY" \
"$CAURA_URL/api/v1/install-plugin?fleet_id=$CAURA_FLEET&api_url=$CAURA_URL" | bash
# Restart the gateway to load the plugin
openclaw gateway restart
The plugin claims the OpenClaw memory slot (replacing memory-core) and exposes the same 12 MCP tools. Full setup, agent prompts, and trust levels: static/docs/integration-guide.md.
Python client
Talk to any Caura deployment (managed or self-hosted) from Python:
pip install caura-client
from caura_client import Caura
mc = Caura("mc_xxx", tenant_id="my-team", agent_id="my-agent")
mc.write("Q3 revenue target is $4M, set on 2026-04-15.")
print(mc.recall("Q3 revenue target").summary)
Formerly memclaw-client — the old package name, the memclaw_client
import, and the MemClaw class all keep working forever as aliases.
A thin wrapper over the REST API — see clients/python/ for the full client.
TypeScript client
Same, from TypeScript / JavaScript (Node 18+, zero dependencies):
npm install @caura/memclaw-client
import { Caura } from "@caura/memclaw-client";
const mc = new Caura("mc_xxx", { tenantId: "my-team", agentId: "my-agent" });
await mc.write("Q3 revenue target is $4M, set on 2026-04-15.");
console.log((await mc.recall("Q3 revenue target")).summary);
MemClaw remains a permanent alias of Caura, and npm install caura
works too (a re-export of this package).
See clients/typescript/ for the full client.
Features
Governance
- Tenant isolation — row-level database separation per tenant; PII auto-detected and flagged on every write (surfaced in memory metadata as
contains_pii/pii_types) - Visibility scopes — every memory is stamped at write time:
scope_agent(private),scope_team(fleet-wide, default), orscope_org(cross-fleet). Cross-fleet recall is permissioned, not open - Agent trust tiers — four levels control cross-fleet reads, writes, and deletes. Agents are either provisioned atomically via
POST /admin/agent-keys/provision(recommended — mints key + row + trust + fleet in one call) or auto-registered on first write (legacy fallback) - Full audit log — every write, delete, and transition logged with tenant and scope context
- Agent activity digests — daily and weekly per-agent digests, generated server-side for opted-in orgs (org setting
agent_digest.enabled, off by default). They run from core-operations'agent-digest/agent-digest-weeklycron ticks and are read back via the reports endpoints incore-api(GET /api/v1/reports,GET /api/v1/reports/agent-activity). A tenant that hasn't opted in pays zero cost
Memory Pipeline
- Single-pass LLM enrichment — every write auto-classifies into one of 14 memory types, generates title/summary/tags, scores importance, flags PII, and extracts entities — from a single
contentfield - Hybrid search — pgvector semantic similarity + full-text keyword matching + knowledge graph expansion (up to 2 hops), ranked by composite score of similarity, importance, freshness, and graph boost
- Live knowledge graph — people, orgs, locations, and concepts extracted into entities and relations on every write. Semantic entity resolution (>0.85 cosine) auto-merges duplicates
- Contradiction detection — RDF triple comparison + LLM semantic analysis detects conflicting memories and automatically supersedes them, with full contradiction chain tracking
Self-Improving Memory
- Outcome-based learning (Karpathy Loop) — agents report success/failure after acting on recalled memories; the system reinforces what works and auto-generates preventive
rule-type memories on failure - Crystallization — LLM merges near-duplicate memories into canonical atomic facts with full provenance; 8-status lifecycle automation retires stale data
- Per-agent retrieval tuning — each agent optimizes its own retrieval profile (top_k, min_similarity, graph_max_hops, blend weights) from feedback, so search quality compounds with every interaction
Integrations
- MCP server — built-in Model Context Protocol at
/mcp(Streamable HTTP). Connect Claude Desktop, Claude Code, Cursor, Windsurf, or any MCP client with a URL and API key - Multi-provider LLM — primary + fallback provider chain per tenant (OpenAI, Gemini, Anthropic, OpenRouter) with platform defaults for zero-config tenants
- Document store — structured JSONB collections alongside semantic memories for exact-field lookups (customer records, config, task lists)
How Caura compares
Accuracy benchmarks cluster the leading tools in a narrow band (see Performance). Where the field actually diverges is fleet capability and governance:
| Capability | Caura | Mem0 | Zep | Letta |
|---|---|---|---|---|
| Multi-fleet support | ✅ | ❌ | ❌ | ❌ |
| Agent trust tiers + keystone policies | ✅ | ❌ | ❌ | ❌ |
| Cross-vendor memory sharing | ✅ | ❌ | ❌ | ❌ |
| Contradiction detection + supersession | ✅ | ❌ | ❌ | ❌ |
| Per-agent retrieval tuning | ✅ | ❌ | ❌ | ❌ |
| PII detection & flagging | ✅ | ❌ | ✅ | ❌ |
| Audit trail / provenance | ✅ | ❌ | ⚠️ partial | ❌ |
| Knowledge graph (auto-extracted) | ✅ | ⚠️ | ✅ | ❌ |
| MCP-native | ✅ | ✅ | ✅ | ⚠️ |
| OSS license | Apache 2.0 | Apache 2.0 | Apache 2.0 | Apache 2.0 |
Mem0, Zep, and Letta are solid projects for single-agent memory. Caura's lane is governed memory across agent fleets — multiple agents, teams, and vendors on one auditable memory plane. Comparison reflects our reading of public docs as of June 2026 — corrections welcome via issue or PR.
Performance
Benchmarked against the two most-cited public agent-memory benchmarks. Full results, methodology, and how to reproduce them live in BENCHMARKS.md; operator-scale context is in docs/performance.md; the full write-up is on the blog.
| LoCoMo | LongMemEval | Search latency | |
|---|---|---|---|
| Accuracy (LLM-judge) | 77.6% | 72.5% | — |
| Token savings vs full context | 96.6% | 98.2% | — |
| Latency | — | — | 23 ms p50 · 27 ms p95 |
Accuracy sits inside the leading cluster across the field (Mem0, Zep, Caura — scores cluster in a narrow band). The axes we push hardest are latency and token efficiency, because those are the ones that compound as agent count grows — a few hundred ms of search latency disappears behind one LLM call, but bills millions of times a day across a fleet.
Single-agent benchmarks can't measure cross-agent recall, outcome propagation between agents, fleet-scoped visibility, or governance-aware retrieval. Those are the questions that decide whether a memory system is deployable inside a company. See
docs/performance.md.
Source: Fast, Token-Efficient, and Built for Fleets (2026-04-19).
MCP (Model Context Protocol)
Add Caura to any MCP client with one config block.
Self-hosted (localhost):
{
"mcpServers": {
"caura": {
"url": "http://localhost:8000/mcp",
"headers": { "X-API-Key": "standalone" }
}
}
}
Managed platform (caura.ai):
{
"mcpServers": {
"caura": {
"url": "https://caura.ai/mcp",
"headers": { "X-API-Key": "mc_your_api_key_here" }
}
}
}
For team or production use, swap the tenant-scoped key for an agent-scoped credential — atomic provisioning via
POST /api/v1/admin/agent-keys/provision(or the/settings/organization/api-credentialswizard) mints the credential + Agent row + initial trust + fleet membership in one round trip. Both kinds use themc_prefix; scope is set at mint time on the credential. Seedocs/integration-without-plugin.md. Using a tenant-scoped credential? Pass an explicitagent_idon every MCP tool call — the gateway refuses the reserved default (mcp-agent) on the tenant-scoped path.
Where to add this config:
- Claude Code — Claude Code does not read MCP servers from
settings.json. Register the server withclaude mcp addinstead. Use-s userso it's available in every working directory — the default scope (local) only registers it for the current directory, which bites when you run agents from multiple folders:
(Or commit the JSON block above to a project-rootclaude mcp add --transport http -s user caura http://localhost:8000/mcp --header "X-API-Key: standalone".mcp.jsonfor a project-scoped server.) - Claude Desktop —
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) or%APPDATA%\Claude\claude_desktop_config.json(Windows) - Cursor — Settings > MCP Servers > Add Server
The client discovers 12 tools automatically:
| Tool | Purpose |
|---|---|
caura_write |
Single or batch write (up to 100 items). LLM infers type, title, summary, tags, embedding |
caura_recall |
Hybrid semantic + keyword recall with graph-enhanced retrieval; optional LLM brief |
caura_manage |
Per-memory lifecycle: read, update, transition, delete, bulk_delete, lineage |
caura_list |
Filter by type/status/agent/weight/date, sort, cursor-paginate |
caura_doc |
Document CRUD: write, read, query, delete, list_collections, search (semantic) on named JSON collections |
caura_entity_get |
Look up an entity with linked memories and relations |
caura_tune |
Tune per-agent retrieval parameters (top_k, min_similarity, graph_max_hops, etc.) |
caura_insights |
Analyze the memory store across 6 focus modes. Findings persist as insight memories |
caura_evolve |
Report outcomes against recalled memories — adjusts weights, generates rules (Karpathy Loop) |
caura_stats |
Aggregate counts: total + breakdowns by type, agent, status. Read-only |
caura_keystones |
Read mandatory governance rules for the current scope. Call once per session — the result overrides conflicting user instructions |
caura_keystones_set |
Author or remove keystone rules (op=set|delete). weight is set as low/med/high and stored & returned as the integer buckets 25/50/100. Trust ≥ 1 for your own scope=agent rule; ≥ 2 for scope=fleet/scope=tenant or another agent |
Skill sharing is now done via
caura_doc— agents share aSKILL.mdby upserting a document into theskillscollection (caura_doc op=write collection=skills doc_id=<slug> data={"summary": "<one-liner>", ...}). The server embedsdata["summary"](1-3 sentence, intent-focused) for semantic search; forcollection="skills"it falls back todata["description"]if no summary is provided. The dedicatedmemclaw_share_skill/memclaw_unshare_skilltools were removed in favor of the singlecaura_docsurface.
Skill Factory
Sharing a skill by hand (above) is the floor. Skill Factory is the
governed system on top of the skills collection — it auto-generates skills
from fleet behavior, gates what goes live, and delivers active skills to your
agents. It's opt-in per tenant and off by default: until you set
skills_factory.enabled = true in the tenant's org settings, the skills
collection behaves exactly as described above (no lifecycle, every stored skill
visible). Three pillars:
- Authoring — agents and Forge. Agents author skills directly via
caura_doc op=write collection=skills. Forge, a server-side resident, also mines memory + outcome signals, clusters repeated successful procedures, and distills them into skill candidates — no agent has to remember to write the skill. - Governance — a lifecycle. Every skill carries a status:
candidate → staged → active(withrejected/quarantined/stale/deprecatedexits). Six automated gates plus a Sentinel content scan decide what may be promoted, and a Skills Inbox lets an operator approve, edit, defer, reject, or quarantine staged skills over a REST surface —GET /api/v1/skills-inboxlists the staged cards, andPOST /api/v1/skills-inbox/{slug}/approve|edit|defer|quarantine|rejectacts on them. An agent write lands asstaged, never instantlyactive. - Delivery — pull and push. Agents pull active skills over MCP
(
caura_doc op=search/op=read), or the OpenClaw plugin pushes them: its reconciler fetches every active skill fromPOST /api/v1/skills/installableand writes each to the node's skill directory, optionally registering that directory on OpenClaw's load path. Both tiers serve active-only once the feature is enabled.
Deep dives: docs/mcp-skill-delivery.md (the
active-only delivery contract + plugin reconcile targets),
docs/operator-forge-cron.md (scheduling Forge),
and docs/skills-inbox-api.md (the operator REST
API for the Skills Inbox).
The full operator/developer guide lives in the
Caura docs → Skill Factory.
The Interviewer
caura_write captures what an agent chose to record. The Interviewer
captures what it did. On a schedule, it reads an agent's own durable work
trail — the transcript or event log the harness already keeps — and asks an
LLM to synthesize the activity into typed memories, so the decisions,
blockers, and preferences an agent never stopped to journal still get stored.
It never re-runs the agent — it works only from the real trail, which grounds
it in actual activity. (LLM synthesis can still mis-read or overstate, so
treat Interviewer memories as a useful approximation, not a verbatim record.)
It's a third way memories enter Caura, alongside realtime writes and
ingestion. Like Skill Factory it's opt-in per tenant and off by default —
inert until you set interviewer.enabled = true in the tenant's org
settings.
- What it writes. Six report sections map onto the memory-type enum:
worked_on → episode,decisions → decision,outcomes → outcome,blockers → task,open_questions → fact,preferences_learned → preference. They land as ordinary enriched, embedded, governed memories, with the trail's real event timestamps preserved. - How activity is captured. Two families, one submit protocol:
- Plugin-buffer — the OpenClaw plugin keeps a durable node-local buffer
and submits windows (add
MEMCLAW_INTERVIEWER=trueto the plugin env). - Disk-parser — the
memclaw-interviewerCLI (shipped in thememclaw-clientpackage) reads a harness's on-disk transcript read-only and submits windows. Ships for Claude Code (~/.claude/projects) and Cursor (~/.cursor/…/agent-transcripts) today; Hermes and others are planned.
- Plugin-buffer — the OpenClaw plugin keeps a durable node-local buffer
and submits windows (add
- Crash-safe by construction. Each window is written under a
deterministic attempt id (
sha1(node_id:cursor_from:cursor_to)) then the per-node watermark advances — a crash mid-flight re-submits and dedups, so never a gap and never a duplicate. There is no local cursor state; the server watermark is the source of truth. - Privacy. The disk-parser is default-deny — it harvests nothing until you allowlist projects — and credential-shaped strings are scrubbed locally before submit and masked again server-side.
Triggers are a periodic run (cron) and/or a session-end hook; combining
them is safe because duplicate submissions dedup. Full setup, per-harness
wiring, and the protocol are in the
Caura docs → Interviewer.
The Caura Broker
The Caura Broker is a local daemon (memclawd, driven by the memclaw
CLI) that runs on a developer's machine and connects coding agents — Claude
Code, Codex, Cursor, Gemini — to Caura. Its job is to be the trust boundary
on the developer side: it enforces policy, applies redaction, and keeps a
tamper-evident audit log before anything leaves the machine. The Broker
runs in personal mode out of the box; installs that join a Broker
Fleet (a fleet of machines — distinct from the fleet_id memory scope)
are governed together: heartbeats, a policy stream, and a shared dashboard.
The Broker itself ships separately, but its server-side identity plumbing
lives in this repo: a Broker call authenticates with
X-Caura-Credential-Kind: install_credential plus X-Install-UUID, and its
writes are attributed under the broker:<install> ownership namespace — see
core-api/src/core_api/mcp_server.py and core-api/src/core_api/auth.py.
The broker↔cloud wire contract is frozen at v1: both repos run oasdiff
breaking-change gates in CI (in this repo the baseline is generated by
core-api/scripts/gen_broker_openapi.py, gate added in
#620), so a
contract-breaking change fails the build rather than breaking installed
Brokers. Operations — install, fleet join, policy — are documented at
Caura docs → Broker Fleet.
Install the skill (Claude Code & Codex)
Install Caura's usage guide as a skill so your agent knows when and how to use the 12 tools — the memory/doc mental model, the three rules (recall, write, supersede), trust levels, common patterns, and anti-patterns. The skill is loaded on-demand (not per-turn), so it costs nothing until the agent reaches for Caura.
Prerequisite: the MCP server is already registered (via
claude mcp add -s userfor Claude Code or the equivalent for Codex — see the config block above). Confirm withclaude mcp list— you should seecaura: ... ✓ Connected.
Option A — one-liner (fastest)
Self-hosted (localhost):
curl -s "http://localhost:8000/api/v1/install-skill" | bash
Managed platform:
curl -s "https://caura.ai/api/v1/install-skill" | bash
Option B — download, inspect, run (recommended for agents)
Automated agents (Claude Code, Codex) may refuse curl | bash for
safety. Two-step install lets them audit the script first:
curl -s "http://localhost:8000/api/v1/install-skill" > /tmp/install-memclaw-skill.sh
less /tmp/install-memclaw-skill.sh # review — it only does mkdir + curl + write
bash /tmp/install-memclaw-skill.sh
Options
| Query param | Effect |
|---|---|
| (none) | Install the memclaw skill for both Claude Code and Codex (default) |
?agent=claude-code |
Only Claude Code → ~/.claude/skills/<skill>/SKILL.md |
?agent=codex |
Only Codex → ~/.agents/skills/<skill>/SKILL.md |
?skill=company-brain |
Install the optional Company Brain posture skill instead of memclaw (see below; combine with ?agent=) |
Verify
ls -la ~/.claude/skills/memclaw/SKILL.md # Claude Code
ls -la ~/.agents/skills/memclaw/SKILL.md # Codex
Restart your agent after installing — skills are loaded at startup. Re-run the installer any time to pull the latest version.
OpenClaw-plugin users get the skill automatically when the plugin installs; skip this step.
Optional: the Company Brain skill
memclaw teaches the agent the tools. company-brain is a thin,
concept-first posture skill that layers on top: it frames the agent as one
mind in a shared Company Brain and defers all tool mechanics back to the
memclaw skill. Install it alongside memclaw when you want that framing:
curl -s "https://caura.ai/api/v1/install-skill?skill=company-brain" | bash
It installs to ~/.claude/skills/company-brain/SKILL.md (Claude Code) and/or
~/.agents/skills/company-brain/SKILL.md (Codex), and obeys the same
?agent= filter. The default install (no ?skill=) is unchanged — it
installs memclaw only.
Deployment
The recommended way to run Caura is via Docker Compose (see Quick Start). This gives you a production-ready PostgreSQL + pgvector + Redis + API stack with a single command.
Published container images
Each release publishes multi-arch (linux/amd64, linux/arm64) images to GitHub Container Registry:
ghcr.io/caura-ai/caura-memclaw-core-api:v2.5.0
ghcr.io/caura-ai/caura-memclaw-core-storage-api:v2.5.0
Tags follow SemVer with floating aliases — :v1, :v1.0, :v1.0.0, plus :latest for the latest stable release. Pull them in your own compose file or Kubernetes manifests instead of building from source.
Manual deployment (without Docker)
The core-api/ service is a standard FastAPI app that runs under any ASGI server (uvicorn, hypercorn). Requirements:
- Python 3.12+
- PostgreSQL 16+ with the
pgvectorextension - Redis (optional — falls back to in-memory cache if unavailable)
uvicorn core_api.app:app --host 0.0.0.0 --port 8000 --workers 2
Deployment topologies
Caura ships with two operational modes for the storage layer. Single-node (default) is what you get from Docker Compose, pip install, or any fresh deploy — one core-storage-api instance serves both reads and writes. This is the right choice for any deployment that isn't seeing sustained 100+ writes/sec.
The reader/writer split is an opt-in topology for high-write-rate deploys that want to scale reads independently of writes — e.g. by pointing read traffic at a Postgres streaming replica. Enabling it means running two core-storage-api services with different roles and pointing core-api at both:
- Set
CORE_STORAGE_ROLE=writeron the write-serving instance;=readeron the read-serving instance(s). - Set
CORE_STORAGE_READ_URLoncore-apito the reader service URL. LeaveCORE_STORAGE_API_URLpointing at the writer. READ_DATABASE_URLon eachcore-storage-apican point at a read replica if you have one.
Defaults: CORE_STORAGE_ROLE=hybrid and CORE_STORAGE_READ_URL="" — both null-safe, so single-node deploys need zero configuration to get the legacy single-service behavior.
Upgrading from v1.x
⚠️ v2.0.0 ships a destructive schema migration. If your installation is on v1.x and has any memories already stored, follow this procedure carefully — the migration NULLs every existing embedding to widen the pgvector column from 768 → 1024 dim. The application is designed to refuse the migration automatically; you must opt in.
What changes
- Defau
No comments yet
Be the first to share your take.