Integrations
Tutorial
April 13, 2026
Give Claude Persistent Memory with REM Labs
Anthropic's Claude API is stateless by design -- every message request starts fresh. If you are building a Claude-powered assistant that needs to remember users across sessions, you need an external memory layer. This guide shows how to wire REM Labs into your Claude application so it remembers everything, permanently.
Why Claude Needs External Memory
Claude's Messages API processes each request independently. There is no built-in mechanism to persist context between API calls. When your application restarts, when a user returns the next day, or when you deploy a new version -- all prior context is gone unless you saved it somewhere.
You could store raw conversation logs in a database and dump them into the system prompt. But that breaks down quickly: context windows have limits, old messages dilute relevance, and keyword search misses semantic connections. REM Labs solves this with a purpose-built memory API that stores, indexes, and retrieves memories using vector embeddings, full-text search, and entity graphs -- all in one call.
Step 1: Get Your API Key
Sign up at remlabs.ai/console or run npx @remlabs/memory from your terminal. The free tier gives you 1,000 memory operations per month.
Step 2: Store Memories from Claude Conversations
import anthropic
import requests
CLAUDE_KEY = "sk-ant-..."
REM_KEY = "sk-slop-..."
REM_BASE = "https://api.api.remlabs.ai"
client = anthropic.Anthropic(api_key=CLAUDE_KEY)
user_msg = "I'm a Python developer at Datadog. I prefer functional programming patterns."
resp = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": user_msg}]
)
reply = resp.content[0].text
# Store the interaction as a memory
requests.post(f"{REM_BASE}/v1/memory-set", json={
"key": "claude-agent",
"value": f"User: {user_msg}\nAssistant: {reply}",
"namespace": "user-456",
"tags": ["conversation", "preferences"]
}, headers={"Authorization": f"Bearer {REM_KEY}"})
The POST /v1/memory-set endpoint stores the memory and automatically indexes it three ways: vector embedding for semantic search, full-text index for exact matches, and entity extraction for structured queries. The namespace isolates this user's memories from all others.
Step 3: Recall Context Before Each Claude Request
# New session -- user returns the next day
user_msg = "What programming patterns do I prefer?"
# Search for relevant memories
search = requests.post(f"{REM_BASE}/v1/memory/search", json={
"query": user_msg,
"namespace": "user-456",
"limit": 5
}, headers={"Authorization": f"Bearer {REM_KEY}"})
memories = search.json().get("results", [])
context = "\n".join([m["value"] for m in memories])
resp = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system=f"Relevant context from previous conversations:\n{context}",
messages=[{"role": "user", "content": user_msg}]
)
print(resp.content[0].text)
# "You mentioned you prefer functional programming patterns. You're a Python developer at Datadog."
The search endpoint returns memories ranked by relevance using reciprocal rank fusion across all three retrieval paths. Claude receives only the most relevant context -- not your entire conversation history.
Step 4: Node.js with the Anthropic SDK
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ apiKey: "sk-ant-..." });
const REM_BASE = "https://api.api.remlabs.ai";
const REM_KEY = "sk-slop-...";
// Store a memory
await fetch(`${REM_BASE}/v1/memory-set`, {
method: "POST",
headers: { "Authorization": `Bearer ${REM_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
key: "claude-agent",
value: "User is a Python developer at Datadog. Prefers functional patterns.",
namespace: "user-456"
})
});
// Recall and use with Claude
const search = await fetch(`${REM_BASE}/v1/memory/search`, {
method: "POST",
headers: { "Authorization": `Bearer ${REM_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ query: "user background", namespace: "user-456", limit: 5 })
});
const { results } = await search.json();
const context = results.map(r => r.value).join("\n");
const msg = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
system: `Relevant memories:\n${context}`,
messages: [{ role: "user", content: "Recommend a project for me." }]
});
Memory Across Claude and Other Models
Because REM Labs is model-agnostic, the same memory store works across providers. A user could interact with Claude in your web app and GPT-4 in your mobile app -- and both agents would share the same persistent memory through the same namespace. No vendor lock-in.
Also works with MCP: If you use Claude Code or Claude Desktop, REM Labs provides an MCP server for direct memory access. See the MCP integration guide.
Give your Claude app a memory
Free tier. No credit card. Works with Claude Sonnet, Opus, and Haiku.
Get started free →