Long-term memory plugin for OpenClaw using Redis vector search.
Give your AI agent persistent memory across conversations. It can remember user preferences, past decisions, important facts, and more.
- Auto-recall: Automatically inject relevant memories into context before each turn
- Auto-capture: Save conversations to working memory for background extraction
- Manual tools:
memory_recall,memory_store,memory_forgetfor explicit control - Summary views: Rolling summaries of long-term memories for stable context
- Multi-tenancy: Namespace and optional
userIdsupport for memory isolation - Multi-agent routing: Named scopes and agent-specific routes for shared and personal memory
- Configurable tool descriptions: Customize how the LLM sees and uses memory tools
- OpenClaw
>=2025.0.0 - Node.js
>=18if you are building locally or using the package programmatically - Docker for the quickest local memory-server setup
- An OpenAI API key for
agent-memory-server
The quickest way to run the latest tested memory server is with the standalone Docker image (includes Redis):
# Create .env file with your OpenAI key
echo "OPENAI_API_KEY=sk-your-key-here" > .env
# Run the standalone image (latest tested release)
docker run -d \
--name agent-memory \
--env-file .env \
-p 8000:8000 \
redislabs/agent-memory-server:0.14.0-standaloneIf you want to use an external Redis instead of the standalone image, run the standard image with REDIS_URL and the asyncio task backend for local development:
docker run -d \
--name agent-memory \
-e OPENAI_API_KEY=sk-your-key-here \
-e REDIS_URL=redis://localhost:6379 \
-p 8000:8000 \
redislabs/agent-memory-server:0.14.0 \
agent-memory api --host 0.0.0.0 --port 8000 --task-backend=asyncioFor production-like deployments with the standard image, run a separate agent-memory task-worker process. For more configuration options, see the agent-memory-server documentation.
openclaw plugins install openclaw-redis-agent-memoryEdit ~/.openclaw/openclaw.json:
{
"plugins": {
"entries": {
"redis-memory": {
"enabled": true,
"config": {
"serverUrl": "http://localhost:8000",
"namespace": "project-memory",
"userId": "demo-user"
}
}
}
}
}Set userId explicitly if you want per-user memory isolation. Leave userId unset only when you intentionally want everyone using the same namespace to share memory.
Use a deterministic smoke test before building on top of the plugin:
- Start OpenClaw with the plugin enabled.
- Confirm the plugin can reach the server. The OpenClaw logs should include a line like
redis-memory: connected to server (...). - In a chat or tool playground, store a known fact:
{
"tool": "memory_store",
"arguments": {
"text": "Project code name is Vector Cats",
"category": "entity"
}
}- Recall it immediately:
{
"tool": "memory_recall",
"arguments": {
"query": "project code name",
"limit": 3
}
}If recall works, your server URL, namespace, auth, and plugin wiring are all in a good state.
Use one shared namespace and leave userId unset:
{
"serverUrl": "http://localhost:8000",
"namespace": "team-shared"
}This is the fastest setup when multiple users or agents should share the same long-term memory.
Use the same namespace, but assign each user their own userId:
{
"serverUrl": "http://localhost:8000",
"namespace": "project-memory",
"userId": "user-123"
}This keeps memories isolated per user while still grouping the application under one namespace.
For multi-agent implementations, define named scopes and route each OpenClaw agent to the right memory boundary:
{
"plugins": {
"entries": {
"redis-memory": {
"enabled": true,
"config": {
"serverUrl": "http://localhost:8000",
"namespace": "project-memory",
"scopes": {
"shared": {
"label": "Shared Memory"
},
"personal": {
"label": "Personal Memory",
"userId": "user-123"
},
"research": {
"label": "Research Memory"
}
},
"agentScopes": {
"main": {
"primaryScope": "shared",
"recallScopes": ["shared", "personal"],
"toolScopes": ["shared", "personal"],
"defaultStoreScope": "shared"
},
"researcher": {
"primaryScope": "research",
"recallScopes": ["shared", "research"],
"toolScopes": ["shared", "research"],
"defaultStoreScope": "research"
}
}
}
}
}
}
}When multiple scopes are available, the manual memory tools expose an optional scope parameter so you can store, search, or delete within a specific memory boundary.
| Option | Type | Default | Description |
|---|---|---|---|
serverUrl |
string | http://localhost:8000 |
Base URL of agent-memory-server |
apiKey |
string | unset | API key for server authentication |
bearerToken |
string | unset | Bearer token for server authentication |
namespace |
string | default |
Top-level memory boundary, usually one app, team, or project |
userId |
string | unset | Optional secondary boundary for per-user memory isolation |
workingMemorySessionId |
string | unset | Reuse one working-memory session across OpenClaw sessions |
timeout |
number | 30000 |
Request timeout in milliseconds |
autoCapture |
boolean | true |
Save new conversation turns to working memory |
autoRecall |
boolean | true |
Inject relevant long-term memory before each turn |
minScore |
number | 0.3 |
Minimum similarity score for memory recall |
recallLimit |
number | 3 |
Max recalled memories per search |
extractionStrategy |
string | server default | discrete, summary, preferences, or custom |
customPrompt |
string | unset | Custom extraction prompt for custom strategy |
summaryViewName |
string | agent_user_summary |
Summary view name for rolling memory summaries |
summaryTimeWindowDays |
number | 30 |
Rolling window for summary generation |
summaryGroupBy |
array | ["user_id"] |
Fields to partition summaries by |
recallDescription |
string | built-in description | Override the LLM-facing description for memory_recall |
storeDescription |
string | built-in description | Override the LLM-facing description for memory_store |
forgetDescription |
string | built-in description | Override the LLM-facing description for memory_forget |
scopes |
object | unset | Named memory boundaries for multi-agent setups |
agentScopes |
object | unset | Map OpenClaw agent IDs to recall, capture, and tool scopes |
namespaceis the broadest isolation boundary. It is usually the right place to separate apps, environments, or product areas.userIdis optional. If you do not set it, memory is scoped only bynamespace.- For stable deployments or repeatable demos, prefer setting
userIdexplicitly whenever memory should stay isolated to one person or one bot persona.
scopeslet you define named boundaries with their ownnamespace,userId, summary settings, and extraction strategy.agentScopesroute an OpenClaw agent ID to one or more scopes.- If you configure
scopesbut notagentScopes, the plugin falls back to the first defined scope. AddagentScopesfor deterministic routing.
If multiple scopes are available for the current agent, the tools expose an optional scope parameter.
Search through long-term memories.
{
"query": "user preferences for notifications",
"limit": 5
}Scoped recall example:
{
"query": "shipping deadline",
"limit": 5,
"scope": "team"
}Save important information to long-term memory.
{
"text": "User prefers dark mode",
"category": "preference"
}Scoped store example:
{
"text": "Team demo is at 2 PM on Friday",
"category": "decision",
"scope": "team"
}Categories: preference, fact, decision, entity, other
Delete specific memories.
{
"query": "dark mode preference"
}Or by ID:
{
"memoryId": "abc123"
}Scoped delete example:
{
"memoryId": "abc123",
"scope": "team"
}- discrete: Extract semantic and episodic memories
- summary: Maintain a running conversation summary
- preferences: Focus on user preferences and settings
- custom: Use your own extraction prompt
If you do not set extractionStrategy, the plugin leaves extraction behavior to the server default.
Use ${VAR_NAME} syntax for environment variable substitution:
{
"serverUrl": "${AGENT_MEMORY_SERVER_URL}",
"apiKey": "${AGENT_MEMORY_API_KEY}",
"userId": "${OPENCLAW_USER_ID}"
}The .env file for agent-memory-server supports many options:
# Required
OPENAI_API_KEY=sk-your-key-here
# For the standard (non-standalone) image
# REDIS_URL=redis://localhost:6379
# Recommended for local development if you are not running a separate worker
# TASK_BACKEND=asyncio
# Optional - customize the embedding model
# EMBEDDING_MODEL=text-embedding-3-small
# Optional - use a different LLM for memory extraction
# GENERATION_MODEL=gpt-4o-mini
# Optional - disable auth for local testing
# DISABLE_AUTH=trueSee the full configuration reference for all options.
import redisMemoryPlugin, {
memoryConfigSchema,
type PluginApi,
} from "openclaw-redis-agent-memory";
const pluginConfig = memoryConfigSchema.parse({
serverUrl: "http://localhost:8000",
namespace: "project-memory",
userId: "demo-user",
});
const pluginApi: PluginApi = {
...yourPluginApi,
pluginConfig,
};
redisMemoryPlugin.register(pluginApi);The plugin reads configuration from api.pluginConfig, so make sure the parsed config is attached there before calling register.
- If you see
server not reachable, make sure the container is running andserverUrlmatches the exposed port. - If auto-recall seems empty, verify that you are using the same
namespaceanduserIdacross sessions. - If you use
extractionStrategy: "custom", you must also setcustomPrompt. - If you use
agentScopes, every referenced scope must exist inscopes. - If you want one shared memory pool for an implementation, leave
userIdunset. If you want isolated memory, set it explicitly.
MIT