Hi David,
I built a 17-case conformance suite for AI memory trust primitives
(signed deletion receipts, default-DENY policy contracts, bi-temporal
validity) and ran four upstream substrates against it via thin HTTP
adapters.. no shimming, no simulation, just calls to the real packages.
Results:
graphiti (Neo4j 5) 11/17
Letta v0.16.7 9/17
txtai 9.7.0 9/17
mem0 2.0.1 8/17
Two notes specifically about txtai:
-
Embeddings.upsert(id, ...) gave the cleanest supersession
behaviour of any substrate I tested. Same id -> replaced row,
exactly what the conformance case expects. mem0 and Letta both
needed adapter logic to map "kind+key" to their internal model;
txtai just worked.
-
The only thing standing between txtai and a higher score on the
optional bi-temporal cases is surfacing valid_at / invalid_at
on search() results. The data already lives in the metadata
dict, it's just not first-class on the result row.
Adapter (~150 lines, deterministic id from sha256(kind+key), HTTP
wrapper around an Embeddings instance per tenant):
https://github.com/upcomingsimplecoder/mosaic/blob/main/adapters/txtai_real.py
Full suite + reproduction:
https://github.com/upcomingsimplecoder/mosaic
Happy to send a PR exposing optional first-class temporal fields if
that direction is interesting. Either way — txtai was a pleasure to
integrate with, wanted to say so.
Thanks,
Jed
Hi David,
I built a 17-case conformance suite for AI memory trust primitives
(signed deletion receipts, default-DENY policy contracts, bi-temporal
validity) and ran four upstream substrates against it via thin HTTP
adapters.. no shimming, no simulation, just calls to the real packages.
Results:
Two notes specifically about txtai:
Embeddings.upsert(id, ...)gave the cleanest supersessionbehaviour of any substrate I tested. Same id -> replaced row,
exactly what the conformance case expects. mem0 and Letta both
needed adapter logic to map "kind+key" to their internal model;
txtai just worked.
The only thing standing between txtai and a higher score on the
optional bi-temporal cases is surfacing
valid_at/invalid_aton
search()results. The data already lives in the metadatadict, it's just not first-class on the result row.
Adapter (~150 lines, deterministic id from sha256(kind+key), HTTP
wrapper around an Embeddings instance per tenant):
https://github.com/upcomingsimplecoder/mosaic/blob/main/adapters/txtai_real.py
Full suite + reproduction:
https://github.com/upcomingsimplecoder/mosaic
Happy to send a PR exposing optional first-class temporal fields if
that direction is interesting. Either way — txtai was a pleasure to
integrate with, wanted to say so.
Thanks,
Jed