Compare commits

..
Author SHA1 Message Date
Himanshu-Sangshetti c05e889c73 fix(minimax-mem0): convert to Agent Plugins 1.0 format (plugin.json + mcp.json at root)
The runtime imports validate against the open Agent Plugins 1.0 spec
(agent-plugins.org), not the Feishu submission guide's .minimax-plugin/ layout.
Discovered via the in-app import (GitHub Plugin cannot be imported).
2026-08-31 22:34:00 +05:30
Himanshu-Sangshetti 9b7001e44c docs(minimax-mem0): clarify OAuth-only auth in the package + fix MCP URL trailing slash (review) 2026-08-31 18:41:32 +05:30
Himanshu-Sangshetti fa80bfdb3f docs(minimax-mem0): drop internal submission/review notes from repo files 2026-08-31 18:36:08 +05:30
Himanshu-Sangshetti 57b0846784 chore(minimax-mem0): add Apache LICENSE, UTM key link, AGENTS.md rows (plugin conventions) 2026-08-31 18:34:08 +05:30
Himanshu-Sangshetti c9a0c19ac2 feat(integrations): minimax-mem0 — Mem0 plugin for the MiniMax Marketplace
A declarative MiniMax plugin (MiniMax Code desktop / MiniMax Agent cloud) that
gives an agent persistent long-term memory via Mem0.

- MCP capability points at Mem0's hosted server (https://mcp.mem0.ai/mcp/,
  streamable-http); no secrets in the package.
- Skill (skills/memory/SKILL.md) tells the agent when to recall, save, update,
  and delete memory.
- Manifest, icon (180x180), and structure follow the MiniMax plugin spec;
  validated against the submission checklist and size limits.

