Identity resolution for mem0. Same person, different IDs = unified memory.
Project description
kanoniv-mem0
Identity resolution for mem0. Same person, different IDs = unified memory.
The Problem
mem0 stores memories keyed by user_id. If two agents use different identifiers for the same person, mem0 treats them as separate users:
from mem0 import Memory
m = Memory()
m.add("Prefers annual billing", user_id="bill@acme.com")
m.add("Needs 50 seat quote", user_id="william.smith@acme.com")
m.search("billing", user_id="bill@acme.com")
# Only finds 1 memory. The other is invisible.
Bill and William Smith are the same person. But mem0 doesn't know that.
The Fix
from kanoniv_mem0 import KanonivMemory
m = KanonivMemory(kanoniv_api_key="kn_live_...")
m.add("Prefers annual billing", user_id="bill@acme.com")
m.add("Needs 50 seat quote", user_id="william.smith@acme.com")
m.search("billing", user_id="bill@acme.com")
# Finds BOTH memories. Same canonical entity.
KanonivMemory resolves every user_id to a canonical entity via Kanoniv's identity graph before mem0 stores or retrieves anything. Different IDs that belong to the same person get the same entity_id. Memories unify automatically.
Install
pip install kanoniv-mem0
Quick Start
from kanoniv_mem0 import KanonivMemory
# Drop-in replacement for mem0's Memory
m = KanonivMemory(kanoniv_api_key="kn_live_...")
# Agent A - support agent
m.add(
"I'm Bill, VP of Engineering at Acme. Switch us to annual billing.",
user_id="bill@acme.com",
)
# Agent B - sales agent (different email, same person)
m.add(
"This is William Smith. Quote me for 50 Enterprise seats.",
user_id="william.smith@acme.com",
)
# Agent C - searches by either ID, gets everything
results = m.search("billing", user_id="bill@acme.com")
# Returns memories from BOTH agents
results = m.get_all(user_id="william.smith@acme.com")
# Returns ALL memories for this person, regardless of which ID was used
How It Works
Your code KanonivMemory mem0
| | |
| add(user_id="bill@..") | |
|------------------------>| |
| | resolve("bill@..") |
| |-----> Kanoniv API |
| |<----- entity_id: ENT_7f|
| | |
| | add(user_id="ENT_7f") |
| |----------------------->|
| | | store
- You call
add()orsearch()with anyuser_id(email, phone, name, internal ID) KanonivMemorycalls Kanoniv's resolve endpoint to get the canonicalentity_id- The canonical ID is passed to mem0 as the
user_id - Different identifiers for the same person resolve to the same entity
- mem0 stores and retrieves using the unified ID
The resolve call adds ~5ms (sub-ms if cached in Kanoniv's Redis layer). Results are also cached locally per session.
API
KanonivMemory is a drop-in replacement for mem0.Memory. All the same methods work:
| Method | Identity Resolved? | Description |
|---|---|---|
add() |
Yes | Add memories from messages |
search() |
Yes | Search memories by query |
get_all() |
Yes | Get all memories for a user |
delete_all() |
Yes | Delete all memories for a user |
get() |
No | Get a specific memory by ID |
update() |
No | Update a specific memory |
delete() |
No | Delete a specific memory |
history() |
No | Get memory change history |
reset() |
No | Reset all memories |
Additional methods
# Check how a user_id resolves
m.get_entity_id("bill@acme.com")
# -> "ENT_7f82..."
# Same person, same entity
m.get_entity_id("william.smith@acme.com")
# -> "ENT_7f82..."
# Clear the local resolve cache
m.clear_cache()
Configuration
m = KanonivMemory(
# mem0 config (optional - pass any mem0 MemoryConfig or dict)
config={"vector_store": {"provider": "qdrant", ...}},
# Kanoniv config
kanoniv_api_key="kn_live_...", # Get free key at app.kanoniv.com
kanoniv_base_url="https://api.kanoniv.com", # Default
source_name="mem0", # Source name in identity graph
cache_resolves=True, # Cache resolve results (default: True)
)
Using Kanoniv's sandbox (free, no limits during development)
m = KanonivMemory(
kanoniv_api_key="kn_test_...", # Sandbox keys start with kn_test_
)
Sandbox gives you 1,000 entities for free, instant reset, full API access.
Graceful Degradation
If Kanoniv's API is unreachable, KanonivMemory falls back to using the raw user_id - exactly like vanilla mem0. Memory still works, you just lose cross-ID unification until the connection is restored. No data loss, no errors.
Why Kanoniv?
Kanoniv is deterministic identity infrastructure for AI systems. It resolves records to canonical entities using configurable matching rules (email, phone, name, company), probabilistic scoring, and constraint-based merging.
- Deterministic: Same input always produces the same entity_id
- Real-time: Resolve calls return in <10ms
- Explainable: Every resolution includes confidence scores and match reasons
- Multi-signal: Matches on email, phone, name, company, and custom fields
Get a free API key at app.kanoniv.com.
License
Apache 2.0
Project details
Release history Release notifications | RSS feed
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 kanoniv_mem0-0.1.0.tar.gz.
File metadata
- Download URL: kanoniv_mem0-0.1.0.tar.gz
- Upload date:
- Size: 8.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dffa54e193374699121179eaa2b7065701ef1db5204ed0fbe8d810205270399d
|
|
| MD5 |
8a1276287149ca5a9ebffed124f005f4
|
|
| BLAKE2b-256 |
0ae62eda483bc3e89c1f9cc3c7cee85245596ca0f5675d4844c137daae9e2000
|
File details
Details for the file kanoniv_mem0-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kanoniv_mem0-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea9880e56b8a308e6f164c213ebca6ece287f95f2102e62efaf7c984d8a4290d
|
|
| MD5 |
8c17c9431ddf7515736697ff723e6441
|
|
| BLAKE2b-256 |
e2c5e5fd9a1ee92dc3479928f4435feb7d4b3ffaffeff8d08224bbc68abd7d77
|