Tutorial - CrewAI: shared, portable memory¶
SwarmStateStorage is a small, dependency-free keyword memory store (save,
search, reset) backed by a swarmstate Store. Its value is
portability and durability: crew memories live in the same store as your LangGraph
checkpoints, can be snapshotted, and can be read by any other system.
This is not CrewAI's built-in memory backend
As of CrewAI 1.x, the native memory StorageBackend is embedding-based (it
stores MemoryRecords and searches by vector similarity) - a vector store, which
swarmstate is not. SwarmStateStorage is a lightweight lexical alternative you
wire in yourself (e.g. from a task callback or your own loop) when you want durable,
portable, dependency-free recall. For semantic RAG recall, use CrewAI's own storage.
(Verified against crewai 1.15.)
Create the storage¶
import swarmstate as ss
from swarmstate.integrations.crewai import SwarmStateStorage
store = ss.Store() # in-memory
storage = SwarmStateStorage(store, namespace="crew:research")
For persistence across runs/processes, back it with Redis - same one line:
from swarmstate.backends.redis import RedisStore
storage = SwarmStateStorage(RedisStore("redis://localhost:6379/0"), namespace="crew:research")
Save and recall memory¶
storage.save("The Q2 churn rate was 4.1%", {"agent": "analyst"})
storage.save("Top objection in calls: pricing", {"agent": "sales"})
storage.search("churn rate", limit=3)
# [{"context": "The Q2 churn rate was 4.1%", "metadata": {"agent": "analyst"}, "score": 1.0}]
storage.reset() # clear this namespace
search returns {"context", "metadata", "score"} entries, ranked by token overlap
then recency.
Use it around a crew¶
You drive it yourself - typically from a task callback or right after kickoff() -
rather than plugging it into CrewAI's native (embedding-based) memory slot:
from crewai import Agent, Task, Crew # your normal setup
# ... define agents & tasks ...
result = crew.kickoff()
storage.save(str(result), {"run": "research", "ts": "2026-07-03"})
# next run, recall prior findings before kicking off again
prior = storage.search("research findings", limit=5)
This keeps the useful part - durable, portable, snapshot-able recall in a shared store - without pretending to be a vector database.
Portability: one store, many agents¶
Because the memory lives in a Store, anything else can read it - a LangGraph app, a
dashboard, another language:
key = store.keys("crew:research")[0]
store.get("crew:research", key) # {"value": "...", "metadata": {...}}
See state portability for the full anti-lock-in story, and the Redis backend to make it persistent.