saihm-crewai
SAIHM external memory for CrewAI — a StorageBackend your crew owns: one encrypted source of truth every agent in the crew shares, portable across every model, and provably erasable.
SaihmStorageBackend is a drop-in crewai.memory.storage.backend.StorageBackend — the protocol CrewAI's unified memory resolves through. Register it once and that crew's long-term memory becomes memory the user actually owns: portable across models and frameworks, non-custodial (sealed client-side; Python never holds a key), and provably erasable (GDPR Art. 17 — reset crypto-shreds the cells, it does not merely hide them).
pip install saihm-crewai # needs crewai >= 1.15 and Node.js >= 20 on PATH (see "How it works")
from crewai.memory.storage.factory import set_memory_storage_factory
from saihm_memory import SaihmStorageBackend
# Register once at startup; return None for other specs to defer to CrewAI's own selection.
set_memory_storage_factory(
lambda spec: SaihmStorageBackend() if spec == "saihm" else None # sandbox by default — no account, offline
)
Any CrewAI memory built afterwards for the "saihm" storage spec is then backed by SAIHM.
Or drive the store directly (any Python app):
from crewai.memory.types import MemoryRecord
from saihm_memory import SaihmStorageBackend
store = SaihmStorageBackend() # local blind sandbox, no signup
store.save([MemoryRecord(content="the user is vegetarian", categories=["diet"])])
hits = store.search(query_embedding, limit=5) # -> [(MemoryRecord, score), ...] best-first
store.reset() # crypto-shred everything this store wrote
SaihmStorageBackend implements the full StorageBackend protocol — save / search / delete / update / get_record / list_records / get_scope_info / list_scopes / list_categories / count / reset, plus async asave / asearch / adelete. Each record is one encrypted SAIHM cell.
CrewAI version. CrewAI replaced its memory storage API between 1.9 and 1.15 (
storage.interface.StorageandExternalMemorygave way tostorage.backend.StorageBackend,types.MemoryRecord, and thestorage.factoryhook). This package targets the current API and therefore requires crewai >= 1.15; it is verified against 1.15.14.
Why not just the built-in storage?
CrewAI's default storage is only as portable as the process it runs in, and only as private as whoever holds the store behind it. SAIHM changes the ownership model — same StorageBackend protocol, a fundamentally different guarantee about who owns the memory:
- Yours across every model. The same memory opens under Claude, GPT, DeepSeek, Qwen, Kimi, or GLM — and under the LangGraph, LangChain, and AutoGen adapters. Switch models or frameworks and the crew's memory follows it. No migration, no re-embedding, no vendor lock-in.
- The store is blind. Every entry is sealed client-side with post-quantum cryptography (ML-DSA-65 / ML-KEM-768 / AES-256-GCM) before it ever leaves your process. The endpoint holds ciphertext it cannot read; Python never holds a key.
- Erasure you can prove.
resetanddeletedestroy each cell's key, so its ciphertext becomes unrecoverable noise — a cryptographic shred, not a soft-delete. That is GDPR Art. 17 built into the backend. On the hosted tier each shred is recorded in SAIHM's audit chain; in the offline sandbox the identical code path runs locally, with no external record. - Free to start, offline in seconds. Runs against a local blind sandbox with no account and no network; point it at the hosted free tier when you're ready to persist.
Give your crew long-term memory your users actually own — portable, private, and provably forgettable — without leaving the StorageBackend protocol CrewAI already uses.
How it works
All cryptography runs in a small Node sidecar (built on @saihm/mcp-server-pro, ML-DSA-65 / ML-KEM-768 / AES-256-GCM); Python drives it over MCP stdio and holds no keys — one audited crypto implementation, not a second one ported to Python. That is why Node.js ≥ 20 is required. The sidecar ships inside the wheel as source only; its Node dependencies are installed once into a per-user cache (~/.cache/saihm-crewai) on first use, then reused offline.
- Sandbox (default): no configuration → a local, in-process blind endpoint (ciphertext only). Great for trying it with zero signup; memory lasts for the client's life.
- Live: set
SAIHM_ENDPOINT_URL+SAIHM_MASTER_SECRET_HEXand eitherSAIHM_TIER=FREE(free tier — runnpx -y @saihm/mcp-server-pro free-joinonce) orSAIHM_AUTH_HEADER(Pro; join at https://saihm.coti.global/join) → durable, hosted, blind memory.
Always close() the backend (or close a shared client); a dropped client is reaped on GC, but explicit close is cleaner.
Ranking (blind store)
SAIHM is a blind store — the endpoint holds ciphertext only and cannot run a server-side vector index — so search ranks client-side:
- Semantic, using CrewAI's own embeddings.
searchtakes aquery_embeddingand CrewAI puts anembeddingon eachMemoryRecord, so ranking is cosine similarity computed in your process. The embedding is sealed into the cell alongside the content; the endpoint sees neither. This adapter never embeds anything itself — whatever embedding model CrewAI is configured with is the one that applies. - Recency fallback. When no embeddings are present (for example the offline sandbox, where nothing has been embedded),
searchdegrades to newest-first rather than returning nothing. min_score,limit,scope_prefix,categories, andmetadata_filterare all honored — filtering happens before ranking.
Each result is a (MemoryRecord, score) tuple, best-first. Exact recall (get_record, list_records) and erasure (delete, reset) are always exact, never approximate.
scope_prefix matches on path boundaries: /demo covers /demo and /demo/inner but never /demo2 or /demonstrate. That distinction matters because delete and reset crypto-shred irreversibly.
A cell written outside this adapter (e.g. by the LangGraph, LangChain, or AutoGen SAIHM adapters, or a raw remember) is left untouched — one owned store can hold facts from several adapters without collision, and reset only ever shreds the entries this backend wrote.
Related
- Try it in your browser (offline, no signup): https://citw2.github.io/saihm-demos/
- Runnable end-to-end demo: https://github.com/citw2/saihm-crewai
- Other adapters: LangGraph · LangChain/LlamaIndex · AutoGen
- What SAIHM is: https://saihm.coti.global
License
Apache-2.0.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file saihm_crewai-0.1.0.tar.gz.
File metadata
- Download URL: saihm_crewai-0.1.0.tar.gz
- Upload date:
- Size: 39.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed7b6b086ac5976d56c64e84d0fbe6bef281249d752a13adcff872c223d70ad8
|
|
| MD5 |
934408552e114ae6241d4951d0560301
|
|
| BLAKE2b-256 |
d288b19f253769d548df5837922cd1ef482a2b4bcfb117852f38352201232b90
|
File details
Details for the file saihm_crewai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: saihm_crewai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 36.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b103dc2930ced0d4cd7397e1e60969af77dd7e25c61e72f1adadd00d61c8a28
|
|
| MD5 |
24137d0018286528bac64f1b97b0b7e1
|
|
| BLAKE2b-256 |
275fed59fc18d5a659cc179202ba4827d97c27cc18cb3fe5f86dad95d87df8d5
|