API-first memory infrastructure for LLM-powered agents.
MemoryLayer provides cognitive memory capabilities for AI agents, including episodic, semantic, procedural, and working memory with vector-based retrieval, graph-based associations, and server-side computation sandboxes.
- Cognitive Memory Architecture — Episodic, semantic, procedural, and working memory types
- Vector Search — SQLite with sqlite-vec for efficient similarity search
- Knowledge Graph — 60+ relationship types organized into 11 categories for memory associations
- Context Environment — Server-side Python sandboxes for memory analysis and computation
- Session Management — Working memory with TTL and commit to long-term storage
- REST API — Full-featured HTTP API for all memory operations
- Multiple Embedding Providers — OpenAI, Google GenAI, embed-server (self-hosted GPU via
memorylayer-embed-server), and mock (testing) - Health Endpoints —
/healthand/health/readyfor monitoring and readiness checks
# Basic installation
pip install memorylayer-server
# With OpenAI embeddings
pip install memorylayer-server[openai]
# With Google GenAI embeddings
pip install memorylayer-server[google]
# Self-hosted embeddings: install + run memorylayer-embed-server separately
# (no extras here — the main server only speaks HTTP to embed-server)
# pip install memorylayer-embed-server[gpu]
# All cloud embedding providers + LLM + document parsers
pip install memorylayer-server[all]Package name: memorylayer-server (PyPI)
Import name: memorylayer_server
# Start on default port (61001)
memorylayer serve
# Custom port
memorylayer serve --port 8080
# Bind to all interfaces
memorylayer serve --host 0.0.0.0
# Debug mode
memorylayer serve --verboseThe official Docker image comes with all optional dependencies pre-installed and pins MEMORYLAYER_EMBEDDING_PROVIDER=embed_server, which delegates all GPU/ML work to a peer memorylayer-embed-server container — set MEMORYLAYER_EMBED_SERVER_URL accordingly, or override the provider entirely (openai/google for cloud, hash for a dependency-free lexical default):
docker run -d \
--name memorylayer \
-p 61001:61001 \
-v memorylayer-data:/data \
scitrera/memorylayer-serverWith OpenAI embeddings:
docker run -d \
--name memorylayer \
-p 61001:61001 \
-v memorylayer-data:/data \
-e MEMORYLAYER_EMBEDDING_PROVIDER=openai \
-e MEMORYLAYER_EMBEDDING_OPENAI_API_KEY=sk-... \
scitrera/memorylayer-serverThe server exposes a REST API. Use any HTTP client, or install the Python SDK (pip install memorylayer-client) for a typed client:
from memorylayer import MemoryLayerClient
async with MemoryLayerClient(base_url="http://localhost:61001") as client:
# Store a memory
memory = await client.remember(
content="User prefers Python for backend development",
type="semantic",
importance=0.8,
tags=["preferences", "programming"]
)
# Recall memories
results = await client.recall(
query="What programming languages does the user like?",
limit=5
)
# Create associations
await client.associate(
source_id=memory.id,
target_id=other_memory.id,
relationship="related_to",
strength=0.9
)| Variable | Default | Description |
|---|---|---|
MEMORYLAYER_SERVER_HOST |
127.0.0.1 |
Server bind address |
MEMORYLAYER_SERVER_PORT |
61001 |
Server port |
MEMORYLAYER_DATA_DIR |
~ |
State root, not the data directory itself. Data is written to <root>/.config/memorylayer-server/, so the default resolves to ~/.config/memorylayer-server and MEMORYLAYER_DATA_DIR=/data resolves to /data/.config/memorylayer-server. |
MEMORYLAYER_SQLITE_STORAGE_PATH |
memorylayer.db |
SQLite database path (relative to the resolved data directory) |
MEMORYLAYER_EMBEDDING_PROVIDER |
hash |
Embedding provider (hash, openai, google, embed_server, mock). The default hash is lexical and dependency-free so the server runs with no setup — set a real provider for production (see below). |
MEMORYLAYER_SESSION_SERVICE |
persistent |
persistent (survives restarts, uses the storage backend) or in-memory (ephemeral) |
MEMORYLAYER_EMBEDDING_OPENAI_API_KEY |
— | OpenAI API key |
MEMORYLAYER_EMBEDDING_GOOGLE_API_KEY |
— | Google API key |
MEMORYLAYER_EMBEDDING_DIMENSIONS |
384 (hash / embed_server) |
Vector width. Must match the model actually producing the embeddings — see Embedding dimensions |
MEMORYLAYER_EMBED_SERVER_URL |
http://localhost:61051 |
Base URL for memorylayer-embed-server (used by embed_server provider) |
MEMORYLAYER_EMBED_TRANSPORT |
http |
http for direct calls or aether for cross-DC mTLS via Aether |
MEMORYLAYER_ENRICHMENT_POLICY controls generative model use at the central LLM
service boundary. Its compatibility default is generative. deterministic
rejects every completion before provider selection while remember, RAG recall,
checkpoint capture, context packs, and context deltas continue to work.
adaptive allows only activities named in
MEMORYLAYER_ADAPTIVE_GENERATION_ACTIVITIES (default: reflection,synthesis).
Explicit LLM/agentic recall modes return generation_not_allowed when policy
does not authorize their required activity.
| Variable | Default | Rollback value / effect |
|---|---|---|
MEMORYLAYER_ENRICHMENT_POLICY |
generative |
generative restores compatibility behavior; deterministic is the zero-generation guarantee |
MEMORYLAYER_ADAPTIVE_GENERATION_ACTIVITIES |
reflection,synthesis |
Empty disables all adaptive generation |
MEMORYLAYER_GENERATION_MAX_CALLS |
8 |
Per-operation call ceiling |
MEMORYLAYER_GENERATION_MAX_INPUT_TOKENS |
100000 |
Per-operation estimated input ceiling |
MEMORYLAYER_GENERATION_MAX_OUTPUT_TOKENS |
16384 |
Per-operation reserved/actual output ceiling |
MEMORYLAYER_EXTRACTIVE_TIERS_ENABLED |
true |
false disables new extractive tier writes |
MEMORYLAYER_SESSION_CHECKPOINT_CAPTURE_ENABLED |
true |
false disables the checkpoint endpoint without deleting captures |
MEMORYLAYER_SESSION_CHECKPOINT_MAX_BYTES |
1048576 |
Maximum UTF-8 raw segment size |
MEMORYLAYER_CONTEXT_PACK_ENABLED |
true |
false disables pack/delta reads without deleting events |
MEMORYLAYER_CONTEXT_CURSOR_SECRET |
built-in local default | Set a stable private value shared by all server replicas |
MEMORYLAYER_CONTEXT_EVENT_RETENTION_DAYS |
30 |
Retained delta window; expired cursors require a full pack |
MEMORYLAYER_RELATIONAL_RECALL_ENABLED |
true |
false leaves stored relation/evidence rows intact but disables the recall arm |
MEMORYLAYER_RETRIEVAL_CONFIDENCE_ENABLED |
true |
false returns compatibility confidence fields |
MEMORYLAYER_RECALL_TOKEN_BUDGET_DEFAULT |
0 |
0 preserves count/detail behavior unless a caller supplies a budget |
Session recovery APIs are additive:
POST /v1/sessions/{session_id}/checkpointsdurably stores the exact raw transcript segment before deterministic indexing. Idempotency is scoped to the session and key.POST /v1/sessions/{session_id}/context-packreturns a ready-to-inject, deterministic rendering and opaque delta cursor under a hard token budget.POST /v1/sessions/{session_id}/context-deltareturns at-least-once changes, including tombstones, and advances only through delivered events.
Recall accepts budget_tokens, include_confidence, and include_relations.
Remember accepts explicit typed entity relations with source spans. Structural
relations are stored separately from similarity associations and remain backed
by active source-memory evidence.
Connectors can also acquire general professional-work relations without an LLM
by placing a typed profile under metadata.knowledge_work. The profile maps
owners, assignees, authors, contributors, reviewers, approvers, projects,
dependencies, decisions, references, evidence, impacts, and topics onto the
canonical entity registry and relation store. See
docs/DESIGN_knowledge_work_relations.md.
Connector-shaped requests may instead declare metadata.connector_type and
provide ordinary source fields such as title, assignee, creator,
reviewers, project, dependencies, or their supported vendor forms. The
single-memory API, batch API, email adapter, and document pipeline normalize
that explicit envelope into the same auditable profile. Arbitrary metadata
without a connector declaration is never interpreted.
Prometheus metrics separate memorylayer_generation_*,
memorylayer_embedding_*, and memorylayer_reranker_* work. Generation metric
labels are limited to activity, policy, and outcome; provider/profile attribution
is emitted in logs.
Choose your embedding model before ingesting data. The vector width it produces is written into every stored memory, so it is a property of your data, not just of configuration — and nothing in the schema stops you from mixing widths.
| Provider | Default model | Dimensions |
|---|---|---|
hash (default) |
— (lexical feature hashing) | 384 |
embed_server |
sentence-transformers/all-MiniLM-L6-v2 |
384 |
embed_server (GPU/vLLM) |
Qwen/Qwen3-VL-Embedding-2B |
2048 |
openai |
text-embedding-3-small |
1536 |
google |
gemini-embedding-001 |
768 |
Set MEMORYLAYER_EMBEDDING_DIMENSIONS to match whatever model you actually run —
and set it on the memorylayer-embed-server peer too, if you use one.
What goes wrong if you don't. Two memories embedded at different widths cannot be compared:
- On SQLite with
sqlite-vec(the default),vec_distance_cosine()raises on a width mismatch and the entire query returns no results — not just the mismatched rows. A few wrong-width memories break recall for the whole workspace. - If the
sqlite-vecextension is unavailable, the pure-Python fallback scores mismatched vectors as0.0, so older memories silently stop matching.
No schema migration is involved — memories.embedding is a plain BLOB with no
dimension in the DDL — but changing dimensions on a populated deployment means
re-embedding the existing memories, or starting a fresh workspace.
Matching widths is necessary but not sufficient: the default hash provider is
also 384-d, so switching from hash to MiniLM produces vectors that compare
without error while being semantically unrelated to the ones already stored.
Re-embed when you change the model, not only when you change the width.
The default (hash) works offline with zero setup, but is not a semantic model.
It hashes tokens into a vector, so it matches on shared words rather than meaning —
fine for local development, tests, and the retrieval-eval harness; not for production
recall quality. The server logs a warning at startup while it is in use. Pick one of
the real providers below for anything beyond trying it out.
The legacy in-process providers local (sentence-transformers), colpali (colpali-engine),
and qwen3-vl (qwen-vl-utils) were removed. All self-hosted/multi-vector embedding now
routes through the embed_server provider, which delegates to the standalone
memorylayer-embed-server package. Setting any of those legacy values for
MEMORYLAYER_EMBEDDING_PROVIDER raises a startup error with migration guidance.
Embed-server (self-hosted) — Run memorylayer-embed-server as a peer
process or container; the main server only speaks HTTP to it. This is what the
published Docker image is pinned to:
# In a GPU-equipped peer:
pip install memorylayer-embed-server[gpu]
memorylayer-embed-server serve --port 61051
# In the main server process:
export MEMORYLAYER_EMBEDDING_PROVIDER=embed_server
export MEMORYLAYER_EMBED_SERVER_URL=http://embed-host:61051
memorylayer serveOpenAI:
pip install memorylayer-server[openai]
export MEMORYLAYER_EMBEDDING_PROVIDER=openai
export MEMORYLAYER_EMBEDDING_OPENAI_API_KEY=sk-...
memorylayer serveGoogle GenAI:
pip install memorylayer-server[google]
export MEMORYLAYER_EMBEDDING_PROVIDER=google
export MEMORYLAYER_EMBEDDING_GOOGLE_API_KEY=...
memorylayer serveMock (testing only):
export MEMORYLAYER_EMBEDDING_PROVIDER=mock
memorylayer serveSome features (reflection, smart extraction, context environment queries) require an LLM provider configured via profiles:
# OpenAI
export MEMORYLAYER_LLM_PROFILE_DEFAULT_PROVIDER=openai
export MEMORYLAYER_LLM_PROFILE_DEFAULT_API_KEY=sk-...
# Anthropic Claude
export MEMORYLAYER_LLM_PROFILE_DEFAULT_PROVIDER=anthropic
export MEMORYLAYER_LLM_PROFILE_DEFAULT_API_KEY=sk-ant-...
# Google Gemini
export MEMORYLAYER_LLM_PROFILE_DEFAULT_PROVIDER=google
export MEMORYLAYER_LLM_PROFILE_DEFAULT_API_KEY=...Profile configuration variables (replace DEFAULT with any profile name):
| Variable | Description |
|---|---|
MEMORYLAYER_LLM_PROFILE_<NAME>_PROVIDER |
Provider (openai, anthropic, google) |
MEMORYLAYER_LLM_PROFILE_<NAME>_API_KEY |
API key |
MEMORYLAYER_LLM_PROFILE_<NAME>_MODEL |
Model name override |
MEMORYLAYER_LLM_PROFILE_<NAME>_BASE_URL |
Custom API base URL |
MEMORYLAYER_LLM_PROFILE_<NAME>_MAX_TOKENS |
Max response tokens |
MEMORYLAYER_LLM_PROFILE_<NAME>_TEMPERATURE |
Sampling temperature |
Without an LLM provider, core memory operations (remember, recall, forget, associate) work normally, but synthesis features will be unavailable.
The Context Environment provides server-side Python sandboxes for memory analysis and computation. See Context Environment documentation for details.
Configuration:
| Variable | Default | Description |
|---|---|---|
MEMORYLAYER_CONTEXT_EXECUTOR |
smolagents |
Executor backend (smolagents or restricted) |
MEMORYLAYER_CONTEXT_MAX_EXEC_SECONDS |
30 |
Timeout per code execution |
MEMORYLAYER_CONTEXT_MAX_OUTPUT_CHARS |
50000 |
Max captured stdout characters |
MEMORYLAYER_CONTEXT_QUERY_MAX_TOKENS |
4096 |
Max tokens for server-side LLM queries |
MEMORYLAYER_CONTEXT_MAX_MEMORY_BYTES |
268435456 |
Memory limit per sandbox (256 MB) |
MEMORYLAYER_CONTEXT_RLM_MAX_ITERATIONS |
10 |
Max iterations for RLM loops |
MEMORYLAYER_CONTEXT_RLM_MAX_EXEC_SECONDS |
120 |
Total timeout for RLM loops |
MEMORYLAYER_CONTEXT_MAX_OPERATIONS |
1000000 |
Max operations per sandbox execution |
The default storage backend is SQLite with sqlite-vec for vector operations. The database file defaults to ~/.config/memorylayer-server/memorylayer.db and contains all memories, embeddings, associations, and session data.
Override the data directory:
export MEMORYLAYER_DATA_DIR=/var/lib/memorylayerOverride the database path:
export MEMORYLAYER_SQLITE_STORAGE_PATH=/var/lib/memorylayer/data.dbThe active recall mode is RAG (vector similarity + graph traversal). LLM and Hybrid modes are deprecated.
The Model Context Protocol (MCP) server is a separate TypeScript package (@scitrera/memorylayer-mcp-server), not part of this Python server CLI.
To use MemoryLayer with Claude Code or Claude Desktop:
- Start the HTTP server:
memorylayer serve - Install and configure the MCP server:
npm install -g @scitrera/memorylayer-mcp-server
See the MCP Server documentation for setup instructions.
GET /health— Basic health check (returns immediately)GET /health/ready— Readiness check (verifies storage connectivity)
The Docker image includes a built-in health check at /health (every 30s, 10s startup grace period).
- Website: https://memorylayer.ai
- Docs: https://docs.memorylayer.ai
- GitHub: https://github.com/scitrera/memorylayer
Apache 2.0 License -- see LICENSE for details.