memio 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- memio-0.1.0/.github/workflows/docs.yml +20 -0
- memio-0.1.0/.github/workflows/publish.yml +22 -0
- memio-0.1.0/.gitignore +9 -0
- memio-0.1.0/LICENSE +21 -0
- memio-0.1.0/PKG-INFO +24 -0
- memio-0.1.0/README.md +228 -0
- memio-0.1.0/docs/api/client.md +5 -0
- memio-0.1.0/docs/api/exceptions.md +5 -0
- memio-0.1.0/docs/api/models.md +13 -0
- memio-0.1.0/docs/api/protocols.md +11 -0
- memio-0.1.0/docs/concepts/architecture.md +168 -0
- memio-0.1.0/docs/contributing/adding-providers.md +232 -0
- memio-0.1.0/docs/contributing/development.md +113 -0
- memio-0.1.0/docs/getting-started/installation.md +88 -0
- memio-0.1.0/docs/getting-started/quickstart.md +248 -0
- memio-0.1.0/docs/guides/custom-providers.md +272 -0
- memio-0.1.0/docs/index.md +85 -0
- memio-0.1.0/docs/providers/chroma.md +171 -0
- memio-0.1.0/docs/providers/mem0.md +139 -0
- memio-0.1.0/docs/providers/zep.md +212 -0
- memio-0.1.0/memio/__init__.py +19 -0
- memio-0.1.0/memio/client.py +55 -0
- memio-0.1.0/memio/exceptions.py +19 -0
- memio-0.1.0/memio/models.py +101 -0
- memio-0.1.0/memio/protocols.py +87 -0
- memio-0.1.0/memio/providers/__init__.py +0 -0
- memio-0.1.0/memio/providers/chroma/__init__.py +3 -0
- memio-0.1.0/memio/providers/chroma/document.py +107 -0
- memio-0.1.0/memio/providers/mem0/__init__.py +5 -0
- memio-0.1.0/memio/providers/mem0/fact.py +162 -0
- memio-0.1.0/memio/providers/mem0/graph.py +130 -0
- memio-0.1.0/memio/providers/zep/__init__.py +5 -0
- memio-0.1.0/memio/providers/zep/fact.py +183 -0
- memio-0.1.0/memio/providers/zep/graph.py +159 -0
- memio-0.1.0/memio/providers/zep/history.py +158 -0
- memio-0.1.0/memio/py.typed +0 -0
- memio-0.1.0/mkdocs.yml +71 -0
- memio-0.1.0/pyproject.toml +27 -0
- memio-0.1.0/tests/__init__.py +0 -0
- memio-0.1.0/tests/conformance/__init__.py +0 -0
- memio-0.1.0/tests/conformance/document_store.py +36 -0
- memio-0.1.0/tests/conformance/fact_store.py +43 -0
- memio-0.1.0/tests/conformance/graph_store.py +19 -0
- memio-0.1.0/tests/conformance/history_store.py +31 -0
- memio-0.1.0/tests/conftest.py +0 -0
- memio-0.1.0/tests/integration/__init__.py +0 -0
- memio-0.1.0/tests/integration/test_chroma.py +17 -0
- memio-0.1.0/tests/integration/test_mem0.py +20 -0
- memio-0.1.0/tests/integration/test_zep.py +78 -0
- memio-0.1.0/tests/providers/__init__.py +0 -0
- memio-0.1.0/tests/providers/test_chroma_doc.py +114 -0
- memio-0.1.0/tests/providers/test_mem0_fact.py +119 -0
- memio-0.1.0/tests/providers/test_mem0_graph.py +90 -0
- memio-0.1.0/tests/providers/test_zep_fact.py +132 -0
- memio-0.1.0/tests/providers/test_zep_graph.py +104 -0
- memio-0.1.0/tests/providers/test_zep_history.py +162 -0
- memio-0.1.0/tests/test_client.py +131 -0
- memio-0.1.0/tests/test_exceptions.py +35 -0
- memio-0.1.0/tests/test_models.py +81 -0
- memio-0.1.0/tests/test_protocols.py +80 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: Deploy docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
deploy:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: '3.12'
|
|
19
|
+
- run: pip install mkdocs-material "mkdocstrings[python]"
|
|
20
|
+
- run: mkdocs gh-deploy --force
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: pypi
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: '3.12'
|
|
20
|
+
- run: pip install build
|
|
21
|
+
- run: python -m build
|
|
22
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
memio-0.1.0/.gitignore
ADDED
memio-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 y3zai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
memio-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: memio
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified memory gateway for AI agents
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Provides-Extra: all
|
|
9
|
+
Requires-Dist: chromadb; extra == 'all'
|
|
10
|
+
Requires-Dist: mem0ai; extra == 'all'
|
|
11
|
+
Requires-Dist: zep-cloud; extra == 'all'
|
|
12
|
+
Provides-Extra: chroma
|
|
13
|
+
Requires-Dist: chromadb; extra == 'chroma'
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest-mock>=3.12; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
18
|
+
Provides-Extra: docs
|
|
19
|
+
Requires-Dist: mkdocs-material; extra == 'docs'
|
|
20
|
+
Requires-Dist: mkdocstrings[python]; extra == 'docs'
|
|
21
|
+
Provides-Extra: mem0
|
|
22
|
+
Requires-Dist: mem0ai; extra == 'mem0'
|
|
23
|
+
Provides-Extra: zep
|
|
24
|
+
Requires-Dist: zep-cloud; extra == 'zep'
|
memio-0.1.0/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# memio
|
|
2
|
+
|
|
3
|
+
Unified memory gateway for AI agents. One interface, multiple memory providers.
|
|
4
|
+
|
|
5
|
+
memio lets you swap between memory backends (Mem0, Zep, Chroma) without changing your application code. Define what memory capabilities you need — facts, conversation history, documents, knowledge graphs — and plug in any supported provider.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Protocol-based architecture** — providers implement Python protocols, so you can mix and match or bring your own
|
|
10
|
+
- **Async-first** — all operations are `async`/`await`
|
|
11
|
+
- **Zero production dependencies** — install only the providers you need
|
|
12
|
+
- **Composable** — use Mem0 for facts, Zep for history, and Chroma for documents in the same client
|
|
13
|
+
- **Multi-tenant** — scope data by `user_id` or `agent_id`
|
|
14
|
+
- **Consistent error handling** — all provider errors wrapped in `ProviderError` with context
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install memio
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Install with providers:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install memio[mem0] # Mem0 provider
|
|
26
|
+
pip install memio[zep] # Zep provider
|
|
27
|
+
pip install memio[chroma] # Chroma provider
|
|
28
|
+
pip install memio[all] # All providers
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from memio import Memio
|
|
35
|
+
from memio.providers.mem0 import Mem0FactAdapter
|
|
36
|
+
from memio.providers.zep import ZepHistoryAdapter
|
|
37
|
+
from memio.providers.chroma import ChromaDocumentAdapter
|
|
38
|
+
import chromadb
|
|
39
|
+
|
|
40
|
+
client = Memio(
|
|
41
|
+
facts=Mem0FactAdapter(api_key="your-mem0-key"),
|
|
42
|
+
history=ZepHistoryAdapter(api_key="your-zep-key"),
|
|
43
|
+
documents=ChromaDocumentAdapter(
|
|
44
|
+
client=chromadb.EphemeralClient(),
|
|
45
|
+
collection_name="my-docs",
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Store and retrieve facts
|
|
50
|
+
fact = await client.facts.add(content="likes coffee", user_id="alice")
|
|
51
|
+
results = await client.facts.search(query="coffee", user_id="alice")
|
|
52
|
+
|
|
53
|
+
# Manage conversation history
|
|
54
|
+
from memio import Message
|
|
55
|
+
|
|
56
|
+
await client.history.add(
|
|
57
|
+
session_id="session-1",
|
|
58
|
+
messages=[
|
|
59
|
+
Message(role="user", content="hello"),
|
|
60
|
+
Message(role="assistant", content="hi there"),
|
|
61
|
+
],
|
|
62
|
+
)
|
|
63
|
+
messages = await client.history.get(session_id="session-1")
|
|
64
|
+
|
|
65
|
+
# Store and search documents
|
|
66
|
+
doc = await client.documents.add(content="memio is a memory gateway")
|
|
67
|
+
results = await client.documents.search(query="memory")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Memory stores
|
|
71
|
+
|
|
72
|
+
memio defines four memory store protocols. Each provider implements one or more:
|
|
73
|
+
|
|
74
|
+
| Store | Purpose | Mem0 | Zep | Chroma |
|
|
75
|
+
|-------|---------|------|-----|--------|
|
|
76
|
+
| `FactStore` | Structured facts about users/agents | yes | yes | - |
|
|
77
|
+
| `HistoryStore` | Conversation message history | - | yes | - |
|
|
78
|
+
| `DocumentStore` | Document storage with semantic search | - | - | yes |
|
|
79
|
+
| `GraphStore` | Knowledge graph triples | yes | yes | - |
|
|
80
|
+
|
|
81
|
+
### FactStore
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
fact = await store.add(content="prefers dark mode", user_id="alice")
|
|
85
|
+
fact = await store.get(fact_id=fact.id)
|
|
86
|
+
results = await store.search(query="preferences", user_id="alice")
|
|
87
|
+
updated = await store.update(fact_id=fact.id, content="prefers light mode")
|
|
88
|
+
all_facts = await store.get_all(user_id="alice")
|
|
89
|
+
await store.delete(fact_id=fact.id)
|
|
90
|
+
await store.delete_all(user_id="alice")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### HistoryStore
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
await store.add(session_id="s1", messages=[Message(role="user", content="hello")])
|
|
97
|
+
messages = await store.get(session_id="s1", limit=50)
|
|
98
|
+
results = await store.search(session_id="s1", query="hello")
|
|
99
|
+
sessions = await store.get_all(user_id="alice")
|
|
100
|
+
await store.delete(session_id="s1")
|
|
101
|
+
await store.delete_all(user_id="alice")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### DocumentStore
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
doc = await store.add(content="some text", metadata={"source": "wiki"})
|
|
108
|
+
doc = await store.get(doc_id=doc.id)
|
|
109
|
+
results = await store.search(query="text", limit=10)
|
|
110
|
+
all_docs = await store.get_all(limit=100)
|
|
111
|
+
updated = await store.update(doc_id=doc.id, content="updated text")
|
|
112
|
+
await store.delete(doc_id=doc.id)
|
|
113
|
+
await store.delete_all()
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### GraphStore
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from memio import Triple
|
|
120
|
+
|
|
121
|
+
await store.add(
|
|
122
|
+
triples=[Triple(subject="Alice", predicate="likes", object="coffee")],
|
|
123
|
+
user_id="alice",
|
|
124
|
+
)
|
|
125
|
+
result = await store.get(entity="Alice", user_id="alice")
|
|
126
|
+
result = await store.search(query="coffee", user_id="alice")
|
|
127
|
+
await store.delete_all(user_id="alice")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Data models
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from memio import Fact, Message, Document, Triple, GraphResult
|
|
134
|
+
|
|
135
|
+
# Fact — a stored piece of knowledge
|
|
136
|
+
Fact(id, content, user_id, agent_id, metadata, score, created_at, updated_at)
|
|
137
|
+
|
|
138
|
+
# Message — a conversation message
|
|
139
|
+
Message(role, content, metadata, timestamp, name)
|
|
140
|
+
|
|
141
|
+
# Document — a stored document
|
|
142
|
+
Document(id, content, metadata, score, created_at, updated_at)
|
|
143
|
+
|
|
144
|
+
# Triple — a knowledge graph triple
|
|
145
|
+
Triple(subject, predicate, object, metadata)
|
|
146
|
+
|
|
147
|
+
# GraphResult — result from graph queries
|
|
148
|
+
GraphResult(triples, nodes, scores)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Custom providers
|
|
152
|
+
|
|
153
|
+
Implement any protocol to create your own provider:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
from memio import Memio, DocumentStore, Document
|
|
157
|
+
|
|
158
|
+
class MyDocumentStore:
|
|
159
|
+
async def add(self, *, content, doc_id=None, metadata=None):
|
|
160
|
+
# your implementation
|
|
161
|
+
return Document(id="...", content=content, metadata=metadata)
|
|
162
|
+
|
|
163
|
+
async def get(self, *, doc_id):
|
|
164
|
+
...
|
|
165
|
+
|
|
166
|
+
async def search(self, *, query, limit=10, filters=None):
|
|
167
|
+
...
|
|
168
|
+
|
|
169
|
+
async def update(self, *, doc_id, content, metadata=None):
|
|
170
|
+
...
|
|
171
|
+
|
|
172
|
+
async def delete(self, *, doc_id):
|
|
173
|
+
...
|
|
174
|
+
|
|
175
|
+
async def get_all(self, *, limit=100, filters=None):
|
|
176
|
+
...
|
|
177
|
+
|
|
178
|
+
async def delete_all(self):
|
|
179
|
+
...
|
|
180
|
+
|
|
181
|
+
# memio validates the protocol at runtime
|
|
182
|
+
client = Memio(documents=MyDocumentStore())
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Error handling
|
|
186
|
+
|
|
187
|
+
All provider errors are wrapped in `ProviderError`:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from memio import ProviderError, MemioError
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
await client.facts.search(query="test", user_id="alice")
|
|
194
|
+
except ProviderError as e:
|
|
195
|
+
print(e.provider) # "mem0", "zep", etc.
|
|
196
|
+
print(e.operation) # "search", "add", etc.
|
|
197
|
+
print(e.cause) # original exception
|
|
198
|
+
except MemioError:
|
|
199
|
+
# base class for all memio errors
|
|
200
|
+
...
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Provider notes
|
|
204
|
+
|
|
205
|
+
**Mem0** — content may be rephrased by Mem0's LLM. Duplicate content is deduplicated automatically.
|
|
206
|
+
|
|
207
|
+
**Zep** — graph operations are eventually consistent. `graph.add` sends text to an LLM for asynchronous fact extraction. Individual fact/triple deletion is not supported; use `delete_all` instead.
|
|
208
|
+
|
|
209
|
+
**Chroma** — uses a local client you provide. No API key required for ephemeral or persistent local usage.
|
|
210
|
+
|
|
211
|
+
## Development
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
git clone https://github.com/y3zai/memio.git
|
|
215
|
+
cd memio
|
|
216
|
+
python -m venv .venv && source .venv/bin/activate
|
|
217
|
+
pip install -e ".[all,dev]"
|
|
218
|
+
|
|
219
|
+
# Run unit tests
|
|
220
|
+
pytest
|
|
221
|
+
|
|
222
|
+
# Run integration tests (requires API keys)
|
|
223
|
+
MEM0_API_KEY=... ZEP_API_KEY=... pytest -m integration -v
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
memio is a unified memory gateway for AI agents. It lets you connect any
|
|
4
|
+
combination of memory providers behind a single client, so your agent code
|
|
5
|
+
never depends on a specific vendor SDK.
|
|
6
|
+
|
|
7
|
+
This page explains the design decisions that make that possible.
|
|
8
|
+
|
|
9
|
+
## Protocol-based design
|
|
10
|
+
|
|
11
|
+
memio defines four store **protocols** using Python's `@runtime_checkable`
|
|
12
|
+
`Protocol` from the `typing` module:
|
|
13
|
+
|
|
14
|
+
| Protocol | Purpose |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `FactStore` | Structured facts scoped to a user or agent |
|
|
17
|
+
| `HistoryStore` | Conversation message history grouped by session |
|
|
18
|
+
| `DocumentStore` | Documents with semantic search and metadata filtering |
|
|
19
|
+
| `GraphStore` | Knowledge graph triples (subject-predicate-object) |
|
|
20
|
+
|
|
21
|
+
Because these are protocols -- not base classes -- any class that provides the
|
|
22
|
+
right async methods satisfies the contract. No inheritance is required. The
|
|
23
|
+
`Memio` client validates each store with `isinstance()` at init time and raises
|
|
24
|
+
`TypeError` if the check fails.
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from memio import Memio
|
|
28
|
+
from memio.providers.mem0 import Mem0FactAdapter
|
|
29
|
+
|
|
30
|
+
# Mem0FactAdapter has no base class -- it just implements
|
|
31
|
+
# the same async methods that FactStore declares.
|
|
32
|
+
client = Memio(facts=Mem0FactAdapter(api_key="..."))
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## The adapter pattern
|
|
36
|
+
|
|
37
|
+
Each provider ships one or more **adapter** classes. An adapter translates
|
|
38
|
+
memio's protocol methods into the provider's own SDK calls and normalizes
|
|
39
|
+
responses into memio's data models:
|
|
40
|
+
|
|
41
|
+
| Model | Fields |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `Fact` | id, content, user_id, agent_id, metadata, score, created_at, updated_at |
|
|
44
|
+
| `Message` | role, content, metadata, timestamp, name |
|
|
45
|
+
| `Document` | id, content, metadata, score, created_at, updated_at |
|
|
46
|
+
| `Triple` | subject, predicate, object, metadata |
|
|
47
|
+
| `GraphResult` | triples, nodes, scores |
|
|
48
|
+
|
|
49
|
+
Your agent code works exclusively with these models. If you swap providers,
|
|
50
|
+
you change one import and one constructor call -- the rest of your code stays
|
|
51
|
+
the same.
|
|
52
|
+
|
|
53
|
+
## Architecture diagram
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
Your AI Agent
|
|
57
|
+
|
|
|
58
|
+
v
|
|
59
|
+
Memio Client
|
|
60
|
+
|
|
|
61
|
+
|-- facts -> Mem0FactAdapter -> Mem0 Cloud API
|
|
62
|
+
|-- history -> ZepHistoryAdapter -> Zep Cloud API
|
|
63
|
+
|-- documents -> ChromaDocumentAdapter -> Local Chroma
|
|
64
|
+
|-- graph -> ZepGraphAdapter -> Zep Cloud API
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Composability
|
|
68
|
+
|
|
69
|
+
You can mix providers freely. The `Memio` client accepts any combination of
|
|
70
|
+
stores -- use whichever provider is strongest for each memory type:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from memio import Memio
|
|
74
|
+
from memio.providers.mem0 import Mem0FactAdapter
|
|
75
|
+
from memio.providers.zep import ZepHistoryAdapter
|
|
76
|
+
from memio.providers.chroma import ChromaDocumentAdapter
|
|
77
|
+
|
|
78
|
+
import chromadb
|
|
79
|
+
|
|
80
|
+
client = Memio(
|
|
81
|
+
facts=Mem0FactAdapter(api_key="mem0-key"),
|
|
82
|
+
history=ZepHistoryAdapter(api_key="zep-key"),
|
|
83
|
+
documents=ChromaDocumentAdapter(
|
|
84
|
+
client=chromadb.PersistentClient(path="./chroma_data"),
|
|
85
|
+
collection_name="docs",
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
At least one store must be provided. Stores you do not need can be omitted --
|
|
91
|
+
accessing an omitted store attribute returns `None`.
|
|
92
|
+
|
|
93
|
+
### Provider support matrix
|
|
94
|
+
|
|
95
|
+
| Store | Mem0 | Zep | Chroma |
|
|
96
|
+
|---|---|---|---|
|
|
97
|
+
| FactStore | Mem0FactAdapter | ZepFactAdapter | -- |
|
|
98
|
+
| HistoryStore | -- | ZepHistoryAdapter | -- |
|
|
99
|
+
| DocumentStore | -- | -- | ChromaDocumentAdapter |
|
|
100
|
+
| GraphStore | Mem0GraphAdapter | ZepGraphAdapter | -- |
|
|
101
|
+
|
|
102
|
+
## Error handling
|
|
103
|
+
|
|
104
|
+
Every adapter wraps provider SDK exceptions in a single error type:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from memio.exceptions import ProviderError
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
fact = await client.facts.add(content="likes coffee", user_id="alice")
|
|
111
|
+
except ProviderError as e:
|
|
112
|
+
print(e.provider) # "mem0"
|
|
113
|
+
print(e.operation) # "add"
|
|
114
|
+
print(e.cause) # the original SDK exception
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`ProviderError` always carries three attributes:
|
|
118
|
+
|
|
119
|
+
- **`provider`** -- the name of the provider (`"mem0"`, `"zep"`, `"chroma"`).
|
|
120
|
+
- **`operation`** -- the protocol method that failed (`"add"`, `"search"`, etc.).
|
|
121
|
+
- **`cause`** -- the original exception from the provider SDK.
|
|
122
|
+
|
|
123
|
+
This means your error-handling code never needs to import provider-specific
|
|
124
|
+
exception types.
|
|
125
|
+
|
|
126
|
+
## Async-first
|
|
127
|
+
|
|
128
|
+
All store operations are `async`/`await`. Every method on every protocol is
|
|
129
|
+
declared `async def`, and every adapter implements them as coroutines:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# Every call goes through await
|
|
133
|
+
fact = await client.facts.add(content="likes coffee", user_id="alice")
|
|
134
|
+
results = await client.facts.search(query="coffee", user_id="alice")
|
|
135
|
+
await client.facts.delete(fact_id=fact.id)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
This makes memio a natural fit for async frameworks, LLM tool-calling loops,
|
|
139
|
+
and any agent runtime that uses `asyncio`.
|
|
140
|
+
|
|
141
|
+
## Multi-tenancy
|
|
142
|
+
|
|
143
|
+
`FactStore` and `GraphStore` support **`user_id`** and **`agent_id`**
|
|
144
|
+
parameters for scoped data access. This lets a single memio deployment serve
|
|
145
|
+
multiple users or agents without data leaking across boundaries:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
# Facts scoped to a specific user
|
|
149
|
+
await client.facts.add(
|
|
150
|
+
content="prefers dark mode",
|
|
151
|
+
user_id="alice",
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Search only returns facts for this user
|
|
155
|
+
results = await client.facts.search(
|
|
156
|
+
query="UI preferences",
|
|
157
|
+
user_id="alice",
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# Graph triples scoped to a user
|
|
161
|
+
await client.graph.add(
|
|
162
|
+
triples=[Triple(subject="Alice", predicate="works_at", object="Acme")],
|
|
163
|
+
user_id="alice",
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`HistoryStore` scopes data by **`session_id`**, with `get_all` accepting a
|
|
168
|
+
`user_id` to list all sessions for a given user.
|