Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d6bac1af6 | ||
|
|
443895110b | ||
|
|
8af9cc5793 | ||
|
|
74570ead11 | ||
|
|
5020fa1a0d | ||
|
|
3ea7cc82cd | ||
|
|
fdfb763d6e |
@@ -1,6 +1,8 @@
|
||||
# Mem0 Python SDK
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/mem0ai/mem0">
|
||||
<img src="docs/images/banner-sm.png" width="800px" alt="Mem0 - The Memory Layer for Personalized AI">
|
||||
<img src="docs/images/banner-sm.png" width="800px" alt="Mem0, the memory layer for personalized AI">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center" style="display: flex; justify-content: center; gap: 20px; align-items: center;">
|
||||
@@ -22,166 +24,187 @@
|
||||
<img src="https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white" alt="Mem0 Discord">
|
||||
</a>
|
||||
<a href="https://pepy.tech/project/mem0ai">
|
||||
<img src="https://img.shields.io/pypi/dm/mem0ai" alt="Mem0 PyPI - Downloads">
|
||||
<img src="https://img.shields.io/pypi/dm/mem0ai" alt="Mem0 PyPI downloads">
|
||||
</a>
|
||||
<a href="https://github.com/mem0ai/mem0">
|
||||
<img src="https://img.shields.io/github/commit-activity/m/mem0ai/mem0?style=flat-square" alt="GitHub commit activity">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/mem0ai" target="blank">
|
||||
<img src="https://img.shields.io/pypi/v/mem0ai?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/mem0ai" target="blank">
|
||||
<img src="https://img.shields.io/npm/v/mem0ai" alt="Npm package">
|
||||
<img src="https://img.shields.io/pypi/v/mem0ai?color=%2334D058&label=pypi%20package" alt="PyPI package version">
|
||||
</a>
|
||||
<a href="https://www.ycombinator.com/companies/mem0">
|
||||
<img src="https://img.shields.io/badge/Y%20Combinator-S24-orange?style=flat-square" alt="Y Combinator S24">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://mem0.ai/research"><strong>📄 Benchmarking Mem0's token-efficient memory algorithm →</strong></a>
|
||||
</p>
|
||||
Mem0 gives AI assistants and agents persistent memory. It extracts useful facts from conversations, scopes them to a user, agent, or run, and retrieves the relevant facts for later interactions. The Python package includes `MemoryClient` for the hosted Mem0 Platform and `Memory` for open-source, in-process memory.
|
||||
|
||||
## New Memory Algorithm (April 2026)
|
||||
## Requirements
|
||||
|
||||
| Benchmark | Old | New | Tokens | Latency p50 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| **LoCoMo** | 71.4 | **92.5** | 7.0K | 0.88s |
|
||||
| **LongMemEval** | 67.8 | **94.4** | 6.8K | 1.09s |
|
||||
| **BEAM (1M)** | — | **64.1** | 6.7K | 1.00s |
|
||||
| **BEAM (10M)** | — | **48.6** | 6.9K | 1.05s |
|
||||
- Python 3.10 or later
|
||||
- Hosted Platform: `MEM0_API_KEY` from the [Mem0 dashboard](https://app.mem0.ai/dashboard/api-keys)
|
||||
- Open source with the default providers: `OPENAI_API_KEY`
|
||||
|
||||
All benchmarks run on the same production-representative model stack. Single-pass retrieval (one call, no agentic loops) at a top_200 retrieval budget. Scores reflect Mem0's managed platform, which includes proprietary optimizations not available in the open-source SDK; open-source users should expect directionally similar gains but not identical numbers.
|
||||
|
||||
**What changed:**
|
||||
- **Single-pass ADD-only extraction** -- one LLM call, no UPDATE/DELETE. Memories accumulate; nothing is overwritten.
|
||||
- **Agent-generated facts are first-class** -- when an agent confirms an action, that information is now stored with equal weight.
|
||||
- **Entity linking** -- entities are extracted, embedded, and linked across memories for retrieval boosting.
|
||||
- **Multi-signal retrieval** -- semantic, BM25 keyword, and entity matching scored in parallel and fused.
|
||||
- **Temporal Reasoning** -- time-aware retrieval that ranks the right dated instance for queries about current state, past events, and upcoming plans.
|
||||
|
||||
See the [migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for upgrade instructions. The [evaluation framework](https://github.com/mem0ai/memory-benchmarks) is open-sourced so anyone can reproduce the numbers.
|
||||
|
||||
## Research Highlights
|
||||
- **92.5 on LoCoMo** -- +21 points over the previous algorithm
|
||||
- **94.4 on LongMemEval** -- +27 points, with 98.2 on assistant memory recall
|
||||
- **64.1 on BEAM (1M)** -- production-scale memory evaluation at 1M tokens
|
||||
- [Read the full paper](https://mem0.ai/research)
|
||||
|
||||
# Introduction
|
||||
|
||||
[Mem0](https://mem0.ai) ("mem-zero") enhances AI assistants and agents with an intelligent memory layer, enabling personalized AI interactions. It remembers user preferences, adapts to individual needs, and continuously learns over time—ideal for customer support chatbots, AI assistants, and autonomous systems.
|
||||
|
||||
### Key Features & Use Cases
|
||||
|
||||
**Core Capabilities:**
|
||||
- **Multi-Level Memory**: Seamlessly retains User, Session, and Agent state with adaptive personalization
|
||||
- **Developer-Friendly**: Intuitive API, cross-platform SDKs, and a fully managed service option
|
||||
|
||||
**Applications:**
|
||||
- **AI Assistants**: Consistent, context-rich conversations
|
||||
- **Customer Support**: Recall past tickets and user history for tailored help
|
||||
- **Healthcare**: Track patient preferences and history for personalized care
|
||||
- **Productivity & Gaming**: Adaptive workflows and environments based on user behavior
|
||||
|
||||
## 🚀 Quickstart Guide <a name="quickstart"></a>
|
||||
|
||||
### Sign up as an agent
|
||||
|
||||
AI agents can mint a working Mem0 API key in under five seconds — no email, no dashboard, no OTP. Four commands end-to-end:
|
||||
|
||||
```bash
|
||||
# 1. Install
|
||||
npm install -g @mem0/cli # or: pip install mem0-cli
|
||||
|
||||
# 2. Sign up as an agent (replace `claude-code` with your name)
|
||||
mem0 init --agent --agent-caller claude-code
|
||||
|
||||
# 3. Add a memory
|
||||
mem0 add "I am using mem0"
|
||||
|
||||
# 4. Search
|
||||
mem0 search "am I using mem0"
|
||||
```
|
||||
|
||||
The human owner can claim the account later with `mem0 init --email <their-email>` — same key, memories preserved. Full guide: [Sign up as an agent](https://docs.mem0.ai/platform/agent-signup).
|
||||
|
||||
| | Library | Self-Hosted Server | Cloud Platform |
|
||||
|---|---------|-------------------|----------------|
|
||||
| **Best for** | Testing, prototyping | Teams running on their own infrastructure | Zero-ops production use |
|
||||
| **Setup** | `pip install mem0ai` | `docker compose up` | Sign up at [app.mem0.ai](https://app.mem0.ai?utm_source=oss&utm_medium=readme) |
|
||||
| **Dashboard** | -- | [Yes](https://docs.mem0.ai/open-source/setup) | Yes |
|
||||
| **Auth & API Keys** | -- | Yes | Yes |
|
||||
| **Advanced Features** | -- | Teasers | All included |
|
||||
|
||||
Just testing? Use the library. Building for a team? Self-hosted. Want zero ops? Cloud.
|
||||
|
||||
### Library (pip / npm)
|
||||
## Install
|
||||
|
||||
```bash
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
For enhanced hybrid search with BM25 keyword matching and entity extraction, install with NLP support:
|
||||
For enhanced hybrid search with BM25 keyword matching and entity extraction:
|
||||
|
||||
```bash
|
||||
pip install mem0ai[nlp]
|
||||
pip install "mem0ai[nlp]"
|
||||
python -m spacy download en_core_web_sm
|
||||
```
|
||||
|
||||
Install sdk via npm:
|
||||
## Platform or open source
|
||||
|
||||
```bash
|
||||
npm install mem0ai
|
||||
| | Platform (`MemoryClient`) | Open source (`Memory`) |
|
||||
|---|---|---|
|
||||
| Import | `from mem0 import MemoryClient` | `from mem0 import Memory` |
|
||||
| Where memories live | Mem0's hosted API | Your configured vector store |
|
||||
| Required key | `MEM0_API_KEY` | `OPENAI_API_KEY` with the defaults, or keys for your chosen providers |
|
||||
| Extraction | Managed and asynchronous | Runs synchronously against your configured LLM |
|
||||
| Best for | Zero-ops production use | Local development and custom infrastructure |
|
||||
|
||||
## Platform quickstart
|
||||
|
||||
Set `MEM0_API_KEY`, then add a conversation:
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key=os.environ["MEM0_API_KEY"])
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "I am vegetarian and allergic to nuts."},
|
||||
{"role": "assistant", "content": "I will remember that."},
|
||||
]
|
||||
result = client.add(messages, user_id="alex")
|
||||
print(result)
|
||||
```
|
||||
|
||||
### Self-Hosted Server
|
||||
Hosted `add()` queues extraction and usually returns an `event_id` with `status: "PENDING"`. Do not search immediately after `add()`. Wait for processing to finish in the dashboard, or use a [`memory_add` webhook](https://docs.mem0.ai/platform/features/webhooks), then search:
|
||||
|
||||
> **Note:** Self-hosted auth is on by default. Upgrading from a pre-auth build? Set `ADMIN_API_KEY`, register an admin through the wizard, or `AUTH_DISABLED=true` for local dev only. See [upgrade notes](https://docs.mem0.ai/open-source/setup#upgrade-notes).
|
||||
```python
|
||||
import os
|
||||
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key=os.environ["MEM0_API_KEY"])
|
||||
results = client.search(
|
||||
"What does Alex eat?",
|
||||
filters={"user_id": "alex"},
|
||||
top_k=5,
|
||||
)
|
||||
print(results["results"])
|
||||
```
|
||||
|
||||
`search()` and `get_all()` take entity IDs inside `filters`. `add()` and `delete_all()` take `user_id`, `agent_id`, or `run_id` as top-level keyword arguments.
|
||||
|
||||
## Open-source quickstart
|
||||
|
||||
Set `OPENAI_API_KEY` before using the default OpenAI LLM and embedder:
|
||||
|
||||
```python
|
||||
from mem0 import Memory
|
||||
|
||||
memory = Memory()
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "I am vegetarian and allergic to nuts."},
|
||||
{"role": "assistant", "content": "I will remember that."},
|
||||
]
|
||||
memory.add(messages, user_id="alex")
|
||||
|
||||
results = memory.search(
|
||||
"What does Alex eat?",
|
||||
filters={"user_id": "alex"},
|
||||
top_k=5,
|
||||
)
|
||||
print(results["results"])
|
||||
```
|
||||
|
||||
The default `Memory` configuration uses OpenAI `gpt-5-mini`, OpenAI `text-embedding-3-small`, local Qdrant storage, and a SQLite history database. Pass a `MemoryConfig` or use `Memory.from_config()` to change the LLM, embedder, vector store, history path, or reranker.
|
||||
|
||||
## Configuration and features
|
||||
|
||||
| Feature | Documentation |
|
||||
|---|---|
|
||||
| Memory operations: `add`, `search`, `get`, `get_all`, `update`, `delete`, `delete_all`, `history` | [Python quickstart](https://docs.mem0.ai/open-source/python-quickstart) |
|
||||
| Entity scoping with `user_id`, `agent_id`, and `run_id` | [Entity-scoped memory](https://docs.mem0.ai/platform/features/entity-scoped-memory) |
|
||||
| Metadata and filters | [Metadata filtering](https://docs.mem0.ai/open-source/features/metadata-filtering) |
|
||||
| Async clients: `AsyncMemory` and `AsyncMemoryClient` | [Async memory](https://docs.mem0.ai/open-source/features/async-memory) |
|
||||
| LLMs, embedders, vector stores, and rerankers | [Components](https://docs.mem0.ai/components/llms/overview) |
|
||||
| Graph memory | [Graph memory](https://docs.mem0.ai/platform/features/graph-memory) |
|
||||
| Custom instructions | [Custom instructions](https://docs.mem0.ai/open-source/features/custom-instructions) |
|
||||
| Multimodal input | [Multimodal support](https://docs.mem0.ai/open-source/features/multimodal-support) |
|
||||
| Platform webhooks, export, feedback, expiration, and custom categories | [Platform features](https://docs.mem0.ai/platform/features) |
|
||||
|
||||
## Benchmarks
|
||||
|
||||
<p align="center">
|
||||
<a href="https://mem0.ai/research"><strong>Benchmarking Mem0's token-efficient memory algorithm</strong></a>
|
||||
</p>
|
||||
|
||||
| Benchmark | Old | New | Tokens | Latency p50 |
|
||||
|---|---:|---:|---:|---:|
|
||||
| **LoCoMo** | 71.4 | **92.5** | 7.0K | 0.88s |
|
||||
| **LongMemEval** | 67.8 | **94.4** | 6.8K | 1.09s |
|
||||
| **BEAM (1M)** | n/a | **64.1** | 6.7K | 1.00s |
|
||||
| **BEAM (10M)** | n/a | **48.6** | 6.9K | 1.05s |
|
||||
|
||||
All benchmarks use the same production-representative model stack, single-pass retrieval, and a top-200 retrieval budget. Scores reflect the managed Platform, which includes proprietary optimizations not available in the open-source SDK. Open-source results should show similar directional gains, but may not match these scores.
|
||||
|
||||
The current algorithm uses single-pass ADD-only extraction, first-class agent facts, entity linking, multi-signal retrieval, and temporal reasoning. Read the [research paper](https://mem0.ai/research), the [migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3), or the open-source [evaluation framework](https://github.com/mem0ai/memory-benchmarks).
|
||||
|
||||
## Self-hosted server
|
||||
|
||||
Run Mem0 as a FastAPI service with PostgreSQL, pgvector, and Neo4j:
|
||||
|
||||
```bash
|
||||
# Recommended: one command — start the stack, create an admin, issue the first API key.
|
||||
# Recommended: start the stack, create an admin, and issue the first API key.
|
||||
cd server && make bootstrap
|
||||
|
||||
# Manual: start the stack and finish setup via the browser wizard.
|
||||
cd server && docker compose up -d # http://localhost:3000
|
||||
# Manual: start the stack, then finish setup in the browser wizard.
|
||||
cd server && docker compose up -d
|
||||
```
|
||||
|
||||
See the [self-hosted docs](https://docs.mem0.ai/open-source/overview) for configuration.
|
||||
Self-hosted authentication is enabled by default. See the [self-hosted documentation](https://docs.mem0.ai/open-source/overview) and [upgrade notes](https://docs.mem0.ai/open-source/setup#upgrade-notes).
|
||||
|
||||
### Cloud Platform
|
||||
## CLI
|
||||
|
||||
1. Sign up on [Mem0 Platform](https://app.mem0.ai?utm_source=oss&utm_medium=readme)
|
||||
2. Embed the memory layer via SDK or API keys
|
||||
3. Using hosted Qdrant vectors? See the [Platform migration guide](https://docs.mem0.ai/migration/oss-to-platform) to import them into Mem0 Platform.
|
||||
|
||||
### CLI
|
||||
|
||||
Manage memories from your terminal:
|
||||
Manage hosted memories from your terminal:
|
||||
|
||||
```bash
|
||||
npm install -g @mem0/cli # or: pip install mem0-cli
|
||||
pip install mem0-cli
|
||||
|
||||
mem0 init
|
||||
mem0 add "Prefers dark mode and vim keybindings" --user-id alice
|
||||
mem0 search "What does Alice prefer?" --user-id alice
|
||||
```
|
||||
|
||||
See the [CLI documentation](https://docs.mem0.ai/platform/cli) for the full command reference.
|
||||
AI agents can create an account without email or a dashboard:
|
||||
|
||||
### Agent Skills
|
||||
```bash
|
||||
mem0 init --agent --agent-caller claude-code
|
||||
```
|
||||
|
||||
Teach your AI coding assistant (Claude Code, Codex, Cursor, Windsurf, OpenCode, OpenClaw, and any tool that supports the skills standard) how to build with Mem0. Two categories:
|
||||
The human owner can claim the account later with `mem0 init --email <their-email>`. The API key and memories remain unchanged. See the [CLI documentation](https://docs.mem0.ai/platform/cli) and [agent signup guide](https://docs.mem0.ai/platform/agent-signup).
|
||||
|
||||
**Reference skills — always on** (SDK knowledge loaded into the assistant's context):
|
||||
## Agent skills
|
||||
|
||||
Install reference skills to give compatible coding assistants Mem0 context:
|
||||
|
||||
```bash
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-cli
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-vercel-ai-sdk
|
||||
```
|
||||
|
||||
**Pipeline skills — run on demand** (execute an end-to-end workflow in an existing repo):
|
||||
Install pipeline skills for end-to-end workflows:
|
||||
|
||||
```bash
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-integrate
|
||||
@@ -189,72 +212,30 @@ npx skills add https://github.com/mem0ai/mem0 --skill mem0-test-integration
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-oss-to-platform
|
||||
```
|
||||
|
||||
Use `/mem0-integrate` to wire Mem0 into an existing repo via a test-first pipeline, then `/mem0-test-integration` to verify. Use `/mem0-oss-to-platform` to migrate an existing project from Mem0 OSS to the hosted Platform SDK. See the [skills catalog](./skills/) or [Vibecoding with Mem0](https://docs.mem0.ai/vibecoding) for the full picture.
|
||||
See the [skills catalog](./skills/) or [Vibecoding with Mem0](https://docs.mem0.ai/vibecoding).
|
||||
|
||||
### Basic Usage
|
||||
## Integrations and demos
|
||||
|
||||
Mem0 requires an LLM to function, with `gpt-5-mini` from OpenAI as the default. However, it supports a variety of LLMs; for details, refer to our [Supported LLMs documentation](https://docs.mem0.ai/components/llms/overview).
|
||||
- [ChatGPT with Memory demo](https://mem0.dev/demo)
|
||||
- [Browser extension](https://chromewebstore.google.com/detail/onihkkbipkfeijkadecaafbgagkhglop?utm_source=item-share-cb)
|
||||
- [LangGraph integration](https://docs.mem0.ai/integrations/langgraph)
|
||||
- [CrewAI integration](https://docs.mem0.ai/integrations/crewai)
|
||||
|
||||
Mem0 uses `text-embedding-3-small` from OpenAI as the default embedding model. For best results with hybrid search (semantic + keyword + entity boosting), we recommend using at least [Qwen 600M](https://huggingface.co/Alibaba-NLP/gte-Qwen2-1.5B-instruct) or a comparable embedding model. See [Supported Embeddings](https://docs.mem0.ai/components/embedders/overview) for configuration details.
|
||||
## Documentation and help
|
||||
|
||||
First step is to instantiate the memory:
|
||||
- [Python quickstart](https://docs.mem0.ai/open-source/python-quickstart)
|
||||
- [Platform quickstart](https://docs.mem0.ai/platform/quickstart)
|
||||
- [API reference](https://docs.mem0.ai/api-reference)
|
||||
- [Discord](https://mem0.dev/DiG)
|
||||
- [GitHub issues](https://github.com/mem0ai/mem0/issues)
|
||||
- Email: founders@mem0.ai
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
## Contributing
|
||||
|
||||
openai_client = OpenAI()
|
||||
memory = Memory()
|
||||
|
||||
def chat_with_memories(message: str, user_id: str = "default_user") -> str:
|
||||
# Retrieve relevant memories
|
||||
relevant_memories = memory.search(query=message, filters={"user_id": user_id}, top_k=3)
|
||||
memories_str = "\n".join(f"- {entry['memory']}" for entry in relevant_memories["results"])
|
||||
|
||||
# Generate Assistant response
|
||||
system_prompt = f"You are a helpful AI. Answer the question based on query and memories.\nUser Memories:\n{memories_str}"
|
||||
messages = [{"role": "system", "content": system_prompt}, {"role": "user", "content": message}]
|
||||
response = openai_client.chat.completions.create(model="gpt-5-mini", messages=messages)
|
||||
assistant_response = response.choices[0].message.content
|
||||
|
||||
# Create new memories from the conversation
|
||||
messages.append({"role": "assistant", "content": assistant_response})
|
||||
memory.add(messages, user_id=user_id)
|
||||
|
||||
return assistant_response
|
||||
|
||||
def main():
|
||||
print("Chat with AI (type 'exit' to quit)")
|
||||
while True:
|
||||
user_input = input("You: ").strip()
|
||||
if user_input.lower() == 'exit':
|
||||
print("Goodbye!")
|
||||
break
|
||||
print(f"AI: {chat_with_memories(user_input)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
For detailed integration steps, see the [Quickstart](https://docs.mem0.ai/quickstart) and [API Reference](https://docs.mem0.ai/api-reference).
|
||||
|
||||
## 🔗 Integrations & Demos
|
||||
|
||||
- **ChatGPT with Memory**: Personalized chat powered by Mem0 ([Live Demo](https://mem0.dev/demo))
|
||||
- **Browser Extension**: Store memories across ChatGPT, Perplexity, and Claude ([Chrome Extension](https://chromewebstore.google.com/detail/onihkkbipkfeijkadecaafbgagkhglop?utm_source=item-share-cb))
|
||||
- **Langgraph Support**: Build a customer bot with Langgraph + Mem0 ([Guide](https://docs.mem0.ai/integrations/langgraph))
|
||||
- **CrewAI Integration**: Tailor CrewAI outputs with Mem0 ([Example](https://docs.mem0.ai/integrations/crewai))
|
||||
|
||||
## 📚 Documentation & Support
|
||||
|
||||
- Full docs: https://docs.mem0.ai
|
||||
- Community: [Discord](https://mem0.dev/DiG) · [X (formerly Twitter)](https://x.com/mem0ai)
|
||||
- Contact: founders@mem0.ai
|
||||
Read [CONTRIBUTING.md](https://github.com/mem0ai/mem0/blob/main/CONTRIBUTING.md) before opening an issue or pull request.
|
||||
|
||||
## Citation
|
||||
|
||||
We now have a paper you can cite:
|
||||
|
||||
```bibtex
|
||||
@article{mem0,
|
||||
title={Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory},
|
||||
@@ -264,6 +245,6 @@ We now have a paper you can cite:
|
||||
}
|
||||
```
|
||||
|
||||
## ⚖️ License
|
||||
## License
|
||||
|
||||
Apache 2.0 — see the [LICENSE](https://github.com/mem0ai/mem0/blob/main/LICENSE) file for details.
|
||||
Apache 2.0. See [LICENSE](https://github.com/mem0ai/mem0/blob/main/LICENSE).
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Preview Dream Scope"
|
||||
description: "A no-write preview of the scope Dream synthesis would analyze for a project."
|
||||
openapi: "post /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/preview/"
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Get Dream Activity"
|
||||
description: "Supersede/merge activity feed for a project, newest first (keyset-paginated)."
|
||||
openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/activity/"
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Get Dream Configuration"
|
||||
description: "Retrieve a project's Dream (memory synthesis) configuration and plan entitlements."
|
||||
openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/config/"
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Get a Synthesized Memory's Sources"
|
||||
description: "The source memories a synthesized (pattern) memory was distilled from."
|
||||
openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/memory/{memory_id}/sources/"
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Get Memories in a Dream Run"
|
||||
description: "Keyset page of the synthesized memories within a single synthesis run."
|
||||
openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/runs/{run_id}/memories/"
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Get Dream Synthesis Runs"
|
||||
description: "Synthesis activity grouped per run, newest first (keyset-paginated)."
|
||||
openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/runs/"
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Get Dream Stats"
|
||||
description: "Lifecycle and synthesis counts for a project, plus reflection freshness."
|
||||
openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/stats/"
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Update Dream Configuration"
|
||||
description: "Enable or disable Synthesis (reflection) for a project, or change the reflection mode."
|
||||
openapi: "patch /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/config/"
|
||||
---
|
||||
@@ -1,278 +0,0 @@
|
||||
---
|
||||
title: Give Agents Shared Working Memory
|
||||
description: Keep a claims adjuster's personal preferences separate from a claim's shared decisions using user_id, agent_id, and two sets of custom instructions.
|
||||
---
|
||||
|
||||
Sarah is a claims adjuster. Every claim she opens should remember how she likes things drafted. Every claim itself should remember its own decisions, no matter which adjuster opens it next. A single `user_id` and one project-wide instruction set cannot hold both without one leaking into the other.
|
||||
|
||||
<Info icon="cloud">
|
||||
**Works with:** Mem0 Platform (`MemoryClient`)
|
||||
</Info>
|
||||
|
||||
<Info icon="clock">
|
||||
**Time to complete:** ~15 minutes · **Languages:** Python, TypeScript
|
||||
</Info>
|
||||
|
||||
## Setup
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key=os.environ["MEM0_API_KEY"])
|
||||
```
|
||||
```typescript TypeScript
|
||||
import { MemoryClient } from "mem0ai";
|
||||
|
||||
const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
Grab an API key from the <a href="https://app.mem0.ai/?utm_source=oss&utm_medium=cookbook-agent-memory" rel="nofollow">Mem0 dashboard</a>. `agent_custom_instructions` needs Python SDK `v2.0.17` or TypeScript SDK `v3.1.5` or later.
|
||||
</Note>
|
||||
|
||||
## Make It Work Once
|
||||
|
||||
Claim CLM-48211 is a warehouse fire loss for Meridian Logistics, and Sarah is the adjuster who opened it. Set two rule sets on the project once: `custom_instructions` for what belongs to the adjuster, `agent_custom_instructions` for what belongs to the claim.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
ADJUSTER = "adjuster_sarah_cookbook_demo"
|
||||
CLAIM = "claims_agent_clm48211_cookbook_demo"
|
||||
|
||||
user_instructions = """Your Task: Track what a claims adjuster needs remembered about themselves, not about any single claim.
|
||||
|
||||
Information to Extract:
|
||||
1. Drafting and communication style
|
||||
2. Working preferences, such as coverage lines they focus on
|
||||
|
||||
Guidelines:
|
||||
- Store preferences that should carry over to every claim this adjuster works.
|
||||
|
||||
Exclude:
|
||||
- Decisions made on a specific claim (settle vs litigate, reserve changes, subrogation)
|
||||
- Policy numbers, coverage limits, or other one-off lookups"""
|
||||
|
||||
agent_instructions = """Your Task: Track what matters about this specific claim, regardless of which adjuster is working it.
|
||||
|
||||
Information to Extract:
|
||||
1. Claim decisions and reasoning: settle vs litigate calls, reserve changes, subrogation
|
||||
2. Durable claim facts, such as cause of loss
|
||||
|
||||
Guidelines:
|
||||
- Store facts that the next adjuster to open this claim needs to see.
|
||||
|
||||
Exclude:
|
||||
- Personal style or communication preferences of whichever adjuster is talking"""
|
||||
|
||||
client.project.update(
|
||||
custom_instructions=user_instructions,
|
||||
agent_custom_instructions=agent_instructions,
|
||||
)
|
||||
```
|
||||
```typescript TypeScript
|
||||
const ADJUSTER = "adjuster_sarah_cookbook_demo";
|
||||
const CLAIM = "claims_agent_clm48211_cookbook_demo";
|
||||
|
||||
const userInstructions = `Your Task: Track what a claims adjuster needs remembered about themselves, not about any single claim.
|
||||
|
||||
Information to Extract:
|
||||
1. Drafting and communication style
|
||||
2. Working preferences, such as coverage lines they focus on
|
||||
|
||||
Guidelines:
|
||||
- Store preferences that should carry over to every claim this adjuster works.
|
||||
|
||||
Exclude:
|
||||
- Decisions made on a specific claim (settle vs litigate, reserve changes, subrogation)
|
||||
- Policy numbers, coverage limits, or other one-off lookups`;
|
||||
|
||||
const agentInstructions = `Your Task: Track what matters about this specific claim, regardless of which adjuster is working it.
|
||||
|
||||
Information to Extract:
|
||||
1. Claim decisions and reasoning: settle vs litigate calls, reserve changes, subrogation
|
||||
2. Durable claim facts, such as cause of loss
|
||||
|
||||
Guidelines:
|
||||
- Store facts that the next adjuster to open this claim needs to see.
|
||||
|
||||
Exclude:
|
||||
- Personal style or communication preferences of whichever adjuster is talking`;
|
||||
|
||||
await client.updateProject({
|
||||
customInstructions: userInstructions,
|
||||
agentCustomInstructions: agentInstructions,
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Now a normal exchange with the claim, passing both ids on the same `add()` call:
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
client.add(
|
||||
[
|
||||
{"role": "user", "content": "I'm raising the reserve on CLM-48211 to $1.8 million. The structural engineer's report says the warehouse needs a full rebuild, not a repair."},
|
||||
{"role": "assistant", "content": "Got it. Reserve raised to $1.8 million on CLM-48211 for a full rebuild, per the structural engineer's report."},
|
||||
],
|
||||
user_id=ADJUSTER,
|
||||
agent_id=CLAIM,
|
||||
)
|
||||
```
|
||||
```typescript TypeScript
|
||||
await client.add(
|
||||
[
|
||||
{ role: "user", content: "I'm raising the reserve on CLM-48211 to $1.8 million. The structural engineer's report says the warehouse needs a full rebuild, not a repair." },
|
||||
{ role: "assistant", content: "Got it. Reserve raised to $1.8 million on CLM-48211 for a full rebuild, per the structural engineer's report." },
|
||||
],
|
||||
{ userId: ADJUSTER, agentId: CLAIM },
|
||||
);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Info icon="check">
|
||||
Expected output: two memories, both attributed to `CLAIM`: `"Reserve for claim CLM-48211 was increased to $1.8 million to cover a full rebuild, as indicated by the structural engineer's report"`, plus the engineer's rebuild finding stored as its own durable fact. Nothing lands on Sarah's personal shelf, the instructions exclude claim decisions from it.
|
||||
</Info>
|
||||
|
||||
## The Problem
|
||||
|
||||
Suppose Marcus, a second adjuster, needs to pick up CLM-48211 while Sarah is out. If claim decisions only ever went on the acting adjuster's `user_id`, with no `agent_id` and no `agent_custom_instructions`, Marcus's own memory would be empty no matter what Sarah decided:
|
||||
|
||||
```python
|
||||
marcus_personal = client.get_all(filters={"user_id": "adjuster_marcus_cookbook_demo"})
|
||||
print(marcus_personal["count"])
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```
|
||||
0
|
||||
```
|
||||
|
||||
Marcus has never talked to Mem0 before, so an empty personal shelf is expected. The real gap is structural: if the reserve decision above had gone on Sarah's `user_id` alone, it would live there permanently, and Marcus would have no identifier that reaches it. The claim's history would be trapped on one person's shelf.
|
||||
|
||||
## Fix It: Give the Claim Its Own Shelf
|
||||
|
||||
`agent_id` fixes this because it names the claim, not the person handling it. Anyone who searches with that `agent_id` sees the same claim history, regardless of whose `user_id` they search alongside:
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
marcus_view = client.search(
|
||||
"What's going on with CLM-48211?",
|
||||
filters={"OR": [{"user_id": "adjuster_marcus_cookbook_demo"}, {"agent_id": CLAIM}]},
|
||||
)
|
||||
for r in marcus_view["results"]:
|
||||
print(f"- [{r.get('user_id') or r.get('agent_id')}] {r['memory']}")
|
||||
```
|
||||
```typescript TypeScript
|
||||
const marcusView = await client.search(
|
||||
"What's going on with CLM-48211?",
|
||||
{ filters: { OR: [{ userId: "adjuster_marcus_cookbook_demo" }, { agentId: CLAIM }] } },
|
||||
);
|
||||
for (const r of marcusView.results) {
|
||||
console.log(`- [${r.userId ?? r.agentId}] ${r.memory}`);
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
**Output** (from the full notebook run, four claim facts on file):
|
||||
```
|
||||
- [claims_agent_clm48211_cookbook_demo] Reserve for claim CLM-48211 was increased to $1.8 million to cover a full rebuild, as indicated by the structural engineer's report
|
||||
- [claims_agent_clm48211_cookbook_demo] The structural engineer's report for claim CLM-48211 states that the warehouse requires a full rebuild rather than a repair
|
||||
- [claims_agent_clm48211_cookbook_demo] The building coverage limit for claim CLM-48211 under the Meridian Logistics policy is $2,400,000 with a $25,000 deductible
|
||||
- [claims_agent_clm48211_cookbook_demo] Assistant noted that subrogation will be pursued against Voss Electrical, with the fire marshal's report identifying faulty wiring as the ignition source
|
||||
```
|
||||
|
||||
Marcus sees the full claim history and none of Sarah's personal preferences, because those never carried `agent_id` attribution in the first place.
|
||||
|
||||
## Build On It: One Message, Two Shelves
|
||||
|
||||
A single message can touch both shelves in one `add()` call. Sarah makes a claim decision and states a personal preference in the same breath:
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
client.add(
|
||||
[
|
||||
{"role": "user", "content": "I've decided to pursue subrogation against Voss Electrical, the contractor who rewired the warehouse six months ago. The fire marshal's report points to faulty wiring as the ignition source. Also, from now on keep my claim summaries to bullet points, not paragraphs."},
|
||||
{"role": "assistant", "content": "Noted both. Pursuing subrogation against Voss Electrical based on the fire marshal's faulty-wiring finding, and I'll keep your summaries in bullet points going forward."},
|
||||
],
|
||||
user_id=ADJUSTER,
|
||||
agent_id=CLAIM,
|
||||
)
|
||||
```
|
||||
```typescript TypeScript
|
||||
await client.add(
|
||||
[
|
||||
{ role: "user", content: "I've decided to pursue subrogation against Voss Electrical, the contractor who rewired the warehouse six months ago. The fire marshal's report points to faulty wiring as the ignition source. Also, from now on keep my claim summaries to bullet points, not paragraphs." },
|
||||
{ role: "assistant", content: "Noted both. Pursuing subrogation against Voss Electrical based on the fire marshal's faulty-wiring finding, and I'll keep your summaries in bullet points going forward." },
|
||||
],
|
||||
{ userId: ADJUSTER, agentId: CLAIM },
|
||||
);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
**Output:** two memories from one call, one per shelf. The subrogation decision lands on the claim shelf with the fire marshal's faulty-wiring finding folded into its reasoning, and the bullet-point formatting rule lands on Sarah's personal shelf.
|
||||
|
||||
<Warning>
|
||||
Extraction makes judgment calls, it does not mirror your instructions line by line. In the full notebook run, a one-off policy-limit lookup (excluded by name in the instructions above) still landed on the claim shelf, because it was judged a durable fact worth keeping for the life of the claim. Read what actually got stored with `get_all()` rather than assuming the instructions were applied literally.
|
||||
</Warning>
|
||||
|
||||
## Production Patterns
|
||||
|
||||
- **Reviewing and correcting a personal shelf**: `get_all()` with the adjuster's `user_id`, then act on what is actually stored.
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
sarah_shelf = client.get_all(filters={"user_id": ADJUSTER})
|
||||
for r in sarah_shelf["results"]:
|
||||
print(r["id"], "-", r["memory"])
|
||||
```
|
||||
```typescript TypeScript
|
||||
const sarahShelf = await client.getAll({ filters: { userId: ADJUSTER } });
|
||||
for (const r of sarahShelf.results) {
|
||||
console.log(r.id, "-", r.memory);
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
- **Editing without losing a neighbor**: `delete()` removes a whole memory, not a substring of one. If two preferences were extracted into a single combined memory, deleting it to revise one loses both. Use `update()` to rewrite the text in place instead:
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
client.update(memory_id, text="User prefers drafts to contain no em dashes")
|
||||
```
|
||||
```typescript TypeScript
|
||||
await client.update(memoryId, { text: "User prefers drafts to contain no em dashes" });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## What You Built
|
||||
|
||||
- **A personal shelf per adjuster**: `user_id` plus `custom_instructions` for preferences that follow one person across every claim they touch.
|
||||
- **A shared shelf per claim**: `agent_id` plus `agent_custom_instructions` for decisions and facts that outlive any single adjuster's session.
|
||||
- **One query across both**: an `OR` filter on `user_id` and `agent_id` for status updates that need the person's context and the claim's history together.
|
||||
|
||||
## Production Checklist
|
||||
|
||||
- Set `agent_custom_instructions` alongside `custom_instructions` in the same `project.update()` call, an unset agent instruction set silently falls back to the user one.
|
||||
- Pass both `user_id` and `agent_id` on every `add()` call for a claim conversation, not just one or the other.
|
||||
- Use `update()` to correct a single fact; reach for `delete()` only when you mean to remove the whole memory record.
|
||||
- Delete demo or test data with `delete_all(user_id=...)` and `delete_all(agent_id=...)`, and restore any project instructions you changed for a test run.
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Custom Instructions"
|
||||
description="The full reference for custom_instructions and agent_custom_instructions, including per-call overrides."
|
||||
icon="shield-check"
|
||||
href="/platform/features/custom-instructions"
|
||||
/>
|
||||
<Card
|
||||
title="Run the Full Notebook"
|
||||
description="The same scenario end to end, executed live against the Mem0 Platform API with real outputs."
|
||||
icon="rocket"
|
||||
href="https://github.com/mem0ai/mem0/blob/main/examples/notebooks/agent-memory-insurance.ipynb"
|
||||
/>
|
||||
</CardGroup>
|
||||
|
||||
<Snippet file="star-on-github.mdx" />
|
||||
+15
-2
@@ -406,8 +406,7 @@
|
||||
"cookbooks/essentials/building-ai-companion",
|
||||
"cookbooks/essentials/entity-partitioning-playbook",
|
||||
"cookbooks/essentials/tagging-and-organizing-memories",
|
||||
"cookbooks/essentials/exporting-memories",
|
||||
"cookbooks/essentials/agent-memory-insurance-claims"
|
||||
"cookbooks/essentials/exporting-memories"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -540,6 +539,20 @@
|
||||
"api-reference/project/delete-project"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Dream",
|
||||
"icon": "sparkles",
|
||||
"pages": [
|
||||
"api-reference/dream/get-dream-config",
|
||||
"api-reference/dream/update-dream-config",
|
||||
"api-reference/dream/get-dream-stats",
|
||||
"api-reference/dream/get-dream-activity",
|
||||
"api-reference/dream/get-dream-runs",
|
||||
"api-reference/dream/get-dream-run-memories",
|
||||
"api-reference/dream/get-dream-memory-sources",
|
||||
"api-reference/dream/dream-preview"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Webhooks",
|
||||
"icon": "webhook",
|
||||
|
||||
+10
-1
@@ -300,7 +300,6 @@ If the user is on a pre-current major (Python < 2, TS < 3, or a Platform call st
|
||||
- [Partition Memories by Entity](https://docs.mem0.ai/cookbooks/essentials/entity-partitioning-playbook) [Both]: Use when isolating multi-tenant memories.
|
||||
- [Tagging and Organizing Memories](https://docs.mem0.ai/cookbooks/essentials/tagging-and-organizing-memories) [Both]: Use when memory taxonomy matters.
|
||||
- [Exporting Memories](https://docs.mem0.ai/cookbooks/essentials/exporting-memories) [Both]: Use when backing up or migrating memory data.
|
||||
- [Give Agents Shared Working Memory](https://docs.mem0.ai/cookbooks/essentials/agent-memory-insurance-claims) [Platform]: Use when a shared record must outlive the individual using it, such as a claim, ticket, or account that multiple people work over time.
|
||||
|
||||
### AI Companions
|
||||
- [Quickstart Demo](https://docs.mem0.ai/cookbooks/companions/quickstart-demo) [Both]: Use when showing the smallest end-to-end companion.
|
||||
@@ -384,6 +383,16 @@ All API Reference docs describe Mem0 Platform REST endpoints (requires API key).
|
||||
- [Remove Project Member](https://docs.mem0.ai/api-reference/project/remove-project-member) [Platform]: Use when removing a member from a project.
|
||||
- [Delete Project](https://docs.mem0.ai/api-reference/project/delete-project) [Platform]: Use when removing a project.
|
||||
|
||||
### Dream
|
||||
- [Get Dream Configuration](https://docs.mem0.ai/api-reference/dream/get-dream-config) [Platform]: Use when reading a project's Dream (memory synthesis) config and plan entitlements.
|
||||
- [Update Dream Configuration](https://docs.mem0.ai/api-reference/dream/update-dream-config) [Platform]: Use when enabling/disabling Synthesis or changing its mode for a project.
|
||||
- [Get Dream Stats](https://docs.mem0.ai/api-reference/dream/get-dream-stats) [Platform]: Use when fetching lifecycle and synthesis counts for the Dream dashboard.
|
||||
- [Get Dream Activity](https://docs.mem0.ai/api-reference/dream/get-dream-activity) [Platform]: Use when listing recent supersede/merge activity for a project.
|
||||
- [Get Dream Synthesis Runs](https://docs.mem0.ai/api-reference/dream/get-dream-runs) [Platform]: Use when listing synthesis runs and the memories they generated.
|
||||
- [Get Memories in a Dream Run](https://docs.mem0.ai/api-reference/dream/get-dream-run-memories) [Platform]: Use when paging the synthesized memories within a single run.
|
||||
- [Get a Synthesized Memory's Sources](https://docs.mem0.ai/api-reference/dream/get-dream-memory-sources) [Platform]: Use when tracing the source memories a synthesized memory was distilled from.
|
||||
- [Preview Dream Scope](https://docs.mem0.ai/api-reference/dream/dream-preview) [Platform]: Use when previewing what Synthesis would analyze for a project (no writes).
|
||||
|
||||
### Webhooks
|
||||
- [Create Webhook](https://docs.mem0.ai/api-reference/webhook/create-webhook) [Platform]: Use when registering a webhook endpoint.
|
||||
- [Get Webhook](https://docs.mem0.ai/api-reference/webhook/get-webhook) [Platform]: Use when fetching webhook config.
|
||||
|
||||
@@ -7207,6 +7207,869 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/config/": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"dream"
|
||||
],
|
||||
"summary": "Get Dream configuration",
|
||||
"description": "Retrieve the project's Dream (memory synthesis) configuration together with the plan entitlement snapshot. Dream automatically supersedes/merges memories on the add path; **Synthesis** (reflection) is the opt-in part controlled by `reflection_enabled`.",
|
||||
"operationId": "get_dream_config",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the organization.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the project.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reflection_enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether background synthesis (reflection) is enabled for the project."
|
||||
},
|
||||
"reflection_enabled_at": {
|
||||
"type": "string",
|
||||
"description": "When synthesis was last enabled. Synthesis only considers memories created on or after this time (forward-only).",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"reflection_mode": {
|
||||
"type": "string",
|
||||
"description": "Synthesis execution mode.",
|
||||
"enum": [
|
||||
"batch",
|
||||
"direct"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"entitlements": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"plan": {
|
||||
"type": "string",
|
||||
"description": "Resolved billing tier for the project (e.g. `free`, `pro`, `custom`)."
|
||||
},
|
||||
"reflection_interval_days": {
|
||||
"type": "integer",
|
||||
"description": "How often synthesis runs for this plan, in days (Pro weekly, Enterprise daily)."
|
||||
},
|
||||
"features": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"description": "Per-feature entitlement snapshot, keyed by Dream feature (e.g. `dream_reflection`, `dream_tab`, `dream_preview`).",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entitled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the plan is entitled to the feature."
|
||||
},
|
||||
"killed": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the feature is globally disabled by a kill switch."
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Effective state: entitled AND not killed AND turned on."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"tags": [
|
||||
"dream"
|
||||
],
|
||||
"summary": "Update Dream configuration",
|
||||
"description": "Enable or disable Synthesis (reflection) for the project, or change the reflection mode. Requires a Pro or Enterprise (CUSTOM) plan and organization-owner permission. Synthesis is forward-only: after enabling, it only synthesizes memories added from that point on.",
|
||||
"operationId": "update_dream_config",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the organization.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the project.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reflection_enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Turn background synthesis on or off."
|
||||
},
|
||||
"reflection_mode": {
|
||||
"type": "string",
|
||||
"description": "Synthesis execution mode.",
|
||||
"enum": [
|
||||
"batch",
|
||||
"direct"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Updated configuration.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reflection_enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether background synthesis (reflection) is enabled for the project."
|
||||
},
|
||||
"reflection_enabled_at": {
|
||||
"type": "string",
|
||||
"description": "When synthesis was last enabled. Synthesis only considers memories created on or after this time (forward-only).",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"reflection_mode": {
|
||||
"type": "string",
|
||||
"description": "Synthesis execution mode.",
|
||||
"enum": [
|
||||
"batch",
|
||||
"direct"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"entitlements": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"plan": {
|
||||
"type": "string",
|
||||
"description": "Resolved billing tier for the project (e.g. `free`, `pro`, `custom`)."
|
||||
},
|
||||
"reflection_interval_days": {
|
||||
"type": "integer",
|
||||
"description": "How often synthesis runs for this plan, in days (Pro weekly, Enterprise daily)."
|
||||
},
|
||||
"features": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"description": "Per-feature entitlement snapshot, keyed by Dream feature (e.g. `dream_reflection`, `dream_tab`, `dream_preview`).",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entitled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the plan is entitled to the feature."
|
||||
},
|
||||
"killed": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the feature is globally disabled by a kill switch."
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Effective state: entitled AND not killed AND turned on."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Validation error (e.g. a field the plan is not entitled to change)."
|
||||
},
|
||||
"403": {
|
||||
"description": "Not entitled on the current plan (`upgrade_required: true`), or the caller is not an organization owner."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/stats/": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"dream"
|
||||
],
|
||||
"summary": "Get Dream stats",
|
||||
"description": "Lifecycle + synthesis counts for the project's Dream dashboard, plus reflection freshness. Requires a Pro or Enterprise (CUSTOM) plan.",
|
||||
"operationId": "get_dream_stats",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the organization.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the project.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"active": {
|
||||
"type": "integer",
|
||||
"description": "Active (current) memory count."
|
||||
},
|
||||
"merged": {
|
||||
"type": "integer",
|
||||
"description": "Count of memories merged into a canonical one."
|
||||
},
|
||||
"superseded": {
|
||||
"type": "integer",
|
||||
"description": "Count of memories superseded by a newer one."
|
||||
},
|
||||
"synthesized": {
|
||||
"type": "integer",
|
||||
"description": "Count of higher-order pattern memories created by synthesis."
|
||||
},
|
||||
"last_run_at": {
|
||||
"type": "string",
|
||||
"description": "When synthesis last completed.",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"processed_through": {
|
||||
"type": "string",
|
||||
"description": "Timestamp of the newest source memory synthesis has processed.",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"running": {
|
||||
"type": "boolean",
|
||||
"description": "Whether a synthesis run is currently in flight."
|
||||
},
|
||||
"next_run_at": {
|
||||
"type": "string",
|
||||
"description": "Projected next synthesis run.",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Not entitled on the current plan (`upgrade_required: true`)."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/activity/": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"dream"
|
||||
],
|
||||
"summary": "Get Dream activity",
|
||||
"description": "Supersede/merge activity feed (newest first), keyset-paginated. Synthesis output is not included here — see the runs endpoint.",
|
||||
"operationId": "get_dream_activity",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the organization.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the project.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"description": "Page size (default 50, max 200).",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 50
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cursor",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"description": "Opaque keyset cursor from a previous page's `next_cursor`.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"results": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memory_id": {
|
||||
"type": "string",
|
||||
"description": "The superseded/merged memory's ID."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "The memory's text (truncated)."
|
||||
},
|
||||
"transition": {
|
||||
"type": "string",
|
||||
"description": "Lifecycle transition.",
|
||||
"enum": [
|
||||
"merged",
|
||||
"superseded"
|
||||
]
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
"description": "When the transition happened.",
|
||||
"format": "date-time"
|
||||
},
|
||||
"replaced_by": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "ID of the newer memory."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Text of the newer memory (truncated).",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"nullable": true,
|
||||
"description": "The newer memory that replaced this one (null for a merge with no single replacement)."
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Source memory ID."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Source memory text (truncated)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"nullable": true,
|
||||
"description": "Always null on this feed; synthesis provenance is shown on the runs feed."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"next_cursor": {
|
||||
"type": "string",
|
||||
"description": "Cursor for the next page, or null when there are no more.",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/runs/": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"dream"
|
||||
],
|
||||
"summary": "Get Dream synthesis runs",
|
||||
"description": "Synthesis activity grouped per run (newest first), keyset-paginated. Each run inlines its first page of synthesized memories with their sources; larger runs page the rest via the run-memories endpoint.",
|
||||
"operationId": "get_dream_runs",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the organization.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the project.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"description": "Number of runs per page (default 20, max 100).",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cursor",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"description": "Opaque keyset cursor from a previous page's `next_cursor`.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"results": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"run_id": {
|
||||
"type": "string",
|
||||
"description": "Identifier of the synthesis run."
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
"description": "When the run produced memories.",
|
||||
"format": "date-time"
|
||||
},
|
||||
"count": {
|
||||
"type": "integer",
|
||||
"description": "Total synthesized memories in this run."
|
||||
},
|
||||
"synthesized": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Synthesized memory ID."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Synthesized (pattern) memory text."
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Source memory ID."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Source memory text (truncated)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Source memories this pattern was distilled from."
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "First page of synthesized memories (each with its sources)."
|
||||
},
|
||||
"has_more": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the run has more memories than are inlined here."
|
||||
},
|
||||
"mem_cursor": {
|
||||
"type": "string",
|
||||
"description": "Cursor to page this run's remaining memories via the run-memories endpoint.",
|
||||
"nullable": true
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Source memory ID."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Source memory text (truncated)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "De-duplicated source memories across the inlined page."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"next_cursor": {
|
||||
"type": "string",
|
||||
"description": "Cursor for the next page, or null when there are no more.",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/runs/{run_id}/memories/": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"dream"
|
||||
],
|
||||
"summary": "Get memories in a Dream run",
|
||||
"description": "Keyset page of the synthesized memories within a single run (for runs whose `has_more` is true).",
|
||||
"operationId": "get_dream_run_memories",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the organization.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the project.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "run_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Identifier of the synthesis run.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"description": "Page size (default 50, max 200).",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 50
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cursor",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"description": "Opaque keyset cursor (use the run's `mem_cursor` or a previous `next_cursor`).",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"results": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Synthesized memory ID."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Synthesized (pattern) memory text."
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Source memory ID."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Source memory text (truncated)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Source memories this pattern was distilled from."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"next_cursor": {
|
||||
"type": "string",
|
||||
"description": "Cursor for the next page, or null when there are no more.",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/memory/{memory_id}/sources/": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"dream"
|
||||
],
|
||||
"summary": "Get a synthesized memory's sources",
|
||||
"description": "The source memories a synthesized (pattern) memory was distilled from, for the memory drawer's provenance panel.",
|
||||
"operationId": "get_dream_memory_sources",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the organization.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the project.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "memory_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "ID of the (synthesized) memory.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memory_id": {
|
||||
"type": "string",
|
||||
"description": "The memory's ID."
|
||||
},
|
||||
"synthesized": {
|
||||
"type": "boolean",
|
||||
"description": "Whether this memory was produced by synthesis."
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Source memory ID."
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Source memory text."
|
||||
},
|
||||
"lifecycle_state": {
|
||||
"type": "string",
|
||||
"description": "Source memory lifecycle state.",
|
||||
"enum": [
|
||||
"active",
|
||||
"merged",
|
||||
"superseded"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Memory not found in this project."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/preview/": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"dream"
|
||||
],
|
||||
"summary": "Preview Dream scope",
|
||||
"description": "A no-write preview of the scope Dream synthesis would analyze for the project (a capped sample plus the count of users with enough memories to benefit). Never runs the LLM and never mutates anything.",
|
||||
"operationId": "dream_preview",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the organization.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "Unique identifier of the project.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"active_total": {
|
||||
"type": "integer",
|
||||
"description": "Total active memories in the project."
|
||||
},
|
||||
"scanned": {
|
||||
"type": "integer",
|
||||
"description": "How many recent memories the preview aggregated over (capped)."
|
||||
},
|
||||
"cap": {
|
||||
"type": "integer",
|
||||
"description": "The scan cap applied."
|
||||
},
|
||||
"eligible_users": {
|
||||
"type": "integer",
|
||||
"description": "Users with enough memories to benefit from synthesis."
|
||||
},
|
||||
"note": {
|
||||
"type": "string",
|
||||
"description": "Human-readable note about the preview scope."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Preview not available on the current plan (`upgrade_required: true`)."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
|
||||
@@ -1,842 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Agent Memory: An Insurance Claims Cookbook\n",
|
||||
"\n",
|
||||
"This notebook builds a claims workflow on top of Mem0 where two kinds of memory live side by side:\n",
|
||||
"\n",
|
||||
"- **A claims adjuster's own preferences**: drafting style, communication rules, the lines of coverage they focus on. These follow the adjuster from claim to claim and are private to them.\n",
|
||||
"- **A claim's working memory**: the decisions made on one specific claim and why, plus durable facts about that claim. This is shared by every adjuster who opens the claim, because a claim outlives any single person handling it.\n",
|
||||
"\n",
|
||||
"Mem0 keeps these apart using two identifiers on every `add()` call, `user_id` for the adjuster and `agent_id` for the claim, plus two separate sets of extraction rules, `custom_instructions` for the adjuster shelf and `agent_custom_instructions` for the claim shelf. This mirrors the id convention used in Mem0's CoCounsel example, where a lawyer maps to `user_id` and a case maps to `agent_id`. Here the adjuster is the person, and the claim is the shared case file.\n",
|
||||
"\n",
|
||||
"This notebook was executed live against the Mem0 Platform API. Every output below is a real response, not a mock.\n",
|
||||
"\n",
|
||||
"For the narrative walkthrough of this same pattern, see the [Give Agents Shared Working Memory](https://docs.mem0.ai/cookbooks/essentials/agent-memory-insurance-claims) cookbook page."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:08.774876Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:08.774699Z",
|
||||
"iopub.status.idle": "2026-08-27T09:46:09.471287Z",
|
||||
"shell.execute_reply": "2026-08-27T09:46:09.470775Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Note: you may need to restart the kernel to use updated packages.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%pip install -q mem0ai"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:09.472860Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:09.472717Z",
|
||||
"iopub.status.idle": "2026-08-27T09:46:14.361722Z",
|
||||
"shell.execute_reply": "2026-08-27T09:46:14.361005Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import json\n",
|
||||
"import os\n",
|
||||
"import time\n",
|
||||
"\n",
|
||||
"from mem0 import MemoryClient\n",
|
||||
"\n",
|
||||
"os.environ[\"MEM0_API_KEY\"] = \"YOUR_MEM0_API_KEY\"\n",
|
||||
"client = MemoryClient()\n",
|
||||
"\n",
|
||||
"ADJUSTER_SARAH = \"adjuster_sarah_cookbook_demo\"\n",
|
||||
"ADJUSTER_MARCUS = \"adjuster_marcus_cookbook_demo\"\n",
|
||||
"CLAIM_AGENT = \"claims_agent_clm48211_cookbook_demo\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 1. The mapping\n",
|
||||
"\n",
|
||||
"Claim CLM-48211 is a commercial property fire loss at a Meridian Logistics warehouse. Sarah is the adjuster who opened it.\n",
|
||||
"\n",
|
||||
"| Mem0 identifier | Maps to | What lives there |\n",
|
||||
"|---|---|---|\n",
|
||||
"| `user_id` | An individual adjuster, e.g. Sarah | Her drafting style, her communication rules, durable across every claim she works |\n",
|
||||
"| `agent_id` | One claim's agent instance, e.g. `claims_agent_clm48211` | Decisions made on this claim and why, plus durable facts about it, shared by anyone who opens the claim |\n",
|
||||
"\n",
|
||||
"Every `add()` call below passes both `user_id=ADJUSTER_SARAH` and `agent_id=CLAIM_AGENT` at once. Mem0 does not require you to pick a shelf ahead of time, it extracts facts from the conversation and routes each one against the rules for its shelf."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 2. Configure the two rule sets\n",
|
||||
"\n",
|
||||
"`custom_instructions` governs memories that land under `user_id`. `agent_custom_instructions` is a second, optional rule set that governs memories that land under `agent_id`. Until you set it, agent-scoped memories fall back to `custom_instructions`, which is why the next cell sets both at once.\n",
|
||||
"\n",
|
||||
"Before changing anything, save what the project already has, so it can be restored at the end of this notebook."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:14.364467Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:14.364243Z",
|
||||
"iopub.status.idle": "2026-08-27T09:46:14.692628Z",
|
||||
"shell.execute_reply": "2026-08-27T09:46:14.692110Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"had custom_instructions: True\n",
|
||||
"had agent_custom_instructions: False\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"project_snapshot = client.project.get(fields=[\"custom_instructions\", \"agent_custom_instructions\"])\n",
|
||||
"print(\"had custom_instructions:\", bool(project_snapshot.get(\"custom_instructions\")))\n",
|
||||
"print(\"had agent_custom_instructions:\", bool(project_snapshot.get(\"agent_custom_instructions\")))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:14.694276Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:14.694156Z",
|
||||
"iopub.status.idle": "2026-08-27T09:46:15.051548Z",
|
||||
"shell.execute_reply": "2026-08-27T09:46:15.050970Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{'message': 'Updated custom instructions and agent custom instructions'}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"USER_INSTRUCTIONS = \"\"\"Your Task: Track what a claims adjuster needs remembered about themselves, not about any single claim.\n",
|
||||
"\n",
|
||||
"Information to Extract:\n",
|
||||
"1. Drafting and communication style:\n",
|
||||
" - Tone, formatting, and length preferences for letters and summaries\n",
|
||||
" - Rules for how the assistant should write on their behalf\n",
|
||||
"\n",
|
||||
"2. Working preferences:\n",
|
||||
" - Coverage lines or claim types they focus on\n",
|
||||
" - How they like updates delivered\n",
|
||||
"\n",
|
||||
"Guidelines:\n",
|
||||
"- Store preferences that should carry over to every claim this adjuster works, not just the current one.\n",
|
||||
"\n",
|
||||
"Exclude:\n",
|
||||
"- Decisions made on a specific claim (settle vs litigate, reserve changes, subrogation, coverage determinations)\n",
|
||||
"- Policy numbers, coverage limits, or other one-off lookups\n",
|
||||
"- Greetings, small talk, and weather\"\"\"\n",
|
||||
"\n",
|
||||
"AGENT_INSTRUCTIONS = \"\"\"Your Task: Track what matters about this specific claim, regardless of which adjuster is working it.\n",
|
||||
"\n",
|
||||
"Information to Extract:\n",
|
||||
"1. Claim decisions and reasoning:\n",
|
||||
" - Settle vs litigate calls\n",
|
||||
" - Reserve changes and why\n",
|
||||
" - Subrogation decisions\n",
|
||||
" - Coverage determinations\n",
|
||||
"\n",
|
||||
"2. Durable claim facts:\n",
|
||||
" - Cause of loss and other facts that stay true for the life of the claim\n",
|
||||
"\n",
|
||||
"Guidelines:\n",
|
||||
"- Store facts that the next adjuster to open this claim needs to see.\n",
|
||||
"\n",
|
||||
"Exclude:\n",
|
||||
"- Personal style or communication preferences of whichever adjuster is talking\n",
|
||||
"- One-off lookups that go stale (current weather, a single quoted estimate)\n",
|
||||
"- Greetings and small talk\"\"\"\n",
|
||||
"\n",
|
||||
"update_response = client.project.update(\n",
|
||||
" custom_instructions=USER_INSTRUCTIONS,\n",
|
||||
" agent_custom_instructions=AGENT_INSTRUCTIONS,\n",
|
||||
")\n",
|
||||
"print(update_response)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 3. Day 1: Sarah works the claim\n",
|
||||
"\n",
|
||||
"`add()` on the Platform is asynchronous, it returns a `PENDING` status and an `event_id`, and extraction finishes in the background. A production agent does not need to wait for it, but this notebook does, so the next cell reads its own writes. The small polling helper below is only useful for a demo like this one."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:15.053514Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:15.053386Z",
|
||||
"iopub.status.idle": "2026-08-27T09:46:15.057906Z",
|
||||
"shell.execute_reply": "2026-08-27T09:46:15.057402Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def wait_for_event(client, event_id, timeout=90, poll_every=2):\n",
|
||||
" deadline = time.time() + timeout\n",
|
||||
" while time.time() < deadline:\n",
|
||||
" event = client.client.get(f\"/v1/event/{event_id}/\").json()\n",
|
||||
" if event[\"status\"] in (\"SUCCEEDED\", \"FAILED\"):\n",
|
||||
" return event\n",
|
||||
" time.sleep(poll_every)\n",
|
||||
" raise TimeoutError(f\"Event {event_id} did not finish in {timeout}s\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_and_wait(client, messages, **kwargs):\n",
|
||||
" response = client.add(messages, **kwargs)\n",
|
||||
" event = wait_for_event(client, response[\"event_id\"])\n",
|
||||
" if event[\"status\"] == \"FAILED\":\n",
|
||||
" raise RuntimeError(f\"Add failed: {event.get('error')}\")\n",
|
||||
" return event\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def summarize(event):\n",
|
||||
" print(\"status:\", event[\"status\"], \"| created:\", len(event.get(\"results\", [])))\n",
|
||||
" for r in event.get(\"results\", []):\n",
|
||||
" print(\" -\", r[\"data\"][\"memory\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Sarah starts the day by pulling a number off the policy."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:15.059720Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:15.059580Z",
|
||||
"iopub.status.idle": "2026-08-27T09:46:23.223178Z",
|
||||
"shell.execute_reply": "2026-08-27T09:46:23.222458Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[\n",
|
||||
" {\n",
|
||||
" \"id\": \"c76bf47b-c5bf-4893-95d5-6ae8c5a4177b\",\n",
|
||||
" \"data\": {\n",
|
||||
" \"memory\": \"The building coverage limit for claim CLM-48211 under the Meridian Logistics policy is $2,400,000 with a $25,000 deductible\"\n",
|
||||
" },\n",
|
||||
" \"event\": \"ADD\",\n",
|
||||
" \"user_id\": \"adjuster_sarah_cookbook_demo\",\n",
|
||||
" \"event_end\": null,\n",
|
||||
" \"event_date\": null,\n",
|
||||
" \"event_start\": null,\n",
|
||||
" \"memory_type\": null,\n",
|
||||
" \"plan_status\": null,\n",
|
||||
" \"attributed_to\": \"assistant\"\n",
|
||||
" }\n",
|
||||
"]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"event = add_and_wait(\n",
|
||||
" client,\n",
|
||||
" [\n",
|
||||
" {\"role\": \"user\", \"content\": \"What's the building coverage limit on the Meridian Logistics policy for claim CLM-48211?\"},\n",
|
||||
" {\"role\": \"assistant\", \"content\": \"Checking the policy now. The building coverage limit is $2,400,000 with a $25,000 deductible.\"},\n",
|
||||
" ],\n",
|
||||
" user_id=ADJUSTER_SARAH,\n",
|
||||
" agent_id=CLAIM_AGENT,\n",
|
||||
")\n",
|
||||
"print(json.dumps(event[\"results\"], indent=2))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Notice the created record's own `user_id` field. That field just echoes who the call was made for, it is not proof of which shelf the memory actually landed on. `attributed_to` is closer, but the only reliable check is asking Mem0 directly with `get_all()`, which section 5 does. Keep that in mind through the rest of this notebook, a coverage limit like this one turns out to be exactly the kind of durable claim fact `agent_custom_instructions` asks Mem0 to keep, so it is worth checking where it really ends up.\n",
|
||||
"\n",
|
||||
"Next, a real decision with the reasoning behind it."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:23.225503Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:23.225354Z",
|
||||
"iopub.status.idle": "2026-08-27T09:46:50.042538Z",
|
||||
"shell.execute_reply": "2026-08-27T09:46:50.041648Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"status: SUCCEEDED | created: 2\n",
|
||||
" - Reserve for claim CLM-48211 was increased to $1.8 million to cover a full rebuild, as indicated by the structural engineer's report\n",
|
||||
" - The structural engineer's report for claim CLM-48211 states that the warehouse requires a full rebuild rather than a repair\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"event = add_and_wait(\n",
|
||||
" client,\n",
|
||||
" [\n",
|
||||
" {\"role\": \"user\", \"content\": \"I'm raising the reserve on CLM-48211 to $1.8 million. The structural engineer's report says the warehouse needs a full rebuild, not a repair.\"},\n",
|
||||
" {\"role\": \"assistant\", \"content\": \"Got it. Reserve raised to $1.8 million on CLM-48211 for a full rebuild, per the structural engineer's report. I'll keep that on file for the claim.\"},\n",
|
||||
" ],\n",
|
||||
" user_id=ADJUSTER_SARAH,\n",
|
||||
" agent_id=CLAIM_AGENT,\n",
|
||||
")\n",
|
||||
"summarize(event)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Then a personal rule for how Sarah wants things written."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:50.044560Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:50.044403Z",
|
||||
"iopub.status.idle": "2026-08-27T09:46:58.104329Z",
|
||||
"shell.execute_reply": "2026-08-27T09:46:58.103578Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"status: SUCCEEDED | created: 1\n",
|
||||
" - User prefers that any drafted documents contain no em dashes and that coverage position letters be limited to one page\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"event = add_and_wait(\n",
|
||||
" client,\n",
|
||||
" [\n",
|
||||
" {\"role\": \"user\", \"content\": \"Also, for anything you draft for me: no em dashes, and keep coverage position letters to one page.\"},\n",
|
||||
" {\"role\": \"assistant\", \"content\": \"Understood. No em dashes, and coverage letters kept to one page, for everything I draft for you.\"},\n",
|
||||
" ],\n",
|
||||
" user_id=ADJUSTER_SARAH,\n",
|
||||
" agent_id=CLAIM_AGENT,\n",
|
||||
")\n",
|
||||
"summarize(event)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"And finally, small talk that neither rule set wants."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:46:58.106438Z",
|
||||
"iopub.status.busy": "2026-08-27T09:46:58.106284Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:04.002795Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:04.002018Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"status: SUCCEEDED | created: 0\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"event = add_and_wait(\n",
|
||||
" client,\n",
|
||||
" [\n",
|
||||
" {\"role\": \"user\", \"content\": \"Thanks. Quick one, what's the weather like in Chicago right now?\"},\n",
|
||||
" {\"role\": \"assistant\", \"content\": \"It's 72 degrees and clear in Chicago right now.\"},\n",
|
||||
" ],\n",
|
||||
" user_id=ADJUSTER_SARAH,\n",
|
||||
" agent_id=CLAIM_AGENT,\n",
|
||||
")\n",
|
||||
"summarize(event)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 4. One message, two shelves\n",
|
||||
"\n",
|
||||
"Mem0 does not split a memory across `user_id` and `agent_id`, each extracted fact is attributed to one shelf or the other. When both identifiers are passed to the same `add()` call, Mem0 decides per fact which rule set it matches, so a single exchange that mixes a claim decision with a personal preference comes back split correctly without you doing the routing by hand."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:04.005189Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:04.005036Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:28.624576Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:28.623569Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"status: SUCCEEDED | created: 2\n",
|
||||
" - User prefers claim summaries to be written as bullet points instead of paragraphs\n",
|
||||
" - Assistant noted that subrogation will be pursued against Voss Electrical, with the fire marshal's report identifying faulty wiring as the ignition source\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"event = add_and_wait(\n",
|
||||
" client,\n",
|
||||
" [\n",
|
||||
" {\"role\": \"user\", \"content\": \"I've decided to pursue subrogation against Voss Electrical, the contractor who rewired the warehouse six months ago. The fire marshal's report points to faulty wiring as the ignition source. Also, from now on keep my claim summaries to bullet points, not paragraphs.\"},\n",
|
||||
" {\"role\": \"assistant\", \"content\": \"Noted both. Pursuing subrogation against Voss Electrical based on the fire marshal's faulty-wiring finding, and I'll keep your summaries in bullet points going forward.\"},\n",
|
||||
" ],\n",
|
||||
" user_id=ADJUSTER_SARAH,\n",
|
||||
" agent_id=CLAIM_AGENT,\n",
|
||||
")\n",
|
||||
"summarize(event)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"One exchange produced two memories on two different shelves: a bullet-point formatting preference for Sarah, and a subrogation decision for the claim. Notice the cause of loss (faulty wiring) never got its own memory this run, Mem0 folded it into the subrogation memory's reasoning. Extraction makes judgment calls like that, so read what was actually stored instead of assuming."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 5. Verify the split\n",
|
||||
"\n",
|
||||
"`get_all()` with a `filters` dict is the reliable way to check where memories actually landed, scoped to one shelf at a time."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:28.626951Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:28.626768Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:29.109030Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:29.108411Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"2 memories on Sarah's shelf\n",
|
||||
"- User prefers claim summaries to be written as bullet points instead of paragraphs\n",
|
||||
"- User prefers that any drafted documents contain no em dashes and that coverage position letters be limited to one page\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def dump(results, empty_label=\"(none)\"):\n",
|
||||
" if not results:\n",
|
||||
" print(empty_label)\n",
|
||||
" return\n",
|
||||
" for r in results:\n",
|
||||
" print(\"-\", r[\"memory\"])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"sarah_all = client.get_all(filters={\"user_id\": ADJUSTER_SARAH})\n",
|
||||
"print(f\"{sarah_all['count']} memories on Sarah's shelf\")\n",
|
||||
"dump(sarah_all[\"results\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:29.110873Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:29.110737Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:29.597248Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:29.596174Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"4 memories on the claim's shelf\n",
|
||||
"- Assistant noted that subrogation will be pursued against Voss Electrical, with the fire marshal's report identifying faulty wiring as the ignition source\n",
|
||||
"- The structural engineer's report for claim CLM-48211 states that the warehouse requires a full rebuild rather than a repair\n",
|
||||
"- Reserve for claim CLM-48211 was increased to $1.8 million to cover a full rebuild, as indicated by the structural engineer's report\n",
|
||||
"- The building coverage limit for claim CLM-48211 under the Meridian Logistics policy is $2,400,000 with a $25,000 deductible\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"claim_all = client.get_all(filters={\"agent_id\": CLAIM_AGENT})\n",
|
||||
"print(f\"{claim_all['count']} memories on the claim's shelf\")\n",
|
||||
"dump(claim_all[\"results\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Sarah's shelf holds two personal style rules and nothing about the claim. The claim's shelf holds four claim facts, the coverage limit, the reserve change, the engineer's rebuild finding, and the subrogation call with the cause of loss folded in, and nothing about how Sarah likes things written. The small talk from section 3 is on neither shelf, it was correctly dropped."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 6. Day 2\n",
|
||||
"\n",
|
||||
"Sarah comes back the next day and asks for a status update. A search scoped with `OR` across both identifiers pulls from both shelves at once, ranked by relevance to the query."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:29.599237Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:29.599098Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:30.099318Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:30.098227Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"- Reserve for claim CLM-48211 was increased to $1.8 million to cover a full rebuild, as indicated by the structural engineer's report\n",
|
||||
"- The structural engineer's report for claim CLM-48211 states that the warehouse requires a full rebuild rather than a repair\n",
|
||||
"- The building coverage limit for claim CLM-48211 under the Meridian Logistics policy is $2,400,000 with a $25,000 deductible\n",
|
||||
"- User prefers that any drafted documents contain no em dashes and that coverage position letters be limited to one page\n",
|
||||
"- User prefers claim summaries to be written as bullet points instead of paragraphs\n",
|
||||
"- Assistant noted that subrogation will be pursued against Voss Electrical, with the fire marshal's report identifying faulty wiring as the ignition source\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"status_results = client.search(\n",
|
||||
" \"Draft a status update on claim CLM-48211.\",\n",
|
||||
" filters={\"OR\": [{\"user_id\": ADJUSTER_SARAH}, {\"agent_id\": CLAIM_AGENT}]},\n",
|
||||
")\n",
|
||||
"dump(status_results[\"results\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"One query, one search call, both shelves, correctly ranked. This is what makes the split useful day to day, an agent drafting on Sarah's behalf does not need to know ahead of time which shelf a given fact lives on."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 7. A second adjuster opens the same claim\n",
|
||||
"\n",
|
||||
"Marcus has never worked with Sarah and has never touched CLM-48211 before. His personal shelf should be empty."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:30.101305Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:30.101161Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:30.528115Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:30.527276Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0 memories on Marcus's personal shelf\n",
|
||||
"(none)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"marcus_personal = client.get_all(filters={\"user_id\": ADJUSTER_MARCUS})\n",
|
||||
"print(f\"{marcus_personal['count']} memories on Marcus's personal shelf\")\n",
|
||||
"dump(marcus_personal[\"results\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"But the claim's shelf is not private to Sarah, it belongs to the claim. When Marcus opens CLM-48211 cold, he sees exactly what she left behind."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:30.530364Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:30.530205Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:31.017665Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:31.016750Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"- Reserve for claim CLM-48211 was increased to $1.8 million to cover a full rebuild, as indicated by the structural engineer's report\n",
|
||||
"- The structural engineer's report for claim CLM-48211 states that the warehouse requires a full rebuild rather than a repair\n",
|
||||
"- The building coverage limit for claim CLM-48211 under the Meridian Logistics policy is $2,400,000 with a $25,000 deductible\n",
|
||||
"- Assistant noted that subrogation will be pursued against Voss Electrical, with the fire marshal's report identifying faulty wiring as the ignition source\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"marcus_view = client.search(\n",
|
||||
" \"What's going on with CLM-48211?\",\n",
|
||||
" filters={\"OR\": [{\"user_id\": ADJUSTER_MARCUS}, {\"agent_id\": CLAIM_AGENT}]},\n",
|
||||
")\n",
|
||||
"dump(marcus_view[\"results\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Four claim facts, zero of Sarah's personal preferences. Marcus gets full context on the claim without inheriting a single one of her style rules, exactly the separation the two rule sets were set up to produce."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 8. Review, edit, and forget\n",
|
||||
"\n",
|
||||
"Sarah can inspect and prune her own shelf directly."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:31.019536Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:31.019388Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:31.495240Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:31.494231Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"fab356e1-1603-407e-9f99-24a56c08ff6c - User prefers claim summaries to be written as bullet points instead of paragraphs\n",
|
||||
"895f5c47-64bf-44c7-a36f-b37697be5037 - User prefers that any drafted documents contain no em dashes and that coverage position letters be limited to one page\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"sarah_review = client.get_all(filters={\"user_id\": ADJUSTER_SARAH})\n",
|
||||
"for r in sarah_review[\"results\"]:\n",
|
||||
" print(r[\"id\"], \"-\", r[\"memory\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The one-page rule is stale, the carrier switched templates. `delete()` removes a memory by id."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:31.497312Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:31.497155Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:32.650786Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:32.650172Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"- User prefers claim summaries to be written as bullet points instead of paragraphs\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"stale = next(r for r in sarah_review[\"results\"] if \"one page\" in r[\"memory\"].lower() or \"letter\" in r[\"memory\"].lower())\n",
|
||||
"client.delete(stale[\"id\"])\n",
|
||||
"\n",
|
||||
"sarah_after = client.get_all(filters={\"user_id\": ADJUSTER_SARAH})\n",
|
||||
"dump(sarah_after[\"results\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Worth noticing: the no-em-dashes rule and the one-page rule were extracted into a single combined memory, so deleting it for the stale part removed the em-dash rule too. `delete()` removes a whole memory, not a substring of one. To edit a fact in place without losing its neighbors, use `client.update(memory_id, text=...)` to rewrite the text instead of deleting it.\n",
|
||||
"\n",
|
||||
"This notebook created demo data under three throwaway identifiers and changed the project's shared extraction rules to run its examples. Clean both up before you go, delete the demo memories, then restore whatever `custom_instructions` and `agent_custom_instructions` the project had before this notebook touched them."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {
|
||||
"execution": {
|
||||
"iopub.execute_input": "2026-08-27T09:47:32.652435Z",
|
||||
"iopub.status.busy": "2026-08-27T09:47:32.652317Z",
|
||||
"iopub.status.idle": "2026-08-27T09:47:34.183374Z",
|
||||
"shell.execute_reply": "2026-08-27T09:47:34.182528Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"demo memories deleted\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"project instructions restored\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"client.delete_all(user_id=ADJUSTER_SARAH)\n",
|
||||
"client.delete_all(user_id=ADJUSTER_MARCUS)\n",
|
||||
"client.delete_all(agent_id=CLAIM_AGENT)\n",
|
||||
"print(\"demo memories deleted\")\n",
|
||||
"\n",
|
||||
"client.project.update(\n",
|
||||
" custom_instructions=project_snapshot.get(\"custom_instructions\") or \"\",\n",
|
||||
" agent_custom_instructions=project_snapshot.get(\"agent_custom_instructions\") or \"\",\n",
|
||||
")\n",
|
||||
"print(\"project instructions restored\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 9. Recap\n",
|
||||
"\n",
|
||||
"| Concept | This notebook | CoCounsel example |\n",
|
||||
"|---|---|---|\n",
|
||||
"| `user_id` | One claims adjuster, durable across every claim they work | One lawyer |\n",
|
||||
"| `agent_id` | One claim's agent instance, shared by every adjuster who opens it | One case |\n",
|
||||
"| `custom_instructions` | Governs the adjuster's personal shelf | Governs the lawyer's personal shelf |\n",
|
||||
"| `agent_custom_instructions` | Governs the claim's shared shelf | Governs the case's shared shelf |\n",
|
||||
"\n",
|
||||
"The pattern is not specific to insurance. Anywhere a person works inside a longer-lived, shared context, a support agent inside a ticket, a sales rep inside an account, a caseworker inside a file, the same two identifiers and two rule sets separate what belongs to the person from what belongs to the thing they are working on."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.14.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
+207
-36
@@ -1,64 +1,235 @@
|
||||
# Mem0 - The Memory Layer for Your AI Apps
|
||||
# Mem0 TypeScript SDK
|
||||
|
||||
Mem0 is a self-improving memory layer for LLM applications, enabling personalized AI experiences that save costs and delight users. We offer both cloud and open-source solutions to cater to different needs.
|
||||
<p align="center">
|
||||
<a href="https://github.com/mem0ai/mem0">
|
||||
<img src="../docs/images/banner-sm.png" width="800px" alt="Mem0, the memory layer for personalized AI">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center" style="display: flex; justify-content: center; gap: 20px; align-items: center;">
|
||||
<a href="https://trendshift.io/repositories/11194" target="blank">
|
||||
<img src="https://trendshift.io/api/badge/repositories/11194" alt="mem0ai%2Fmem0 | Trendshift" width="250" height="55"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
See the complete [OSS Docs](https://docs.mem0.ai/open-source/node-quickstart).
|
||||
See the complete [Platform API Reference](https://docs.mem0.ai/api-reference).
|
||||
<p align="center">
|
||||
<a href="https://mem0.ai">Learn more</a>
|
||||
·
|
||||
<a href="https://mem0.dev/DiG">Join Discord</a>
|
||||
·
|
||||
<a href="https://mem0.dev/demo">Demo</a>
|
||||
</p>
|
||||
|
||||
## 1. Installation
|
||||
<p align="center">
|
||||
<a href="https://mem0.dev/DiG">
|
||||
<img src="https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white" alt="Mem0 Discord">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/mem0ai">
|
||||
<img src="https://img.shields.io/npm/dm/mem0ai" alt="Mem0 npm downloads">
|
||||
</a>
|
||||
<a href="https://github.com/mem0ai/mem0">
|
||||
<img src="https://img.shields.io/github/commit-activity/m/mem0ai/mem0?style=flat-square" alt="GitHub commit activity">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/mem0ai" target="blank">
|
||||
<img src="https://img.shields.io/npm/v/mem0ai?color=%2334D058&label=npm%20package" alt="npm package version">
|
||||
</a>
|
||||
<a href="https://www.ycombinator.com/companies/mem0">
|
||||
<img src="https://img.shields.io/badge/Y%20Combinator-S24-orange?style=flat-square" alt="Y Combinator S24">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
For the open-source version, you can install the Mem0 package using npm:
|
||||
Mem0 gives AI assistants and agents persistent memory. It extracts useful facts from conversations, scopes them to a user, agent, or run, and retrieves the relevant facts for later interactions. The TypeScript package, `mem0ai` on npm, includes `MemoryClient` for the hosted Mem0 Platform, imported from `mem0ai`, and `Memory` for open-source, in-process memory, imported from `mem0ai/oss`.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js 20 or later
|
||||
- Hosted Platform: `MEM0_API_KEY` from the [Mem0 dashboard](https://app.mem0.ai/dashboard/api-keys)
|
||||
- Open source with the default providers: `OPENAI_API_KEY`
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm i mem0ai
|
||||
npm install mem0ai
|
||||
```
|
||||
|
||||
## 2. API Key Setup
|
||||
## Platform or open source
|
||||
|
||||
For the cloud offering, sign in to [Mem0 Platform](https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=mem0-ts-readme) to obtain your API Key.
|
||||
| | Platform (`MemoryClient`) | Open source (`Memory`) |
|
||||
| ------------------- | --------------------------------------- | --------------------------------------------------------------------- |
|
||||
| Import | `import { MemoryClient } from "mem0ai"` | `import { Memory } from "mem0ai/oss"` |
|
||||
| Where memories live | Mem0's hosted API | Your configured vector store |
|
||||
| Required key | `MEM0_API_KEY` | `OPENAI_API_KEY` with the defaults, or keys for your chosen providers |
|
||||
| Extraction | Managed and asynchronous | Runs against your configured LLM |
|
||||
| Best for | Zero-ops production use | Local development and custom infrastructure |
|
||||
|
||||
## 3. Client Features
|
||||
## Platform quickstart
|
||||
|
||||
### Cloud Offering
|
||||
Set `MEM0_API_KEY`, then add a conversation:
|
||||
|
||||
The cloud version provides a comprehensive set of features, including:
|
||||
```ts
|
||||
import { MemoryClient, type Message } from "mem0ai";
|
||||
|
||||
- **Memory Operations**: Perform CRUD operations on memories.
|
||||
- **Search Capabilities**: Search for relevant memories using advanced filters.
|
||||
- **Memory History**: Track changes to memories over time.
|
||||
- **Error Handling**: Robust error handling for API-related issues.
|
||||
- **Async/Await Support**: All methods return promises for easy integration.
|
||||
const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
|
||||
|
||||
### Open-Source Offering
|
||||
const messages: Message[] = [
|
||||
{ role: "user", content: "I am vegetarian and allergic to nuts." },
|
||||
{ role: "assistant", content: "I will remember that." },
|
||||
];
|
||||
await client.add(messages, { userId: "alex" });
|
||||
```
|
||||
|
||||
The open-source version includes the following top features:
|
||||
Hosted `add()` queues extraction and usually returns an `eventId` with `status: "PENDING"`. Do not search immediately after `add()`. Wait for processing to finish in the dashboard, or use a [`memory_add` webhook](https://docs.mem0.ai/platform/features/webhooks), then search:
|
||||
|
||||
- **Memory Management**: Add, update, delete, and retrieve memories.
|
||||
- **Vector Store Integration**: Supports various vector store providers for efficient memory retrieval.
|
||||
- **LLM Support**: Integrates with multiple LLM providers for generating responses.
|
||||
- **Customizable Configuration**: Easily configure memory settings and providers.
|
||||
- **SQLite Storage**: Use SQLite for memory history management.
|
||||
```ts
|
||||
import { MemoryClient } from "mem0ai";
|
||||
|
||||
## 4. Memory Operations
|
||||
const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
|
||||
const results = await client.search("What does Alex eat?", {
|
||||
filters: { user_id: "alex" },
|
||||
topK: 5,
|
||||
});
|
||||
console.log(results.results);
|
||||
```
|
||||
|
||||
Mem0 provides a simple and customizable interface for performing memory operations. You can create long-term and short-term memories, search for relevant memories, and manage memory history.
|
||||
`search()` and `getAll()` take entity IDs inside `filters` with snake_case keys. `add()` and `deleteAll()` take `userId`, `agentId`, or `runId` as top-level camelCase options.
|
||||
|
||||
## 5. Error Handling
|
||||
## Open-source quickstart
|
||||
|
||||
The MemoryClient throws errors for any API-related issues. You can catch and handle these errors effectively.
|
||||
Set `OPENAI_API_KEY` before using the default OpenAI LLM and embedder:
|
||||
|
||||
## 6. Using with async/await
|
||||
```ts
|
||||
import { Memory } from "mem0ai/oss";
|
||||
|
||||
All methods of the MemoryClient return promises, allowing for seamless integration with async/await syntax.
|
||||
const memory = new Memory();
|
||||
|
||||
## 7. Testing the Client
|
||||
const messages = [
|
||||
{ role: "user", content: "I am vegetarian and allergic to nuts." },
|
||||
{ role: "assistant", content: "I will remember that." },
|
||||
];
|
||||
await memory.add(messages, { userId: "alex" });
|
||||
|
||||
To test the MemoryClient in a Node.js environment, you can create a simple script to verify the functionality of memory operations.
|
||||
const results = await memory.search("What does Alex eat?", {
|
||||
filters: { user_id: "alex" },
|
||||
topK: 5,
|
||||
});
|
||||
console.log(results.results);
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
The default `Memory` configuration uses OpenAI `gpt-5-mini`, OpenAI `text-embedding-3-small`, a SQLite-backed vector store at `~/.mem0/vector_store.db`, and a SQLite history database at `memory.db`. Pass a config object to `Memory` to change the LLM, embedder, vector store, history path, or reranker.
|
||||
|
||||
If you have any questions or need assistance, please reach out to us:
|
||||
## Configuration and features
|
||||
|
||||
| Feature | Documentation |
|
||||
| ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| Memory operations: `add`, `search`, `get`, `getAll`, `update`, `delete`, `deleteAll`, `history`, all async and Promise-based | [Node quickstart](https://docs.mem0.ai/open-source/node-quickstart) |
|
||||
| Entity scoping with `userId`, `agentId`, and `runId` | [Entity-scoped memory](https://docs.mem0.ai/platform/features/entity-scoped-memory) |
|
||||
| Metadata and filters | [Metadata filtering](https://docs.mem0.ai/open-source/features/metadata-filtering) |
|
||||
| LLMs, embedders, vector stores, and rerankers | [Components](https://docs.mem0.ai/components/llms/overview) |
|
||||
| Graph memory | [Graph memory](https://docs.mem0.ai/platform/features/graph-memory) |
|
||||
| Custom instructions | [Custom instructions](https://docs.mem0.ai/open-source/features/custom-instructions) |
|
||||
| Multimodal input | [Multimodal support](https://docs.mem0.ai/open-source/features/multimodal-support) |
|
||||
| Platform webhooks, export, feedback, expiration, and custom categories | [Platform features](https://docs.mem0.ai/platform/features) |
|
||||
|
||||
## Benchmarks
|
||||
|
||||
<p align="center">
|
||||
<a href="https://mem0.ai/research"><strong>Benchmarking Mem0's token-efficient memory algorithm</strong></a>
|
||||
</p>
|
||||
|
||||
| Benchmark | Old | New | Tokens | Latency p50 |
|
||||
| --------------- | ---: | -------: | -----: | ----------: |
|
||||
| **LoCoMo** | 71.4 | **92.5** | 7.0K | 0.88s |
|
||||
| **LongMemEval** | 67.8 | **94.4** | 6.8K | 1.09s |
|
||||
| **BEAM (1M)** | n/a | **64.1** | 6.7K | 1.00s |
|
||||
| **BEAM (10M)** | n/a | **48.6** | 6.9K | 1.05s |
|
||||
|
||||
All benchmarks use the same production-representative model stack, single-pass retrieval, and a top-200 retrieval budget. Scores reflect the managed Platform, which includes proprietary optimizations not available in the open-source SDK. Open-source results should show similar directional gains, but may not match these scores.
|
||||
|
||||
The current algorithm uses single-pass ADD-only extraction, first-class agent facts, entity linking, multi-signal retrieval, and temporal reasoning. Read the [research paper](https://mem0.ai/research), the [migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3), or the open-source [evaluation framework](https://github.com/mem0ai/memory-benchmarks).
|
||||
|
||||
## Self-hosted server
|
||||
|
||||
Run Mem0 as a FastAPI service with PostgreSQL, pgvector, and Neo4j:
|
||||
|
||||
```bash
|
||||
# Recommended: start the stack, create an admin, and issue the first API key.
|
||||
cd server && make bootstrap
|
||||
|
||||
# Manual: start the stack, then finish setup in the browser wizard.
|
||||
cd server && docker compose up -d
|
||||
```
|
||||
|
||||
Self-hosted authentication is enabled by default. See the [self-hosted documentation](https://docs.mem0.ai/open-source/overview) and [upgrade notes](https://docs.mem0.ai/open-source/setup#upgrade-notes).
|
||||
|
||||
## CLI
|
||||
|
||||
Manage hosted memories from your terminal:
|
||||
|
||||
```bash
|
||||
npm install -g @mem0/cli
|
||||
|
||||
mem0 init
|
||||
mem0 add "Prefers dark mode and vim keybindings" --user-id alice
|
||||
mem0 search "What does Alice prefer?" --user-id alice
|
||||
```
|
||||
|
||||
AI agents can create an account without email or a dashboard:
|
||||
|
||||
```bash
|
||||
mem0 init --agent --agent-caller claude-code
|
||||
```
|
||||
|
||||
The human owner can claim the account later with `mem0 init --email <their-email>`. The API key and memories remain unchanged. See the [CLI documentation](https://docs.mem0.ai/platform/cli) and [agent signup guide](https://docs.mem0.ai/platform/agent-signup).
|
||||
|
||||
## Agent skills
|
||||
|
||||
Install reference skills to give compatible coding assistants Mem0 context:
|
||||
|
||||
```bash
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-cli
|
||||
```
|
||||
|
||||
Install pipeline skills for end-to-end workflows:
|
||||
|
||||
```bash
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-integrate
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-test-integration
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-oss-to-platform
|
||||
```
|
||||
|
||||
See the [skills catalog](../skills/) or [Vibecoding with Mem0](https://docs.mem0.ai/vibecoding).
|
||||
|
||||
## Integrations and demos
|
||||
|
||||
- [ChatGPT with Memory demo](https://mem0.dev/demo)
|
||||
- [Browser extension](https://chromewebstore.google.com/detail/onihkkbipkfeijkadecaafbgagkhglop?utm_source=item-share-cb)
|
||||
- [LangGraph integration](https://docs.mem0.ai/integrations/langgraph)
|
||||
- [CrewAI integration](https://docs.mem0.ai/integrations/crewai)
|
||||
|
||||
## Documentation and help
|
||||
|
||||
- [Node quickstart](https://docs.mem0.ai/open-source/node-quickstart)
|
||||
- [Platform quickstart](https://docs.mem0.ai/platform/quickstart)
|
||||
- [API reference](https://docs.mem0.ai/api-reference)
|
||||
- [Discord](https://mem0.dev/DiG)
|
||||
- [GitHub issues](https://github.com/mem0ai/mem0/issues)
|
||||
- Email: founders@mem0.ai
|
||||
- [Join our discord community](https://mem0.ai/discord)
|
||||
- GitHub Issues: [Report bugs or request features](https://github.com/mem0ai/mem0/issues)
|
||||
|
||||
## Contributing
|
||||
|
||||
Read [CONTRIBUTING.md](https://github.com/mem0ai/mem0/blob/main/CONTRIBUTING.md) before opening an issue or pull request.
|
||||
|
||||
## Citation
|
||||
|
||||
```bibtex
|
||||
@article{mem0,
|
||||
title={Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory},
|
||||
author={Chhikara, Prateek and Khant, Dev and Aryan, Saket and Singh, Taranjeet and Yadav, Deshraj},
|
||||
journal={arXiv preprint arXiv:2504.19413},
|
||||
year={2025}
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0. See [LICENSE](https://github.com/mem0ai/mem0/blob/main/LICENSE).
|
||||
|
||||
Reference in New Issue
Block a user