memlayer-py 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Victor Sunday
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.
@@ -0,0 +1,430 @@
1
+ Metadata-Version: 2.4
2
+ Name: memlayer-py
3
+ Version: 0.1.0
4
+ Summary: Persistent memory for AI agents — one API key, your agent remembers everything.
5
+ Home-page: https://github.com/yourusername/memlayer
6
+ Author: Victor Sunday
7
+ Author-email: sunvictor567@gmail.com
8
+ License: MIT
9
+ Project-URL: Documentation, https://memlayer.online/docs
10
+ Project-URL: Bug Tracker, https://github.com/yourusername/memlayer/issues
11
+ Project-URL: Homepage, https://memlayer.online
12
+ Keywords: ai agent memory vector search langchain langgraph memlayer persistent memory
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Intended Audience :: Developers
22
+ Classifier: Development Status :: 4 - Beta
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: httpx>=0.27.0
27
+ Dynamic: author
28
+ Dynamic: author-email
29
+ Dynamic: classifier
30
+ Dynamic: description
31
+ Dynamic: description-content-type
32
+ Dynamic: home-page
33
+ Dynamic: keywords
34
+ Dynamic: license
35
+ Dynamic: license-file
36
+ Dynamic: project-url
37
+ Dynamic: requires-dist
38
+ Dynamic: requires-python
39
+ Dynamic: summary
40
+
41
+ # memlayer-py
42
+
43
+ > Persistent memory for AI agents. One API key. Your agent remembers everything.
44
+
45
+ [![PyPI version](https://badge.fury.io/py/memlayer-py.svg)](https://badge.fury.io/py/memlayer-py)
46
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
47
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
48
+
49
+ ---
50
+
51
+ ## The Problem
52
+
53
+ Every time a user starts a new conversation with your AI agent, it starts from zero. It doesn't remember their name, their preferences, what they complained about last week, or anything they've ever told it. You're either stuffing conversation history into the system prompt and hitting token limits, or your agent is asking the same questions over and over.
54
+
55
+ **MemLayer fixes that.**
56
+
57
+ ---
58
+
59
+ ## Install
60
+
61
+ ```bash
62
+ pip install memlayer-py
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Quick Start
68
+
69
+ ```python
70
+ from memlayer import MemLayerClient
71
+
72
+ client = MemLayerClient(
73
+ api_key="ml_live_xxx",
74
+ base_url="https://memlayer.online",
75
+ )
76
+
77
+ # Store what your agent learns
78
+ client.remember(
79
+ "User prefers concise bullet points over long paragraphs",
80
+ user_id="user_123",
81
+ agent_id="support_bot",
82
+ memory_type="semantic",
83
+ importance=0.8,
84
+ )
85
+
86
+ # Load context at the start of every session
87
+ context = client.context(user_id="user_123", agent_id="support_bot")
88
+ for m in context.memories:
89
+ print(m.content)
90
+
91
+ # Search when the user asks something
92
+ memories = client.recall(
93
+ "what are this user's communication preferences?",
94
+ user_id="user_123",
95
+ agent_id="support_bot",
96
+ )
97
+ for m in memories:
98
+ print(f"[{m.score:.3f}] {m.content}")
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Get an API Key
104
+
105
+ 1. Visit [memlayer.online](https://memlayer.online)
106
+ 2. Sign up for a free account
107
+ 3. Copy your API key (`ml_live_xxx`)
108
+
109
+ Free plan includes 500 memories and 100 requests per day — enough to build and test your agent fully.
110
+
111
+ ---
112
+
113
+ ## Core Methods
114
+
115
+ ### `remember()` — Store a memory
116
+
117
+ ```python
118
+ result = client.remember(
119
+ content="User is based in Lagos, Nigeria",
120
+ user_id="user_123",
121
+ agent_id="support_bot",
122
+ memory_type="semantic", # episodic | semantic | summary
123
+ importance=0.8, # 0.0 (low) to 1.0 (high)
124
+ ttl_days=30, # auto-expire after 30 days. None = permanent
125
+ )
126
+
127
+ print(result.id) # memory UUID
128
+ print(result.is_duplicate) # True if already stored
129
+ ```
130
+
131
+ ### `recall()` — Semantic search
132
+
133
+ ```python
134
+ memories = client.recall(
135
+ query="what does this user prefer?",
136
+ user_id="user_123",
137
+ agent_id="support_bot",
138
+ top_k=5, # return top 5 results
139
+ min_score=0.70, # minimum relevance threshold
140
+ )
141
+
142
+ for m in memories:
143
+ print(m.content) # memory text
144
+ print(m.score) # hybrid relevance score
145
+ print(m.importance) # importance weight
146
+ print(m.memory_type) # episodic | semantic | summary
147
+ ```
148
+
149
+ Retrieval uses hybrid scoring — **70% semantic similarity + 20% recency + 10% importance** — so the most relevant and recent memories always rank first.
150
+
151
+ ### `context()` — Load session context
152
+
153
+ ```python
154
+ # Call this at the start of every conversation
155
+ context = client.context(
156
+ user_id="user_123",
157
+ agent_id="support_bot",
158
+ top_k=10,
159
+
160
+ # Optional: pass the user's first message for smarter retrieval
161
+ current_message="I need help with my order",
162
+ )
163
+
164
+ # Inject into your system prompt
165
+ system_prompt = "You are a helpful assistant.\n\nWhat you know about this user:\n"
166
+ for m in context.memories:
167
+ system_prompt += f"- {m.content}\n"
168
+ ```
169
+
170
+ ### `update()` — Update a memory
171
+
172
+ ```python
173
+ # User moved cities — update the old memory in place
174
+ updated = client.update(
175
+ memory_id="775263ee-73af-4416-9804-1f274048ae08",
176
+ user_id="user_123",
177
+ agent_id="support_bot",
178
+ new_content="User moved from Lagos to Abuja, Nigeria",
179
+ importance=0.95,
180
+ )
181
+
182
+ print(updated.content) # "User moved from Lagos to Abuja, Nigeria"
183
+ ```
184
+
185
+ Same memory ID — just new content and a fresh embedding. No duplicate memories.
186
+
187
+ ### `forget()` — Delete one memory
188
+
189
+ ```python
190
+ result = client.forget(
191
+ memory_id="775263ee-73af-4416-9804-1f274048ae08",
192
+ user_id="user_123",
193
+ agent_id="support_bot",
194
+ )
195
+ print(result.deleted) # 1
196
+ ```
197
+
198
+ ### `forget_all()` — Wipe all memories
199
+
200
+ ```python
201
+ # Use for GDPR requests or account resets
202
+ result = client.forget_all(user_id="user_123", agent_id="support_bot")
203
+ print(result.deleted) # number of memories deleted
204
+ ```
205
+
206
+ ### `is_duplicate()` — Check before storing
207
+
208
+ ```python
209
+ # Optional — remember() already checks internally
210
+ # Use this when you want to check without committing to store
211
+ already_known = client.is_duplicate(
212
+ content="User is based in Lagos",
213
+ user_id="user_123",
214
+ agent_id="support_bot",
215
+ threshold=0.95,
216
+ )
217
+
218
+ if not already_known:
219
+ client.remember("User is based in Lagos", user_id="user_123", agent_id="support_bot")
220
+ ```
221
+
222
+ ### `list()` — Browse all memories
223
+
224
+ ```python
225
+ # Paginate through all stored memories
226
+ page = client.list(
227
+ user_id="user_123",
228
+ agent_id="support_bot",
229
+ limit=20,
230
+ offset=0,
231
+ )
232
+
233
+ print(f"Total: {page.total}")
234
+ for m in page.memories:
235
+ print(m.content, m.created_at)
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Memory Types
241
+
242
+ | Type | Use For | Example |
243
+ |---|---|---|
244
+ | `episodic` | Things that happened | "User complained about slow delivery" |
245
+ | `semantic` | Facts about the user | "User is based in Lagos, Nigeria" |
246
+ | `summary` | Compressed older memories | Auto-generated by MemLayer |
247
+
248
+ ---
249
+
250
+ ## Async Support
251
+
252
+ For LangGraph, FastAPI, and any async application:
253
+
254
+ ```python
255
+ from memlayer import AsyncMemLayerClient
256
+
257
+ async def main():
258
+ async with AsyncMemLayerClient(api_key="ml_live_xxx") as client:
259
+
260
+ # Store
261
+ result = await client.remember(
262
+ "User prefers dark mode",
263
+ user_id="user_123",
264
+ agent_id="support_bot",
265
+ )
266
+
267
+ # Search
268
+ memories = await client.recall(
269
+ "UI preferences",
270
+ user_id="user_123",
271
+ agent_id="support_bot",
272
+ )
273
+ ```
274
+
275
+ ---
276
+
277
+ ## LangGraph Integration
278
+
279
+ Drop MemLayer into any LangGraph graph as store and retrieve nodes:
280
+
281
+ ```python
282
+ from memlayer import AsyncMemLayerClient
283
+ from langgraph.graph import StateGraph, MessagesState
284
+
285
+ maas = AsyncMemLayerClient(api_key="ml_live_xxx")
286
+
287
+
288
+ async def load_memory(state: MessagesState):
289
+ """Load relevant memories before the agent responds."""
290
+ last_message = state["messages"][-1].content
291
+
292
+ memories = await maas.recall(
293
+ query=last_message,
294
+ user_id=state["user_id"],
295
+ agent_id="my_agent",
296
+ top_k=5,
297
+ )
298
+
299
+ memory_context = "\n".join(f"- {m.content}" for m in memories)
300
+ state["memory_context"] = memory_context
301
+ return state
302
+
303
+
304
+ async def save_memory(state: MessagesState):
305
+ """Save what the agent learned after responding."""
306
+ last_message = state["messages"][-1].content
307
+
308
+ await maas.remember(
309
+ content=last_message,
310
+ user_id=state["user_id"],
311
+ agent_id="my_agent",
312
+ memory_type="episodic",
313
+ )
314
+ return state
315
+
316
+
317
+ # Wire into your graph
318
+ builder = StateGraph(MessagesState)
319
+ builder.add_node("load_memory", load_memory)
320
+ builder.add_node("agent", your_agent_node)
321
+ builder.add_node("save_memory", save_memory)
322
+
323
+ builder.add_edge("load_memory", "agent")
324
+ builder.add_edge("agent", "save_memory")
325
+ ```
326
+
327
+ ---
328
+
329
+ ## Error Handling
330
+
331
+ ```python
332
+ from memlayer import (
333
+ MemLayerClient,
334
+ AuthenticationError,
335
+ PlanLimitError,
336
+ MemoryNotFoundError,
337
+ DuplicateMemoryError,
338
+ MemLayerError,
339
+ )
340
+
341
+ client = MemLayerClient(api_key="ml_live_xxx")
342
+
343
+ try:
344
+ result = client.remember(
345
+ "User prefers dark mode",
346
+ user_id="user_123",
347
+ agent_id="support_bot",
348
+ )
349
+
350
+ except AuthenticationError:
351
+ print("Invalid API key — check your ml_live_xxx key")
352
+
353
+ except PlanLimitError:
354
+ print("Memory limit reached — upgrade your plan at memlayer.online")
355
+
356
+ except DuplicateMemoryError:
357
+ print("This memory already exists — skipped")
358
+
359
+ except MemoryNotFoundError:
360
+ print("Memory ID not found")
361
+
362
+ except MemLayerError as e:
363
+ print(f"API error {e.status_code}: {e.detail}")
364
+ ```
365
+
366
+ ---
367
+
368
+ ## Context Manager
369
+
370
+ ```python
371
+ # Sync
372
+ with MemLayerClient(api_key="ml_live_xxx") as client:
373
+ client.remember("something", user_id="u1", agent_id="bot")
374
+
375
+ # Async
376
+ async with AsyncMemLayerClient(api_key="ml_live_xxx") as client:
377
+ await client.remember("something", user_id="u1", agent_id="bot")
378
+ ```
379
+
380
+ ---
381
+
382
+ ## Pricing
383
+
384
+ | Plan | Memories | Requests/day | Price |
385
+ |---|---|---|---|
386
+ | Free | 500 | 100 | $0/mo |
387
+ | Pro | 50,000 | 10,000 | $19/mo |
388
+ | Enterprise | Unlimited | Unlimited | $99+/mo |
389
+
390
+ Enterprise includes BYOD (Bring Your Own Database) — your data never leaves your Supabase instance.
391
+
392
+ ---
393
+
394
+ ## REST API
395
+
396
+ You don't need the SDK — every method maps to a REST endpoint:
397
+
398
+ ```bash
399
+ # Store
400
+ curl -X POST https://memlayer.online/memories \
401
+ -H "X-API-Key: ml_live_xxx" \
402
+ -H "Content-Type: application/json" \
403
+ -d '{"content": "User prefers dark mode", "user_id": "u1", "agent_id": "bot"}'
404
+
405
+ # Search
406
+ curl "https://memlayer.online/memories/search?query=preferences&user_id=u1&agent_id=bot" \
407
+ -H "X-API-Key: ml_live_xxx"
408
+
409
+ # Context
410
+ curl "https://memlayer.online/memories/context?user_id=u1&agent_id=bot" \
411
+ -H "X-API-Key: ml_live_xxx"
412
+ ```
413
+
414
+ Full API reference at [memlayer.online/docs](https://memlayer.online/docs).
415
+
416
+ ---
417
+
418
+ ## Links
419
+
420
+ - [Website](https://memlayer.online)
421
+ - [API Docs](https://memlayer.online/docs)
422
+ - [GitHub](https://github.com/yourusername/memlayer)
423
+ - [Report a Bug](https://github.com/yourusername/memlayer/issues)
424
+ - [Email](mailto:support@memlayer.online)
425
+
426
+ ---
427
+
428
+ ## License
429
+
430
+ MIT — see [LICENSE](LICENSE) for details.