Skip to main content

Caura — governed shared memory for AI agent fleets

Caura (formerly MemClaw) is an Agent DB — governed shared memory for AI agent fleets. Agents commit what they learn once; every agent in the fleet recalls it through MCP tools, REST, or Caura Rail (preview), subject to tenant isolation, visibility scope (scope_agent / scope_team / scope_org) and caller trust level.

caura-client is the official Python client for Caura and the canonical package name; caura and caura-sdk install the same client. It is a thin wrapper over the Caura REST API. Point it at a managed (https://caura.ai) or self-hosted (http://localhost:8000) deployment.

Formerly memclaw-client. That package is retired and provides no memclaw_client module, so move imports to caura_client and the retired MemClaw/MemClawError/MemClawAPIError names to the Caura class and CauraAPIError below.

Install

pip install caura-client

Quickstart

from caura_client import Caura

# Recommended: the client is a context manager and closes its HTTP
# connection on exit (use close() for manual management).
with Caura("mc_xxx", tenant_id="my-team", agent_id="my-agent") as mc:
    # Write a memory — enriched server-side with type, title, tags, importance.
    mc.write("Q3 revenue target is $4M, set on 2026-04-15.")

    # Search (ranked raw results)
    for m in mc.search("Q3 revenue target", top_k=5):
        print(m.title, "—", m.content)

    # Recall (LLM-synthesized context brief)
    print(mc.recall("Q3 revenue target").summary)

Self-hosted? Pass base_url:

with Caura("standalone", tenant_id="default", base_url="http://localhost:8000") as mc:
    ...

New to Caura? Start with what Caura is and the LongMemEval benchmark harness. To reach the same memory from an MCP client with no SDK, see the caura page. Source and issues live at github.com/caura-ai/caura.

API

Method Endpoint Returns
write(content, ...) POST /api/v1/memories Memory
search(query, top_k=5, ...) POST /api/v1/search list[Memory]
recall(query, top_k=5, ...) POST /api/v1/recall RecallResult
health() GET /api/v1/health dict
get_document(doc_id, *, collection, ...) GET /api/v1/documents/{doc_id} dict
submit_interview(...) POST /api/v1/interview/submit dict
close() — None

The client is a context manager (with Caura(...) as mc:) and raises AuthError (401/403), NotFoundError (404), or CauraAPIError on HTTP failures. Network failures and timeouts raise TransportError, with the original httpx exception in __cause__. Catch CauraError to handle both HTTP and transport failures. Transport errors have no HTTP status code; requests are not retried. Every result also exposes the full API payload on .raw.

Fetching a document

get_document() returns the full DocOut envelope — the stored record is nested under the "data" key, not returned directly. collection is a required keyword-only argument, and a missing document raises NotFoundError:

with Caura("mc_xxx", tenant_id="my-team", agent_id="my-agent") as mc:
    doc = mc.get_document("doc-123", collection="interviews")
    record = doc["data"]       # the stored record lives under "data"

Lifecycle

Caura holds an httpx.Client, so prefer the with form above — the connection is closed on exit. For manual management, call close() explicitly when you are done:

mc = Caura("mc_xxx", tenant_id="my-team", agent_id="my-agent")
try:
    mc.write("...")
finally:
    mc.close()

Request headers

Every request carries X-API-Key (your key), Content-Type: application/json and a User-Agent of the form caura-client-python/<version> (python/<major>.<minor>). The User-Agent lets a Caura server count which SDK families talk to it; it names only the package, its version and the Python release. The client sends nothing to any host other than the base_url you configure.

submit_interview() is an Interviewer-internal surface

submit_interview() is used by the caura-interviewer adapter below to submit parsed session windows to the server. It is not intended as a general-purpose SDK method: it calls the server synchronously (the server interviews the window in-line, up to a 90s budget), so its timeout defaults to 120s rather than the client-wide 30s, and the returned body carries an extra "http_status" key so callers can tell a 207 partial from a 200 committed. New SDK users should not need it.

For credentials, scopes, and the full API surface, see the Caura docs. Production fleets should use per-agent keys.

Unknown fields on writes are rejected

write() forwards any extra keyword arguments straight into the request body (mc.write("...", some_field=1)). The API rejects a field it does not declare with 422 and names it:

try:
    mc.write("a memory", tags=["alpha"])   # `tags` is not a write field
except CauraAPIError as exc:
    exc.payload["error"]["details"]["unknown_fields"]   # ["tags"]

This used to return 201 with the field silently discarded, so an integration that "worked" may start failing here — the data it sent was never being stored. Caller-owned keys belong under metadata (mc.write("...", metadata={"tags": [...]})).

search() and recall() are unaffected: filter bodies still accept unknown fields, deliberately. See api-surfaces.md.

caura-interviewer — Claude Code + Cursor adapter

Installing this package provides the caura-interviewer CLI. When upgrading an older install, run caura-interviewer install; for one release it can find and replace an existing memclaw-interviewer crontab entry. The Caura Interviewer is a disk-parser adapter for Claude Code and Cursor workstations. It reads agent session transcripts read-only — Claude Code's ~/.claude/projects/…/*.jsonl or Cursor's ~/.cursor/projects/…/agent-transcripts/…/*.jsonl — tracks a per-file cursor via the server's forward-only watermark documents (no local state), and submits event windows to POST /api/v1/interview/submit, where Caura synthesizes them into typed memories. Requires the tenant to have interviewer.enabled = true.

export CAURA_API_KEY=mc_xxx CAURA_TENANT_ID=my-team
export CAURA_INTERVIEWER_PROJECTS="-Users-me-work-*"     # allowlist, default-deny

caura-interviewer status --since-hours 24       # cursors vs. local line counts
caura-interviewer run --dry-run -v              # parse + window, submit nothing
caura-interviewer run --max-windows 8           # submit due windows
caura-interviewer run --harness cursor          # harvest Cursor instead (or
                                                # CAURA_INTERVIEWER_HARNESS=cursor)

Every CAURA_* variable above also answers to its pre-rename MEMCLAW_* name; where both are set the first non-empty value wins.

Privacy: default-deny — with no allowlist the CLI lists discovered project dirs and exits with guidance; --all-projects is the explicit opt-in. Credential-shaped strings are scrubbed locally before anything leaves the machine, and the server masks PII again on receipt.

Triggers: run it from cron, or wire the harness's session-end hook so a session is interviewed the moment it ends (a failed harvest never fails the session — the hook always exits 0). The SAME hook command serves both harnesses: each sends transcript_path on stdin, and the harness is inferred from the path shape.

Claude Code (~/.claude/settings.json):

{ "hooks": { "SessionEnd": [ { "hooks": [
  { "type": "command", "command": "caura-interviewer hook", "timeout": 300 }
] } ] } }

Cursor (~/.cursor/hooks.json):

{ "version": 1, "hooks": {
  "sessionEnd": [ { "command": "caura-interviewer hook" } ]
} }

Schedule the cron in one command. Rather than hand-editing crontab, install writes an idempotent cron entry (and a 0600 env file it sources, since cron doesn't inherit your shell environment). Config comes from the same flags/env as run:

caura-interviewer install --interval 30m          # add --harness cursor for Cursor
caura-interviewer uninstall                        # removes the entry + env file

It refuses to schedule a job that would no-op (missing credentials or no project allowlist). On Windows (no crontab), use Task Scheduler to run caura-interviewer run on a timer instead.

Crash-safety is inherited from the Interviewer protocol: the watermark advances only after the server commits a window, and retries of the same window dedup server-side via a deterministic attempt id — never a gap, never a duplicate.

License

Apache-2.0

Metadata

Release files for caura-client 1.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for caura-client 1.0.3
File Size Uploaded Provenance
caura_client-1.0.3.tar.gz 56.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for caura-client 1.0.3
File Interpreter ABI Platform
caura_client-1.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 94.8 kB

Release files / caura_client-1.0.3.tar.gz

Download URL caura_client-1.0.3.tar.gz
Size 56.2 kB
Tags Source
SHA-256 checksum
How to use checksums
fdc94a0e9d24a81cbc27eeefd4da5f4a2b0e2e711c53fe1ec3b57e39ce212738
BLAKE2b-256 checksum
How to use checksums
125bebe7e51d78381d2ef903cfc955c7d7b83966e824aee3ff39267c4aeea536
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / caura_client-1.0.3-py3-none-any.whl

Download URL caura_client-1.0.3-py3-none-any.whl
Size 38.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0555fd50ea614a9909d720bfc40d7641a5579b1700b4e494f6391f047e5e13f4
BLAKE2b-256 checksum
How to use checksums
76f3ec8a197b93b3b7d5f8a1f6ec954c4e4be7e8092ec05fc47ff38f4f83efe8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Security for caura-client 1.0.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for caura_client-1.0.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page