# Consolidate Memories Source: https://docs.memoclaw.com/api-reference/consolidate POST https://api.memoclaw.com/v1/memories/consolidate POST /v1/memories/consolidate — Auto-merge similar memories to reduce redundancy. **Price:** \$0.01 USDC Consolidate automatically finds and merges semantically similar memories. It uses vector similarity to identify clusters of redundant memories and merges them via rule-based or LLM-powered strategies. ## Request Body All fields are optional. The API auto-discovers similar memory pairs. Minimum cosine similarity threshold for clustering (0.5–1.0). Default: `0.85`. Higher = stricter matching. Merge strategy: * `rule` (default): Keep highest-importance memory, merge tags, soft-delete rest. Creates `supersedes` relationships. * `llm`: Synthesize a new memory from the cluster via LLM. Creates `derived_from` relationships. Only consolidate memories in this namespace. If `true`, return clusters that would be merged without actually merging. Default: `false`. ## Response (200 OK) Number of similar memory clusters found. Number of memories that were soft-deleted (merged into others). Number of new synthesized memories (LLM mode only). Details of each cluster. IDs of memories in this cluster. Average pairwise similarity within the cluster. ID of the surviving/synthesized memory (absent in dry\_run). ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/memories/consolidate \ -H "Content-Type: application/json" \ -d '{ "min_similarity": 0.85, "mode": "rule", "dry_run": true }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/memories/consolidate", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ min_similarity: 0.85, mode: "rule", dry_run: true, }), }); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.consolidate(min_similarity=0.85, mode="rule", dry_run=True) ``` ```json Response theme={null} { "clusters_found": 2, "memories_merged": 3, "memories_created": 0, "clusters": [ { "memory_ids": ["uuid-1", "uuid-2"], "similarity": 0.92, "merged_into": "uuid-1" }, { "memory_ids": ["uuid-3", "uuid-4", "uuid-5"], "similarity": 0.87, "merged_into": "uuid-3" } ] } ``` In `rule` mode, the highest-importance memory survives and inherits tags from all merged memories. In `llm` mode, a new memory is synthesized that combines all unique information from the cluster. # Assemble Context Source: https://docs.memoclaw.com/api-reference/context POST https://api.memoclaw.com/v1/context POST /v1/context — Assemble a context block from memories for LLM prompts. **Price:** \$0.01 USDC Automatically assemble relevant memories into a context block ready for LLM prompts. This is useful for building AI assistants that need contextual memory. ## Request Body Natural language query describing what context is needed. Used to find relevant memories. Filter by namespace. Filter by session ID. Filter by agent ID. Maximum number of memories to include. Default: `10`. Max: `100`. Target maximum tokens for the context. Default: `4000`. Range: `100-16000`. Output format: `text` (plain text) or `structured` (JSON with metadata). Default: `text`. Include memory metadata (tags, importance, type) in the output. Default: `false`. Use LLM to summarize multiple similar memories into fewer entries. Default: `false`. ## Response (200 OK) The assembled context text or JSON. Number of memories included in the context. Approximate token count of the context. ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/context \ -H "Content-Type: application/json" \ -d '{ "query": "user preferences and project context", "max_memories": 5, "max_tokens": 2000, "format": "text" }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/context", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: "user preferences and project context", max_memories: 5, max_tokens: 2000, format: "text", }), }); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.assemble_context( query="user preferences and project context", max_memories=5, max_tokens=2000, format="text", ) print(result.context) ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const result = await client.assembleContext({ query: "user preferences and project context", maxMemories: 5, maxTokens: 2000, format: "text", }); console.log(result.context); ``` ```json Response theme={null} { "context": "User preferences:\n- Prefers dark mode\n- Uses vim keybindings\n- Timezone: PST\n\nProject context:\n- Using PostgreSQL 15 with pgvector\n- Deploy to staging before production", "memories_used": 5, "tokens": 180 } ``` ```json Response (structured format) theme={null} { "context": { "memories": [ { "content": "User prefers dark mode", "importance": 0.8, "memory_type": "preference", "tags": ["ui"], "source": "recall" }, { "content": "Uses vim keybindings", "importance": 0.7, "memory_type": "preference", "tags": ["editor"], "source": "recall" } ] }, "memories_used": 2, "tokens": 85 } ``` # Core Memories Source: https://docs.memoclaw.com/api-reference/core-memories Pin important memories to exempt them from type-based decay. Core memories are pinned memories that are exempt from type-based decay. Use them for critical facts that should persist indefinitely — user identity, foundational preferences, or key decisions that never expire. **Price:** FREE (all core memory endpoints) ## GET /v1/memories/core List all pinned core memories for your wallet. ### Query Parameters Filter by namespace. Defaults to all namespaces. Maximum number of results (1–100). Pagination offset. ### Response (200) Array of pinned memory objects. Total count of core memories. ### Example ```bash curl theme={null} curl https://api.memoclaw.com/v1/memories/core \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() core = client.list(filters={"pinned": True}) for m in core.memories: print(f"[core] {m.content}") ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const response = await fetch("https://api.memoclaw.com/v1/memories/core", { headers: { "x-wallet-auth": await getAuthHeader() }, }); const { memories } = await response.json(); ``` ```json Response theme={null} { "memories": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User's name is Ana", "importance": 1.0, "pinned": true, "memory_type": "preference", "tags": ["identity"], "created_at": "2026-02-01T12:00:00Z" } ], "total": 1 } ``` *** ## POST /v1/memories/core Pin an existing memory as a core memory. Pinned memories are exempt from type-based decay — they never fade regardless of their `memory_type` half-life. ### Request Body UUID of the memory to pin. ### Response (200) Always `true`. The pinned memory's UUID. ### Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/memories/core \ -H "Content-Type: application/json" \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." \ -d '{"memory_id": "550e8400-e29b-41d4-a716-446655440000"}' ``` ```python Python theme={null} client.update("550e8400-e29b-41d4-a716-446655440000", pinned=True) ``` ```typescript TypeScript theme={null} await client.update("550e8400-e29b-41d4-a716-446655440000", { pinned: true }); ``` ```json Response theme={null} { "pinned": true, "id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### Errors | Status | Description | | ------ | ---------------------------------------------- | | 404 | Memory not found or belongs to another wallet. | | 422 | Invalid UUID format. | *** ## DELETE /v1/memories/core/:id Unpin a core memory. The memory is not deleted — it simply resumes normal type-based decay. ### Path Parameters UUID of the memory to unpin. ### Response (200) Always `true`. The unpinned memory's UUID. ### Example ```bash curl theme={null} curl -X DELETE https://api.memoclaw.com/v1/memories/core/550e8400-e29b-41d4-a716-446655440000 \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." ``` ```python Python theme={null} client.update("550e8400-e29b-41d4-a716-446655440000", pinned=False) ``` ```typescript TypeScript theme={null} await client.update("550e8400-e29b-41d4-a716-446655440000", { pinned: false }); ``` ```json Response theme={null} { "unpinned": true, "id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### Errors | Status | Description | | ------ | ------------------------------- | | 404 | Memory not found or not pinned. | | 422 | Invalid UUID format. | *** ## When to Use Core Memories **Good candidates for pinning:** * User identity (name, timezone, role) * Foundational preferences that rarely change * Critical project decisions * Corrections that must persist indefinitely **Avoid over-pinning.** If everything is a core memory, nothing is. Reserve pinning for truly permanent facts. Most memories benefit from natural decay — it keeps recall results relevant. Learn about type-based decay and why pinning matters. Set `pinned: true` at store time to pin immediately. # Delete Memories Source: https://docs.memoclaw.com/api-reference/delete DELETE https://api.memoclaw.com/v1/memories/{id} Soft-delete one or many memories by ID. **Price:** FREE ## Path Parameters UUID of the memory to delete. ## Response (200) Always `true`. The deleted memory's UUID. Deletion is soft — it sets `deleted_at` on the record. Deleted memories are excluded from all queries (recall, list). This allows future recovery if needed. ## Errors | Status | Description | | ------ | -------------------------------------------------------------------- | | 404 | Memory not found (or already deleted, or belongs to another wallet). | | 409 | Memory is immutable and cannot be deleted. | | 422 | Invalid UUID format. | ## Example ```bash curl theme={null} curl -X DELETE https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000 ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000", { method: "DELETE" } ); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.delete("550e8400-e29b-41d4-a716-446655440000") ``` ```json Response theme={null} { "deleted": true, "id": "550e8400-e29b-41d4-a716-446655440000" } ``` *** ## Bulk Delete — DELETE /v1/memories Delete multiple memories in a single request. Also free. **Price:** FREE ### Request Body Array of memory UUIDs to delete (max 100). ### Response (200) Number of memories successfully deleted. Array of IDs that could not be deleted (not found, immutable, or wrong wallet), if any. ### Example ```bash curl theme={null} curl -X DELETE https://api.memoclaw.com/v1/memories \ -H "Content-Type: application/json" \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." \ -d '{"ids": ["id-1", "id-2", "id-3"]}' ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() # Delete multiple memories at once result = client.bulk_delete(["id-1", "id-2", "id-3"]) print(f"Deleted {result.deleted} memories") ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const result = await client.bulkDelete(["id-1", "id-2", "id-3"]); console.log(`Deleted ${result.deleted} memories`); ``` ```json Response theme={null} { "deleted": 3, "errors": [] } ``` ### Errors | Status | Description | | ------ | ---------------------------------------------- | | 422 | `ids` is missing, empty, or exceeds 100 items. | # Export Memories Source: https://docs.memoclaw.com/api-reference/export GET https://api.memoclaw.com/v1/export GET /v1/export — Export memories in JSON, CSV, or Markdown format. **Price:** FREE Export memories in various formats for backup or migration purposes. ## Query Parameters Output format: `json`, `csv`, or `markdown`. Default: `json`. Filter by namespace. Filter by memory type: `correction`, `preference`, `decision`, `project`, `observation`, or `general`. Comma-separated tags to filter by. Filter by session ID. Filter by agent ID. ISO 8601 date string. Only return memories created before this time. ISO 8601 date string. Only return memories created after this time. Set to `true` to include soft-deleted memories. Default: `false`. ## Response (200 OK) The format used for export. Array of memory objects (JSON) or formatted output (CSV/Markdown). Total number of exported memories. ## Example ```bash curl theme={null} # Export all memories as JSON curl https://api.memoclaw.com/v1/export \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." # Export as CSV curl "https://api.memoclaw.com/v1/export?format=csv" \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." # Export specific namespace curl "https://api.memoclaw.com/v1/export?namespace=acme-project" \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." ``` ```javascript JavaScript theme={null} // Export all memories as JSON const response = await fetch("https://api.memoclaw.com/v1/export", { headers: { "x-wallet-auth": await getAuthHeader() }, }); const data = await response.json(); // Export as CSV const csvResponse = await fetch("https://api.memoclaw.com/v1/export?format=csv", { headers: { "x-wallet-auth": await getAuthHeader() }, }); const csvText = await csvResponse.text(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() # Export all as JSON result = client.export() print(f"Exported {result.count} memories") # Export as CSV csv_result = client.export(format="csv") # Export specific namespace ns_result = client.export(namespace="acme-project") ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); // Export all as JSON const result = await client.export(); console.log(`Exported ${result.count} memories`); // Export as CSV const csvResult = await client.export({ format: "csv" }); // Export specific namespace const nsResult = await client.export({ namespace: "acme-project" }); ``` ```json Response (JSON) theme={null} { "format": "json", "memories": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User prefers dark mode", "importance": 0.8, "memory_type": "preference", "namespace": "default", "tags": ["ui", "preferences"], "created_at": "2026-02-13T10:30:00Z", "updated_at": "2026-02-13T10:30:00Z" } ], "count": 1 } ``` # Extract Facts Source: https://docs.memoclaw.com/api-reference/extract POST https://api.memoclaw.com/v1/memories/extract POST /v1/memories/extract — Extract and store facts from conversation via LLM. **Price:** \$0.01 USDC (includes LLM processing) Extract automatically identifies and stores important facts from a conversation. The LLM parses the messages and creates individual memories for each distinct fact, with automatic deduplication. ## Request Body Array of conversation messages. Each message must have `role` (string) and `content` (string). Max 100 messages, 32,768 characters per message. Namespace for extracted memories. Default: `"default"`. Associate extracted memories with a session. Associate extracted memories with an agent. ## Response (201 Created) UUIDs of the stored memories (includes both new and deduplicated). Total facts identified by the LLM. New facts stored (not duplicates). Facts that matched existing memories (skipped). Total tokens consumed (LLM + embeddings). ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/memories/extract \ -H "Content-Type: application/json" \ -d '{ "messages": [ {"role": "user", "content": "I prefer dark mode in all my apps. Also, my timezone is PST."}, {"role": "assistant", "content": "Got it! I will remember your preferences."} ] }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/memories/extract", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ messages: [ { role: "user", content: "I prefer dark mode in all my apps. Also, my timezone is PST." }, { role: "assistant", content: "Got it! I will remember your preferences." }, ], }), }); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.extract([ {"role": "user", "content": "I prefer dark mode in all my apps. Also, my timezone is PST."}, {"role": "assistant", "content": "Got it! I will remember your preferences."}, ]) ``` ```json Response theme={null} { "memory_ids": [ "550e8400-e29b-41d4-a716-446655440010", "550e8400-e29b-41d4-a716-446655440011" ], "facts_extracted": 2, "facts_stored": 2, "facts_deduplicated": 0, "tokens_used": 185 } ``` The LLM automatically assigns importance and memory type based on the content. Corrections and preferences get higher importance; observations get lower. Each fact is deduplicated against existing memories. # Free Tier Source: https://docs.memoclaw.com/api-reference/free-tier GET https://api.memoclaw.com/v1/free-tier/info GET /v1/free-tier/* — Check and manage your free tier allowance. Every wallet gets **100 free API calls** to paid endpoints. No payment required to start. Free endpoints (list, get, delete, search, suggested, relations, history, graph, export, namespaces, stats) don't consume free tier credits. ## GET /v1/free-tier/info Public endpoint (no auth required). Returns free tier policy. ```bash curl theme={null} curl https://api.memoclaw.com/v1/free-tier/info ``` ```json Response theme={null} { "free_tier": { "enabled": true, "calls_per_wallet": 100, "description": "Every wallet gets 100 free API calls. No payment required." }, "auth": { "header": "x-wallet-auth", "format": "{wallet_address}:{unix_timestamp}:{signature}", "message_to_sign": "memoclaw-auth:{unix_timestamp}", "expiry_seconds": 300 }, "after_free_tier": { "payment": "x402 (USDC on Base)", "note": "Only endpoints using OpenAI are charged. See /reference/pricing for details." } } ``` ## GET /v1/free-tier/status Check your remaining free tier calls. Requires wallet authentication. ### Headers Format: `{address}:{timestamp}:{signature}` ### Response Your wallet address. Calls remaining in free tier. Total free tier allowance (100). Calls already used. ## Example ```bash curl theme={null} curl https://api.memoclaw.com/v1/free-tier/status \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." ``` ```javascript JavaScript theme={null} const timestamp = Math.floor(Date.now() / 1000); const message = `memoclaw-auth:${timestamp}`; const signature = await wallet.signMessage(message); const response = await fetch("https://api.memoclaw.com/v1/free-tier/status", { headers: { "x-wallet-auth": `${wallet.address}:${timestamp}:${signature}`, }, }); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() # auth is handled automatically status = client.status() print(f"Remaining: {status.free_tier_remaining}/{status.free_tier_total}") ``` ```json Response theme={null} { "wallet": "0x1234...abcd", "free_tier_remaining": 87, "free_tier_total": 100, "free_tier_used": 13 } ``` # Get Memory Source: https://docs.memoclaw.com/api-reference/get-memory GET https://api.memoclaw.com/v1/memories/{id} GET /v1/memories/:id — Retrieve a single memory by ID. **Price:** FREE ## Path Parameters UUID of the memory to retrieve. ## Response (200) Returns the full memory object. UUID of the memory. UUID of the owning user. Namespace of the memory. The memory text. Metadata attached to the memory. Importance value (0–1). Memory type: `correction`, `preference`, `decision`, `project`, `observation`, or `general`. Session ID, if set. Agent ID, if set. Whether the memory is pinned (exempt from decay). ISO 8601 expiry date, if set. ISO 8601 creation timestamp. ISO 8601 last update timestamp. ISO 8601 last access timestamp. Number of times this memory has been recalled. ## Errors | Status | Description | | ------ | -------------------------------------------------------- | | 404 | Memory not found, deleted, or belongs to another wallet. | | 422 | Invalid UUID format. | ## Example ```bash curl theme={null} curl https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000 ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000" ); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() memory = client.get("550e8400-e29b-41d4-a716-446655440000") print(memory.content) ``` ```typescript TypeScript theme={null} const memory = await client.get("550e8400-e29b-41d4-a716-446655440000"); console.log(memory.content); ``` ```json Response theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "user_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "namespace": "default", "content": "User prefers dark mode and vim keybindings", "metadata": { "tags": ["preferences", "ui"] }, "importance": 0.8, "memory_type": "preference", "session_id": null, "agent_id": null, "pinned": false, "expires_at": null, "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:30:00Z", "accessed_at": "2025-01-20T14:22:00Z", "access_count": 3 } ``` # Health Check Source: https://docs.memoclaw.com/api-reference/health GET https://api.memoclaw.com/health GET /health — Check API and database status. This endpoint is free and does not require authentication. ## Response (200 — Healthy) `"healthy"` `"connected"` API version. ISO 8601 timestamp. ## Response (503 — Unhealthy) Same response shape, but with degraded values: `"unhealthy"` `"disconnected"` A 503 response means the database is unreachable. The health check has a 2-second timeout. ## Example ```json Healthy (200) theme={null} { "status": "healthy", "db": "connected", "version": "1.0.0", "timestamp": "2025-01-15T10:30:00Z" } ``` ```json Unhealthy (503) theme={null} { "status": "unhealthy", "db": "disconnected", "version": "1.0.0", "timestamp": "2025-01-15T10:30:05Z" } ``` # Ingest Source: https://docs.memoclaw.com/api-reference/ingest POST https://api.memoclaw.com/v1/ingest POST /v1/ingest — Zero-effort ingestion: dump a conversation or raw text, get extracted facts, dedup, and auto-relations. **Price:** \$0.01 USDC Ingest is the easiest way to add memories. Dump a conversation or raw text and MemoClaw will extract facts, deduplicate against existing memories, and optionally create relations between them — all in one call. ## Request Body Array of conversation messages (`{role, content}`). Provide either `messages` or `text`. Raw text to extract facts from. Provide either `messages` or `text`. Namespace for extracted memories. Default: `"default"`. Session identifier for multi-agent scoping. Agent identifier for multi-agent scoping. Automatically create relations between extracted facts. Default: `false`. ## Response (201 Created) Array of UUIDs for the stored memories. Total facts extracted from the input. Facts that were stored (after deduplication). Facts that were skipped because they already existed. Number of relations created between facts (when `auto_relate` is true). Tokens consumed by the LLM extraction. ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/ingest \ -H "Content-Type: application/json" \ -d '{ "messages": [ {"role": "user", "content": "I prefer dark mode and use vim. My timezone is PST."}, {"role": "assistant", "content": "Got it! Dark mode, vim, and PST timezone noted."} ], "namespace": "default", "auto_relate": true }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/ingest", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ messages: [ { role: "user", content: "I prefer dark mode and use vim. My timezone is PST." }, { role: "assistant", content: "Got it! Dark mode, vim, and PST timezone noted." }, ], namespace: "default", auto_relate: true, }), }); ``` ```bash CLI theme={null} memoclaw ingest "I prefer dark mode and use vim. My timezone is PST." ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.ingest( messages=[ {"role": "user", "content": "I prefer dark mode and use vim. My timezone is PST."}, {"role": "assistant", "content": "Got it! Dark mode, vim, and PST timezone noted."}, ], auto_relate=True, ) ``` ```json Response theme={null} { "memory_ids": [ "550e8400-e29b-41d4-a716-446655440020", "550e8400-e29b-41d4-a716-446655440021", "550e8400-e29b-41d4-a716-446655440022" ], "facts_extracted": 3, "facts_stored": 3, "facts_deduplicated": 0, "relations_created": 2, "tokens_used": 185 } ``` Ingest combines extract, dedup, and relate into a single call. If you only need extraction without dedup/relations, use the [Extract](/api-reference/extract) endpoint instead. # List Memories Source: https://docs.memoclaw.com/api-reference/list-memories GET https://api.memoclaw.com/v1/memories GET /v1/memories — List memories with pagination and filters. **Price:** FREE ## Query Parameters Maximum number of results, 1–100. Default: `20`. Pagination offset. Default: `0`. Comma-separated tags. Filter memories matching any of the specified tags. Filter by namespace. Filter by session ID. Filter by agent ID. ## Response (200) Array of memory objects. UUID of the memory. UUID of the owning user. Namespace of the memory. The memory text. Metadata attached to the memory. Importance value (0–1). Memory type: `correction`, `preference`, `decision`, `project`, `observation`, or `general`. Session ID, if set. Agent ID, if set. Whether the memory is pinned (exempt from decay). ISO 8601 expiry date, if set. ISO 8601 creation timestamp. ISO 8601 last update timestamp. ISO 8601 last access timestamp. Number of times this memory has been recalled. Total number of matching memories. Applied limit. Applied offset. ## Example ```bash curl theme={null} curl "https://api.memoclaw.com/v1/memories?limit=10&offset=0&tags=preferences,ui" ``` ```javascript JavaScript theme={null} const params = new URLSearchParams({ limit: "10", offset: "0", tags: "preferences,ui", }); const response = await fetch( `https://api.memoclaw.com/v1/memories?${params}` ); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.list(limit=10, tags=["preferences", "ui"]) ``` ```json Response theme={null} { "memories": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "user_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "namespace": "default", "content": "User prefers dark mode and vim keybindings", "metadata": { "tags": ["preferences", "ui"] }, "importance": 0.8, "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:30:00Z", "accessed_at": "2025-01-20T14:22:00Z", "access_count": 3 } ], "total": 1, "limit": 10, "offset": 0 } ``` # Memory Graph Source: https://docs.memoclaw.com/api-reference/memory-graph GET https://api.memoclaw.com/v1/memories/{id}/graph GET /v1/memories/{id}/graph — Traverse the memory knowledge graph. **Price:** FREE Traverse the knowledge graph of related memories. Returns connected memories up to N hops away, with relationship edges. This endpoint helps visualize and explore how memories relate to each other through the relations API. ## Path Parameters UUID of the starting memory. ## Query Parameters Maximum hops to traverse. Default: `2`. Max: `5`. Maximum total memories to return. Default: `50`. Max: `200`. Comma-separated list of relation types to include: `related_to`, `derived_from`, `contradicts`, `supersedes`, `supports`. ## Response (200 OK) The starting memory. UUID of the memory. Memory text content. Importance score. All memories discovered in the graph traversal. Relationships between memories. UUID of the source memory. UUID of the target memory. Type of relationship. Actual depth traversed. ## Example ```bash curl theme={null} curl "https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000/graph?depth=2" \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000/graph?depth=2", { headers: { "x-wallet-auth": await getAuthHeader() } } ); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.get_memory_graph( "550e8400-e29b-41d4-a716-446655440000", depth=2, ) print(f"Found {len(result.nodes)} nodes and {len(result.edges)} edges") ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const result = await client.getMemoryGraph( "550e8400-e29b-41d4-a716-446655440000", { depth: 2 } ); console.log(`Found ${result.nodes.length} nodes and ${result.edges.length} edges`); ``` ```json Response theme={null} { "root": { "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User prefers dark mode", "importance": 0.8 }, "nodes": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User prefers dark mode", "importance": 0.8 }, { "id": "660e8400-e29b-41d4-a716-446655440001", "content": "Dark mode saves battery", "importance": 0.5 }, { "id": "770e8400-e29b-41d4-a716-446655440002", "content": "User uses vim keybindings", "importance": 0.7 } ], "edges": [ { "source_id": "550e8400-e29b-41d4-a716-446655440000", "target_id": "660e8400-e29b-41d4-a716-446655440001", "relation_type": "supports" }, { "source_id": "550e8400-e29b-41d4-a716-446655440000", "target_id": "770e8400-e29b-41d4-a716-446655440002", "relation_type": "related_to" } ], "depth": 2 } ``` # Memory History Source: https://docs.memoclaw.com/api-reference/memory-history GET https://api.memoclaw.com/v1/memories/{id}/history GET /v1/memories/:id/history — Get the change history for a memory. **Price:** FREE Retrieve the full change history for a memory. Every update (content, importance, metadata, etc.) is tracked as a history entry. ## Path Parameters UUID of the memory. ## Response (200) Array of history entries, ordered by creation time (newest first). UUID of the history entry. UUID of the memory. Object containing the fields that were changed and their new values. ISO 8601 timestamp of when the change was made. ## Errors | Status | Description | | ------ | -------------------------------------------------------- | | 404 | Memory not found, deleted, or belongs to another wallet. | | 422 | Invalid UUID format. | ## Example ```bash curl theme={null} curl https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000/history ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000/history" ); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() history = client.get_history("550e8400-e29b-41d4-a716-446655440000") for entry in history: print(f"{entry.created_at}: {entry.changes}") ``` ```typescript TypeScript theme={null} const history = await client.getHistory("550e8400-e29b-41d4-a716-446655440000"); for (const entry of history) { console.log(`${entry.created_at}: ${JSON.stringify(entry.changes)}`); } ``` ```json Response theme={null} { "history": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "memory_id": "550e8400-e29b-41d4-a716-446655440000", "changes": { "importance": 0.95, "content": "User prefers 2-space indentation (not tabs)" }, "created_at": "2026-02-11T15:30:00Z" }, { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "memory_id": "550e8400-e29b-41d4-a716-446655440000", "changes": { "metadata": { "tags": ["preferences", "code-style"] } }, "created_at": "2026-02-10T12:00:00Z" } ] } ``` History is only created when a memory is updated via `PATCH /v1/memories/:id`. The initial store does not create a history entry. # Migrate Source: https://docs.memoclaw.com/api-reference/migrate POST https://api.memoclaw.com/v1/migrate Import markdown files (e.g., OpenClaw memory files) as MemoClaw memories. Parses markdown files, splits by `##` headers, auto-detects importance and memory type, and stores each section as a separate memory. Idempotent — duplicate content is deduplicated via content hashing. ## Request Body Array of file objects to import. Maximum **50 files** per request. Original filename (e.g., `2026-01-30.md`). Dates in `YYYY-MM-DD` format are extracted and added as tags. Raw markdown content of the file. ## Response Number of files successfully processed. Number of new memories stored. Number of memories skipped due to duplicate content. Present only if some files failed. Each entry has `filename` and `error`. ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/migrate \ -H "Content-Type: application/json" \ -d '{ "files": [ { "filename": "2026-01-30.md", "content": "## Project Setup\nDecided to use PostgreSQL with pgvector.\n\n## Config\nUser prefers dark mode." } ] }' ``` ```json 201 theme={null} { "files_processed": 1, "memories_created": 2, "memories_deduplicated": 0 } ``` ## How parsing works 1. Each file is split on `## ` headers 2. Each section becomes one memory with: * **content**: header + body text (max 8,000 chars) * **importance**: 0.6–0.9 based on keyword heuristics (decisions=0.9, preferences=0.8, etc.) * **memory\_type**: auto-detected (`decision`, `preference`, `correction`, `project`, `observation`, `general`) * **tags**: header words + `date:YYYY-MM-DD` from filename + `migrated` + `openclaw` 3. Content is SHA-256 hashed for intra-batch and cross-request deduplication 4. Files without `##` headers are stored as a single memory ## Pricing | Endpoint | Cost | | ------------------ | ------------------ | | `POST /v1/migrate` | \$0.01 per request | # List Namespaces Source: https://docs.memoclaw.com/api-reference/namespaces GET https://api.memoclaw.com/v1/namespaces GET /v1/namespaces — List all namespaces with memory counts. **Price:** FREE Returns all namespaces for the authenticated wallet with memory counts. ## Query Parameters No query parameters required. ## Response (200 OK) List of namespace objects. Namespace name. Number of non-deleted, non-expired memories in this namespace. ISO 8601 timestamp of the most recent memory in this namespace. Total number of namespaces. ## Example ```bash curl theme={null} curl https://api.memoclaw.com/v1/namespaces \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/namespaces", { headers: { "x-wallet-auth": await getAuthHeader() }, }); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.list_namespaces() for ns in result.namespaces: print(f"{ns.name}: {ns.count} memories") ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const result = await client.listNamespaces(); result.namespaces.forEach(ns => { console.log(`${ns.name}: ${ns.count} memories`); }); ``` ```json Response theme={null} { "namespaces": [ { "name": "default", "count": 42, "last_memory_at": "2026-02-13T10:30:00Z" }, { "name": "acme-project", "count": 15, "last_memory_at": "2026-02-12T16:45:00Z" } ], "total": 2 } ``` # API Overview Source: https://docs.memoclaw.com/api-reference/overview Base URL, request format, authentication headers, and common patterns. ## Base URL ``` https://api.memoclaw.com ``` ## Request Format All requests use `Content-Type: application/json`. The maximum request body size is **64 KB**. ## Authentication MemoClaw uses your wallet as identity — no API keys or accounts needed. * **Paid endpoints** (store, recall, update, extract, ingest, consolidate, context, migrate) require an [x402 payment header](/get-started/authentication) or [free tier](/api-reference/free-tier) credits. Your wallet address is extracted from the payment proof. * **Free endpoints** (list, get, delete, search, suggested, core memories, relations, history, graph, export, namespaces, stats) require only a wallet signature via the `x-wallet-auth` header. No payment needed. See [Pricing](/reference/pricing) for the full breakdown of paid vs. free endpoints. ## Request ID Every response includes a unique `X-Request-Id` header. Include this when contacting support or debugging issues. ``` X-Request-Id: 550e8400-e29b-41d4-a716-446655440000 ``` ## Error Format All errors return a consistent JSON structure: ```json theme={null} { "error": { "code": "VALIDATION_ERROR", "message": "Content is required", "details": { "field": "content" } } } ``` See [Error Codes](/reference/error-codes) for a full list of error codes and their meanings. ## TypeScript Examples Some API reference pages include TypeScript code samples using the `memoclaw` package. The SDK client (`MemoClawClient`) is planned but not yet exported — these examples show the intended interface. For now, use the [CLI](/get-started/cli) (`npm install -g memoclaw`) or direct [REST API](/api-reference/overview) calls. See [TypeScript SDK](/get-started/typescript-sdk) for details. # Recall Memories Source: https://docs.memoclaw.com/api-reference/recall POST https://api.memoclaw.com/v1/recall POST /v1/recall — Semantic search across your memories. **Price:** \$0.005 USDC ## Request Body Natural language search query. Max 32,768 characters. Maximum number of results, 1–100. Default: `5`. Minimum similarity threshold, 0–1. Default: `0.0`. Filter results to a specific namespace. Filter results to a specific session. Filter results to a specific agent. Include related memories in results. Default: `false`. Additional filters to narrow results. Match memories with any of these tags. Max 10. ISO 8601 date. Only return memories created after this date. ## Scoring **Hybrid recall scoring (4-signal approach):** ``` hybrid = vector_sim × 0.55 + keyword_match × 0.25 + recency × 0.20 score = hybrid × context_importance × access_boost × type_decay ``` Signals: * **vector\_sim**: Cosine similarity (0–1) — primary semantic signal * **keyword\_match**: Full-text/BM25 match, normalized (0–1) — exact term matches * **recency**: `exp(-age_days / 30)` — temporal freshness * **context\_importance**: Importance dynamically boosted by query relevance * **access\_boost**: `min(1 + access_count × 0.1, 2.0)` — frequently recalled memories rank higher * **type\_decay**: Exponential decay based on memory type half-life (correction: 180d, preference: 180d, decision: 90d, project: 30d, observation: 14d, general: 60d). Pinned memories are exempt from decay. Memories with more relations decay slower. When keyword match is strong (>0.3), its weight increases to 0.35 (vector drops to 0.45) for adaptive boosting. ## Response (200) Array of matching memories. UUID of the memory. The memory text. Weighted similarity score. Metadata attached to the memory. Importance value (0–1). Namespace of the memory. Memory type: `correction`, `preference`, `decision`, `project`, `observation`, or `general`. Session identifier, if set. Agent identifier, if set. ISO 8601 creation timestamp. Number of times this memory has been recalled. Whether the memory is pinned (exempt from decay). Signal breakdown for debugging/transparency. Includes `vector`, `keyword`, `recency`, `base_importance`, `effective_importance`, `context_importance`, `relation_count`, and `type_decay`. Tokens used for the query embedding. ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/recall \ -H "Content-Type: application/json" \ -d '{ "query": "What are the user editor preferences?", "limit": 5, "filters": { "tags": ["preferences"] } }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/recall", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: "What are the user editor preferences?", limit: 5, filters: { tags: ["preferences"], }, }), }); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.recall( "What are the user editor preferences?", limit=5, tags=["preferences"], ) ``` ```json Response theme={null} { "memories": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User prefers dark mode and vim keybindings", "similarity": 0.89, "metadata": { "tags": ["preferences", "ui"] }, "importance": 0.8, "memory_type": "preference", "namespace": "default", "session_id": null, "agent_id": null, "created_at": "2025-01-15T10:30:00Z", "access_count": 3, "pinned": false, "_signals": { "vector": 0.92, "keyword": 0.15, "recency": 0.78, "base_importance": 0.8, "effective_importance": 0.96, "context_importance": 0.98, "relation_count": 1, "type_decay": 0.95 } } ], "query_tokens": 12 } ``` # Memory Relations Source: https://docs.memoclaw.com/api-reference/relations POST https://api.memoclaw.com/v1/memories/{id}/relations CRUD operations for memory relationships — link memories together. **Price:** FREE Relations let you create explicit links between memories. Use them to build knowledge graphs, track contradictions, or group related facts. ## Relation Types | Type | Description | | -------------- | ---------------------------------------------------------------- | | `related_to` | General relationship between related memories | | `derived_from` | Memory was derived/synthesized from another (e.g. consolidation) | | `contradicts` | Memories that conflict (useful for tracking corrections) | | `supersedes` | New memory replaces old one | | `supports` | Memory provides supporting evidence for another | *** ## POST /v1/memories/:id/relations Create a relationship from one memory to another. ### Path Parameters Source memory UUID. ### Request Body Target memory UUID to link to. One of: `related_to`, `derived_from`, `contradicts`, `supersedes`, `supports`. Optional metadata for the relationship. ### Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440001/relations \ -H "Content-Type: application/json" \ -d '{ "target_id": "550e8400-e29b-41d4-a716-446655440002", "relation_type": "supersedes", "metadata": { "reason": "User corrected their timezone preference" } }' ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() relation = client.create_relation( "550e8400-e29b-41d4-a716-446655440001", target_id="550e8400-e29b-41d4-a716-446655440002", relation_type="supersedes", metadata={"reason": "User corrected their timezone preference"}, ) ``` ```json Response theme={null} { "id": "rel-123e4567-e89b-12d3-a456-426614174000", "source_id": "550e8400-e29b-41d4-a716-446655440001", "target_id": "550e8400-e29b-41d4-a716-446655440002", "relation_type": "supersedes", "metadata": { "reason": "User corrected their timezone preference" }, "created_at": "2024-02-11T10:45:00Z" } ``` *** ## GET /v1/memories/:id/relations List all relationships for a memory (both incoming and outgoing). ### Path Parameters Memory UUID. ### Example ```bash curl theme={null} curl https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440001/relations ``` ```json Response theme={null} { "relations": [ { "id": "rel-123e4567-e89b-12d3-a456-426614174000", "source_id": "550e8400-e29b-41d4-a716-446655440001", "target_id": "550e8400-e29b-41d4-a716-446655440002", "relation_type": "supersedes", "direction": "outgoing", "created_at": "2024-02-11T10:45:00Z" }, { "id": "rel-223e4567-e89b-12d3-a456-426614174001", "source_id": "550e8400-e29b-41d4-a716-446655440005", "target_id": "550e8400-e29b-41d4-a716-446655440001", "relation_type": "supports", "direction": "incoming", "created_at": "2024-02-10T08:30:00Z" } ] } ``` *** ## DELETE /v1/memories/:id/relations/:relationId Remove a relationship. ### Path Parameters Memory UUID. Relation UUID to delete. ### Example ```bash curl theme={null} curl -X DELETE https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440001/relations/rel-123e4567-e89b-12d3-a456-426614174000 ``` ```json Response theme={null} { "deleted": true } ``` # Search Memories Source: https://docs.memoclaw.com/api-reference/search POST https://api.memoclaw.com/v1/search POST /v1/search — Full-text search without embedding costs. **Price:** FREE Full-text keyword search using BM25 ranking. A lightweight alternative to `/v1/recall` when you don't need semantic embeddings or want to reduce costs. This endpoint uses PostgreSQL full-text search (tsvector) rather than vector similarity, making it faster and free from embedding API costs. ## Request Body Search query string. Max 1,000 characters. Maximum number of results. Default: `10`. Max: `100`. Filter by namespace. Filter by memory type: `correction`, `preference`, `decision`, `project`, `observation`, or `general`. Filter by tags. Filter by session ID. Filter by agent ID. ## Response (200 OK) Array of matching memories sorted by BM25 relevance. UUID of the memory. Memory text content. Importance score (0-1). Memory type. Namespace. Tags. ISO 8601 timestamp. Total number of matches. The search query used. ## When to Use Search vs Recall | Use Case | Endpoint | | --------------------------------- | ------------ | | Natural language semantic search | `/v1/recall` | | Keyword/exact match search | `/v1/search` | | Need vector similarity scoring | `/v1/recall` | | Reduce embedding API costs | `/v1/search` | | Find memories with specific words | `/v1/search` | ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/search \ -H "Content-Type: application/json" \ -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." \ -d '{ "query": "dark mode preferences", "limit": 10, "tags": ["preferences"] }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/search", { method: "POST", headers: { "Content-Type": "application/json", "x-wallet-auth": await getAuthHeader(), }, body: JSON.stringify({ query: "dark mode preferences", limit: 10, tags: ["preferences"], }), }); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.search( query="dark mode preferences", limit=10, tags=["preferences"], ) for m in result.memories: print(f"[{m.id}] {m.content}") ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const result = await client.search({ query: "dark mode preferences", limit: 10, tags: ["preferences"], }); result.memories.forEach(m => { console.log(`[${m.id}] ${m.content}`); }); ``` ```json Response theme={null} { "memories": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User prefers dark mode", "importance": 0.8, "memory_type": "preference", "namespace": "default", "tags": ["preferences", "ui"], "created_at": "2026-02-13T10:30:00Z" } ], "total": 1, "query": "dark mode preferences" } ``` # Session Auth Source: https://docs.memoclaw.com/api-reference/session POST https://api.memoclaw.com/auth/session POST /auth/session — Exchange a wallet signature for a JWT session token. This endpoint is free and does not require x402 payment. Session auth lets you sign once with your wallet and use a JWT token for subsequent requests. This avoids signing every request individually and is used by the MemoClaw dashboard. ## Request Body Your EVM wallet address. Current Unix timestamp (seconds). Must be within 5 minutes of server time. Signature of the message `memoclaw-auth:{timestamp}` signed with your wallet's private key. ## Response (200) JWT session token. Valid for 7 days. Include as `Authorization: Bearer {token}` in subsequent requests. Your wallet address. ISO 8601 expiry timestamp for the token. ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/auth/session \ -H "Content-Type: application/json" \ -d '{ "address": "0x1234567890abcdef1234567890abcdef12345678", "timestamp": 1707800000, "signature": "0x..." }' ``` ```javascript JavaScript theme={null} import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const timestamp = Math.floor(Date.now() / 1000); const message = `memoclaw-auth:${timestamp}`; const signature = await account.signMessage({ message }); const response = await fetch("https://api.memoclaw.com/auth/session", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address: account.address, timestamp, signature, }), }); const { token } = await response.json(); // Use the token for subsequent requests const memories = await fetch("https://api.memoclaw.com/v1/memories", { headers: { Authorization: `Bearer ${token}` }, }); ``` ```python Python theme={null} from eth_account import Account from eth_account.messages import encode_defunct import time, requests account = Account.from_key("0x...") timestamp = int(time.time()) message = f"memoclaw-auth:{timestamp}" signed = account.sign_message(encode_defunct(text=message)) response = requests.post("https://api.memoclaw.com/auth/session", json={ "address": account.address, "timestamp": timestamp, "signature": signed.signature.hex(), }) token = response.json()["token"] # Use the token for subsequent requests memories = requests.get("https://api.memoclaw.com/v1/memories", headers={"Authorization": f"Bearer {token}"}) ``` ```typescript TypeScript theme={null} import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const timestamp = Math.floor(Date.now() / 1000); const signature = await account.signMessage({ message: `memoclaw-auth:${timestamp}`, }); const { token } = await fetch("https://api.memoclaw.com/auth/session", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address: account.address, timestamp, signature }), }).then(r => r.json()); // Use: Authorization: Bearer {token} ``` ```json Response theme={null} { "token": "eyJhbGciOiJIUzI1NiIs...", "wallet": "0x1234567890abcdef1234567890abcdef12345678", "expires_at": "2026-02-20T17:00:00Z" } ``` ## Errors | Status | Description | | ------ | -------------------------------------------------------- | | 401 | Invalid signature or expired timestamp. | | 422 | Missing required fields (address, timestamp, signature). | Session tokens are ideal for frontend applications like the dashboard where you don't want to sign every request. For server-to-server usage, the free tier `x-wallet-auth` header or x402 payment is more straightforward. # Memory Stats Source: https://docs.memoclaw.com/api-reference/stats GET https://api.memoclaw.com/v1/stats GET /v1/stats — Get memory usage statistics for your wallet. **Price:** FREE Returns aggregate statistics about your stored memories, broken down by type and namespace. ## Response (200) Total number of active (non-deleted, non-expired) memories. Number of pinned memories. Memories that have never been recalled. Sum of all access counts across all memories. Average importance score across all memories. ISO 8601 timestamp of the oldest memory. ISO 8601 timestamp of the newest memory. Memory count grouped by type. Memory count grouped by namespace. ## Example ```bash curl theme={null} curl https://api.memoclaw.com/v1/stats ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/stats"); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() stats = client.stats() print(f"Total memories: {stats.total_memories}") ``` ```typescript TypeScript theme={null} const stats = await client.stats(); console.log(`Total memories: ${stats.total_memories}`); ``` ```json Response theme={null} { "total_memories": 142, "pinned_count": 8, "never_accessed": 23, "total_accesses": 891, "avg_importance": 0.64, "oldest_memory": "2025-06-01T08:00:00Z", "newest_memory": "2026-02-13T10:30:00Z", "by_type": [ { "memory_type": "preference", "count": 45 }, { "memory_type": "general", "count": 38 }, { "memory_type": "observation", "count": 25 }, { "memory_type": "decision", "count": 18 }, { "memory_type": "project", "count": 12 }, { "memory_type": "correction", "count": 4 } ], "by_namespace": [ { "namespace": "default", "count": 89 }, { "namespace": "project-memoclaw", "count": 35 }, { "namespace": "client-acme", "count": 18 } ] } ``` # Store Memory Source: https://docs.memoclaw.com/api-reference/store POST https://api.memoclaw.com/v1/store POST /v1/store — Store a single memory with semantic embeddings. **Price:** \$0.005 USDC ## Request Body The memory text. Max 8,192 characters. Arbitrary key-value metadata. Max 4 KB, 20 keys, 3 levels deep. Tags for filtering. Max 10 tags, 64 characters each. Float between 0 and 1. Affects ranking in recall. Default: `0.5`. Isolate memories per project or context. Default: `"default"`. Max 255 characters. One of: `correction`, `preference`, `decision`, `project`, `observation`, `general`. Each type has a different decay half-life. Default: `"general"`. Session identifier for multi-agent scoping. Max 255 characters. Agent identifier for multi-agent scoping. Max 255 characters. ISO 8601 date string. Memory auto-expires after this time and is excluded from all queries. Must be in the future. Pin this memory to exempt it from decay. Default: `false`. Lock the memory from future updates and deletes. Default: `false`. Once stored as immutable, the memory cannot be modified or removed (returns 409 Conflict). ## Response (201 Created) UUID of the stored memory. Always `true`. Whether the memory was deduplicated (merged with an existing similar memory instead of creating a new one). Embedding tokens consumed. ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/store \ -H "Content-Type: application/json" \ -d '{ "content": "User prefers dark mode and vim keybindings", "metadata": { "tags": ["preferences", "ui"] }, "importance": 0.8 }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/store", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content: "User prefers dark mode and vim keybindings", metadata: { tags: ["preferences", "ui"], }, importance: 0.8, }), }); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.store( "User prefers dark mode and vim keybindings", importance=0.8, tags=["preferences", "ui"], ) ``` ```json Response theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "stored": true, "deduplicated": false, "tokens_used": 15 } ``` # Store Batch Source: https://docs.memoclaw.com/api-reference/store-batch POST https://api.memoclaw.com/v1/store/batch POST /v1/store/batch — Store up to 100 memories in a single request. **Price:** \$0.04 USDC ## Request Body Array of memory objects. Min 1, max 100. Each object accepts the same fields as [Store Memory](/api-reference/store). The memory text. Max 8,192 characters. Arbitrary key-value metadata. Max 4 KB, 20 keys, 3 levels deep. Float between 0 and 1. Default: `0.5`. Namespace to isolate memories. Default: `"default"`. Max 255 characters. One of: `correction`, `preference`, `decision`, `project`, `observation`, `general`. Default: `"general"`. Session identifier. Max 255 characters. Agent identifier. Max 255 characters. ISO 8601 date string. Must be in the future. Pin this memory to exempt it from decay. Default: `false`. Lock the memory from future updates and deletes. Default: `false`. ## Response (201 Created) Array of UUIDs for the stored memories. Always `true`. Number of memories stored. Number of memories that were deduplicated (merged with existing similar memories). Total embedding tokens consumed. ## Example ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/store/batch \ -H "Content-Type: application/json" \ -d '{ "memories": [ { "content": "User prefers dark mode and vim keybindings", "metadata": { "tags": ["preferences"] }, "importance": 0.8 }, { "content": "Project uses PostgreSQL with pgvector extension", "metadata": { "tags": ["stack", "database"] }, "importance": 0.6 } ] }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.memoclaw.com/v1/store/batch", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ memories: [ { content: "User prefers dark mode and vim keybindings", metadata: { tags: ["preferences"] }, importance: 0.8, }, { content: "Project uses PostgreSQL with pgvector extension", metadata: { tags: ["stack", "database"] }, importance: 0.6, }, ], }), }); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.store_batch([ {"content": "User prefers dark mode and vim keybindings", "metadata": {"tags": ["preferences"]}, "importance": 0.8}, {"content": "Project uses PostgreSQL with pgvector extension", "metadata": {"tags": ["stack", "database"]}, "importance": 0.6}, ]) ``` ```json Response theme={null} { "ids": [ "550e8400-e29b-41d4-a716-446655440000", "6ba7b810-9dad-11d1-80b4-00c04fd430c8" ], "stored": true, "count": 2, "deduplicated_count": 0, "tokens_used": 28 } ``` # Suggested Memories Source: https://docs.memoclaw.com/api-reference/suggested GET https://api.memoclaw.com/v1/suggested GET /v1/suggested — Get proactive memory suggestions for review. **Price:** FREE Suggested returns memories you *should* be reviewing based on access patterns and importance. Use this for proactive memory maintenance instead of only recalling on-demand. ## Categories | Category | Description | | ---------- | -------------------------------------------------------------- | | `stale` | High importance but not recently accessed — might need refresh | | `fresh` | Recently stored but never accessed — verify they're useful | | `hot` | Frequently accessed — your most valuable memories | | `decaying` | Approaching decay threshold — access soon or they'll fade | ## Query Parameters Max memories to return. Default: `10`, max: `50`. Filter to a specific category: `stale`, `fresh`, `hot`, or `decaying`. Filter by namespace. Filter by session ID. Filter by agent ID. ## Response Array of suggested memories with category labels. Breakdown of counts per category. Total suggestions available. ## Example ```bash curl theme={null} curl "https://api.memoclaw.com/v1/suggested?limit=5&category=stale" ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.memoclaw.com/v1/suggested?limit=5&category=stale" ); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.suggested(limit=5, category="stale") ``` ```json Response theme={null} { "suggested": [ { "id": "550e8400-e29b-41d4-a716-446655440001", "content": "User's API key for production is stored in 1Password", "metadata": { "tags": ["secrets"] }, "importance": 0.9, "memory_type": "preference", "namespace": "default", "session_id": null, "agent_id": null, "created_at": "2024-01-01T08:00:00Z", "accessed_at": "2024-01-15T10:30:00Z", "access_count": 5, "relation_count": 2, "category": "stale", "review_score": 1.35 } ], "categories": { "stale": 12, "fresh": 5, "hot": 8, "decaying": 3 }, "total": 28 } ``` Run `/v1/suggested` periodically (e.g., daily) to maintain memory health. Accessing a memory resets its decay timer. # Update Memory Source: https://docs.memoclaw.com/api-reference/update PATCH https://api.memoclaw.com/v1/memories/{id} PATCH /v1/memories/:id — Update a memory in-place. **Price:** \$0.005 USDC Update one or more fields on an existing memory. If `content` is changed, the embedding and full-text search vector are regenerated automatically. All other fields (metadata, importance, etc.) are updated without re-embedding. ## Path Parameters UUID of the memory to update. ## Request Body At least one field must be provided. Only provided fields are updated — omitted fields are left unchanged. New memory text. Max 8,192 characters. Triggers re-embedding. Replace metadata entirely. Max 4 KB, 20 keys, 3 levels deep. Tags for filtering. Max 10 tags, 64 characters each. Float between 0 and 1. One of: `correction`, `preference`, `decision`, `project`, `observation`, `general`. Move memory to a different namespace. Max 255 characters. Pin or unpin a memory. Pinned memories are exempt from type-based decay. ISO 8601 date string to set a TTL, or `null` to clear expiration. Must be in the future. Set to `true` to lock the memory permanently. Once immutable, the memory cannot be updated or deleted. This is a one-way operation. Immutable memories cannot be updated or deleted. Attempting either returns **409 Conflict**. If you need to update a memory, do so *before* setting `immutable: true`. ## Response (200) Returns the full updated memory object. UUID of the memory. Memory content. Memory metadata. Importance score. Memory type. Memory namespace. Expiration date or `null`. Timestamp of this update. Update does **not** run deduplication — you explicitly chose this memory ID, so the content is stored as-is. Relations, access history, and decay state are preserved. ## Errors | Status | Description | | ------ | ------------------------------------------------------------ | | 404 | Memory not found (or deleted, or belongs to another wallet). | | 409 | Memory is immutable and cannot be modified. | | 422 | Invalid UUID format, empty body, or field validation failed. | ## Example ```bash curl theme={null} curl -X PATCH https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000 \ -H "Content-Type: application/json" \ -d '{ "content": "User prefers 2-space indentation (not tabs)", "importance": 0.95, "expires_at": "2026-06-01T00:00:00Z" }' ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.memoclaw.com/v1/memories/550e8400-e29b-41d4-a716-446655440000", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content: "User prefers 2-space indentation (not tabs)", importance: 0.95, expires_at: "2026-06-01T00:00:00Z", }), } ); const data = await response.json(); ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.update( "550e8400-e29b-41d4-a716-446655440000", content="User prefers 2-space indentation (not tabs)", importance=0.95, expires_at="2026-06-01T00:00:00Z", ) ``` ```json Response theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User prefers 2-space indentation (not tabs)", "metadata": { "tags": ["preferences", "code-style"] }, "importance": 0.95, "memory_type": "preference", "namespace": "default", "expires_at": "2026-06-01T00:00:00Z", "updated_at": "2026-02-11T15:30:00Z", "created_at": "2026-02-10T12:00:00Z", "access_count": 3 } ``` # Batch Update Source: https://docs.memoclaw.com/api-reference/update-batch PATCH https://api.memoclaw.com/v1/memories/batch PATCH /v1/memories/batch — Update multiple memories in a single request. **Price:** \$0.005 USDC Update multiple memories at once. Each update object must include the memory `id` and at least one field to change. If `content` is changed on any memory, its embedding is regenerated. ## Request Body Array of update objects. Min 1, max 100. Each must include `id` plus at least one field to change. UUID of the memory to update. New memory text. Max 8,192 characters. Triggers re-embedding. Replace metadata entirely. Max 4 KB, 20 keys, 3 levels deep. Float between 0 and 1. One of: `correction`, `preference`, `decision`, `project`, `observation`, `general`. Move memory to a different namespace. Max 255 characters. Pin or unpin the memory. ISO 8601 date string or `null` to clear expiration. Lock the memory permanently. One-way operation. Immutable memories in the batch are skipped and returned in the `errors` array with a 409 status. The rest of the batch still processes. ## Response (200) Number of memories successfully updated. Array of error objects for memories that failed to update. UUID of the memory that failed. HTTP status code (404, 409, 422). Error description. ## Example ```bash curl theme={null} curl -X PATCH https://api.memoclaw.com/v1/memories/batch \ -H "Content-Type: application/json" \ -d '{ "updates": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "importance": 0.95, "pinned": true }, { "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "content": "Updated: team now uses pnpm instead of npm", "metadata": { "tags": ["stack", "tooling"] } } ] }' ``` ```bash CLI theme={null} memoclaw update 550e8400-e29b-41d4-a716-446655440000 \ --importance 0.95 --pinned memoclaw update 6ba7b810-9dad-11d1-80b4-00c04fd430c8 \ --content "Updated: team now uses pnpm instead of npm" \ --tags stack,tooling ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() result = client.update_batch([ { "id": "550e8400-e29b-41d4-a716-446655440000", "importance": 0.95, "pinned": True, }, { "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "content": "Updated: team now uses pnpm instead of npm", "metadata": {"tags": ["stack", "tooling"]}, }, ]) ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const result = await client.updateBatch({ updates: [ { id: "550e8400-e29b-41d4-a716-446655440000", importance: 0.95, pinned: true, }, { id: "6ba7b810-9dad-11d1-80b4-00c04fd430c8", content: "Updated: team now uses pnpm instead of npm", metadata: { tags: ["stack", "tooling"] }, }, ], }); ``` ```json Response theme={null} { "updated": 2, "errors": [] } ``` ## Errors | Status | Description | | ------ | ---------------------------------------------------- | | 404 | Memory not found (skipped, reported in `errors`). | | 409 | Memory is immutable (skipped, reported in `errors`). | | 422 | Invalid request body or field validation failed. | # Changelog Source: https://docs.memoclaw.com/changelog All notable changes to MemoClaw. ## v0.12.0 - 2026-03-06 ### Added * **Context endpoint**: AI-curated memory retrieval in one call * **OG/Twitter meta tags** for social sharing on all pages ### Improved * Hero performance badges: under 200ms recall, 99.9% uptime * Accessibility improvements: ARIA labels, skip links, focus-visible *** ## v0.11.0 - 2026-03-01 ### Added * **Consolidate endpoint**: Merge related memories with GPT-4o-mini * **Dashboard empty states** and keyboard shortcuts ### Fixed * CSV export formula injection sanitization *** ## v0.10.0 - 2026-02-20 ### Added * **Extract endpoint**: Auto-extract structured facts from raw text * **Ingest endpoint**: Extract, deduplicate, and store in one call * **Migrate endpoint**: Import `.md` files via API *** ## v0.9.0 - 2026-02-13 ### Added * **TypeScript SDK** (`memoclaw`) interface designed (client not yet exported — see [TypeScript SDK](/get-started/typescript-sdk)) * **Memory history endpoint**: Track how memories evolve over time * **Session-scoped memories** with `GET /v1/session/:id` ### Improved * Dashboard redesign with wallet management and usage stats *** ## Pricing Overhaul - 2026-02-15 ### Changed * **Free endpoints**: List, get, delete, search (text), suggested, core memories, relations, history, graph, export, namespaces, and stats are now **completely free** — no payment required * **Paid endpoints** now only include those using OpenAI (embeddings or LLM): * Embedding endpoints: store (\$0.005), store/batch (\$0.04), recall (\$0.005), update (\$0.005) * LLM + embedding endpoints: extract (\$0.01), consolidate (\$0.01), ingest (\$0.01), context (\$0.01), migrate (\$0.01) * **Free tier** reduced from 1,000 to **100 calls** (only paid endpoints consume credits) *** ## v0.8.0 - 2026-02-01 ### Added * **Smart ingestion endpoint**: Auto-extract, deduplicate, and relate memories * **Proactive memory suggestions**: Surface stale, fresh, hot, and decaying memories ### Improved * Recall latency improved to under 200ms p95 *** ## v0.7.0 - 2026-01-15 ### Added * **Python SDK** (`pip install memoclaw`) with sync + async support * **MCP server** integration for Claude Desktop and Cursor * **Connection-weighted decay** algorithm * **4-signal hybrid retrieval**: Semantic + recency + importance + frequency *** ## v0.6.0 - 2025-12-20 ### Added * **Initial launch**: Store, recall, list, delete endpoints * **x402 payment protocol** integration (no API keys needed) * **1,000 free calls** per wallet # Architecture Overview Source: https://docs.memoclaw.com/concepts/architecture How MemoClaw is built: API server, managed memory storage, embeddings, and payment layer. MemoClaw is a managed memory service, not a general-purpose vector database. We run PostgreSQL + pgvector under the hood so you don't have to, but you can't use MemoClaw as a drop-in vector store. ## System Architecture ```mermaid theme={null} graph LR A["Your Agent\n(SDK / CLI / MCP)"] <--> B["MemoClaw API\n(Hono on Bun)"] B <--> C["PostgreSQL +\npgvector"] B --> D["OpenAI\nEmbeddings API"] B --> E["x402 Facilitator\n(Coinbase)"] ``` ## Components ### API Server The MemoClaw API runs on [Hono](https://hono.dev) with [Bun](https://bun.sh) as the runtime. It handles: * Request validation and rate limiting * Wallet authentication (free tier) and x402 payment verification * Memory CRUD operations * LLM-powered extraction and consolidation * Hybrid recall scoring ### Database: PostgreSQL + pgvector All memories are stored in PostgreSQL with the [pgvector](https://github.com/pgvector/pgvector) extension: * **Memory content** stored as text with full-text search (tsvector) * **Embeddings** stored as 512-dimensional vectors * **HNSW index** for fast approximate nearest neighbor search * **GIN index** on tsvector for keyword/BM25 matching ### Embeddings Text is converted to vectors using OpenAI's `text-embedding-3-small` model (512 dimensions). An LRU cache of 1,000 embeddings avoids redundant API calls for repeated queries. ### Payment Layer: x402 MemoClaw uses the [x402 protocol](https://x402.org) for payment-as-authentication: 1. **Free tier**: Wallet signature verification (100 free calls) 2. **Paid tier**: USDC micropayments on Base (chain ID 8453) via EIP-3009 or Permit2 3. **Identity**: Your wallet address is extracted from the payment proof — no accounts needed The x402 facilitator (Coinbase) verifies payments before requests are processed. ### LLM Processing Some endpoints use an LLM (OpenAI GPT) for intelligent processing: * **Extract** (`/v1/memories/extract`): Parses conversations into discrete facts * **Ingest** (`/v1/ingest`): Extracts, deduplicates, and relates facts * **Consolidate** (`/v1/memories/consolidate`, LLM mode): Synthesizes merged memories ## Data Flow: Store 1. Client sends memory content + metadata 2. API validates input, verifies payment/auth 3. Content is embedded via OpenAI (or cache hit) 4. Deduplication check: cosine similarity ≥ 0.95 against existing memories 5. Memory + embedding stored in PostgreSQL 6. Response with UUID returned ## Data Flow: Recall 1. Client sends natural language query 2. Query embedded via OpenAI (or cache hit) 3. pgvector HNSW index finds nearest vectors 4. Full-text search (BM25) runs in parallel 5. Results scored with 4-signal hybrid formula: * Vector similarity (55%) * Keyword match (25%) * Recency decay (20%) * Multiplied by importance, access boost, and type decay 6. Top-K results returned with signal breakdown ## Data Isolation All data is scoped by wallet address. Wallet A cannot access Wallet B's memories. Namespaces provide additional isolation within a single wallet. ## Deployment MemoClaw runs as a single stateless API server. The only stateful component is PostgreSQL. This makes horizontal scaling straightforward — add more API instances behind a load balancer. Deep dive into scoring, decay, and retrieval. Protocol-level details of payment-as-auth. # How Memory Works Source: https://docs.memoclaw.com/concepts/how-memory-works Embeddings, vector search, similarity scoring, and importance weighting. ## From text to vectors When you store a memory, MemoClaw converts the text into a **512-dimensional vector** using OpenAI's `text-embedding-3-small` model. These vectors capture semantic meaning — similar concepts produce similar vectors, even with different wording. For example, "user prefers dark mode" and "they like dark themes" will have vectors that are very close together, even though the words are completely different. ## Vector similarity search When you recall, your query is also converted to a vector. PostgreSQL with [pgvector](https://github.com/pgvector/pgvector) finds the closest stored vectors using **cosine distance**. The HNSW (Hierarchical Navigable Small World) index makes this fast even with millions of memories. ## Scoring formula **Hybrid recall scoring (4-signal approach):** ``` hybrid = vector_sim × 0.55 + keyword_match × 0.25 + recency × 0.20 score = hybrid × context_importance × access_boost × type_decay ``` Signals: * **vector\_sim**: Cosine similarity (0–1) — primary semantic signal * **keyword\_match**: Full-text/BM25 match, normalized (0–1) — exact term matches * **recency**: `exp(-age_days / 30)` — temporal freshness * **context\_importance**: Importance dynamically boosted by query relevance * **access\_boost**: `min(1 + access_count × 0.1, 2.0)` — frequently recalled memories rank higher * **type\_decay**: Exponential decay based on memory type half-life (correction: 180d, preference: 180d, decision: 90d, project: 30d, observation: 14d, general: 60d). Pinned memories are exempt from decay. Memories with more relations decay slower. When keyword match is strong (>0.3), its weight increases to 0.35 (vector drops to 0.45) for adaptive boosting. This means highly important memories surface first when similarity is close, but a low-importance memory with high semantic relevance can still beat a high-importance memory with weak relevance. ## Embedding cache MemoClaw maintains an **LRU cache of 1,000 embeddings**. Repeated text won't consume additional OpenAI API tokens. Cache hits are instant. This is particularly useful for agents that recall the same queries across sessions — the embedding is computed once and reused. ## Namespaces Use namespaces to isolate memories per project or context. The default namespace is `"default"`. **Suggested strategy:** | Namespace pattern | Use case | | ----------------- | --------------------------------- | | `default` | General user info and preferences | | `project-{name}` | Project-specific knowledge | | `session-{date}` | Session summaries | Namespaces are scoped per user — two different wallets can each have a `default` namespace without any overlap. ## Tags and metadata filtering Attach **tags** to memories for category-based filtering. Recall supports filtering by tags (match any) and by date (`after`). Metadata is stored as JSONB and supports: * Up to **20 keys** per memory * Up to **3 levels** of nesting * Any JSON-compatible values ```json theme={null} { "tags": ["preference", "editor"], "source": "onboarding", "context": { "project": "memoclaw", "session": "2025-01-15" } } ``` ## When to store **Good candidates for storage:** * User preferences and settings * Important decisions and rationale * Context useful in future sessions * Project-specific knowledge * Lessons learned from corrections ## When NOT to store **Avoid storing:** * Passwords, API keys, tokens, or secrets * Ephemeral back-and-forth conversation * Information already stored (recall first to check) * Raw data dumps (summarize first) ## Best practices 1. **Be specific** — "Ana prefers VSCode with vim bindings" beats "user likes editors" 2. **Add metadata** — Tags enable filtered recall later 3. **Set importance** — 0.9+ for critical info, 0.5 for nice-to-have 4. **Use namespaces** — Isolate memories per project 5. **Don't duplicate** — Recall before storing similar content 6. **Respect privacy** — Never store secrets # x402 Payment Flow Source: https://docs.memoclaw.com/concepts/x402-payment-flow How payment-as-authentication works at the protocol level. ## Overview The [x402 protocol](https://x402.org) turns HTTP 402 (Payment Required) into a machine-readable payment flow. Every protected MemoClaw endpoint requires a **signed payment proof** in the request header. The payment amount depends on the endpoint, and the payer's wallet address automatically becomes their user identity. Think of it like a vending machine: insert payment, get memory services. No accounts, no API keys. ## The flow Client sends a request to a protected endpoint (e.g., `POST /v1/store`) without any payment header. Server responds with **HTTP 402** and a JSON body containing payment requirements: the exact USDC amount, the receiving wallet address, the network (Base, chain ID 8453), and the payment scheme (`exact`). The client signs a USDC transfer using either **EIP-3009** (`transferWithAuthorization`) or **Permit2**, then base64-encodes the signed payload. Client retries the original request with the payment proof in the `X-PAYMENT` or `payment-signature` header. Server verifies the payment via the x402 facilitator, extracts the payer's wallet address from the signed payload, auto-creates or finds the user, and processes the original request. ## Wallet identity extraction The payer's EVM address is extracted from the signed payment payload. For **EIP-3009** transfers, it comes from `payload.authorization.from`. For **Permit2**, from `payload.permit2Authorization.from`. This address becomes the user's identity — all memories are scoped to it. No registration, no API keys, no email verification. Your wallet address **is** your account. ## Per-route pricing Only endpoints that use OpenAI (embeddings or LLM) are charged. Everything else is free. | Endpoint | Price (USDC) | | ------------------------------------------------------------------------------------------ | ------------ | | `POST /v1/store` | \$0.005 | | `POST /v1/store/batch` | \$0.04 | | `POST /v1/recall` | \$0.005 | | `PATCH /v1/memories/:id` | \$0.005 | | `PATCH /v1/memories/batch` | \$0.005 | | `POST /v1/memories/extract` | \$0.01 | | `POST /v1/memories/consolidate` | \$0.01 | | `POST /v1/ingest` | \$0.01 | | `POST /v1/context` | \$0.01 | | `POST /v1/migrate` | \$0.01 | | List, get, delete, search, suggested, relations, history, graph, export, namespaces, stats | Free | | `GET /health` | Free | All payments are in **USDC on Base** (chain ID 8453). ## Client options There are three approaches for handling x402 payments: ### 1. @x402/fetch (recommended) The JavaScript SDK handles the 402 → pay → retry flow automatically. ```javascript JavaScript theme={null} import { x402Fetch } from '@x402/fetch'; const response = await x402Fetch('https://api.memoclaw.com/v1/store', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: "User prefers dark mode", importance: 0.8 }), walletPrivateKey: process.env.WALLET_PRIVATE_KEY }); ``` ### 2. @x402/cli CLI tool for manual or shell usage. Useful for testing and scripting. ### 3. Manual signing Construct EIP-3009 or Permit2 payloads yourself. See [x402.org/docs](https://x402.org/docs) for the full specification. ## Learn more Full protocol specification and reference implementations. Setup guide for configuring x402 payments in your agent. Complete pricing breakdown for all endpoints. # Authentication Source: https://docs.memoclaw.com/get-started/authentication Free tier with wallet signatures, then x402 payments. No API keys. MemoClaw uses your wallet as identity. No API keys, no accounts. Two auth methods: 1. **Free Tier** — Sign a message with your wallet (100 free calls) 2. **x402 Payment** — Pay-per-request after free tier (automatic fallback) *** ## Free Tier (Recommended Start) Every wallet gets **100 free API calls to paid endpoints**. No payment required — just prove you own a wallet. ### How wallet verification works You sign a timestamped message with your wallet's private key. We verify the signature matches the claimed address. ``` Message format: memoclaw-auth:{unix_timestamp} Header format: x-wallet-auth: {address}:{timestamp}:{signature} ``` Get current Unix timestamp (seconds since epoch). Sign `memoclaw-auth:{timestamp}` with your wallet's private key. Include `x-wallet-auth: {address}:{timestamp}:{signature}` in your request. We cryptographically verify the signature matches the address. If valid and you have free calls remaining, the request proceeds. ### Code example ```typescript theme={null} import { privateKeyToAccount } from 'viem/accounts'; const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); async function getAuthHeader() { const timestamp = Math.floor(Date.now() / 1000); const message = `memoclaw-auth:${timestamp}`; const signature = await account.signMessage({ message }); return `${account.address}:${timestamp}:${signature}`; } // Use in requests const response = await fetch('https://api.memoclaw.com/v1/recall', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-wallet-auth': await getAuthHeader(), }, body: JSON.stringify({ query: 'what did I learn today?' }), }); // Check remaining free calls console.log(response.headers.get('x-free-tier-remaining')); ``` ### Check your free tier status ```bash theme={null} curl https://api.memoclaw.com/v1/free-tier/info ``` Timestamps must be within 5 minutes of server time to prevent replay attacks. Your private key never leaves your machine — only the signature is sent. *** ## x402 Payment (After Free Tier) Once you've used your 100 free calls, requests automatically require x402 payment. ## How it works Client sends a request to a protected route with no payment header. Server responds with HTTP `402 Payment Required`, including payment requirements — USDC amount and receiving address. Client pays USDC on Base and retries the request with an `X-PAYMENT` header containing the signed payment proof. Server verifies the payment and extracts the payer wallet address from the EIP-3009 or Permit2 payload. Server auto-creates a user if needed. Your wallet address scopes all your memories — wallet A cannot see wallet B's data. Your wallet address is extracted from the payment proof. It becomes your user identity and scopes all your memories. No registration needed. ## Payment methods Two EVM payment signature types are supported: * **EIP-3009** — `transferWithAuthorization` * **Permit2** — Uniswap's permit-based transfer Both are automatically handled by x402-compatible clients. You don't need to choose between them. ## Making authenticated requests Three options for making authenticated requests: 1. **@x402/fetch** — JavaScript SDK ```javascript theme={null} import { x402Fetch } from "@x402/fetch"; ``` 2. **@x402/cli** — CLI tool ```bash theme={null} npx @x402/cli pay POST https://api.memoclaw.com/v1/store --data '...' ``` 3. **Direct signing** — Construct payment headers manually. See [x402.org/docs](https://x402.org/docs) for the full specification. You need a wallet with USDC on Base network (chain ID 8453). Get USDC from any exchange that supports Base. # CLI Reference Source: https://docs.memoclaw.com/get-started/cli Complete reference for all memoclaw CLI commands, flags, and options. ## Installation ```bash theme={null} npm install -g memoclaw ``` ## Setup ### `memoclaw init` Generate a new wallet or configure an existing one. ```bash theme={null} # Generate a new wallet memoclaw init # Use an existing wallet memoclaw init --private-key 0xYourExistingKey ``` Config is saved to `~/.memoclaw/config.json`. Every wallet gets **100 free API calls** — no payment required to start. | Flag | Description | | --------------------- | ------------------------------- | | `--private-key ` | Use an existing EVM private key | *** ## Storing Memories ### `memoclaw store` Store a single memory with semantic embeddings. ```bash theme={null} memoclaw store "User prefers dark mode and vim keybindings" \ --importance 0.8 \ --tags preferences,editor \ --namespace project-x ``` | Flag | Type | Default | Description | | ------------------ | ------ | --------- | ---------------------------------------------------------------------------------------- | | `--importance ` | number | `0.5` | Importance score (0–1) | | `--tags ` | string | — | Comma-separated tags | | `--namespace ` | string | `default` | Memory namespace | | `--type ` | string | `general` | Memory type: `correction`, `preference`, `decision`, `project`, `observation`, `general` | | `--agent ` | string | — | Agent identifier | | `--session ` | string | — | Session identifier | | `--pinned` | flag | `false` | Pin memory (exempt from decay) | **Price:** \$0.005 ### `memoclaw store-batch` Store multiple memories in a single request (up to 100). ```bash theme={null} memoclaw store-batch \ '{"content": "Uses PostgreSQL 15", "importance": 0.9}' \ '{"content": "Deploys to Railway", "importance": 0.8}' \ '{"content": "Team of 3 developers", "importance": 0.7}' ``` | Flag | Type | Default | Description | | ------------------ | ------ | --------- | -------------------------- | | `--namespace ` | string | `default` | Namespace for all memories | | `--agent ` | string | — | Agent identifier | | `--session ` | string | — | Session identifier | **Price:** \$0.04 per batch *** ## Retrieving Memories ### `memoclaw recall` Semantic search — find memories by meaning. ```bash theme={null} memoclaw recall "What are the user's editor preferences?" \ --limit 5 \ --min-similarity 0.7 \ --namespace project-x ``` | Flag | Type | Default | Description | | ---------------------- | ------ | --------- | ---------------------------------- | | `--limit ` | number | `10` | Max results (1–100) | | `--min-similarity ` | number | `0.0` | Minimum similarity threshold (0–1) | | `--tags ` | string | — | Filter by tags (match any) | | `--namespace ` | string | `default` | Filter by namespace | | `--type ` | string | — | Filter by memory type | | `--after ` | string | — | Only memories after this ISO date | **Price:** \$0.005 ### `memoclaw search` Full-text keyword search (no embeddings). Always free. ```bash theme={null} memoclaw search "PostgreSQL" --limit 10 --namespace project-x ``` | Flag | Type | Default | Description | | ------------------ | ------ | --------- | --------------------- | | `--limit ` | number | `10` | Max results (1–100) | | `--namespace ` | string | `default` | Filter by namespace | | `--tags ` | string | — | Filter by tags | | `--type ` | string | — | Filter by memory type | | `--agent ` | string | — | Filter by agent | | `--session ` | string | — | Filter by session | **Price:** FREE ### `memoclaw list` List stored memories with pagination. ```bash theme={null} memoclaw list --limit 20 --namespace project-x --tags preferences ``` | Flag | Type | Default | Description | | ------------------ | ------ | --------- | --------------------- | | `--limit ` | number | `20` | Max results | | `--offset ` | number | `0` | Pagination offset | | `--namespace ` | string | `default` | Filter by namespace | | `--tags ` | string | — | Filter by tags | | `--type ` | string | — | Filter by memory type | | `--agent ` | string | — | Filter by agent | **Price:** FREE ### `memoclaw suggested` Get proactive memory suggestions (stale, fresh, hot, decaying). ```bash theme={null} memoclaw suggested --category stale --limit 5 ``` | Flag | Type | Default | Description | | ------------------ | ------ | --------- | -------------------------------------- | | `--category ` | string | — | `stale`, `fresh`, `hot`, or `decaying` | | `--limit ` | number | `10` | Max results | | `--namespace ` | string | `default` | Filter by namespace | **Price:** FREE *** ## Updating & Deleting ### `memoclaw delete` Delete a memory by ID. ```bash theme={null} memoclaw delete 550e8400-e29b-41d4-a716-446655440000 ``` **Price:** FREE ### `memoclaw update` Update an existing memory (content change re-embeds). ```bash theme={null} memoclaw update 550e8400-e29b-41d4-a716-446655440000 \ --importance 0.95 \ --tags corrections,critical ``` | Flag | Type | Description | | ------------------ | ------ | ----------------------------------- | | `--content ` | string | New content (triggers re-embedding) | | `--importance ` | number | New importance score | | `--tags ` | string | New tags (replaces existing) | | `--type ` | string | New memory type | | `--pinned` | flag | Pin the memory | **Price:** \$0.005 (if content changes), FREE (metadata-only update) *** ## Intelligence ### `memoclaw ingest` Extract facts from a conversation, deduplicate, and optionally create relations. ```bash theme={null} memoclaw ingest \ --messages '[{"role":"user","content":"I prefer dark mode and use vim."},{"role":"assistant","content":"Got it!"}]' \ --auto-relate \ --namespace project-x ``` | Flag | Type | Default | Description | | ------------------- | ------ | --------- | ------------------------------------------------------ | | `--messages ` | string | — | JSON array of `{role, content}` messages | | `--namespace ` | string | `default` | Target namespace | | `--auto-relate` | flag | `false` | Automatically create relations between extracted facts | **Price:** \$0.01 ### `memoclaw consolidate` Merge similar/duplicate memories by clustering. ```bash theme={null} memoclaw consolidate --namespace default --dry-run ``` | Flag | Type | Default | Description | | ---------------------- | ------ | --------- | -------------------------------- | | `--namespace ` | string | `default` | Target namespace | | `--min-similarity ` | number | `0.9` | Similarity threshold for merging | | `--dry-run` | flag | `false` | Preview without merging | **Price:** \$0.01 *** ## Import & Export ### `memoclaw migrate` Import markdown files (`.md`) into MemoClaw. Each `##` section becomes a separate memory. ```bash theme={null} memoclaw migrate ~/.openclaw/workspace/memory/ ``` | Flag | Type | Default | Description | | ------------------ | ------ | --------- | ------------------------- | | `--namespace ` | string | `default` | Target namespace | | `--dry-run` | flag | `false` | Preview without importing | Migration is idempotent — running it twice won't create duplicates. **Price:** \$0.01 per file ### `memoclaw export` Export all memories as JSON. ```bash theme={null} memoclaw export --namespace project-x > memories.json ``` | Flag | Type | Default | Description | | ------------------ | ------ | ------- | ------------------- | | `--namespace ` | string | — | Filter by namespace | | `--agent ` | string | — | Filter by agent | | `--format ` | string | `json` | Output format | **Price:** FREE *** ## Status & Info ### `memoclaw status` Check your free tier remaining calls and wallet info. ```bash theme={null} memoclaw status ``` ``` Wallet: 0x1a2B...9cDe Free tier: 87/100 calls remaining ``` **Price:** FREE ### `memoclaw config` Show current configuration. ```bash theme={null} memoclaw config ``` *** ## Relations ### `memoclaw relate` Create a directed relationship between two memories. ```bash theme={null} memoclaw relate --type derived_from ``` | Flag | Type | Default | Description | | --------------- | ------ | ------------ | ------------------------------------------------------------------------------------ | | `--type ` | string | `related_to` | Relation type: `related_to`, `derived_from`, `contradicts`, `supersedes`, `supports` | **Price:** FREE *** ## Global Flags These flags work with any command: | Flag | Description | | ------------- | ------------------------------------------------------ | | `--json` | Output raw JSON instead of formatted text | | `--url ` | Override API URL (default: `https://api.memoclaw.com`) | | `--help` | Show help for a command | | `--version` | Show CLI version | ## Environment Variables | Variable | Description | | ---------------------- | --------------------------------------------------- | | `MEMOCLAW_PRIVATE_KEY` | Wallet private key (alternative to `memoclaw init`) | | `MEMOCLAW_URL` | API URL override | | `MEMOCLAW_NAMESPACE` | Default namespace | ## Next Steps Get started in under 2 minutes. Common patterns and examples. Automatic memory for OpenClaw agents. Full pricing breakdown. # Introduction Source: https://docs.memoclaw.com/get-started/introduction Memory-as-a-Service API for AI agents. Store and recall memories using semantic vector search. AI agents lose context between sessions. Local memory files require manual grep, break under context compression, and are locked to a single device. **MemoClaw** is a hosted API where agents store memories and retrieve them by semantic similarity. Always available, cross-device, backed by PostgreSQL + pgvector. **Using OpenClaw?** Install [memoclaw-hooks](/openclaw-hooks) and your agent gets persistent cloud memory automatically — recalls on session start, stores on session end, consolidates in the background. Three commands, zero code. ## How it works Agent sends a memory with content, metadata, and importance. We generate embeddings and store it. Query by meaning, not keywords. Results ranked by semantic similarity and importance. No API keys. No accounts. x402 payment = authentication. Wallet address = identity. ## What makes MemoClaw different No API keys, no user accounts, no registration. Your EVM wallet address **IS** your identity. Every wallet gets **100 free API calls** — no payment setup needed. After that, pay per request with USDC on Base via the [x402 protocol](https://x402.org). Automatic memory for OpenClaw agents. Install, restart, done. Install → init → store → recall in under 2 minutes. How x402 payment-as-identity works. Explore all available endpoints. Use MemoClaw with Claude Desktop, Cursor, or any MCP client. Per-request pricing details. # Python SDK Source: https://docs.memoclaw.com/get-started/python-sdk Install the official Python SDK and start storing memories in 3 lines. ## Installation ```bash theme={null} pip install memoclaw ``` ### Optional extras ```bash theme={null} pip install "memoclaw[x402]" # automatic x402 payments after free tier pip install "memoclaw[langchain]" # LangChain integration pip install "memoclaw[llamaindex]" # LlamaIndex integration pip install "memoclaw[x402,langchain,llamaindex]" # all extras ``` ## Authentication MemoClaw uses Ethereum wallet signatures for auth. Any private key works — no ETH balance needed for the free tier. ```bash theme={null} # Generate a new key (one-time) python -c "from eth_account import Account; a = Account.create(); print(f'MEMOCLAW_PRIVATE_KEY={a.key.hex()}')" # Set the env var export MEMOCLAW_PRIVATE_KEY=0x... ``` Every wallet gets **100 free API calls**. ## Quick Example ```python theme={null} from memoclaw import MemoClaw client = MemoClaw() # uses MEMOCLAW_PRIVATE_KEY env var result = client.store( "User prefers dark mode and vim keybindings", importance=0.8, tags=["preferences", "editor"], ) print(result.id) ``` ```python theme={null} memories = client.recall("editor preferences", limit=5) for m in memories.memories: print(f"[{m.similarity:.0%}] {m.content}") ``` Output: ``` [87%] User prefers dark mode and vim keybindings ``` ```python theme={null} # Update importance client.update(result.id, importance=0.95) # Delete when no longer needed client.delete(result.id) ``` ## Async Support ```python theme={null} from memoclaw import AsyncMemoClaw async def main(): async with AsyncMemoClaw() as client: result = await client.store("Async memory", importance=0.7) memories = await client.recall("async") print(memories.memories) ``` ## Ingest a Conversation Extract facts automatically from conversation history: ```python theme={null} result = client.ingest( messages=[ {"role": "user", "content": "I prefer dark mode and use vim. My timezone is PST."}, {"role": "assistant", "content": "Got it! I'll remember those preferences."}, ], auto_relate=True, ) print(f"Extracted {result.facts_extracted} facts, created {result.relations_created} relations") ``` ## Error Handling ```python theme={null} from memoclaw import MemoClaw, NotFoundError, RateLimitError client = MemoClaw() try: client.delete("nonexistent-id") except NotFoundError as e: print(f"Not found: {e.message}") except RateLimitError as e: print(f"Rate limited: {e.message}") ``` ## All Methods ### Core | Method | Description | | ------------------------------ | ---------------------------------------- | | `store(content, **kwargs)` | Store a single memory | | `store_batch(memories)` | Store up to 100 memories | | `store_builder()` | Fluent builder for memory creation | | `recall(query, **kwargs)` | Semantic search | | `text_search(query, **kwargs)` | Free keyword text search (no embeddings) | | `get(memory_id)` | Retrieve a single memory by ID | | `list(**kwargs)` | List memories with pagination | | `iter_memories(**kwargs)` | Iterator with auto-pagination | | `update(memory_id, **kwargs)` | Update a memory | | `update_batch(updates)` | Update up to 100 memories in batch | | `delete(memory_id)` | Delete a memory | | `delete_batch(ids)` | Delete multiple memories by ID | | `status()` | Check free tier remaining calls | ### Intelligence | Method | Description | | ----------------------------------- | -------------------------------------- | | `ingest(**kwargs)` | Auto-extract facts from conversation | | `extract(messages, **kwargs)` | Extract structured facts via LLM | | `consolidate(**kwargs)` | Merge similar memories | | `assemble_context(query, **kwargs)` | Assemble context block for LLM prompts | | `suggested(**kwargs)` | Get proactive memory suggestions | ### Relations & Graph | Method | Description | | ------------------------------------ | ------------------------- | | `create_relation(...)` | Create a relationship | | `list_relations(memory_id)` | List relationships | | `delete_relation(...)` | Delete a relationship | | `find_related(memory_id, **kwargs)` | Find filtered relations | | `get_memory_graph(memory_id, depth)` | Traverse the memory graph | ### Import, Export & Management | Method | Description | | -------------------------- | ----------------------------------- | | `migrate(files, **kwargs)` | Bulk import markdown files | | `export(**kwargs)` | Export memories (JSON/CSV/Markdown) | | `get_history(memory_id)` | Get change history for a memory | | `core_memories(**kwargs)` | Get high-importance/pinned memories | | `list_namespaces()` | List namespaces with counts | | `stats()` | Get memory usage statistics | ## Configuration ```python theme={null} client = MemoClaw( private_key="0x...", # or MEMOCLAW_PRIVATE_KEY env var base_url="http://localhost:3000", # for local development timeout=60.0, # request timeout in seconds ) ``` ## Next Steps Explore all available endpoints. Learn how x402 payment-as-identity works. # Quickstart Source: https://docs.memoclaw.com/get-started/quickstart Install → init → store → recall in under 2 minutes. **Using OpenClaw?** Skip the manual setup — install the [memoclaw-hooks](/openclaw-hooks) package and your agent gets persistent memory automatically. Three commands, zero code. ## Get started in 4 steps ```bash theme={null} npm install -g memoclaw ``` ```bash theme={null} memoclaw init ``` This generates a new wallet, saves your config to `~/.memoclaw/config.json`, and gives you **100 free API calls**. No accounts, no API keys. ``` ✔ Generated new wallet: 0x1a2B...9cDe ✔ Saved config to ~/.memoclaw/config.json ✔ Free tier: 100 calls remaining You're ready to go! Try: memoclaw store "Hello, MemoClaw" ``` Already have a wallet? Pass it directly: ```bash theme={null} memoclaw init --private-key 0xYourExistingKey ``` ```bash theme={null} memoclaw store "User prefers dark mode and vim keybindings" ``` ```json theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "stored": true, "tokens_used": 8 } ``` ```bash theme={null} memoclaw recall "What are the user's editor preferences?" ``` ``` [0.847] User prefers dark mode and vim keybindings tags: preferences, editor ``` **That's it.** Your agent now has persistent memory. *** ## Using namespaces Namespaces isolate memories per project: ```bash theme={null} memoclaw store "Uses PostgreSQL 15 with pgvector" --namespace acme-api memoclaw recall "database setup" --namespace acme-api ``` ## CLI reference ```bash theme={null} memoclaw store "content" --importance 0.9 --tags tag1,tag2 --namespace project-x memoclaw recall "query" --limit 10 --min-similarity 0.7 --namespace project-x memoclaw list --limit 20 --namespace project-x memoclaw delete memoclaw migrate ~/path/to/memory/files # Import OpenClaw files ``` ## Pricing Endpoints using OpenAI are charged per request (USDC on Base). Every wallet gets **100 free API calls** — no payment required. After that, you pay per request. List, get, delete, search, and stats endpoints are always free. | Operation | Cost | | ----------------------- | ------- | | Store | \$0.005 | | Store Batch (up to 100) | \$0.04 | | Recall | \$0.005 | | List | FREE | | Migrate | \$0.01 | See [full pricing](/reference/pricing) for all endpoints. ## Next steps Automatic memory for OpenClaw agents. Install, restart, done. Moving from OpenClaw? Import your memory files in one command. Use MemoClaw as an MCP server for any compatible client. Explore all available endpoints. # Recipes Source: https://docs.memoclaw.com/get-started/recipes Common patterns and recipes for MemoClaw. ## Store User Preference ```bash CLI theme={null} memoclaw store "User prefers dark mode" \ --importance 0.8 \ --tags preferences,ui ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() client.store( "User prefers dark mode", importance=0.8, tags=["preferences", "ui"], ) ``` ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/store \ -H "Content-Type: application/json" \ -H "x-wallet-auth: $WALLET:$TIMESTAMP:$SIGNATURE" \ -d '{ "content": "User prefers dark mode", "importance": 0.8, "metadata": { "tags": ["preferences", "ui"] } }' ``` ## Store After Correction ```bash CLI theme={null} memoclaw store "Correction: The database connection uses port 5433, not 5432" \ --importance 0.95 \ --tags corrections ``` ```python Python theme={null} client.store( "Correction: The database connection uses port 5433, not 5432", importance=0.95, tags=["corrections"], ) ``` ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/store \ -H "Content-Type: application/json" \ -H "x-wallet-auth: $WALLET:$TIMESTAMP:$SIGNATURE" \ -d '{ "content": "Correction: The database connection uses port 5433, not 5432", "importance": 0.95, "metadata": { "tags": ["corrections"] } }' ``` ## Recall Before Responding ```bash CLI theme={null} memoclaw recall "user's theme preference" ``` ```python Python theme={null} memories = client.recall("user's theme preference") if memories.memories: theme = memories.memories[0].content print(f"User prefers: {theme}") ``` ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/recall \ -H "Content-Type: application/json" \ -H "x-wallet-auth: $WALLET:$TIMESTAMP:$SIGNATURE" \ -d '{ "query": "user'\''s theme preference" }' ``` ## Filter by Namespace ```bash CLI theme={null} memoclaw recall "database configuration" \ --namespace project-api \ --limit 10 ``` ```python Python theme={null} memories = client.recall( "database configuration", namespace="project-api", limit=10, ) ``` ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/recall \ -H "Content-Type: application/json" \ -H "x-wallet-auth: $WALLET:$TIMESTAMP:$SIGNATURE" \ -d '{ "query": "database configuration", "namespace": "project-api", "limit": 10 }' ``` ## Batch Import ```bash CLI theme={null} memoclaw store-batch \ '{"content": "Uses PostgreSQL 15", "importance": 0.9}' \ '{"content": "Deploys to Railway", "importance": 0.8}' \ '{"content": "Team of 3 developers", "importance": 0.7}' ``` ```python Python theme={null} memories = [ {"content": "Uses PostgreSQL 15", "importance": 0.9}, {"content": "Deploys to Railway", "importance": 0.8}, {"content": "Team of 3 developers", "importance": 0.7}, ] result = client.store_batch(memories) print(f"Stored {result.count} memories") ``` ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/store/batch \ -H "Content-Type: application/json" \ -H "x-wallet-auth: $WALLET:$TIMESTAMP:$SIGNATURE" \ -d '{ "memories": [ { "content": "Uses PostgreSQL 15", "importance": 0.9 }, { "content": "Deploys to Railway", "importance": 0.8 }, { "content": "Team of 3 developers", "importance": 0.7 } ] }' ``` ## Extract Facts from Conversation ```bash CLI theme={null} memoclaw ingest \ --messages '[{"role":"user","content":"I prefer dark mode and use vim."},{"role":"assistant","content":"Got it!"},{"role":"user","content":"My timezone is PST."}]' \ --auto-relate ``` ```python Python theme={null} result = client.ingest( messages=[ {"role": "user", "content": "I prefer dark mode and use vim."}, {"role": "assistant", "content": "Got it!"}, {"role": "user", "content": "My timezone is PST."}, ], auto_relate=True, ) print(f"Extracted {result.facts_extracted} facts") print(f"Created {result.relations_created} relations") ``` ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/ingest \ -H "Content-Type: application/json" \ -H "x-wallet-auth: $WALLET:$TIMESTAMP:$SIGNATURE" \ -d '{ "messages": [ { "role": "user", "content": "I prefer dark mode and use vim." }, { "role": "assistant", "content": "Got it!" }, { "role": "user", "content": "My timezone is PST." } ], "auto_relate": true }' ``` ## Proactive Memory Suggestions ```bash CLI theme={null} memoclaw suggested --category stale --limit 5 ``` ```python Python theme={null} suggested = client.suggested(category="stale", limit=5) for memory in suggested.memories: print(f"- {memory.content[:50]}... (importance: {memory.importance})") ``` ```bash curl theme={null} curl "https://api.memoclaw.com/v1/suggested?category=stale&limit=5" \ -H "x-wallet-auth: $WALLET:$TIMESTAMP:$SIGNATURE" ``` ## Error Handling ```bash CLI theme={null} # CLI exits with non-zero codes on errors memoclaw delete some-id || echo "Delete failed" ``` ```python Python theme={null} from memoclaw import MemoClaw, NotFoundError, RateLimitError, ValidationError try: client.delete("some-id") except NotFoundError: print("Memory already deleted") except RateLimitError: print("Rate limited - wait and retry") except ValidationError as e: print(f"Validation error: {e.message}") ``` ```bash curl theme={null} # Check HTTP status codes # 404 = not found, 429 = rate limited, 422 = validation error curl -s -o /dev/null -w "%{http_code}" \ -X DELETE "https://api.memoclaw.com/v1/memories/some-id" \ -H "x-wallet-auth: $WALLET:$TIMESTAMP:$SIGNATURE" ``` # TypeScript SDK Source: https://docs.memoclaw.com/get-started/typescript-sdk Use MemoClaw from TypeScript via the official SDK or CLI. MemoClaw ships an official TypeScript SDK inside the [`memoclaw`](https://www.npmjs.com/package/memoclaw) package. The same package also contains the CLI, so you get both programmatic access and terminal commands from a single install. Use it anywhere Node.js 18+, Bun, or modern Edge runtimes run. Prefer a no-code setup for OpenClaw agents? Install [memoclaw-hooks](/openclaw-hooks) alongside the SDK so your agent auto-stores and recalls memories during each session. ## Installation ```bash theme={null} npm install memoclaw # or pnpm add memoclaw # or yarn add memoclaw ``` ## Authentication MemoClaw uses wallet-based identity. Set `MEMOCLAW_PRIVATE_KEY` (hex string with `0x` prefix) so the client can sign free-tier auth headers and x402 payments. ```bash theme={null} export MEMOCLAW_PRIVATE_KEY=0xyourprivatekey ``` Every wallet gets **100 free paid-endpoint calls**. After that, calls fall back to x402 payments ($0.005–$0.01 per request depending on the endpoint). ## Initialize the client ```typescript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient({ // optional overrides // baseUrl: "http://localhost:8787", // privateKey: "0x...", // defaults to MEMOCLAW_PRIVATE_KEY }); ``` ## Quick Example ```typescript theme={null} const created = await client.store({ content: "User prefers dark mode and vim keybindings", importance: 0.8, metadata: { tags: ["preferences", "editor"] }, }); console.log(created.id); ``` ```typescript theme={null} const memories = await client.recall({ query: "editor preferences", limit: 5, }); for (const m of memories.memories) { console.log(`[${(m.similarity * 100).toFixed(0)}%] ${m.content}`); } ``` Output: ``` [87%] User prefers dark mode and vim keybindings ``` ```typescript theme={null} await client.update(created.id, { importance: 0.95 }); await client.delete(created.id); ``` ## Ingest a conversation Extract facts automatically from conversation history and auto-create relations. ```typescript theme={null} const result = await client.ingest({ messages: [ { role: "user", content: "I prefer dark mode and use vim. My timezone is PST." }, { role: "assistant", content: "Got it! I'll remember those preferences." }, ], auto_relate: true, }); console.log( `Extracted ${result.facts_extracted} facts, created ${result.relations_created} relations`, ); ``` ## Error handling ```typescript theme={null} import { MemoClawClient, MemoClawError } from "memoclaw"; const client = new MemoClawClient(); try { await client.delete("nonexistent-id"); } catch (err) { if (err instanceof MemoClawError) { console.log(`Error ${err.status}: ${err.message}`); } } ``` ## Available methods | Method | Description | | -------------------------------- | ------------------------------------ | | `store(opts)` | Store a single memory | | `storeBatch(memories)` | Store up to 100 memories | | `recall(opts)` | Semantic search | | `list(opts?)` | List memories with pagination | | `update(id, opts)` | Update a memory | | `delete(id)` | Delete a memory | | `ingest(opts)` | Auto-extract facts from conversation | | `extract(messages, opts?)` | Extract structured facts via LLM | | `consolidate(opts?)` | Merge similar memories | | `suggested(opts?)` | Get proactive memory suggestions | | `createRelation(id, opts)` | Create a relationship | | `listRelations(id)` | List relationships | | `deleteRelation(id, relationId)` | Delete a relationship | | `status()` | Check remaining free-tier calls | ## Configuration options ```typescript theme={null} const client = new MemoClawClient({ privateKey: "0x...", // defaults to MEMOCLAW_PRIVATE_KEY baseUrl: "https://api.memoclaw.com", // override for staging/local timeout: 60_000, // request timeout in ms }); ``` ## Next steps Explore every REST endpoint. Learn how wallet signatures and x402 payments work. # Migrate from Mem0 Source: https://docs.memoclaw.com/guides/migrate-from-mem0 Switch from Mem0 to MemoClaw in under 10 minutes. MemoClaw and Mem0 both provide memory for AI agents, but MemoClaw uses **wallet-based identity** — no API keys, no accounts. ## Key Differences | Feature | Mem0 | MemoClaw | | -------------- | ------------------ | --------------------------------------------------------- | | Authentication | API key | Wallet signature / x402 payment | | Pricing | Subscription tiers | Pay-per-request (variable per endpoint) | | Free tier | Limited | 100 free calls per wallet | | Memory types | Generic | Typed (correction, preference, decision, etc.) | | Decay model | None | Per-type exponential decay with pinning | | Relations | No | Yes (related\_to, contradicts, supersedes, etc.) | | Scoring | Vector similarity | 4-signal hybrid (vector + keyword + recency + importance) | ## Concept Mapping | Mem0 | MemoClaw | | -------------------------- | ---------------------------------- | | `m.add(messages, user_id)` | `client.ingest(messages=messages)` | | `m.search(query, user_id)` | `client.recall(query)` | | `m.get_all(user_id)` | `client.list()` | | `m.delete(memory_id)` | `client.delete(memory_id)` | | `user_id` | Wallet address (automatic) | | `app_id` | `namespace` | ## Migration Steps ```bash Python theme={null} pip install memoclaw ``` ```bash TypeScript theme={null} npm install memoclaw # or pnpm add memoclaw ``` ```bash theme={null} python -c "from eth_account import Account; a = Account.create(); print(f'MEMOCLAW_PRIVATE_KEY={a.key.hex()}')" export MEMOCLAW_PRIVATE_KEY=0x... ``` ```python Mem0 (before) theme={null} from mem0 import Memory m = Memory() m.add("User prefers dark mode", user_id="alice") results = m.search("preferences", user_id="alice") ``` ```python MemoClaw (after) theme={null} from memoclaw import MemoClaw client = MemoClaw() client.store("User prefers dark mode", importance=0.8) results = client.recall("preferences") ``` ```python theme={null} from mem0 import Memory from memoclaw import MemoClaw m = Memory() mc = MemoClaw() all_memories = m.get_all(user_id="alice") batch = [{"content": mem["memory"], "importance": 0.7} for mem in all_memories] mc.store_batch(batch) ``` ## What You Gain * **No vendor lock-in** — wallet-based identity * **Transparent pricing** — from \$0.005 per call (free endpoints available), no surprise bills * **Smart decay** — memories fade by type, unless pinned * **Relations** — link memories into knowledge graphs * **Hybrid search** — vector + keyword + recency scoring # Migrate from OpenClaw Source: https://docs.memoclaw.com/guides/migrate-from-openclaw Import your OpenClaw memory files to MemoClaw in one command. OpenClaw stores memories as local markdown files (`memory/YYYY-MM-DD.md`, `MEMORY.md`). MemoClaw can import these directly — each `##` section becomes a separate, searchable memory with auto-detected importance, tags, and type. ## CLI migration (recommended) ```bash theme={null} # Install & init (skip if already done) npm install -g memoclaw memoclaw init # Migrate your memory files memoclaw migrate ~/.openclaw/workspace/memory/ ``` The CLI reads all `.md` files in the directory, splits them by `##` headers, and sends them to the `/v1/migrate` endpoint. ``` ✔ Scanned 42 files ✔ Created 187 memories (12 deduplicated) ✔ Migration complete ``` Migration is **idempotent** — running it twice won't create duplicates. Each memory chunk is content-hashed and checked against existing memories. ## What gets imported Each `##` section in a markdown file becomes one memory: | Source | MemoClaw field | | ---------------------------- | -------------------------------------------------------- | | Section body | `content` | | Keywords in content | `memory_type` (decision, preference, correction, etc.) | | Header words + filename date | `tags` (e.g., `date:2026-01-30`, `migrated`, `openclaw`) | | Content heuristics | `importance` (0.6–0.9 based on keywords) | Files without `##` headers are stored as a single memory. ## API migration If you prefer direct API access, use `POST /v1/migrate`: ```bash curl theme={null} curl -X POST https://api.memoclaw.com/v1/migrate \ -H "Content-Type: application/json" \ -d '{ "files": [ { "filename": "2026-01-30.md", "content": "## Project Setup\nDecided to use PostgreSQL with pgvector.\n\n## Editor Config\nUser prefers vim keybindings and dark mode." }, { "filename": "MEMORY.md", "content": "## Long-term preferences\nAlways use TypeScript over JavaScript." } ] }' ``` ```python Python theme={null} import httpx files = [] for path in Path("~/.openclaw/workspace/memory").expanduser().glob("*.md"): files.append({ "filename": path.name, "content": path.read_text() }) response = httpx.post( "https://api.memoclaw.com/v1/migrate", json={"files": files} ) print(response.json()) ``` ```typescript TypeScript theme={null} import { readdir, readFile } from "fs/promises"; import { join } from "path"; const dir = `${process.env.HOME}/.openclaw/workspace/memory`; const entries = await readdir(dir); const files = await Promise.all( entries .filter((f) => f.endsWith(".md")) .map(async (f) => ({ filename: f, content: await readFile(join(dir, f), "utf-8"), })) ); const res = await fetch("https://api.memoclaw.com/v1/migrate", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ files }), }); console.log(await res.json()); ``` ### Response ```json theme={null} { "files_processed": 2, "memories_created": 3, "memories_deduplicated": 0 } ``` If any files fail, partial results are returned with an `errors` array: ```json theme={null} { "files_processed": 1, "memories_created": 2, "memories_deduplicated": 0, "errors": [ { "filename": "bad-file.md", "error": "Content too short" } ] } ``` ## Limits * **Max 50 files** per request * Each section truncated to **8,000 characters** * Sections shorter than 10 characters are skipped * Requires x402 payment or free tier credits ## Install OpenClaw hooks (recommended) After migrating your files, install the MemoClaw hooks so your agent automatically stores and recalls memories going forward — no manual commands needed. ```bash theme={null} # Install the hook pack openclaw hooks install memoclaw-hooks openclaw hooks enable memoclaw ``` Set your wallet key in your environment (same wallet you used for migration): ```bash theme={null} export MEMOCLAW_PRIVATE_KEY=0x... ``` Restart the gateway: ```bash theme={null} openclaw gateway restart ``` Verify everything is wired up: ```bash theme={null} openclaw hooks list --verbose ``` The hooks automatically handle: | Event | What happens | | ---------------------- | ------------------------------------------------------- | | **Session start** | Recalls relevant memories based on the first message | | **Context compaction** | Saves important context before the window is compressed | | **/new command** | Extracts and stores key info before session reset | | **Heartbeat** | Periodic consolidation to merge duplicate memories | With hooks installed, you can remove memory-related instructions from your `AGENTS.md` and `SOUL.md` — MemoClaw handles it automatically. ## After migration Your memories are now searchable by meaning: ```bash theme={null} memoclaw recall "What database are we using?" # [0.92] Decided to use PostgreSQL with pgvector. # tags: date:2026-01-30, project, setup, migrated, openclaw ``` New to MemoClaw? Start here. Full endpoint documentation. # Migrate from Zep Source: https://docs.memoclaw.com/guides/migrate-from-zep Switch from Zep to MemoClaw — simpler auth, pay-per-request pricing. Zep provides memory and knowledge graphs for AI assistants. MemoClaw offers similar capabilities with wallet-based identity — no API keys to manage. ## Key Differences | Feature | Zep | MemoClaw | | --------------- | ----------------- | --------------------------------------- | | Authentication | API key + project | Wallet signature / x402 | | Pricing | Subscription | Pay-per-request (variable per endpoint) | | Memory model | Session-based | Content-based with namespaces | | Knowledge graph | Built-in | Relations (5 types) | | Fact extraction | Automatic | Via `/ingest` or `/extract` | ## Concept Mapping | Zep | MemoClaw | | ----------------------------------------- | ---------------------------------- | | `client.memory.add(session_id, messages)` | `client.ingest(messages=messages)` | | `client.memory.search(text)` | `client.recall(query)` | | Session | `session_id` parameter | | User | Wallet address (automatic) | | Collection | `namespace` | ## Migration Steps ```bash Python theme={null} pip install memoclaw ``` ```bash TypeScript theme={null} npm install memoclaw # or pnpm add memoclaw ``` ```python Zep (before) theme={null} from zep_cloud.client import Zep client = Zep(api_key="z_...") client.memory.add(session_id="s1", messages=[ {"role": "user", "content": "I prefer dark mode"}, ]) results = client.memory.search("preferences", limit=5) ``` ```python MemoClaw (after) theme={null} from memoclaw import MemoClaw client = MemoClaw() client.ingest( messages=[{"role": "user", "content": "I prefer dark mode"}], session_id="s1", auto_relate=True, ) results = client.recall("preferences", limit=5) ``` ```python theme={null} client.create_relation( memory_id_1, target_id=memory_id_2, relation_type="related_to", ) ``` ## What You Gain * **Simpler auth** — no API keys to rotate * **Predictable costs** — pay exactly what you use * **100 free calls** (many endpoints are completely free) — try before you pay * **Memory types with decay** — corrections persist longer than observations * **Consolidation** — auto-merge redundant memories # Multi-Agent Memory Source: https://docs.memoclaw.com/guides/multi-agent Share context between multiple AI agents. Enable multiple AI agents to share and coordinate memory. ## Use Case A team of AI agents working on a project: * Research agent finds information * Coding agent implements features * Review agent checks code quality * All share context via MemoClaw ## Implementation ### Share Findings Between Agents ```bash CLI theme={null} # Research agent stores findings memoclaw store "Found that pgvector HNSW index performs better than IVFFlat for small datasets" \ --importance 0.85 \ --agent research-001 \ --namespace project-backend \ --type decision # Coding agent recalls research findings memoclaw recall "vector database performance research" \ --namespace project-backend \ --limit 5 ``` ```python Python theme={null} from memoclaw import MemoClaw research_agent = MemoClaw() research_agent.agent_id = "research-001" coding_agent = MemoClaw() coding_agent.agent_id = "coding-001" # Research agent stores findings research_agent.store( content="Found that pgvector HNSW index performs better than IVFFlat for small datasets", importance=0.85, agent_id="research-001", namespace="project-backend", memory_type="decision" ) # Coding agent recalls research findings findings = coding_agent.recall( query="vector database performance research", namespace="project-backend", limit=5 ) ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const researchAgent = new MemoClawClient({ agentId: "research-001" }); const codingAgent = new MemoClawClient({ agentId: "coding-001" }); // Research agent stores findings await researchAgent.store({ content: "Found that pgvector HNSW index performs better than IVFFlat for small datasets", importance: 0.85, agent_id: "research-001", namespace: "project-backend", memory_type: "decision", }); // Coding agent recalls research findings const findings = await codingAgent.recall({ query: "vector database performance research", namespace: "project-backend", limit: 5, }); ``` ### Filter by Agent ```bash CLI theme={null} memoclaw list --agent research-001 --namespace project-backend ``` ```python Python theme={null} agent_memories = client.list( agent_id="research-001", namespace="project-backend" ) ``` ```typescript TypeScript theme={null} const agentMemories = await client.list({ agent_id: "research-001", namespace: "project-backend", }); ``` ### Create Relations Between Agents' Memories ```bash CLI theme={null} # Store research finding memoclaw store "HNSW is better for our use case" \ --agent research-001 --namespace project-backend # Note the returned ID, e.g. # Store implementation note memoclaw store "Implemented HNSW index for vector search" \ --agent coding-001 --namespace project-backend # Note the returned ID, e.g. # Link them memoclaw relate --type derived_from ``` ```python Python theme={null} research_memory = research_agent.store( content="HNSW is better for our use case", agent_id="research-001", namespace="project-backend" ) implementation_memory = coding_agent.store( content="Implemented HNSW index for vector search", agent_id="coding-001", namespace="project-backend" ) client.create_relation( memory_id=implementation_memory.id, target_id=research_memory.id, relation_type="derived_from" ) ``` ```typescript TypeScript theme={null} const researchMemory = await researchAgent.store({ content: "HNSW is better for our use case", agent_id: "research-001", namespace: "project-backend", }); const implMemory = await codingAgent.store({ content: "Implemented HNSW index for vector search", agent_id: "coding-001", namespace: "project-backend", }); await client.createRelation(implMemory.id, { targetId: researchMemory.id, relationType: "derived_from", }); ``` ## Memory Isolation * **Same wallet** = same user identity * **Different agent\_ids** = different agent perspectives on same memory store * **Namespaces** = completely separate memory pools ## Best Practices 1. Use consistent `agent_id` naming: `{role}-{number}` or `{name}` 2. Use `namespace` to separate projects 3. Use relations to link cross-agent dependencies 4. Use `memory_type` to distinguish findings vs implementations vs reviews # Session Context Loading Source: https://docs.memoclaw.com/guides/session-context Load relevant context at the start of each session. Load memories relevant to the current session when an agent starts. ## Use Case An AI coding assistant that loads context about: * Current project being worked on * Recent files being edited * Current task goals ## Implementation ### Store Session Summary ```bash CLI theme={null} memoclaw store "Session 2026-02-13: Working on memoclaw-api, added rate limiting. Files: src/routes/store.ts, tests/api.test.ts" \ --importance 0.7 \ --type observation \ --session session-123 \ --tags session,project-memoclaw-api ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() session_summary = client.store( content="Session 2026-02-13: Working on memoclaw-api, added rate limiting. Files: src/routes/store.ts, tests/api.test.ts", importance=0.7, memory_type="observation", session_id="session-123", tags=["session", "project-memoclaw-api"] ) ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const sessionSummary = await client.store({ content: "Session 2026-02-13: Working on memoclaw-api, added rate limiting. Files: src/routes/store.ts, tests/api.test.ts", importance: 0.7, memory_type: "observation", session_id: "session-123", metadata: { tags: ["session", "project-memoclaw-api"] }, }); ``` ### Load Context at Session Start ```bash CLI theme={null} memoclaw recall "recent work on memoclaw-api project" \ --limit 5 \ --tags project-memoclaw-api ``` ```python Python theme={null} recent_memories = client.recall( query="recent work on memoclaw-api project", limit=5, filters={ "tags": ["project-memoclaw-api"] } ) context = "Recent context:\n" for m in recent_memories.memories: context += f"- {m.content}\n" ``` ```typescript TypeScript theme={null} const recentMemories = await client.recall({ query: "recent work on memoclaw-api project", limit: 5, filters: { tags: ["project-memoclaw-api"] }, }); let context = "Recent context:\n"; for (const m of recentMemories.memories) { context += `- ${m.content}\n`; } ``` ### Track Session History ```bash CLI theme={null} # List all session memories memoclaw list --tags session --limit 20 # Recall from a specific session memoclaw recall "" --session session-123 ``` ```python Python theme={null} all_sessions = client.list( filters={"tags": ["session"]}, limit=20 ) session_memories = client.recall( query="", session_id="session-123" ) ``` ```typescript TypeScript theme={null} const allSessions = await client.list({ filters: { tags: ["session"] }, limit: 20, }); const sessionMemories = await client.recall({ query: "", session_id: "session-123", }); ``` ## Best Practices 1. **Use session IDs** to scope memories to specific conversations 2. **Store summaries** at session end for faster retrieval later 3. **Set importance** based on relevance to future sessions 4. **Use namespaces** to separate different projects or clients ## Related Endpoints * [Store](/api-reference/store) — Store session memories * [Recall](/api-reference/recall) — Search memories * [List](/api-reference/list-memories) — List by filters # User Preferences Memory Source: https://docs.memoclaw.com/guides/user-preferences Store and recall user preferences across sessions. Store user preferences persistently so your AI assistant remembers them across sessions. ## Use Case An AI assistant that helps users with coding tasks. It should remember: * Preferred programming languages * Editor settings * Notification preferences * Timezone ## Implementation ### Store Preferences ```bash CLI theme={null} memoclaw store "Prefers TypeScript over JavaScript" \ --importance 0.9 --type preference --namespace user-prefs memoclaw store "Uses VS Code with Vim extension" \ --importance 0.8 --type preference --namespace user-prefs memoclaw store "Prefers dark mode" \ --importance 0.85 --type preference --namespace user-prefs memoclaw store "Timezone is PST" \ --importance 0.95 --type preference --namespace user-prefs ``` ```python Python theme={null} from memoclaw import MemoClaw client = MemoClaw() preferences = [ ("Prefers TypeScript over JavaScript", 0.9), ("Uses VS Code with Vim extension", 0.8), ("Prefers dark mode", 0.85), ("Timezone is PST", 0.95), ] for pref, importance in preferences: client.store( content=pref, importance=importance, memory_type="preference", namespace="user-prefs" ) ``` ```typescript TypeScript theme={null} import { MemoClawClient } from "memoclaw"; const client = new MemoClawClient(); const preferences = [ { content: "Prefers TypeScript over JavaScript", importance: 0.9 }, { content: "Uses VS Code with Vim extension", importance: 0.8 }, { content: "Prefers dark mode", importance: 0.85 }, { content: "Timezone is PST", importance: 0.95 }, ]; for (const pref of preferences) { await client.store({ content: pref.content, importance: pref.importance, memory_type: "preference", namespace: "user-prefs", }); } ``` ### Recall on Session Start ```bash CLI theme={null} memoclaw recall "user preferences for coding assistant" \ --namespace user-prefs --limit 10 ``` ```python Python theme={null} memories = client.recall( query="user preferences for coding assistant", namespace="user-prefs", limit=10 ) context = "\n".join([ f"- {m.content}" for m in memories.memories ]) print(f"User preferences:\n{context}") ``` ```typescript TypeScript theme={null} const memories = await client.recall({ query: "user preferences for coding assistant", namespace: "user-prefs", limit: 10, }); const context = memories.memories .map((m) => `- ${m.content}`) .join("\n"); console.log(`User preferences:\n${context}`); ``` ### Update When Changed ```bash CLI theme={null} memoclaw update \ --content "Now prefers React over Vue" \ --importance 0.9 ``` ```python Python theme={null} client.update( memory_id="existing-memory-id", content="Now prefers React over Vue", importance=0.9 ) ``` ```typescript TypeScript theme={null} await client.update("existing-memory-id", { content: "Now prefers React over Vue", importance: 0.9, }); ``` ## Memory Types Use `memory_type: "preference"` for user preferences. This gives them a 180-day half-life, meaning they persist for a long time but eventually decay if not reinforced. ## Next Steps * Add [relations](/api-reference/relations) between related preferences * Use [suggested](/api-reference/suggested) to surface stale preferences * Set up [auto-ingest](/api-reference/ingest) from conversation history # MCP Integration Source: https://docs.memoclaw.com/mcp-integration Use MemoClaw as an MCP server for Claude Desktop, Cursor, and other MCP-compatible tools. # MCP Integration MemoClaw provides an MCP (Model Context Protocol) server for seamless integration with Claude Desktop, Cursor, Windsurf, and any MCP-compatible application. ## Installation ```bash theme={null} npm install -g memoclaw-mcp ``` Set your EVM private key with USDC on Base: ```bash theme={null} export MEMOCLAW_PRIVATE_KEY=0xYourPrivateKey ``` Use a dedicated wallet with USDC for API payments. The free tier includes 100 calls per wallet. Add MemoClaw to your MCP configuration file. ## Client Configuration ### Claude Desktop Add to `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json theme={null} { "mcpServers": { "memoclaw": { "command": "npx", "args": ["-y", "memoclaw-mcp"], "env": { "MEMOCLAW_PRIVATE_KEY": "0xYourPrivateKey" } } } } ``` ### Cursor Add to MCP settings in Cursor preferences: ```json theme={null} { "mcpServers": { "memoclaw": { "command": "npx", "args": ["-y", "memoclaw-mcp"], "env": { "MEMOCLAW_PRIVATE_KEY": "0xYourPrivateKey" } } } } ``` ### OpenClaw (via mcporter) If you're running [OpenClaw](https://openclaw.ai), use mcporter to add MemoClaw: ```bash theme={null} npm install -g memoclaw-mcp mcporter add memoclaw --stdio "memoclaw-mcp" --env "MEMOCLAW_PRIVATE_KEY=0xYourPrivateKey" ``` Or use the auto-setup script from the [MemoClaw skill on ClawHub](https://clawhub.ai/anajuliabit/memoclaw): ```bash theme={null} export MEMOCLAW_PRIVATE_KEY=0xYourPrivateKey bash skills/memoclaw/scripts/setup.sh ``` Once configured, your agent can call MemoClaw directly: ```bash theme={null} mcporter call memoclaw.memoclaw_store '{"content": "User prefers dark mode", "importance": 0.8}' mcporter call memoclaw.memoclaw_recall '{"query": "UI preferences"}' ``` ### Other MCP Clients Any MCP-compatible client can use the server: ```bash theme={null} npx -y memoclaw-mcp ``` ## Available Tools ### Core | Tool | Description | Key Parameters | | ----------------- | -------------------------------------------------- | --------------------------------------------------------------------- | | `memoclaw_init` | Check configuration and connection status | (none) | | `memoclaw_store` | Store a memory with semantic embeddings | `content`, `importance`, `tags`, `namespace`, `memory_type`, `pinned` | | `memoclaw_recall` | Semantic search — find memories by meaning | `query`, `limit`, `min_similarity`, `tags`, `namespace` | | `memoclaw_search` | Keyword search — find memories by exact text match | `query`, `limit`, `namespace`, `tags`, `memory_type` | | `memoclaw_get` | Retrieve a single memory by ID | `id` | | `memoclaw_list` | List stored memories with pagination | `limit`, `offset`, `tags`, `namespace`, `memory_type` | | `memoclaw_update` | Update a memory by ID (partial update) | `id`, `content`, `importance`, `tags`, `memory_type`, `pinned` | | `memoclaw_delete` | Delete a memory by ID | `id` | | `memoclaw_status` | Check free tier remaining calls | (none) | | `memoclaw_count` | Count memories with optional filters | `namespace`, `tags`, `agent_id`, `memory_type` | ### Bulk Operations | Tool | Description | Key Parameters | | ---------------------- | --------------------------------------------- | -------------------------------------- | | `memoclaw_bulk_store` | Store multiple memories in one call (max 100) | `memories[]`, `session_id`, `agent_id` | | `memoclaw_bulk_delete` | Delete multiple memories by IDs (max 100) | `ids[]` | ### Intelligence | Tool | Description | Key Parameters | | ---------------------- | --------------------------------------------------------------------------- | ------------------------------------------------ | | `memoclaw_ingest` | Bulk-ingest conversations/text — auto-extracts facts with dedup & relations | `messages`, `text`, `namespace`, `auto_relate` | | `memoclaw_extract` | Extract structured facts from conversation via LLM (no auto-relations) | `messages`, `namespace` | | `memoclaw_consolidate` | Merge similar/duplicate memories by clustering | `namespace`, `min_similarity`, `mode`, `dry_run` | | `memoclaw_suggested` | Get proactive memory suggestions (stale, fresh, hot, decaying) | `limit`, `namespace`, `category` | ### Relations & Graph | Tool | Description | Key Parameters | | -------------------------- | ------------------------------------------------ | --------------------------------------------- | | `memoclaw_create_relation` | Create a relationship between two memories | `memory_id`, `target_id`, `relation_type` | | `memoclaw_list_relations` | List all relationships for a memory | `memory_id` | | `memoclaw_delete_relation` | Delete a relationship | `memory_id`, `relation_id` | | `memoclaw_graph` | Traverse the memory graph from a starting memory | `memory_id`, `depth` (max 3), `relation_type` | ### Import & Export | Tool | Description | Key Parameters | | ------------------ | ------------------------------------------- | ----------------------------------------- | | `memoclaw_export` | Export all memories as JSON | `namespace`, `agent_id`, `format` | | `memoclaw_import` | Import memories from a JSON array (max 100) | `memories[]`, `session_id`, `agent_id` | | `memoclaw_migrate` | Migrate markdown files into MemoClaw | `path`, `files[]`, `namespace`, `dry_run` | ### Namespace Management | Tool | Description | Key Parameters | | --------------------------- | ------------------------------------------------ | ----------------------- | | `memoclaw_delete_namespace` | Delete ALL memories in a namespace (destructive) | `namespace`, `agent_id` | *** ## Tool Details ### memoclaw\_init Check if MemoClaw is properly configured. Call this first to verify the connection, wallet address, and free tier status. ```json theme={null} {} ``` ### memoclaw\_store Store a new memory with semantic embeddings. ```json theme={null} { "content": "User prefers dark mode and uses vim keybindings", "importance": 0.8, "tags": ["preferences", "editor"], "namespace": "default" } ``` ### memoclaw\_recall Semantic search — find memories by meaning, not exact words. ```json theme={null} { "query": "What are the user's editor preferences?", "limit": 5, "min_similarity": 0.7 } ``` ### memoclaw\_search Keyword search — find memories containing exact text (case-insensitive). ```json theme={null} { "query": "python", "limit": 10, "namespace": "project-x" } ``` ### memoclaw\_get Retrieve a single memory by its exact ID. ```json theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### memoclaw\_list List all stored memories with pagination. ```json theme={null} { "limit": 20, "offset": 0, "tags": ["preferences"], "namespace": "default" } ``` ### memoclaw\_update Update an existing memory. Only provided fields are changed. ```json theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "importance": 0.9, "pinned": true } ``` ### memoclaw\_delete Remove a memory by its ID. ```json theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### memoclaw\_bulk\_store Store multiple memories in a single call (max 100). ```json theme={null} { "memories": [ { "content": "Prefers TypeScript", "importance": 0.7, "tags": ["preferences"] }, { "content": "Uses VS Code", "importance": 0.5, "tags": ["preferences"] } ] } ``` ### memoclaw\_bulk\_delete Delete multiple memories at once (max 100 IDs). ```json theme={null} { "ids": ["id-1", "id-2", "id-3"] } ``` ### memoclaw\_count Get a count of memories with optional filters. Faster than `memoclaw_list` when you only need the total. ```json theme={null} { "namespace": "project-x", "memory_type": "correction" } ``` ### memoclaw\_status Check your free tier usage. ```json theme={null} {} ``` Response: ``` Wallet: 0x... Free tier: 87/100 calls remaining ``` ### memoclaw\_ingest Bulk-ingest a conversation or raw text. The server extracts facts, deduplicates, and optionally creates relations. ```json theme={null} { "messages": [ { "role": "user", "content": "I switched from JavaScript to TypeScript last month" }, { "role": "assistant", "content": "Got it! I'll remember your preference for TypeScript." } ], "auto_relate": true } ``` ### memoclaw\_extract Extract structured facts from a conversation via LLM, without auto-relating them. ```json theme={null} { "messages": [ { "role": "user", "content": "My project uses React with Tailwind CSS" } ] } ``` ### memoclaw\_consolidate Merge similar/duplicate memories by clustering. Use `dry_run: true` first to preview. ```json theme={null} { "namespace": "default", "dry_run": true } ``` ### memoclaw\_suggested Get proactive memory suggestions: stale, fresh, hot, or decaying memories. ```json theme={null} { "category": "stale", "limit": 5 } ``` ### memoclaw\_create\_relation Create a directed relationship between two memories. ```json theme={null} { "memory_id": "source-id", "target_id": "target-id", "relation_type": "supersedes" } ``` Relation types: `related_to`, `derived_from`, `contradicts`, `supersedes`, `supports`. ### memoclaw\_list\_relations List all relationships for a memory (both incoming and outgoing). ```json theme={null} { "memory_id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### memoclaw\_delete\_relation Delete a specific relationship. ```json theme={null} { "memory_id": "source-id", "relation_id": "relation-id" } ``` ### memoclaw\_graph Traverse the memory graph from a starting point. ```json theme={null} { "memory_id": "550e8400-e29b-41d4-a716-446655440000", "depth": 2 } ``` ### memoclaw\_export Export all memories as JSON for backup or analysis. ```json theme={null} { "namespace": "default", "format": "json" } ``` ### memoclaw\_import Import memories from a JSON array (max 100 per call). ```json theme={null} { "memories": [ { "content": "Imported fact 1", "importance": 0.6 }, { "content": "Imported fact 2", "tags": ["imported"] } ] } ``` ### memoclaw\_migrate Migrate markdown files into MemoClaw. Use `dry_run: true` to preview. ```json theme={null} { "path": "/home/user/.openclaw/workspace/memory/", "namespace": "migrated", "dry_run": true } ``` ### memoclaw\_delete\_namespace Delete ALL memories in a namespace. **This is destructive and cannot be undone.** Use `memoclaw_count` first. ```json theme={null} { "namespace": "old-project" } ``` ## Example Prompts Once configured, you can ask Claude: * "Remember that I prefer TypeScript over JavaScript" * "What did I say about my coding preferences?" * "List all memories tagged with 'project'" * "Delete the memory about the old API key" ## Free Tier The MCP server includes a free tier of **100 calls per wallet**. After exhausting the free tier, calls are paid via x402 protocol (USDC on Base). ## Environment Variables | Variable | Description | | ---------------------- | ------------------------------------------------ | | `MEMOCLAW_PRIVATE_KEY` | EVM private key for authentication and payments | | `MEMOCLAW_URL` | API URL (defaults to `https://api.memoclaw.com`) | ## Troubleshooting ### "MEMOCLAW\_PRIVATE\_KEY environment variable required" Make sure the environment variable is set in your MCP configuration or shell profile. ### "Wallet authentication failed" Ensure your wallet has USDC on Base for paid calls, or check your free tier status. ### Connection issues Restart your MCP client after changing configuration. ## Learn More * [MCP Specification](https://modelcontextprotocol.io) * [MemoClaw API Reference](/api-reference/overview) * [x402 Protocol](https://x402.org) # OpenClaw Hooks Source: https://docs.memoclaw.com/openclaw-hooks Give your OpenClaw agent persistent cloud memory with a single install. The `memoclaw-hooks` package integrates MemoClaw directly into OpenClaw's lifecycle. Your agent automatically recalls relevant memories on session start, stores important context when sessions end, and consolidates memories in the background. No code changes. No prompt engineering. Just install and restart. ## Installation ```bash theme={null} npm install -g memoclaw ``` ```bash theme={null} openclaw hooks install memoclaw-hooks openclaw hooks enable memoclaw ``` Add `MEMOCLAW_PRIVATE_KEY` to your environment. If you don't have a wallet yet, run `memoclaw init` to generate one. ```bash theme={null} export MEMOCLAW_PRIVATE_KEY=0xYourPrivateKey ``` Or add it to your OpenClaw config: ```yaml theme={null} env: MEMOCLAW_PRIVATE_KEY: "0xYourPrivateKey" ``` ```bash theme={null} openclaw gateway restart ``` Verify the hook is loaded: ```bash theme={null} openclaw hooks list --verbose openclaw hooks check ``` ## What happens automatically Once installed, the hook fires on five OpenClaw lifecycle events: | Event | What it does | | ---------------------- | ------------------------------------------------------------------------------------------- | | **Session start** | Recalls memories relevant to the user's first message and injects them as context | | **`/new` command** | Extracts important context from the current session and stores it before the session resets | | **Context compaction** | Stores key information before the context window is compressed | | **Heartbeat** | Runs periodic consolidation to merge duplicate memories (every 6 hours) | | **Gateway startup** | Recalls the 3 most recent memories to restore agent continuity | ### What recall looks like When your agent starts a session, it sees something like: ```text theme={null} [MemoClaw] Relevant memories: - (0.92) User prefers direct communication, no fluff - (0.87) Project uses PostgreSQL with JSONB columns - (0.81) Last session: shipped v2.1 auth migration ``` These are injected as system context — the agent doesn't need to do anything special. ## Configuration All config is via environment variables. No config files needed. | Variable | Required | Default | Description | | --------------------------------------- | -------- | -------------------------- | ---------------------------------------- | | `MEMOCLAW_PRIVATE_KEY` | Yes | — | Wallet private key for auth and payments | | `MEMOCLAW_URL` | No | `https://api.memoclaw.com` | API endpoint | | `MEMOCLAW_NAMESPACE` | No | `default` | Memory namespace for isolation | | `MEMOCLAW_HOOK_CONSOLIDATE_INTERVAL_MS` | No | `21600000` (6h) | Min interval between consolidations | ## Multi-agent memory Use `MEMOCLAW_NAMESPACE` to control memory isolation between agents. ```bash theme={null} # Each agent gets its own memory MEMOCLAW_NAMESPACE=agent-frontend MEMOCLAW_NAMESPACE=agent-backend # Or share a namespace for cross-agent knowledge MEMOCLAW_NAMESPACE=shared-project ``` Same wallet, different namespaces = isolated recall. Same wallet, same namespace = shared memory. ## Using with the skill The hook handles the automatic lifecycle (session start/end, compaction, heartbeats). For manual memory operations — like storing specific facts or recalling on demand — install the [MemoClaw skill](https://clawhub.ai/anajuliabit/memoclaw) alongside the hook: ```bash theme={null} clawhub install anajuliabit/memoclaw ``` The skill gives your agent `memoclaw store`, `memoclaw recall`, and other CLI commands it can call mid-conversation. ## Pricing * **100 free calls** per wallet — no payment setup needed * After that: **\$0.005–\$0.01** per call via x402 (USDC on Base) * The hook typically makes 2–4 API calls per session lifecycle * At normal usage, that's a few cents per day ## Source * **npm**: [`memoclaw-hooks`](https://www.npmjs.com/package/memoclaw-hooks) * **GitHub**: [`anajuliabit/memoclaw-hooks`](https://github.com/anajuliabit/memoclaw-hooks) # Error Codes Source: https://docs.memoclaw.com/reference/error-codes Standardized error format and all possible error codes. ## Error Format All errors follow this structure: ```json theme={null} { "error": { "code": "VALIDATION_ERROR", "message": "content is required and must be a string", "details": {} } } ``` The `details` field is optional and provides additional context when available. ## Error Codes Missing or invalid x402 payment header. Returned when no payment proof is provided, or the payment is invalid/expired. ```json theme={null} { "error": { "code": "PAYMENT_REQUIRED", "message": "Valid x402 payment required" } } ``` Invalid or missing authentication. Returned when wallet address cannot be extracted from payment proof. ```json theme={null} { "error": { "code": "UNAUTHORIZED", "message": "Could not extract wallet address from payment" } } ``` Resource not found. Returned when trying to access or delete a memory that doesn't exist, was already deleted, or belongs to a different wallet. ```json theme={null} { "error": { "code": "NOT_FOUND", "message": "Memory not found" } } ``` Invalid request body. Returned when the request fails validation — missing required fields, exceeding limits, or wrong types. Includes details when available. ```json theme={null} { "error": { "code": "VALIDATION_ERROR", "message": "content must be at most 8192 characters", "details": { "max_length": 8192, "actual_length": 9500 } } } ``` Rate limit exceeded. Includes limit and reset time in details. ```json theme={null} { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded", "details": { "limit": 100, "reset_at": "2025-01-15T12:00:00Z" } } } ``` Server error. Something went wrong on our end. If persistent, check the `/health` endpoint. ```json theme={null} { "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred" } } ``` # Input Limits Source: https://docs.memoclaw.com/reference/input-limits Request size limits, character limits, and validation constraints. | Constraint | Limit | | ---------------------- | ----------------------------- | | Request body size | 64 KB | | Content length | 8,192 characters | | Metadata size | 4,096 bytes (JSON serialized) | | Metadata keys | 20 max | | Metadata nesting depth | 3 levels | | Tags per memory | 10 max | | Tag length | 64 characters | | Recall limit | 1–100 results | | Recall min\_similarity | 0.0–1.0 | | Namespace length | 255 characters | | Batch size | 100 memories | | Recall query length | 32,768 characters | | Search query length | 1,000 characters | Exceeding any limit returns a `422 VALIDATION_ERROR` with details about which constraint was violated. # Pricing Source: https://docs.memoclaw.com/reference/pricing Per-request USDC pricing for MemoClaw endpoints. MemoClaw uses pay-per-request pricing. No subscriptions, no API keys, no monthly minimums. Pay with USDC on Base. Only endpoints that use OpenAI (embeddings or GPT-4o-mini) are charged. Everything else is free. ## Paid endpoints These endpoints consume OpenAI resources and are charged per request. ### Embedding endpoints (\$0.005) | Endpoint | Operation | Price | | -------------------------- | ------------------------ | ------- | | `POST /v1/store` | Store a memory | \$0.005 | | `POST /v1/store/batch` | Store up to 100 memories | \$0.04 | | `POST /v1/recall` | Semantic search | \$0.005 | | `PATCH /v1/memories/:id` | Update a memory | \$0.005 | | `PATCH /v1/memories/batch` | Batch update | \$0.005 | ### LLM + embedding endpoints (\$0.01) | Endpoint | Operation | Price | | ------------------------------- | ---------------------- | ------ | | `POST /v1/memories/extract` | Extract facts via LLM | \$0.01 | | `POST /v1/memories/consolidate` | Merge similar memories | \$0.01 | | `POST /v1/ingest` | Zero-effort ingestion | \$0.01 | | `POST /v1/context` | Assemble context block | \$0.01 | | `POST /v1/migrate` | Import markdown files | \$0.01 | ## Free endpoints These endpoints don't use OpenAI and are always free — no credits consumed. | Endpoint | Operation | | ----------------------------------------------- | -------------------------- | | `GET /v1/memories` | List memories | | `GET /v1/memories/:id` | Get a single memory | | `DELETE /v1/memories/:id` | Delete a memory | | `DELETE /v1/memories` | Bulk delete | | `POST /v1/search` | Full-text keyword search | | `GET /v1/suggested` | Proactive suggestions | | `GET /v1/memories/core` | Get core memories | | `POST /v1/memories/core` | Pin a core memory | | `DELETE /v1/memories/core/:id` | Unpin a core memory | | `GET /v1/memories/:id/history` | Memory change history | | `POST /v1/memories/:id/relations` | Create a relation | | `GET /v1/memories/:id/relations` | List relations | | `DELETE /v1/memories/:id/relations/:relationId` | Delete a relation | | `GET /v1/memories/:id/graph` | Traverse memory graph | | `GET /v1/export` | Export memories | | `GET /v1/namespaces` | List namespaces | | `GET /v1/stats` | Usage statistics | | `POST /auth/session` | Exchange signature for JWT | | `GET /v1/free-tier/status` | Check free tier | | `GET /v1/free-tier/info` | Free tier policy | | `GET /health` | Health check | ## Free tier Every wallet gets **100 free paid-endpoint calls**. No payment required to start. Free endpoints are always free regardless. After the free tier, pay per call with x402 (USDC on Base). A typical agent doing 150 store/recall calls per day costs about **\$0.75/day** or **\~\$22.50/month**. ## Cost example | Usage pattern | Daily cost | Monthly cost | | ------------------------------------------ | ---------- | ------------ | | Light (50 store + 50 recall) | \$0.50 | \~\$15 | | Medium (100 store + 200 recall) | \$1.50 | \~\$45 | | Heavy (200 store + 400 recall + 20 ingest) | \$3.20 | \~\$96 | List, get, delete, search, and stats are all free. Only store, recall, and AI-powered endpoints cost money. # Rate Limiting Source: https://docs.memoclaw.com/reference/rate-limiting Per-wallet rate limits and how to handle 429 responses. ## Limits MemoClaw applies rate limits per wallet address to ensure fair usage. | Scope | Limit | Window | | --------------------- | ------------ | -------- | | All endpoints | 100 requests | 1 minute | | Extract / Consolidate | 10 requests | 1 minute | Rate limits are per wallet address, not per API key or IP. If you use the same wallet from multiple agents, they share the same limit. ## Response Headers Every response includes rate limit headers: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1706889600 ``` | Header | Description | | ----------------------- | ---------------------------------------- | | `X-RateLimit-Limit` | Maximum requests allowed in the window | | `X-RateLimit-Remaining` | Requests remaining in the current window | | `X-RateLimit-Reset` | Unix timestamp when the window resets | ## Handling 429 Responses When rate limited, you'll receive a `429` response: ```json theme={null} { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded", "details": { "limit": 100, "reset_at": "2025-01-15T12:00:00Z" } } } ``` ### Retry Strategy Use exponential backoff with the `X-RateLimit-Reset` header: ```python Python theme={null} import time from memoclaw import MemoClaw, RateLimitError client = MemoClaw() def recall_with_retry(query, max_retries=3): for attempt in range(max_retries): try: return client.recall(query) except RateLimitError as e: if attempt == max_retries - 1: raise wait = 2 ** attempt time.sleep(wait) ``` ```typescript TypeScript (fetch) theme={null} async function recallWithRetry(query: string, authHeader: string, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { const res = await fetch("https://api.memoclaw.com/v1/recall", { method: "POST", headers: { "Content-Type": "application/json", "x-wallet-auth": authHeader, }, body: JSON.stringify({ query }), }); if (res.ok) return res.json(); if (res.status !== 429 || attempt === maxRetries - 1) { throw new Error(`Request failed: ${res.status}`); } await new Promise(r => setTimeout(r, 2 ** attempt * 1000)); } } ``` ## Tips * **Batch stores** instead of individual calls — `POST /v1/store/batch` handles up to 100 memories in one request * **Use `ingest`** instead of multiple `extract` + `store` calls * **Cache recall results** client-side when the same query is used repeatedly