CrewAI
rekall-crewai gives your crew durable, server-persisted memory — shared across runs, hosts, and agents — by plugging Rekall into CrewAI 1.x's unified Memory via the StorageBackend protocol.
Overview
CrewAI saves every memory to Rekall (durable, cross-host) and searches it back on demand — no local ChromaDB or SQLite to manage, and the same memories become visible to your other Rekall-connected agents and editors. The package is stdlib-only (no heavy dependencies).
Installation
pip install rekall-crewai # stdlib-only; no heavy deps
Usage
Construct a RekallStorage and hand it to CrewAI's unified Memory:
from crewai import Crewfrom crewai.memory import Memoryfrom rekall_crewai import RekallStoragestorage = RekallStorage(api_url="https://api.rekall.app", # or http://localhost:9876 in devapi_key="rk_...", # or access_token="rat_..."scope="/crews/support", # namespace this crew's memory)crew = Crew(agents=[...],tasks=[...],memory=Memory(storage=storage),)
How It Works
CrewAI's StorageBackend is a vector-store contract: search is handed a precomputed query embedding (from CrewAI's own embedder), not text. Rekall's hosted retrieval (hybrid + rerank) embeds text server-side, so it can't honor a foreign embedding directly. RekallStorage therefore:
- check_circlepersists every record durably to Rekall (
POST /api/v2/memories), keeping the CrewAI embedding + scope + categories in metadata for exact rehydration; - check_circleanswers
searchwith cosine similarity over the records for the active scope, held in an in-process index that's lazily rehydrated from Rekall — so recall is self-consistent (both sides use CrewAI's embedder) and survives across sessions and hosts.
It returns real crewai.memory.types.MemoryRecord / ScopeInfo when crewai is installed, and a duck-typed shim with the same attributes otherwise. The HTTP layer is injectable (transport=) for testing.
StorageBackend Mapping
| StorageBackend | Rekall |
|---|---|
save(records) / asave | POST /api/v2/memories per record (content + scope/categories/embedding in metadata) |
search(query_embedding, …) / asearch | cosine over the scoped in-process index → [(MemoryRecord, score)] |
delete(…) / adelete, reset(scope) | DELETE /api/v2/memories/:id for matching records |
update(record) | PUT /api/v2/memories/:id |
get_record / list_records / count / list_scopes / list_categories / get_scope_info | served from the index |
Want Rekall-Quality Recall? Use MCP or a Tool
The StorageBackend rail gives you durable, cross-session crew memory but recall is plain cosine in CrewAI's embedding space — it does not use Rekall's hybrid search + reranking. For most crews, the higher-quality path is to let Rekall do the retrieval and hand back text:
- hubMCP — point CrewAI at Rekall's MCP server and let agents call its
memory_search/recalltools; or - builda Rekall search tool — wrap
POST /api/v2/memories/search(text in, ranked results out) as a CrewAI@tool.
The two are complementary
Use RekallStorage for durable capture and MCP/tool for best-in-class recall. See the MCP clients docs to wire CrewAI to the Rekall MCP server.
Upgrading from 0.1.x
CrewAI 1.x replaced the separate ShortTermMemory(storage=…) / LongTermMemory(storage=…) classes with a single Memory(storage=…), and the old Storage(save/search/reset) interface with the richer StorageBackend protocol. RekallStorage now targets the new protocol — update your wiring to Memory(storage=RekallStorage(...)).
Authentication
Pass api_key (rk_…) or access_token (rat_…) — sent as Authorization: Bearer. For local dev against header-auth servers, pass headers={"x-user-id": "…"}.