Open item for MiniMax review: the MCP endpoint is authenticated (OAuth or
API-key bearer), so confirm whether it ships as a remote MCP (runtime handles
the OAuth handshake) or via the App/Connector path.
2026-08-31 16:37:48 +05:30
KartikandGitHub 19cb89aff4 docs: add 301 redirects for 49 legacy 404 pages (#7161) 2026-08-28 17:44:10 +05:30
fdfb763d6e docs(api-reference): add Dream (memory synthesis) endpoints (#7109)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-27 22:12:04 +05:30
20 changed files with 1423 additions and 1123 deletions
@@ -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" />
+211 -2
View File
@@ -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",
@@ -1302,6 +1315,202 @@
{
"source": "/api-reference/entities/get-entities",
"destination": "/api-reference/entities/get-users"
},
{
"source": "/api-reference/event/get-events",
"destination": "/api-reference/events/get-events"
},
{
"source": "/api-reference/entities/delete-users",
"destination": "/api-reference/entities/delete-user"
},
{
"source": "/api-reference/organization/update-organization-member",
"destination": "/api-reference/organization/update-org-member"
},
{
"source": "/api-reference/organization/get-organizations",
"destination": "/api-reference/organization/get-orgs"
},
{
"source": "/api-reference/entities/get-user",
"destination": "/api-reference/entities/get-users"
},
{
"source": "/api-reference/export/create-memory-export",
"destination": "/api-reference/memory/create-memory-export"
},
{
"source": "/integrations/mcp",
"destination": "/platform/mem0-mcp"
},
{
"source": "/platform/api-reference",
"destination": "/api-reference"
},
{
"source": "/api-reference/memory/add-memory",
"destination": "/api-reference/memory/add-memories"
},
{
"source": "/api-reference/overview",
"destination": "/api-reference"
},
{
"source": "/platform/reference/python-sdk",
"destination": "/open-source/python-quickstart"
},
{
"source": "/platform/python",
"destination": "/open-source/python-quickstart"
},
{
"source": "/platform/features/memory",
"destination": "/platform/features/memory-decay"
},
{
"source": "/platform/api-reference/python",
"destination": "/open-source/python-quickstart"
},
{
"source": "/api-reference/webhooks",
"destination": "/api-reference/webhook/create-webhook"
},
{
"source": "/platform/python-quickstart",
"destination": "/open-source/python-quickstart"
},
{
"source": "/api-reference/organization/delete-org-project",
"destination": "/api-reference/organization/delete-org"
},
{
"source": "/platform/features/scoping",
"destination": "/platform/features/entity-scoped-memory"
},
{
"source": "/platform/quickstart/python",
"destination": "/open-source/python-quickstart"
},
{
"source": "/api-reference/memory/history",
"destination": "/api-reference/memory/history-memory"
},
{
"source": "/api-reference/entities/get-user-memories",
"destination": "/api-reference/entities/get-users"
},
{
"source": "/platform/api-reference/webhooks/create",
"destination": "/api-reference/webhook/create-webhook"
},
{
"source": "/platform/python/quickstart",
"destination": "/open-source/python-quickstart"
},
{
"source": "/api-reference/memory/batch-update-memory",
"destination": "/api-reference/memory/batch-update"
},
{
"source": "/api-reference/memories/add",
"destination": "/api-reference/memory/add-memories"
},
{
"source": "/python-quickstart",
"destination": "/open-source/python-quickstart"
},
{
"source": "/api-reference/webhook/list-webhooks",
"destination": "/api-reference/webhook/get-webhook"
},
{
"source": "/platform/reference/memory/delete-memory",
"destination": "/api-reference/memory/delete-memory"
},
{
"source": "/platform/webhooks",
"destination": "/platform/features/webhooks"
},
{
"source": "/platform/api-reference/memories/add",
"destination": "/api-reference/memory/add-memories"
},
{
"source": "/api-reference/organization/organizations",
"destination": "/api-reference/organization/create-org"
},
{
"source": "/sdk/python/quickstart",
"destination": "/open-source/python-quickstart"
},
{
"source": "/platform/export",
"destination": "/platform/features/memory-export"
},
{
"source": "/open-source/python-memory",
"destination": "/open-source/python-quickstart"
},
{
"source": "/platform/reference",
"destination": "/api-reference"
},
{
"source": "/api-reference/memory/get-all-memories",
"destination": "/api-reference/memory/get-memories"
},
{
"source": "/api-reference/user/delete-users",
"destination": "/api-reference/entities/delete-user"
},
{
"source": "/api-reference/memories/search-memories",
"destination": "/api-reference/memory/search-memories"
},
{
"source": "/api-reference/organization/update-members",
"destination": "/api-reference/project/update-project-member"
},
{
"source": "/platform/api-reference/memory/batch-update",
"destination": "/api-reference/memory/batch-update"
},
{
"source": "/api-reference/memory/search",
"destination": "/api-reference/memory/search-memories"
},
{
"source": "/api-reference/batch/update-memories",
"destination": "/api-reference/memory/batch-update"
},
{
"source": "/api-reference/organization/update-organization-member-role",
"destination": "/api-reference/project/update-project-member"
},
{
"source": "/api-reference/webhooks/delete",
"destination": "/api-reference/webhook/delete-webhook"
},
{
"source": "/api-reference/memory/delete-all-memories",
"destination": "/api-reference/memory/delete-memories"
},
{
"source": "/platform/reference/overview",
"destination": "/api-reference"
},
{
"source": "/api-reference/mem0/add-memories",
"destination": "/api-reference/memory/add-memories"
},
{
"source": "/platform/mcp/overview",
"destination": "/platform/mem0-mcp"
},
{
"source": "/openmemory/mcp/introduction",
"destination": "https://mem0.ai/blog/introducing-openmemory-mcp"
}
]
}
+10 -1
View File
@@ -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.
+863
View File
@@ -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
}
+2
View File
@@ -13,6 +13,7 @@ Agent and editor integrations. Each subdirectory is self-contained: its own `pac
| `n8n-nodes-mem0/` | `@mem0/n8n-nodes-mem0` | tsc | ESLint (n8n-nodes-base) | none |
| `zapier-mem0/` | `@mem0/zapier` | tsc | none | offline unit tests + `zapier validate` |
| `mem0-strands/` | `mem0-strands` (PyPI) | hatch | Ruff + mypy | pytest |
| `minimax-mem0/` | MiniMax Marketplace plugin | none (declarative) | none | JSON/manifest validation |
pnpm everywhere except `.opencode-plugin/` (Bun) and `mem0-strands/` (Python: pip / hatch). Never npm, never yarn.
@@ -44,6 +45,7 @@ Run the type check after every TypeScript change: `pnpm run typecheck` or `tsc -
- **`openclaw/`**, **`pi-agent-plugin/`**, **`deepseek-plugin/`** are editor and agent plugins with the same shape. `deepseek-plugin/` registers Mem0 search/add tools as a native DeepSeek Harness (Cordis) plugin.
- **`n8n-nodes-mem0/`** is an n8n community node: add, search, get, update, delete.
- **`zapier-mem0/`** is a Zapier Platform CLI app: add, search, get, delete. It deploys to Zapier, not npm, so it is **not** in the release router. Deploy it with `gh workflow run zapier-mem0-cd.yml --ref main` (needs the `ZAPIER_DEPLOY_KEY` secret).
- **`minimax-mem0/`** is a declarative MiniMax Marketplace plugin (no build step): a `.minimax-plugin/plugin.json` manifest plus an MCP capability pointing at the hosted Mem0 MCP server (`https://mcp.mem0.ai/mcp/`) and a memory Skill. It ships to the MiniMax Marketplace as a subdirectory, not through the release router or npm/PyPI.
- **`mem0-strands/`** is a native Strands `MemoryStore` (Python, published to PyPI as `mem0-strands`). It plugs into the Strands `MemoryManager` for automatic recall and server-side extraction, over the hosted Mem0 platform or self-hosted Mem0 OSS. The package lives under `mem0-strands/python/`.
## Adding an integration
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [2023] [Taranjeet Singh]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+35
View File
@@ -0,0 +1,35 @@
# minimax-mem0
The [Mem0](https://mem0.ai) plugin for the MiniMax Marketplace (MiniMax Code desktop and MiniMax Agent cloud).
It gives a MiniMax agent persistent long-term memory: it remembers the user's preferences, decisions, and project context across sessions and recalls them on demand.
## What's in the package
This is a declarative MiniMax plugin (no build step). It follows the MiniMax plugin spec:
Built to the [Agent Plugins 1.0](https://agent-plugins.org/specification) standard, which the MiniMax runtime imports and validates against.
```
minimax-mem0/
plugin.json # manifest (Agent Plugins 1.0, at plugin root)
mcp.json # remote MCP: https://mcp.mem0.ai/mcp/ (auto-discovered at root)
icon.png # square Mem0 icon
skills/
memory/
SKILL.md # when to recall / save / update memory
```
Two capabilities:
- **MCP** (`mcp.json`) points at Mem0's hosted MCP server (`https://mcp.mem0.ai/mcp/`), which exposes the memory tools (`add_memory`, `search_memories`, `update_memory`, `delete_memory`, and more). No secrets are stored in the package.
- **Skill** (`skills/memory/SKILL.md`) tells the agent when to search, save, update, and delete memory so recall happens automatically.
## Authentication
Mem0's MCP server requires authentication. Per the MiniMax plugin spec, no credentials are placed in this package; the MiniMax client authorizes the user's Mem0 account through the MCP OAuth flow on first use. Users get a Mem0 account from the [Mem0 dashboard](https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-minimax).
## Links
- Mem0: https://mem0.ai
- Mem0 MCP docs: https://docs.mem0.ai/platform/mem0-mcp
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

+9
View File
@@ -0,0 +1,9 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"mem0": {
"type": "streamable-http",
"url": "https://mcp.mem0.ai/mcp/"
}
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "mem0",
"version": "0.1.0",
"description": "Persistent long-term memory for your agent: remember preferences, decisions, and project context across sessions, and recall them on demand.",
"author": { "name": "Mem0", "email": "support@mem0.ai", "url": "https://mem0.ai" },
"homepage": "https://mem0.ai",
"repository": "https://github.com/mem0ai/mem0",
"license": "Apache-2.0",
"keywords": ["memory", "long-term-memory", "personalization", "mcp"]
}
@@ -0,0 +1,41 @@
---
name: memory
description: Use Mem0 to persist and recall long-term memory across sessions - the user's preferences, decisions, project context, and durable facts.
---
You have access to Mem0 long-term memory through the `mem0` MCP server. Use it so the
user does not have to repeat themselves across sessions.
## When to recall (search memory)
At the start of a task, and whenever the user references something they expect you to
already know ("my project", "like last time", "the usual"), search memory before asking.
- Call the memory search tool with a short natural-language query describing what you
need (e.g. "preferred language and package manager", "deployment process").
- Use the returned memories as context. Do not announce that you searched; just apply
what you found.
- If nothing relevant comes back, proceed and ask the user only for what is missing.
## When to save (add memory)
Save durable facts as they come up, without being asked:
- Stated preferences ("I use pnpm", "always use TypeScript", "no comments in code").
- Decisions and conventions ("we deploy on Fridays", "the API base is X").
- Stable facts about the user, their team, or their project (stack, roles, goals).
Do not save transient or trivial details (a one-off value, a temporary path, secrets,
or anything the user would not want remembered). Save one clear fact per memory, phrased
so it makes sense on its own later.
## When to update or delete
If a new statement contradicts something you recalled, update that memory rather than
adding a duplicate. If the user says to forget something, delete it.
## Boundaries
- Never store secrets, credentials, API keys, or sensitive personal data.
- Memory is scoped to the connected Mem0 account; keep one user's memories to that user.
- Prefer recalling silently over interrupting the user to confirm what you already know.