Metadata-Version: 2.4
Name: memorylayer-py
Version: 1.1.0
Summary: Privacy-first memory API for LLMs
Author-email: "rec0.ai" <hello@rec0.ai>
License: MIT
Project-URL: Homepage, https://rec0.ai
Project-URL: Documentation, https://docs.rec0.ai
Project-URL: Repository, https://github.com/rec0ai/rec0-python
Project-URL: Bug Tracker, https://github.com/rec0ai/rec0-python/issues
Keywords: llm,memory,ai,privacy,rag
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28.0
Requires-Dist: httpx>=0.24.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: responses>=0.25.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"

# rec0 — memory for any LLM

> Give your AI a permanent memory in 3 lines of code.

[![PyPI version](https://img.shields.io/pypi/v/rec0.svg)](https://pypi.org/project/rec0/)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://python.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

## Install

**Python:**
```bash
pip install rec0
```

**JavaScript / TypeScript:**
```bash
npm install @rec0ai/rec0
```

> See the [JavaScript SDK docs](https://www.npmjs.com/package/@rec0ai/rec0) for JS/TS usage.

## Quickstart

```python
from rec0 import Memory

# Works immediately - connects to production API
mem = Memory(
    api_key="r0_live_sk_...",  # Get your key at https://rec0.vercel.app
    user_id="user_123"
)

mem.store("User prefers dark mode")
results = mem.recall("user preferences")
print(results)
```

That's it. `context` returns a bullet-list string ready to prepend to any system prompt.

## Custom API Endpoint

The SDK defaults to the production API at `https://memorylayer-production.up.railway.app`.

For development or self-hosted instances:

```python
from rec0 import Memory

mem = Memory(
    api_key="r0_dev_...",
    user_id="user_123",
    base_url="http://localhost:8000"  # Development server
)
```

---

## Why rec0

| | rec0 | Mem0 |
|---|---|---|
| **Privacy** | Data never leaves your servers | Processed externally |
| **Cost** | $0.002 / 1K ops | ~$0.10 / 1K ops |
| **Setup** | 3 lines | OAuth + config |
| **LLM support** | Any model | OpenAI-first |
| **GDPR** | 1 API call | Manual |

- **Privacy-first:** embeddings and summaries run on YOUR infrastructure — no user data touches third-party APIs
- **LLM-agnostic:** works with OpenAI, Anthropic, Gemini, Llama, Mistral — anything that takes a string
- **Memory lifecycle:** automatic importance scoring, recall-count boosting, and time-based decay
- **GDPR compliant:** right-to-erasure in one call (`mem.delete_user()`)

---

## Multi-app isolation with app_id

`app_id` is a free-text namespace string (default `"default"`). Memories are isolated per **(user_id, app_id)** pair — recall and list only return memories matching the exact `app_id` you query with.

Use this when one account runs multiple products, bots, or environments and you need their memories to be fully isolated:

```python
from rec0 import Memory

# Slack bot — isolated namespace
mem_slack = Memory(user_id="user_123", app_id="slack-bot", api_key=key)
mem_slack.store("Prefers Slack DMs over channel mentions")

# Website chat — completely separate namespace
mem_web = Memory(user_id="user_123", app_id="website-chat", api_key=key)
mem_web.store("Browses on mobile primarily")

# These never appear in each other's recall() results
slack_results = mem_slack.recall("communication preferences")  # no website memories
web_results   = mem_web.recall("device preferences")          # no slack memories
```

See the [full multi-tenancy guide](https://rec0.ai/docs/api-reference#multitenancy) for more detail.

---

## Full API reference

### `Memory(user_id, api_key, app_id, base_url)`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `user_id` | `str` | required | Your end-user identifier |
| `api_key` | `str` | `$REC0_API_KEY` | Your rec0 API key |
| `app_id` | `str` | `"default"` | Namespace for multi-app isolation |
| `base_url` | `str` | prod URL | Override for self-hosting |

### Methods

#### `mem.store(content)` → `MemoryObject`
Store a new memory. Auto-generates embedding and summary server-side.

```python
m = mem.store("User is building a SaaS product in Python")
print(m.id)          # UUID
print(m.importance)  # starts at 1.0, increases with each recall
```

#### `mem.context(query, limit=25)` → `str`
**The most-used method.** Returns a bullet-list string to inject into your LLM prompt.

```python
context = mem.context("what does the user like", limit=25)
# "- User prefers Python and dark mode\n- User is building a SaaS product"

# Typical usage with OpenAI:
messages = [
    {"role": "system", "content": f"User context:\n{context}"},
    {"role": "user", "content": user_message},
]
```

#### `mem.recall(query, limit=25)` → `List[MemoryObject]`
Returns memories ranked by semantic similarity. Use when you need scores or metadata.

```python
memories = mem.recall("programming preferences", limit=3)  # limit=25 default
for m in memories:
    print(f"{m.content}  (score: {m.relevance_score})")
```

#### `mem.list(limit=20, offset=0)` → `List[MemoryObject]`
All active memories for this user, ordered by creation time. Supports pagination.

```python
page1 = mem.list(limit=20, offset=0)
page2 = mem.list(limit=20, offset=20)
```

#### `mem.delete(memory_id)` → `None`
Soft-delete a specific memory (retained for audit trail).

#### `mem.delete_user(permanent=False)` → `dict`
GDPR right-to-erasure. Removes all memories for this user.

```python
# Soft-delete (recoverable, default)
mem.delete_user()

# Hard-delete — irreversible, destroys all memory rows permanently
mem.delete_user(permanent=True)
```

> **Warning:** `permanent=True` cannot be undone.

#### `mem.export()` → `dict`
GDPR data export. Returns all memory data as a dictionary.

#### `mem.ping()` → `bool`
Connectivity check. Returns `True` if the API is reachable.

```python
if not mem.ping():
    print("rec0 API unreachable — check your key")
```

---

## Error handling

```python
from rec0 import Memory, Rec0Error, AuthError, RateLimitError, NotFoundError

mem = Memory(api_key="r0_xxx", user_id="user_123")

try:
    mem.store("User loves rec0")
except AuthError:
    print("Invalid API key — check REC0_API_KEY")
except RateLimitError as e:
    print(f"Rate limited — retry in {e.retry_after}s")
except NotFoundError:
    print("Memory not found")
except Rec0Error as e:
    print(f"Unexpected error: {e}")
```

Rate limits are handled automatically: rec0 will wait `retry_after` seconds and retry once before raising.

---

## Async usage

Every method has an async equivalent via `AsyncMemory`:

```python
import asyncio
from rec0 import AsyncMemory

async def main():
    mem = AsyncMemory(api_key="r0_xxx", user_id="user_123")
    await mem.store("User is a night-owl developer")
    context = await mem.context("when does the user work")
    print(context)

asyncio.run(main())
```

`AsyncMemory` uses `httpx` under the hood and is safe to use in FastAPI, Django async views, and any `asyncio` application.

---

## Environment variables

| Variable | Description |
|---|---|
| `REC0_API_KEY` | Your rec0 API key (used automatically if `api_key=` not passed) |
| `REC0_BASE_URL` | Override the API base URL (optional, for self-hosting) |

```bash
export REC0_API_KEY=r0_your_key_here
```

```python
# api_key is now auto-loaded — no need to hardcode it
mem = Memory(user_id="user_123")
```

---

## MemoryObject fields

| Field | Type | Description |
|---|---|---|
| `id` | `str` | UUID |
| `content` | `str` | The original memory text |
| `summary` | `str \| None` | Auto-generated summary |
| `importance` | `float` | 1.0–3.0; increases ~5% per recall (capped at 3.0×), updated asynchronously |
| `recall_count` | `int` | Times this memory was recalled |
| `relevance_score` | `float \| None` | Similarity score (recall only) |
| `created_at` | `datetime` | When stored |
| `is_active` | `bool` | False if deleted |

---

## Self-hosting

rec0 is open-source. Deploy your own instance on Railway, Fly, or any server:

```bash
git clone https://github.com/patelyash2511/memorylayer
# See README for Railway deployment instructions
```

Then point the SDK at your instance:

```python
mem = Memory(
    api_key="your_key",
    user_id="user_123",
    base_url="https://your-instance.up.railway.app",
)
```

---

[rec0.vercel.app](https://rec0.vercel.app) · [npm](https://www.npmjs.com/package/@rec0ai/rec0) · [PyPI](https://pypi.org/project/rec0/)
