For server setup, configuration, endpoints, deployment, and smoke tests, see the README. This guide covers only MCP client setup, OpenClaw plugin installation, agent trust levels, agent prompts, and usage examples.
Caura is a shared memory layer for OpenClaw agents. It runs as a separate API service that agents access through an OpenClaw plugin or any MCP client.
MCP Client → Streamable HTTP → Caura API (/mcp) → Postgres + pgvector
OpenClaw Agent → tool call → Caura Plugin → HTTP → Caura API → Postgres + pgvector
Plugin → heartbeat (60s) → Caura API ← commands (response)
| Component | Where it runs | What it does |
|---|---|---|
| Caura API | Any host (Docker, VM, cloud run, local) | FastAPI service — memories, entities, search, enrichment |
| MCP Server | Same process (/mcp) |
Streamable HTTP endpoint for any MCP client |
| Postgres + pgvector | Anywhere (Docker, VM, managed) | Vector + relational store |
| Caura Plugin | OpenClaw gateway VM | Thin adapter forwarding tool calls to the API |
Tool descriptions are derived from the tool registry (core-api/src/core_api/tools/_registry.py) and served at GET /api/v1/tool-descriptions. Both MCP and OpenClaw plugin read from this canonical source.
| Tool | MCP | OpenClaw | Purpose |
|---|---|---|---|
caura_write |
Yes | Yes | Single or batch write. Send content for one memory, or items (≤100) for a batch — the batch path batches embeddings and parallelizes enrichment. LLM auto-infers type, weight, status, title, summary, tags, temporal dates, PII flags. Contradiction detection auto-marks conflicting memories. visibility = scope_agent / scope_team (default) / scope_org. Content >2,000 chars is auto-chunked |
caura_recall |
Yes | Yes | Hybrid semantic + keyword search with graph-enhanced retrieval (expands through entity relations up to 2 hops). include_brief=true adds a brief alongside the raw results, whose summary is the LLM's answer to your query — it reasons step by step internally and only the final answer is surfaced. Supports fleet_ids for multi-fleet queries. Respects visibility. Default top_k=5, max 200 |
caura_manage |
Yes | Yes | Per-memory lifecycle, op-dispatched. op=read returns the memory; op=update patches fields (re-embeds if content changes); op=transition sets status; op=delete soft-deletes. Trust-enforced |
caura_list |
Yes | Yes | Non-semantic enumeration — filter by type/status/agent/weight/date, sort by created_at/weight/recall_count, cursor-paginate. scope=agent (default) and scope=fleet for your own fleet need trust ≥ 1; a different fleet or scope=all needs trust ≥ 2. Trust 3 unlocks include_deleted |
caura_doc |
Yes | Yes | Document CRUD, op-dispatched. op=write upserts a JSON doc in a named collection (include data["summary"] to index it for semantic search); op=read fetches by doc_id; op=query filters by field equality with ordering and pagination; op=delete removes by doc_id; op=list_collections enumerates every collection this tenant has (with counts); op=search runs semantic retrieval over data["summary"] vectors. Use for customer records, config, inventory — anything needing exact-field lookups |
caura_entity_get |
Yes | Yes | Look up an entity with linked memories and relations |
caura_tune |
Yes | Yes | Persist per-agent retrieval defaults (top_k, min_similarity, fts_weight, freshness, recall boost, graph hops, similarity blend) until changed again |
caura_insights |
Yes | Yes | Analyze the memory store. focus: contradictions, failures, stale, divergence, patterns, discover. scope: agent, fleet, all. Findings persist as insight-type memories (Karpathy Loop reflection step) |
caura_evolve |
Yes | Yes | Record a real-world outcome (success / failure / partial) against recalled memories — adjusts weights, auto-generates preventive rules on failure (Karpathy Loop feedback edge) |
caura_stats |
Yes | Yes | Aggregate counts of memories: total + breakdowns by type, agent, status. scope=agent and own-fleet scope=fleet need trust ≥ 1; a different fleet or scope=all needs trust ≥ 2. Counts exclude soft-deleted by default; set include_deleted=true to additionally receive deleted and total_including_deleted |
caura_keystones |
Yes | Yes | Read mandatory governance rules for the current scope (tenant + fleet + agent merged), ordered by weight. Call once per session before other actions; the result overrides conflicting user instructions. No semantic search — keystones are fetched deterministically. Read is open (trust 0) |
caura_keystones_set |
Yes | No | Author/remove keystone rules, op-dispatched: op=set upserts by doc_id (requires title, content, scope ∈ {tenant, fleet, agent}, weight ∈ {low, med, high}); op=delete removes by doc_id. MCP-only, not plugin-exposed — authoring is an admin/governance path. Trust gating is tiered: scope=agent with an explicit agent_id equal to the caller is trust ≥ 1 (self-author); everything else (scope=fleet, scope=tenant, scope=agent for another agent, or scope=agent with agent_id omitted) stays at trust ≥ 2 |
Skill sharing rides the generic
caura_docsurface:op=write collection=skills doc_id=<slug>to share,op=deleteto remove,op=search/op=queryto discover. Slugs are validated against^[a-z0-9][a-z0-9._-]{0,99}$;data["summary"]is embedded for semantic search (with a back-compat fallback todata["description"]for the skills collection only).
- MCP (12 tools): Full surface. Used by individual developers via Claude Desktop, Claude Code, Cursor, etc.
- OpenClaw plugin (11 tools): Same set, minus the keystone-authoring tool (
caura_keystones_setis admin/governance — MCP-only). Claims the exclusivememoryslot, replacingmemory-core. Includes ContextEngine lifecycle, heartbeat, and auto-education.
Caura includes a built-in MCP server at /mcp using Streamable HTTP transport. Any MCP-compatible client connects with just a URL and an API key — no plugin install, no local server.
Add this to your MCP client configuration:
{
"mcpServers": {
"caura": {
"url": "https://your-caura-instance.example.com/mcp",
"headers": {
"X-API-Key": "mc_your_api_key_here"
}
}
}
}Config file locations:
| Client | Config file |
|---|---|
| Claude Desktop (macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Claude Desktop (Windows) | %APPDATA%\Claude\claude_desktop_config.json |
| Claude Code | ~/.claude.json (user scope) — preferred; register via claude mcp add --scope user --transport http caura https://your-caura-instance.example.com/mcp --header "X-API-Key: mc_your_key" |
| Cursor | Settings -> MCP Servers -> Add Server by URL (https://your-caura-instance.example.com/mcp); /mcp serves the Streamable HTTP transport, not SSE |
The Claude Code MCP-server registry lives in
~/.claude.json— NOT~/.claude/settings.json. The latter's schema rejects anmcpServersblock. Prefer theclaude mcp addCLI over hand-editing so the correct file is written.
The MCP connection only exposes the raw tool surface. The usage skill —
the teachable guide that explains when to reach for memory vs doc, how
the two search strategies differ, how to write a good data["summary"], the trust
table, and the "recall-before-you-start / write-when-something-matters
/ supersede-don't-delete" rules — ships as a separate file that your
agent reads on-demand. Install it after the MCP config above:
# Installs SKILL.md into ~/.claude/skills/memclaw/ (Claude Code). legacy-name-floor: installed default-skill path
# And/or ~/.agents/skills/memclaw/ (Codex). legacy-name-floor: installed default-skill path
curl -s "https://your-caura-instance.example.com/api/v1/install-skill" \
-H "X-API-Key: mc_your_key" | bashOptions:
| Query param | Effect |
|---|---|
| (none) | Install for both Claude Code and Codex |
?agent=claude-code |
Only Claude Code |
?agent=codex |
Only Codex |
Restart your agent after installing — skills are loaded at startup.
Why this matters: without the skill, an agent can discover the 12 tool
names and their arg schemas via MCP tools/list, but it has no
mental model for the two-store design (memory vs doc), the trust
levels, or which op to reach for in an ambiguous situation. With the
skill installed, all of that is in the agent's context on-demand. A
brand-new agent that connected via claude mcp add without also
running this installer will still work, but will hit the same
"tools present, guidance missing" gap that made us write the skill
in the first place.
The MCP server exposes 12 tools that clients discover automatically. Descriptions are canonical — served from GET /api/v1/tool-descriptions, derived from the tool registry (core-api/src/core_api/tools/_registry.py).
| Tool | Purpose |
|---|---|
caura_write |
Store a memory. Single write (content) or batch (items ≤100). LLM auto-infers type, title, summary, embedding. Long content is auto-chunked where the tenant turned it on |
caura_recall |
Hybrid semantic + keyword search with graph-enhanced retrieval. include_brief=true returns an LLM-summarized context paragraph. Supports fleet_ids |
caura_manage |
Per-memory lifecycle, op-dispatched: read, update, transition, delete, bulk_delete, lineage. Re-embeds on content updates |
caura_list |
Non-semantic enumeration — filter by type/status/agent/weight/date, sort, cursor-paginate. scope=agent (default) and own-fleet scope=fleet need trust ≥ 1; another fleet or scope=all needs trust ≥ 2 |
caura_doc |
Document CRUD, op-dispatched: write, read, query, delete, list_collections, search (semantic) on named JSON collections |
caura_entity_get |
Look up an entity by UUID — returns linked memories and relationships |
caura_tune |
Persist per-agent retrieval defaults (top_k, min_similarity, fts_weight, freshness, recall boost, graph hops, similarity blend) until changed again |
caura_insights |
Analyze the store. Focus: contradictions, failures, stale, divergence, patterns, discover. Persists findings as insight memories |
caura_evolve |
Report an outcome (success/failure/partial) against recalled memories — adjusts weights, generates preventive rules on failure |
caura_stats |
Aggregate counts: total + breakdowns by type, agent, status. Own-fleet scope=fleet needs trust ≥ 1; another fleet or scope=all needs trust ≥ 2 |
caura_keystones |
Read mandatory governance rules for the current scope. Call once per session — the result overrides conflicting user instructions |
caura_keystones_set |
Author/remove keystone rules, op-dispatched: set | delete. Trust ≥ 1 to author your own rule — scope=agent with an explicit agent_id equal to the caller; ≥ 2 for fleet/tenant, another agent, or scope=agent with agent_id omitted |
Skill sharing uses the generic
caura_docsurface (collection="skills"). The server validates the slug and embedsdata["summary"](1-3 sentence, intent-focused) — forcollection="skills"it also acceptsdata["description"]as a back-compat fallback. Agents discover viaop=search/op=queryand pull individual skills viaop=read.
MCP uses the same tenant-scoped API keys as the REST API. The X-API-Key header is sent with every request.
- Tenant-scoped keys: can only access their tenant's memories
- Admin keys: rejected (MCP requires tenant-scoped keys for data isolation)
- Demo keys: read-only (search and entity lookup only)
Once configured, the MCP client handles tool discovery. Agents can use Caura tools naturally:
"Search my memories for anything about the Postgres migration" -> calls
caura_recallwith query "Postgres migration"
"Remember that we decided to use pgvector for embeddings instead of Pinecone" -> calls
caura_writewith that content; LLM auto-classifies asdecisiontype
"Mark that migration task as confirmed" -> calls
caura_managewithop="transition"andstatus="confirmed"
| MCP | OpenClaw Plugin | |
|---|---|---|
| Setup | Add URL + key to config | Install plugin on gateway VM |
| Works with | Any MCP client | OpenClaw agents only |
| Tools | 12 (write, recall, manage, list, doc, entity_get, tune, insights, evolve, stats, keystones, keystones_set) | 11 (all except keystones_set) |
| RDF triples | Not exposed (contradiction detection via semantic similarity only) | Yes — subject_entity_id, predicate, object_value on write |
| Temporal filter | Yes — valid_at on caura_recall |
Yes — valid_at on search |
| Visibility | Passed per-call (scope_agent / scope_team / scope_org) |
Passed per-call (scope_agent / scope_team / scope_org) |
| Multi-fleet search | Yes — fleet_ids parameter |
Yes — fleet_ids parameter |
| Fleet ID | Passed per-call (optional) | Auto-stamped from gateway env |
| Best for | Individual developers, Claude Desktop/Code users | OpenClaw fleet deployments |
The plugin is a TypeScript package in the plugin/ directory of this repo. It claims the exclusive memory slot on an OpenClaw gateway, replacing the built-in memory-core, and provides 11 agent-facing tools (the 12-tool MCP surface minus caura_keystones_set, which is MCP-only), a ContextEngine with auto-read/write lifecycle, a heartbeat loop, and agent auto-education.
| Component | Minimum | Notes |
|---|---|---|
| OpenClaw runtime | v2026.3.22 |
First release with registerContextEngine + assemble({prompt, …}). Older runtimes fall back to the legacy before_prompt_build path with reduced functionality. |
| Node.js | v18+ |
Required to build and run the plugin. |
Caura backend (this repo's core-api) |
v2.4.0 |
Backend exposes /plugin-manifest for upgrade-path resilience. Plugins on < v2.4.0 fall back to a hardcoded file list (still works against current backends). |
The plugin's install script does a soft preflight on openclaw --version and prints a warning when the local runtime is older than the recommended minimum. It does NOT hard-fail — operators sometimes run patched older builds, and the plugin still loads partially below the minimum. Upgrade OpenClaw when convenient.
On a machine with node (v18+) and npm:
git clone https://github.com/caura-ai/caura.git
cd caura/plugin
npm install
npm run build # emits plugin/dist/# On the gateway machine
mkdir -p ~/.openclaw/plugins/memclaw # legacy-name-floor: frozen plugin install path
# Copy the built plugin from your build machine (or rebuild here):
scp -r plugin/dist plugin/package.json plugin/openclaw.plugin.json \
user@gateway:~/.openclaw/plugins/memclaw/ # legacy-name-floor: frozen plugin install pathAdd to ~/.openclaw/plugins/memclaw/.env:
CAURA_API_URL=https://your-caura-instance.example.com # your Caura API
CAURA_API_KEY=mc_your_key_here # tenant-scoped API key
CAURA_FLEET_ID=fleet-001 # identifies this fleet
CAURA_NODE_NAME=my-gateway # friendly name shown under Agents › Fleets and machines
# CAURA_TENANT_ID= # auto-resolved from API key
# CAURA_AUTO_WRITE_TURNS=false # false/0/no/off turns automatic capture off
# CAURA_AUTO_FIX_CONFIG=false # set true to auto-fix openclaw.json on startupThe plugin loads this .env file automatically. Both CAURA_* and MEMCLAW_* keys are read — and only those, so a .env cannot set PATH or NODE_OPTIONS. The pre-rename MEMCLAW_* spelling of every name above keeps working; where both are set the first non-empty one wins, so a half-filled template cannot blank out a working value. If you use systemd, also add the vars to a drop-in file (.env values don't override existing process env).
Automatic conversation writes include user messages from ingest, assistant
turn summaries, compaction summaries, and the session summary that OpenClaw's
pre-compaction memory-flush turn asks the agent to write, all stored as episode
memories visible only to the agent that captured them (scope_agent). The
server masks credentials and personal data in them even when the PII gate is
off and marks them as captured, and the plugin's automatic recall puts a
captured memory back only into the conversation it came from. Set
CAURA_AUTO_WRITE_TURNS=false (or 0, no, off) and restart the plugin to
disable all four, in .env or as CAURA_AUTO_WRITE_TURNS in the plugin's
config block below; OpenClaw then runs no memory-flush turn. Local message buffering, recall,
explicit memory tools and runtime compaction continue to work. This does not
delete existing memories or disable the separately enabled Interviewer
(CAURA_INTERVIEWER).
Configure OpenClaw — edit ~/.openclaw/openclaw.json:
{
"plugins": {
"allow": ["memclaw"],
"entries": {
"memclaw": { "enabled": true, "config": {} },
"memory-core": { "enabled": false }
},
"slots": {
"memory": "memclaw"
},
"load": { "paths": ["/home/openclaw/.openclaw/plugins/memclaw"] }
},
"tools": {
"alsoAllow": [
"caura_write", "caura_recall", "caura_manage",
"caura_list", "caura_doc", "caura_entity_get",
"caura_tune", "caura_insights", "caura_evolve",
"caura_stats", "caura_keystones"
]
}
}Critical: The plugins.slots.memory and memory-core disablement are required. OpenClaw only loads one kind: "memory" plugin at a time — without switching the slot, the gateway sees the plugin but never calls register(). The automated installer handles this automatically.
Alternatively, use the OpenClaw CLI:
openclaw plugins disable memory-core openclaw plugins enable memclaw # legacy-name-floor: CLI requires the frozen plugin id
Optional — enable ContextEngine (Tier 2): For full auto read/write loop, also set the contextEngine slot:
{
"plugins": {
"slots": {
"memory": "memclaw",
"contextEngine": "memclaw"
}
}
}Without the contextEngine slot, you still get all 11 agent-facing tools, prompt education, flush plan, and memory runtime — but no automatic read/write loop.
Verify — restart OpenClaw and check startup logs:
[caura] Auto-educated workspaces (TOOLS.md: 20, AGENTS.md: 20)
[caura] Smoke test passed (score: 0.953)
You will also see ContextEngine 'memclaw' registered in the same log — the context engine keeps the original plugin id.
The node will appear in GET /api/v1/fleet/nodes?tenant_id=<tenant>&fleet_id=<fleet> within 60 seconds.
The plugin registers 11 tools (the MCP surface minus the MCP-only caura_keystones_set) and runs several lifecycle systems:
- ContextEngine — 7 lifecycle hooks:
bootstrap(smoke test),ingest(message buffering + persistence),assemble(token-budget-aware recall injection),compact(persist summaries),afterTurn(auto-write turn summaries),prepareSubagentSpawn,onSubagentEnded - Memory runtime — API-backed
search()andget()replacing file-basedmemory-core - Heartbeat — every 60 seconds, POSTs node status (agents, tools, OS, IP, plugin version, setup_status) to
/api/v1/fleet/heartbeat. Caura responds with any pending commands - Request identity — every HTTP request to the Caura server carries
User-Agent: openclaw-plugin/<plugin version> (node/<Node major>)alongsideX-API-Key. The server's heartbeat counts connected SDK families from this prefix; nothing else is sent - Commands — the plugin processes HMAC-verified commands from the heartbeat response:
deploy— fetch all source files to memory, backup originals, write + build, rollback on failureeducate— write prompts to agent HEARTBEAT.md files + write SKILL.md, TOOLS.md, AGENTS.md to workspacesping— health check round-triprestart— gateway restart
- Auto-education — on first load, writes SKILL.md, TOOLS.md, AGENTS.md to all agent workspaces. New workspaces are auto-educated on heartbeat
- Auto-resolve —
tenant_idis resolved from the API key at startup, so agents never need to specify it - Gateway RPC — exposes
memclaw.status,memclaw.deploy,memclaw.deploy.status,memclaw.educate,memclaw.allowlist.check,memclaw.allowlist.fixmethods
On first plugin load, agents are auto-educated — the plugin writes SKILL.md, TOOLS.md, and AGENTS.md to all agent workspaces automatically. The .educated flag at ~/.openclaw/plugins/memclaw/.educated prevents re-running on subsequent restarts.
For manual or targeted education in the Caura app, under Agents › Fleets and machines:
- Select the fleet, then the node, and open the node's Education tab
- Review/edit the education prompt (pre-filled with default instructions)
- Untick any agents you want to skip (all the node reports are selected), then click Send to N Agents — or Broadcast when the node reports no agents. Delivered on the next heartbeat (≤60 seconds)
- The plugin writes the prompt to each agent's
HEARTBEAT.mdand updates SKILL.md, TOOLS.md, AGENTS.md in their workspace - Each write is verified by read-back — the command result reports
verifiedcount and any per-workspace failures - Agents process the prompt on their next heartbeat and update their own TOOLS.md, AGENTS.md, SOUL.md, IDENTITY.md
On the node's Overview tab, each agent shows ✓/✗ badges for the files written to its workspace (HB, SKILL, TOOLS), and until setup is complete the node's setup checklist includes Agents educated.
Caura enforces a 4-tier trust system for agents. Agents are auto-registered on their first caura_write call at trust level 1.
| Level | Name | Permissions |
|---|---|---|
| 0 | restricted |
No read or write access. Use to temporarily disable an agent |
| 1 | standard |
Read and write within own fleet only (default for new agents) |
| 2 | cross_fleet |
Read across all fleets in the tenant; write within own fleet only |
| 3 | admin |
Read and write across all fleets, scope_org memories included; can delete memories |
- On first write, the agent is auto-registered with trust level 1 and the
fleet_idfrom that write becomes its "home fleet" - When the tenant setting
agents.require_agent_approvalis on, a new agent is registered at trust level 0 instead — on whichever call first names it (a write, a search or recall, a fleet heartbeat,caura_tune, a document write) — and stays there until an admin raises it - At trust level 0 an agent reads nothing as well as writing nothing.
POST /search,POST /recall,GET /memories(with or withoutscope),/memories/stats,/memories/countand/memories/fieldanswer 403AGENT_TRUST_TOO_LOW;caura_recallreturnsAGENT_TRUST_TOO_LOWandcaura_list/caura_statsreturnFORBIDDEN; a read by id (GET /memories/{id},caura_manageop=read) answers 404. That includes an agent awaiting approval: a REST search or recall registers it at level 0 and is refused. Keystones stay readable. A signed-in person who filters by a restricted agent still sees its memories - Writing or editing a
scope_orgmemory needs trust level 3 (see Memory visibility). So doescaura_insightsorcaura_evolvewithscope=all, which saves its findings or outcome asscope_org;scope=fleetneeds level 2 andscope=agentlevel 1 - Trust level is enforced on every API call — an agent at level 1 attempting a cross-fleet search gets a 403
- Documents follow the delete bar: an agent below level 3 may create documents and update the ones it wrote or that another agent of its own fleet wrote, but replacing a document an agent of another fleet authored (or
force=trueonPOST /documents) needs level 3. Documents with no recorded author stay writable. Graph writes (POST /entities/upsert,POST /relations/upsert) and document writes into a fleet other than the agent's own need level 3, as memory writes do - Soft-deleted rows (
include_deleted=trueonGET /memories,GET /memories/stats,caura_list,caura_stats) andPOST /ingest/undo/{run_id}need level 3 for an agent credential - Trust and home-fleet changes (
PATCH /agents/{id}/trust,PATCH /agents/{id}/fleet) are recorded in the tenant audit log asagent_trust_update/agent_fleet_update - The admin API key bypasses all trust enforcement
Use the API to inspect agents and adjust trust:
| Endpoint | Method | Purpose |
|---|---|---|
/api/v1/agents?tenant_id= |
GET | List all registered agents with trust levels |
/api/v1/agents/{agent_id}?tenant_id= |
GET | Single agent detail (trust level, home fleet, stats) |
/api/v1/agents/{agent_id}/trust?tenant_id= |
PATCH | Update trust level (body: {"trust_level": 2}) |
The OSS server does not bundle a /ui application. Use these REST endpoints,
the MCP/OpenClaw tools, or a separately deployed management client.
Add this to your agent's system prompt (or use Agent Education to let agents self-configure):
You have access to Caura, a shared memory system used by all agents.
BEFORE starting any task:
- Use caura_recall for semantic + keyword search with graph expansion
- Set include_brief=true when you want the LLM's answer to your query
alongside the raw results (brief.summary is the answer itself, not the
model's working)
- Include fleet_id to scope to this fleet, omit for tenant-wide search
- Filter by status="active" to skip deleted/archived memories
- Use `valid_at` for point-in-time queries (REST `/search`, MCP `caura_recall`, and the OpenClaw plugin all accept it)
AFTER completing work:
- Store findings with caura_write — just provide content
- For batch writes, pass items=[...] (up to 100) to the same tool — batches
embeddings and enrichment for much lower latency than looped single writes
- Type, weight, title, summary are auto-inferred by LLM (status defaults to
`active`; tags are caller-supplied)
- Dates auto-extracted: "deadline March 30" → ts_valid_end
- Contradictions auto-detected: conflicting older memories marked outdated
- Long content (>2000 chars) is auto-chunked into atomic facts when the tenant turns auto-chunking on (off by default)
- Set visibility: "scope_agent" (you only), "scope_team" (default), "scope_org" (all fleets; needs trust level 3)
- Optionally override `memory_type` with a caller-writeable type (`fact`,
`episode`, `decision`, `preference`, `task`, `plan`, or `action`), plus
`weight` and `status`. `outcome`, `rule`, and `insight` are server-reserved.
- RDF triples (subject_entity_id, predicate, object_value) available via OpenClaw plugin and REST API
MANAGING EXISTING MEMORIES:
- Use caura_manage with op="update" to correct content or metadata
- Use caura_manage with op="transition" to change status
- Use caura_manage with op="delete" to soft-delete
- Use caura_manage with op="read" to inspect a single memory by id
- Only provide fields you want to change — others are preserved
- If content changes, embedding and entities are re-extracted automatically
- You can only modify your own memories unless you have admin trust level
STATUS LIFECYCLE:
- Use caura_manage op="transition" when things change
- confirmed (done), cancelled (abandoned), outdated (superseded)
- Search status="pending" for unresolved items
VISIBILITY & CROSS-FLEET:
- Default visibility is "scope_team" — shared within your fleet
- Set visibility: "scope_org" to share across all fleets in the organization (needs trust level 3)
- Set visibility: "scope_agent" for agent-only notes
- Use fleet_ids in recall to query multiple fleets at once
ENTITIES & GRAPH:
- Auto-extracted from every write — no manual creation needed
- Same name, one entity: case and spacing are ignored, and a leading
the/a/an/new/old/current/existing/legacy is treated as descriptive, so
"the new analytics service" and "analytics service" are one node
(never below two words, so "new york" stays distinct from "york")
- Fuzzy entity matching after that: "OpenAI" and "Open AI" are auto-merged (cosine similarity ≥ 0.85)
- Every surface form seen is kept as an alias on the entity
- Recall automatically expands through entity relations (up to 2 hops)
Example: searching "Project Atlas" also finds memories about people who work on Atlas
- Use caura_entity_get for direct relationship and linked memory inspection
OUTCOME REPORTING (Karpathy Loop):
- After acting on recalled memories, report what happened with caura_evolve
- outcome_type: "success" / "failure" / "partial"; pass related_ids=[...]
- Successful recalls get reinforced; failures generate preventive rules
- Use caura_insights periodically to surface contradictions, stale
knowledge, cross-agent divergence, and emerging patterns
Note:
tenant_idis resolved from your API key (MCP) or auto-filled from the plugin env — agents never need to pass it.agent_idis also auto-filled (defaults to"mcp-agent"for MCP or the plugin env value for OpenClaw).
Scenario: Researcher discovers info, Planner uses it, Support benefits later.
Step 1 — Researcher stores a finding (visible to all fleets; the researcher is at trust level 3):
{
"tool": "caura_write",
"parameters": {
"content": "Customer X uses PostgreSQL 16 in production on GKE. They process 2M transactions/day.",
"source_uri": "crm://customer-x/infrastructure",
"visibility": "scope_org"
}
}LLM enrichment auto-classifies as fact, weight 0.9, title "Customer X: PostgreSQL 16 on GKE", tags ["customer-x", "postgresql", "gke"]. Entity extraction identifies "Customer X" (org), "PostgreSQL 16" (technology), "GKE" (technology). Visibility scope_org means all fleets can see this.
Step 2 — Planner recalls:
{
"tool": "caura_recall",
"parameters": {
"query": "which customers use PostgreSQL and what is their scale?",
"memory_type": "fact"
}
}Returns the researcher's finding. Graph-enhanced retrieval expands through entity relations — memories linked to matching entities get a 1.3x boost, 1-hop neighbors 1.2x, and 2-hop neighbors 1.1x.
Step 3 — Planner stores a decision:
{
"tool": "caura_write",
"parameters": {
"content": "Customer X should be migrated to managed Postgres in Phase 2 due to high transaction volume."
}
}Step 4 — Support agent picks it up:
{
"tool": "caura_recall",
"parameters": {
"query": "Customer X database setup and migration plans"
}
}Returns both the fact and the decision — full context without agents needing to talk to each other.
Shared memory suits knowledge the whole fleet should find later. When an agent needs an answer from a specific peer now, use the optional agent collaboration extension instead: the agent discovers the peer by its expertise description, sends a direct request and collects the correlated reply. See agent collaboration for the current beta scope and supported hosts.
Scenario: Agent has extracted several findings and stores them all at once via the batch form of caura_write.
{
"tool": "caura_write",
"parameters": {
"items": [
{"content": "Customer A uses PostgreSQL 16 in production on GKE"},
{"content": "Customer A processes 2M transactions per day"},
{"content": "Customer A's DBA team prefers managed database services"},
{"content": "Customer A contract renewal is scheduled for Q3 2026"}
]
}
}Returns per-item results with created, duplicate_attempt,
duplicate_content, or error status, plus overall counts. Much faster than 4
individual single-content calls — embeddings are batched into a single API
call and enrichment runs in parallel. Pass the batch form (items) exactly
when you have more than one memory; items is mutually exclusive with
content.
{
"tool": "caura_entity_get",
"parameters": {
"entity_id": "c5d5ee20-78a4-4dd0-b9ca-6a41809a6ca5"
}
}Returns entity attributes, all linked memories, and outgoing relations (e.g., Customer A -> uses -> PostgreSQL 16).
RDF triple fields (
subject_entity_id,predicate,object_value) are available via the OpenClaw plugin and REST API. MCP clients trigger contradiction detection through semantic similarity only (no explicit RDF triples).
Original memory exists:
{
"id": "aaa-111",
"content": "Sarah Chen lives in Tel Aviv, Israel",
"subject_entity_id": "e663...",
"predicate": "lives_in",
"object_value": "Tel Aviv, Israel",
"status": "active"
}Agent writes contradicting memory:
{
"tool": "caura_write",
"parameters": {
"content": "Sarah Chen moved to Berlin, Germany",
"subject_entity_id": "e663...",
"predicate": "lives_in",
"object_value": "Berlin, Germany"
}
}Response includes:
{
"id": "bbb-222",
"status": "active",
"superseded_by": [
{
"old_memory_id": "aaa-111",
"old_status": "outdated",
"reason": "rdf_conflict",
"old_content_preview": "Sarah Chen lives in Tel Aviv, Israel"
}
]
}The old memory is automatically marked outdated with supersedes_id pointing to the new one.
Auto-classified by LLM on every write. Callers may override memory_type with
fact, episode, decision, preference, task, plan, or action.
outcome, rule, and insight are server-reserved; use caura_evolve,
caura_keystones_set, and caura_insights respectively. semantic,
intention, commitment, and cancellation remain readable for historical
rows but are deprecated on new writes.
| Type | Use for | Default status | Example |
|---|---|---|---|
fact |
Durable knowledge | active |
"Customer A uses Postgres 16" |
episode |
Events that happened | active |
"Deployed v2.3 on March 10" |
decision |
Choices made | active |
"Chose managed Postgres over self-hosted" |
preference |
User/org preferences | active |
"Customer B prefers email over Slack" |
task |
Work items | pending |
"Migrate Customer X by Q3" |
semantic |
Conceptual knowledge | active |
"pgvector supports HNSW and IVFFlat" |
intention |
Goals not yet acted on | active |
"Planning to evaluate FalkorDB" |
plan |
Step sequences | pending |
"Phase 1: schema, Phase 2: data, Phase 3: cutover" |
commitment |
Promises to others | pending |
"Promised timeline by Friday" |
action |
Steps in progress | active |
"Started the migration script" |
outcome |
Results of work | confirmed |
"Migration: 2M rows in 47 min, zero errors" |
cancellation |
Cancelled items | active |
"Cancelled FalkorDB eval" |
rule |
Preventive guardrails | active |
"Never deploy schema changes on Fridays" (often auto-generated by caura_evolve after a failure) |
insight |
Analytical findings | active |
"5 memories contradict each other about customer X's region" (auto-generated by caura_insights) |
| Status | Meaning | How it gets set |
|---|---|---|
active |
Current and valid (default) | LLM default for most types |
pending |
Not yet confirmed | LLM default for tasks, plans, commitments |
confirmed |
Verified or completed | Agent via caura_manage op=transition or LLM for outcomes |
cancelled |
Explicitly cancelled | Agent via caura_manage op=transition |
outdated |
Superseded by newer info | Auto-set by contradiction detection (RDF conflict) or lifecycle automation (past ts_valid_end) |
conflicted |
Contradicts another memory | Auto-set by contradiction detection (semantic); needs review |
archived |
Preserved but no longer current | Agent via caura_manage op=transition or lifecycle automation (stale, low-weight, never-recalled) |
deleted |
Soft-deleted | Set on caura_manage op=delete or DELETE API call |
Attach structured subject-predicate-object triples to memories for graph-friendly retrieval:
{
"subject_entity_id": "c5d5ee20-...",
"predicate": "uses",
"object_value": "PostgreSQL 16"
}Enables contradiction detection (same subject+predicate, different object -> old memory marked outdated).
Controls who can see a memory. Set on write via visibility field.
| Level | Who can see | Use for |
|---|---|---|
scope_agent |
Only the creating agent | Personal notes, drafts, scratch work |
scope_team |
All agents in the same fleet (default) | Team-scoped knowledge |
scope_org |
All agents across all fleets | Company-wide facts, cross-team decisions |
Writing or editing a scope_org memory needs trust level 3, as a write into another fleet does: every fleet reads it. Below that the write is refused with FLEET_SCOPE_FORBIDDEN; an agent may still narrow a scope_org memory it wrote to scope_team or scope_agent.
Search respects visibility automatically. Agents see: all scope_org memories + scope_team memories in their fleet + their own scope_agent memories. Admin API key sees all except scope_agent.
Auto-chunking is opt-in, off by default: set the tenant setting chunking.auto_chunk_enabled to true to turn it on. Then content exceeding 2,000 characters is split into atomic facts via LLM:
- Creates a parent memory with the full content (tagged
auto_chunked: true) - Creates child memories for each extracted fact (tagged
source: "auto_chunk", linked to parent) - Both parent and children inherit type, weight, status, visibility
- Falls back to single-memory write if chunking fails
The core-operations scheduler, which the stock docker compose stack runs, fires these ticks nightly (02:00 UTC by default, each movable in its settings):
- Expires — active memories past
ts_valid_endorexpires_at→ statusoutdated, which default search excludes - Archives — active memories older than 90 days with weight below 0.3 and no recalls → status
archived - Purges — soft-deleted memories past the tenant's retention window are removed
- Crystallizes — merges near-duplicate clusters for tenants with
crystallizer.auto_crystallizeon and more than 1,000 active memories, when something was written since the last run - Links entities and discovers insights — for tenants that enable
entity_linking.auto_entity_linking_enabledandinsights.auto_insights_enabled
Expiry and archival are togglable per tenant via the lifecycle.lifecycle_automation_enabled setting. A deployment that does not run core-operations runs none of these.
ts_valid_start/ts_valid_end— auto-extracted from content by LLM, or set explicitly- Search with
valid_atto return only memories valid at a point in time; relative dates in the query ("last month") resolve against it - For backfilled corpora whose
ts_valid_startis the time the event happened, setsearch.default_profile.freshness_referenceto1in tenant settings — freshness and the temporal window are then measured fromvalid_atagainst event time instead of from now against ingest time. Off by default; inert on requests withoutvalid_at - Memories without temporal bounds are always considered valid
Available as the batch form of the caura_write tool (MCP + OpenClaw plugin, pass items=[...]) and the POST /api/v1/memories/bulk REST endpoint. Writes up to 100 memories in a single request. Optimized for throughput:
REST callers must send a unique X-Bulk-Attempt-Id header (1–128 characters;
letters, digits, ., _, :, and -) and reuse it when retrying the same
logical batch. MCP does not expose that header, so the server generates an
attempt id for each MCP batch call.
- Batch embeddings — single API call for all texts instead of N calls
- Parallel enrichment — LLM enrichment runs concurrently (bounded at 10)
- Batch dedup — one
WHERE content_hash IN (...)query + intra-batch duplicate detection - Single transaction — all memories inserted and committed at once
- Single rate-limit check — quota verified once for the whole batch
{
"tenant_id": "acme",
"fleet_id": "engineering",
"agent_id": "researcher-1",
"items": [
{"content": "Customer A uses PostgreSQL 16 in production"},
{"content": "Customer B migrated to managed Postgres last quarter", "memory_type": "fact"},
{"content": "Customer C prefers email notifications", "weight": 0.8}
]
}Response:
{
"created": 3,
"duplicates": 0,
"errors": 0,
"results": [
{"index": 0, "status": "created", "id": "..."},
{"index": 1, "status": "created", "id": "..."},
{"index": 2, "status": "created", "id": "..."}
],
"bulk_ms": 450
}Each item in items supports the same fields as a single-content write
(memory_type, weight, status, source_uri, entity links, RDF triples,
and temporal bounds). The same caller-writeable memory_type restriction
applies. tenant_id, fleet_id, and agent_id are set once at the top level.
When calling caura_write, pass exactly one of content (single) or items
(batch).
A retry with the same attempt id is reported as
"status": "duplicate_attempt"; an exact content match from a different
attempt is "status": "duplicate_content" with duplicate_of pointing to
the existing memory ID. All enrichment, entity extraction, and contradiction
detection run the same as single writes.
Content-hash rejects exact duplicates within a tenant + fleet + agent scope (HTTP 409). The same content can exist in different fleets, and two agents in one fleet can each write it.
| Issue | Fix |
|---|---|
| Plugin tools don't appear | Ensure all three plugins keys are set in openclaw.json: allow, entries, and load.paths. Restart OpenClaw |
| Tools not in agent sessions | Auto-fixed on first plugin load (adds v1.0 names, removes stale pre-v1.0 names). If it persists after restart, run openclaw gateway memclaw.allowlist.fix or check that CAURA_AUTO_FIX_CONFIG is not set to false |
| Plugin allowed but not loading | Missing plugins.entries.memclaw.enabled: true or plugins.load.paths entry — the installer sets both |
| All config issues | Re-run the installer, then restart OpenClaw. In the Caura app, the node under Agents › Fleets and machines lists the setup checks still failing (plugin loaded, tools registered, config complete, agents educated) |
ECONNREFUSED |
Check CAURA_API_URL, ensure API is running |
| API URL redirects | Set CAURA_API_URL to the final server URL. Credential-bearing plugin requests reject redirects so an API key cannot be forwarded to another host. |
| Agent-key provisioning unavailable | Concurrent calls for one agent share one provisioning attempt. Failed attempts wait 60 seconds before retrying; a 404 disables provisioning until plugin restart. Meanwhile the agent's requests use the tenant key. |
agent_key_revoked |
Managed platform: an admin revoked the agent, and none of its keys is live. The plugin refuses that agent's requests rather than send them with the tenant key, and asks again every 10 minutes. To turn the agent back on, issue it a key (POST /api/v1/admin/agent-keys/provision, or in the Caura app under Connect › Keys › Create agent key). This relies on the plugin: the tenant key can still act as any agent, so to stop an agent's writes outright, set its trust level to 0 |
| 401 Unauthorized | Check CAURA_API_KEY env var on gateway |
| 403 Forbidden | Key used for wrong tenant, or agent trust level too low |
| 409 Conflict | Duplicate content — safe to ignore |
| Empty search results | Verify tenant_id, check fleet_id scope, write test memories |