CrewAI v1.15.2 ships a built-in Memory class that stores agent knowledge in a local LanceDB at ./.crewai/memory/. It persists across runs on the same machine, extracts discrete facts after each task, injects relevant context before each task, and uses LLM-inferred scope hierarchies to organize what gets recalled. For development workflows and single-machine deployments, this is solid. The limitation emerges at scale and in production: memory is tied to a local directory, so container restarts wipe it, multi-machine teams can’t share it, and crew knowledge never reaches your other AI tools (Claude Code, Cursor, Windsurf). For those gaps, PLUR is the complement — an open-format persistent memory layer that connects to any MCP-capable tool and persists to ~/.plur/ regardless of where your crew runs.
Since v1.15.2, CrewAI’s memory is a unified Memory class with composite scoring across three signals: semantic similarity (50%), recency (30%), and importance (20%). Every save goes through an LLM analysis pipeline that infers the optimal scope path (e.g., /project/alpha/decisions), assigns categories, and sets an importance score between 0 and 1. Reads use deep recall by default — a multi-step pipeline that analyzes the query, selects scopes to search, runs parallel vector lookups, and explores further when confidence is low.
Enable it on a crew with a single flag:
from crewai import Crew, Agent, Task, Process
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential,
memory=True, # creates Memory() with LanceDB backend
verbose=True,
)
After each task, the crew runs extract_memories() to distill discrete facts from the task output and stores each one. Before each task, the agent recalls relevant context and injects it into the task prompt. Memory consolidation de-duplicates similar facts (cosine similarity ≥ 0.85 triggers an LLM merge/delete decision). Intra-batch dedup catches near-exact duplicates without any LLM calls (cosine ≥ 0.98 drops the later entry silently).
The default embedder is OpenAI text-embedding-3-large (3072 dimensions). You can swap in a local embedder for private or offline deployments:
from crewai import Memory
memory = Memory(
llm="ollama/llama3.2", # local LLM for analysis
embedder={"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}},
)
Storage defaults to ./.crewai/memory — a directory relative to wherever you run the script. You can override with storage="./my_path" or the CREWAI_STORAGE_DIR environment variable.
Local directory constraint. The ./.crewai/memory default is a relative path. In containerized deployments, cloud functions (AWS Lambda, Google Cloud Run, Azure Functions), or Kubernetes pods, the filesystem is ephemeral — memory accumulated during a run is discarded when the container stops. Pointing to persistent mounted storage fixes this for a single deployment, but adds infrastructure overhead.
Single-machine, single-project scope. If your team runs crews across different machines, or you develop on a laptop and deploy to a server, each environment maintains its own separate memory store. There is no built-in sync, so knowledge accumulated in development stays in development.
Crew-scoped, not tool-scoped. CrewAI memory is only accessible to agents in a crew. The research conclusions, corrections, and decisions your crew accumulates are invisible to your Claude Code session, your Cursor workspace, or any other AI tool you use. Patterns you teach one tool need to be re-taught to others.
LLM overhead on every save. Scope inference, category assignment, and importance scoring require an LLM call on each remember(). For crews that save frequently, this adds latency and token cost. Shallow explicit scopes avoid the call, but then scope management becomes manual.
PLUR (github.com/plur-ai/plur, ~225 GitHub stars as of Jul 2026) is an open-format persistent memory layer that stores knowledge as engrams — typed, plain-YAML assertions in ~/.plur/ — and exposes them via an MCP server. Because the storage path is absolute (~/.plur/ or $PLUR_PATH), it is unaffected by container restarts or working-directory changes. Because it is an MCP server, any MCP-capable tool (Claude Code, Cursor, Windsurf, OpenClaw, and CrewAI via crewai-tools) can read and write the same memory.
PLUR and CrewAI memory are not competing — they store different things. CrewAI’s memory handles within-crew, within-project context (task outputs, decisions, working facts). PLUR handles cross-tool, cross-deployment knowledge (corrections, preferences, conventions, patterns worth keeping forever). The overlap is minimal; the combination is more useful than either alone.
Retrieval comparison:
| CrewAI built-in Memory | PLUR | |
|---|---|---|
| Storage | ./.crewai/memory (local LanceDB) | ~/.plur/ (plain YAML, absolute path) |
| Persists in containers | Only with mounted volumes | Yes, if PLUR_PATH points to mounted storage or cloud sync |
| Cross-machine | No (no sync built in) | Yes, via plur_sync (git-based) |
| Cross-tool | No (CrewAI only) | Yes, any MCP client |
| Search | Semantic + recency + importance | BM25 + embeddings + reciprocal rank fusion |
| Retrieval (LongMemEval R@5) | Not published | 97.0% with openai-3-large; 83.3% with local ms-marco reranker |
| LLM overhead on save | Yes (scope inference, per-save) | No (search is fully local; no per-save LLM call) |
| Open format | No | Yes (YAML engram spec, JSON Schema published) |
CrewAI v1.15.2 supports MCP servers as first-class tools via the mcps field on Agent (using the mcp package) or via MCPServerStdio from crewai-tools. To connect PLUR:
pip install crewai crewai-tools mcp
npx @plur-ai/mcp init # first-time setup: creates ~/.plur/, writes default config
from crewai import Agent, Task, Crew, Process
from crewai.mcp import MCPServerStdio
# PLUR MCP server — persistent memory tools available to this agent
plur_memory = MCPServerStdio(
command="npx",
args=["-y", "@plur-ai/mcp"],
cache_tools_list=True, # avoid re-fetching tool list every call
)
researcher = Agent(
role="Research Analyst",
goal="Find and synthesize information on the given topic",
backstory="Expert researcher who builds on prior work",
mcps=[plur_memory], # agent now has plur_learn, plur_recall, plur_inject, etc.
)
# Standard CrewAI crew — built-in Memory handles within-run context;
# PLUR handles cross-run, cross-tool knowledge
crew = Crew(
agents=[researcher],
tasks=[research_task],
process=Process.sequential,
memory=True, # CrewAI built-in for within-crew context
verbose=True,
)
The researcher agent now has access to 16 PLUR tools: plur_learn, plur_recall, plur_inject, plur_feedback, plur_forget, plur_sync, and others. It can call plur_learn to store a correction (“always use HTTPS endpoints for this API”) that will be available in the next run, next week, and in every other MCP-capable tool on the machine.
With both systems active, memory responsibilities are naturally partitioned:
CrewAI memory handles:
PLUR handles:
# Researcher learns a permanent correction (stored in ~/.plur/)
await plur_learn(
statement="Always verify source accessibility before citing — paywalled links must be noted",
type="constraint",
domain="research.sourcing",
scope="project:plur-research",
)
# Next run, next tool, next machine — the constraint is still there
await plur_recall("source citations paywalled")
# → "Always verify source accessibility before citing — paywalled links must be noted"
Only if you mount a persistent volume at the storage path. The default ./.crewai/memory is a relative path in the container’s ephemeral filesystem; it is wiped on restart. Override with CREWAI_STORAGE_DIR pointing to a mounted volume, or use PLUR (which stores at ~/.plur/ — also mappable to a volume) for corrections and conventions that must survive restarts.
CrewAI memory is scoped per-instance — each Crew(memory=True) creates its own Memory(). You can share a Memory object by constructing it explicitly and passing it to multiple crews, but it must be instantiated in the same process. PLUR is global by design: one ~/.plur/ store, accessible to any MCP client, any agent framework, on any machine you sync to.
No — they are complementary. CrewAI’s memory is optimized for within-run, within-project context: it extracts facts from task outputs, scores by recency and importance, and injects relevant context between tasks. PLUR stores corrections and conventions that should outlive a single run and travel across tools. Use both.
CrewAI uses composite scoring: semantic similarity (50%) + recency (30%) + importance (20%), with LLM-driven deep recall for complex queries. PLUR uses BM25 + local BGE embeddings + reciprocal rank fusion, fully local with zero API calls. On LongMemEval (R@5, N=500), PLUR hybrid search reaches 97.0% with OpenAI text-embedding-3-large and 83.3% with a local ms-marco cross-encoder reranker. CrewAI has not published retrieval benchmarks.
What embedding model does CrewAI use?
The default is OpenAI text-embedding-3-large (3072 dimensions), which requires an OPENAI_API_KEY. You can configure Ollama, Azure, Google, Cohere, and others. Note: changing embedding models after the store is built requires resetting memory (crewai reset-memories -m) because dimension mismatches crash recall. PLUR stores engrams as plain YAML; search indices are rebuilt locally and can be reconfigured without losing the underlying data.