Compare commits

...

46 Commits

Author SHA1 Message Date
kartik-mem0 6b2850c30f Merge branch 'main' into fix/client-host-env
# Conflicts:
#	tests/test_client.py
2026-08-14 17:17:28 +05:30
Kartik 290de24bb8 feat(ci): gate pull requests on an accepted issue (#6894) 2026-08-14 17:05:27 +05:30
Ratish jain ef6f51d977 fix(tests): check for RediSearch module availability in Redis tests (#6687) 2026-08-14 17:00:56 +05:30
Kartik a10c0cd030 fix(mem0-plugin): stop search errors from looking like empty results (#6898) 2026-08-14 16:57:01 +05:30
Kartik 956bf4f88e fix(ts-oss): return snake_case entity ids from the redis and valkey stores (#6902) 2026-08-14 16:56:27 +05:30
Kartik 0f172c2890 fix(ts-oss): stop prototype keys from short-circuiting embedding lookup (#6903) 2026-08-14 16:56:03 +05:30
Kartik 696455fd62 docs: contrast the advanced retrieval modes with distinct examples (#6904) 2026-08-14 16:55:44 +05:30
Kartik 9e99eaadbc docs: correct memory decay claims that contradict the SDK (#6905) 2026-08-14 16:55:26 +05:30
Kartik 02ff6c5595 feat(cli): add a version subcommand and document the --filter JSON shape (#6907) 2026-08-14 16:55:12 +05:30
Kartik a0329f047b docs(cookbooks): repair dead references and label OSS vs Platform support (#6909) 2026-08-14 16:50:46 +05:30
Kartik c50a2bfb8f docs(llms): fix wrong read snippets, dead reranking link, and 24 mis-scoped integration tags (#6950) 2026-08-14 16:50:23 +05:30
Kartik bfb51c6b93 fix(client): honor page_size in get_all when page is not passed (#6900) 2026-08-14 16:49:58 +05:30
Kartik a133287015 fix(llms/aws_bedrock): resolve provider for application inference profile ARNs (#6899) 2026-08-14 16:49:37 +05:30
Kartik c883f52130 fix(llms/vllm): honor VLLM_BASE_URL instead of always using localhost (#6897) 2026-08-14 16:49:18 +05:30
kartik-mem0 d371c1d931 fix(client): honor MEM0_HOST and MEM0_API_URL environment variables
MemoryClient and AsyncMemoryClient hardcoded the default host, so a
self-hosted or proxied deployment had to pass host= at every construction
site even with MEM0_HOST exported. The API key already reads from the
environment; the host now does too.

Resolution order: explicit host argument, MEM0_HOST, MEM0_API_URL, then
https://api.mem0.ai. Existing callers are unaffected.

Closes #6622
2026-08-13 17:31:23 +05:30
Kartik 96d45b78c7 fix(mem0-plugin): drop unused pytest import breaking make lint on main (#6937) 2026-08-13 16:51:01 +05:30
Himanshu ba2fb9f4c3 feat(kimi): Mem0 plugin for Kimi Code (MCP + skills + auto-capture) (#6919) 2026-08-13 16:15:04 +05:30
Kartik 14c431735b fix(cli): surface agent_custom_instructions on add in both CLIs (#6910) 2026-08-12 20:08:34 +05:30
Anas Khan d70cc00ab3 docs(components): point config links to provider overviews (#6126)
Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
2026-08-12 16:11:46 +05:30
Kartik c427a453a8 docs(changelog): backfill Python v2.0.18 and TypeScript v3.1.6 SDK entries (#6918) 2026-08-12 00:25:18 +05:30
Kartik f5b4300449 docs: redirect deprecated OSS graph memory page to platform graph memory (#6914) 2026-08-12 00:25:02 +05:30
Kartik 71f2ebefa3 fix(memory): escape delimiters when building the session scope key (#6892) 2026-08-11 23:23:55 +05:30
Hrushikesh Yadav 35a125585e fix(pgvector): raise ValueError when 'in'/'nin' filter value is not a list (#6879) 2026-08-11 20:15:07 +05:30
Harsh Vardhan Gupta 4debc58a83 fix(security): patch 8 HIGH + 18 MEDIUM Vanta vulnerabilities across 4 pnpm workspaces (#6847) 2026-08-07 19:04:33 +05:30
mintlify[bot] b42cfdd5c8 Fix broken links: unblock link check in oracledb.mdx (#6849)
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
2026-08-07 18:16:06 +05:30
Elif Sema Balcioglu 6fe6140dba fix(vector-stores/oracledb): Fix accuracy bug (#6848) 2026-08-07 18:07:12 +05:30
Diwakar Ray Yadav b05dc2740f docs(memory): note filters-based scoping for search/get_all on add() (#6758) 2026-08-07 14:03:09 +05:30
Kartik 4a0a9a92a6 fix(ts-oss, py): release Oracle client on init failure, validate insert batches (#6839) 2026-08-06 18:16:25 +05:30
Kartik beea626f0a perf(ts-oss): cut Oracle vector store round trips per review feedback (#6835) 2026-08-06 15:12:14 +05:30
Himanshu 3f39fba28f fix(n8n): MIT license + themed icons for verified-node vetting (#6804)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-08-06 00:00:13 +05:30
Saket Aryan 12c47f5249 feat(sdk, docs): expose agent_custom_instructions for agent-scoped extraction (#6809) 2026-08-05 22:12:10 +05:30
Kartik 3f717e5459 docs: frame graph memory as a Platform feature, removed from OSS (#6808) 2026-08-05 18:17:07 +05:30
Kartik 18021dd106 feat(ts-oss): add Oracle AI Vector Search vector store (#6690) 2026-08-05 10:55:33 +05:30
pratik fad0e0e415 fix(ts-sdk): await identity before building project-scoped URLs (#6802) 2026-08-04 16:31:18 -07:00
Kartik 1112be3e5e chore(release): bump SDK, CLI, and plugin versions (#6800) 2026-08-05 00:16:26 +05:30
pratik 6052252250 fix(ts-sdk): take /v1/ping/ off the request critical path (#6788) 2026-08-04 10:37:50 -07:00
mintlify[bot] deca4bd3a5 SEO & metadata audit: trim Dream page description under 160 chars (#6793)
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
2026-08-04 14:18:56 +00:00
Karthik 4cfcd0241a docs: add Dream feature page (#6689)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 19:45:07 +05:30
Himanshu b54710a3c3 fix(zapier): require user_id on Add Memory (#6790) 2026-08-04 18:49:35 +05:30
Himanshu 4cfa98f626 chore(n8n): route package contact to integrations@mem0.ai (#6791) 2026-08-04 17:39:20 +05:30
Rod Boev b830b99abe fix(ts-oss): strip identity scope from add() metadata (#6377)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-08-04 17:11:50 +05:30
Abhinav Singh 45208feebb fix(memory): stop add() metadata from setting a memory's identity scope (#6656) 2026-08-04 16:46:47 +05:30
Hrushikesh Yadav 3ac9ba4b50 fix(upstash): escape quotes in filter values and validate filter types (#5981) 2026-08-04 15:16:24 +05:30
Himanshu 965140eb19 fix(zapier): add root index.js entry shim so deployed app resolves (#6789) 2026-08-04 12:48:46 +05:30
soumil-rathi 6e6f5b8d59 docs(temporal): clarify feature behavior and usage (#6780)
Co-authored-by: Soumil Rathi <soumilrathi@gmail.com>
2026-08-03 11:42:43 -07:00
Kartik dd54e387de docs(openapi): document limit param and error responses on GET /v1/memories/ (#6779) 2026-08-03 23:56:12 +05:30
198 changed files with 7468 additions and 1766 deletions
+1 -1
View File
@@ -12,7 +12,7 @@
"name": "mem0",
"source": "./integrations/mem0-plugin",
"description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search to Claude workflows.",
"version": "0.2.13"
"version": "0.2.14"
}
]
}
+1 -1
View File
@@ -12,7 +12,7 @@
"name": "mem0",
"source": "./integrations/mem0-plugin",
"description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search.",
"version": "0.2.13"
"version": "0.2.14"
}
]
}
+102
View File
@@ -0,0 +1,102 @@
# CI/CD and repository automation (`.github/`)
> **Do not modify any workflow without explicit approval from a maintainer.** Publishing
> credentials are bound to workflow filenames, and the gate workflows decide whether
> contributions are accepted. Read this file before proposing any change here.
## CI: one gate, many pipelines
`ci-gate.yml` (**CI Gate**) is the single entry point. It runs on every PR, detects which packages changed, and calls only the relevant package workflows as reusable workflows (`workflow_call`). Its final `CI Gate` job aggregates the results: skipped pipelines pass, failed or cancelled ones fail. It is the **only CI status check that needs to be required** in branch protection.
Package workflows keep their own push-to-main and manual triggers. Their `pull_request` triggers live in the gate's path filters instead.
| Workflow | File | Standalone triggers | Runs |
|----------|------|---------------------|------|
| CI Gate | `ci-gate.yml` | All PRs | Routes to and aggregates everything below |
| Python SDK | `ci.yml` | Push to main | Ruff + pytest on Python 3.10, 3.11, 3.12 |
| TypeScript SDK | `ts-sdk-ci.yml` | Push to main (`mem0-ts/`) | Prettier + build + jest on Node 20, 22 |
| Python CLI | `cli-python-ci.yml` | Push to main (`cli/python/`), manual | Ruff + pytest + hatch build on Python 3.10, 3.11, 3.12 |
| Node CLI | `cli-node-ci.yml` | Push to main (`cli/node/`), manual | Biome + tsc + vitest + tsup on Node 20, 22 |
| OpenClaw | `openclaw-checks.yml` | Push to main (`integrations/openclaw/`), manual | tsc + vitest (Codecov) + tsup on Node 20, 22 |
| Mem0 Plugin | `mem0-plugin-checks.yml` | Push to main (`integrations/mem0-plugin/`, excluding `.opencode-plugin/`), manual | pytest + hook exec bits + JSON manifest validation on Python 3.10, 3.11, 3.12 |
| OpenCode Plugin | `opencode-plugin-checks.yml` | Push to main (`.opencode-plugin/`), manual | Bun: tsc + build + dist artifact check |
| Pi Agent Plugin | `pi-agent-plugin-checks.yml` | Push to main (`integrations/pi-agent-plugin/`), manual | tsc + vitest + tsup on Node 20, 22 |
| n8n Node | `n8n-nodes-mem0-checks.yml` | Push to main (`integrations/n8n-nodes-mem0/`), manual | ESLint + tsc build on Node 20 |
| Zapier App | `zapier-mem0-checks.yml` | Push to main (`integrations/zapier-mem0/`), manual | tsc + `zapier validate` + offline unit tests on Node 22 |
| docs llms.txt | `docs-llms-txt-check.yml` | Manual | `docs/llms.txt` coverage |
Adding a package CI workflow: give it `workflow_call` plus `push` / `workflow_dispatch` as needed but **no `pull_request` trigger**, then register it in `ci-gate.yml` with a path filter under the `changes` job, a call job, and an entry in the gate job's `needs` list.
## Branch protection on `main`
A repository ruleset named `Main Branch Rule`, id `11813754`. It enforces squash-only merges, linear history, no deletion, no force-push, and one approving review. Two status checks belong in its `required_status_checks` rule:
| Context | Posted by | Why |
|---------|-----------|-----|
| `CI Gate` | `ci-gate.yml` | Aggregates every package pipeline |
| `license/cla` | CLA Assistant | Proves the CLA is signed, not merely requested |
Editing the ruleset requires repo **admin**. `maintain` is not enough, and the API returns 404 rather than 403 in that case. Until `license/cla` is required, the claim in `CONTRIBUTING.md` that unsigned PRs are blocked from merging holds by convention only.
Requiring `CI Gate` also means fork PRs from first-time contributors cannot merge until a maintainer approves the workflow run. Those sit at `action_required`, which is intended behavior.
## CD: one router, many publishers
`release.yml` (**Release Router**) is the only workflow listening to `release: published`. It matches the tag prefix and dispatches the matching package workflow through `workflow_dispatch`, so one release produces exactly one routed run.
| Workflow | File | Tag prefix | Target |
|----------|------|------------|--------|
| Release Router | `release.yml` | all releases | dispatches the rows below |
| Python SDK | `cd.yml` | `v*` | PyPI (`mem0ai`) |
| TypeScript SDK | `ts-sdk-cd.yml` | `ts-v*` | npm (`mem0ai`) |
| Python CLI | `cli-python-cd.yml` | `cli-v*` | PyPI (`mem0-cli`) |
| Node CLI | `cli-node-cd.yml` | `cli-node-v*` | npm (`@mem0/cli`) |
| Vercel AI SDK | `vercel-ai-cd.yml` | `vercel-ai-v*` | npm (`@mem0/vercel-ai-provider`) |
| OpenClaw | `openclaw-cd.yml` | `openclaw-v*` | npm (`@mem0/openclaw-mem0`) |
| OpenCode Plugin | `opencode-plugin-cd.yml` | `opencode-v*` | npm (`@mem0/opencode-plugin`) |
| Pi Agent Plugin | `pi-agent-plugin-cd.yml` | `pi-agent-v*` | npm (`@mem0/pi-agent-plugin`) |
| n8n Node | `n8n-nodes-mem0-cd.yml` | `n8n-nodes-mem0-v*` | npm (`@mem0/n8n-nodes-mem0`) |
- Package CD workflows are `workflow_dispatch`-only, with `tag` and `prerelease` inputs. They check out and build the given tag.
- All publishing uses **OIDC trusted publishing**. No tokens, no secrets.
- Registry trusted-publisher settings are pinned to each package's own workflow **filename**. Renaming a CD workflow breaks publishing for that package.
- First publish of a new npm package must be done manually. OIDC works from the second version onward.
- To re-publish a release, do **not** delete and recreate the GitHub release. Dispatch the workflow directly: `gh workflow run <package>-cd.yml --ref refs/tags/<tag> -f tag=<tag>`.
- The Zapier app deploys to Zapier's platform, not npm, so it is not in the router. Deploy with `gh workflow run zapier-mem0-cd.yml --ref main`.
- Adding a package: add its CD workflow, then register its tag prefix in the `case` block in `release.yml`, keeping the bare `v*` arm last.
## Contribution gates
| Workflow | File | Purpose |
|----------|------|---------|
| PR Gate | `pr-gate.yml` | Closes PRs that do not link an issue labeled `accepted`, with a reopen path. Exempts members, bots, drafts, and docs-only changes. Never checks out PR code. |
| Vouch (check PR) | `vouch-check-pr.yml` | Comments on PRs from authors absent from `VOUCHED.td`. Comment-only mode (`auto-close: false`). |
| Vouch (manage list) | `vouch-manage-by-issue.yml` | Maintainers edit the trust list by commenting `!vouch @user`, `!denounce @user`, or `!unvouch @user` on any issue. Commits back to `VOUCHED.td` through a GitHub App token. |
| Issue Labeler | `issue-labeler.yml` | Labels issues from the `component` field in the issue forms |
| PR Labeler | `pr-labeler.yml` | Path-based labels, plus propagating labels from linked issues |
| Stale Bot | `stale.yml` | Marks stale issues and PRs |
| llms.txt Check | `docs-llms-txt-check.yml` | Blocks PRs touching `docs/**/*.mdx` when `docs/llms.txt` is out of sync |
`pr-gate.yml` and `vouch-check-pr.yml` use `pull_request_target`, which is required to label and close fork PRs. Neither checks out PR code and neither has a `run:` step, so there is no pwn-request or script-injection surface. Keep it that way: any future `run:` step in these files must never interpolate `github.event.*` text.
`GATE_EFFECTIVE_FROM` in `pr-gate.yml` is a `created_at` cutoff. `edited`, `reopened`, and `ready_for_review` fire on PRs opened long before the gate existed, so without the cutoff the whole open backlog would be closed by a rule that did not exist when those PRs were filed. Set it to the actual merge date in UTC.
## Issue forms and templates
`ISSUE_TEMPLATE/*.yml` are GitHub issue **forms**, not markdown templates. Only forms support `required: true` and machine-parseable field ids. Blank issues are disabled in `config.yml`.
`issue-labeler.yml` reads only the `component` field id through `stefanbuck/github-issue-parser` and `redhat-plumbers-in-action/advanced-issue-labeler`, so adding new field ids is safe. Renaming `component` is not.
Current field ids:
| Form | Ids |
|------|-----|
| `bug_report.yml` | `component`, `description`, `verification`, `ai_assistance` |
| `feature_request.yml` | `component`, `description`, `ai_assistance` |
| `documentation_issue.yml` | `description`, `ai_assistance` |
## Trust list
`VOUCHED.td` is one GitHub username per line, `#` for comments. Seeded from every author with at least one merged PR in this repository, then filtered: accounts at or below a 16% merge rate across five or more attempts were dropped, since landing one change out of many is the signature of automated submission rather than contribution.
Vouch's only built-in exemptions are accounts ending in `[bot]` and repo collaborators with `write` or `admin`. **Organization membership alone is not one of them.** So `vouch-check-pr.yml` carries a job-level `if:` that skips the check for `OWNER`, `MEMBER`, and `COLLABORATOR` authors, the same exemption `pr-gate.yml` already applies. `author_association` is `MEMBER` for every org member regardless of repository permission, so no member can be flagged even if their `VOUCHED.td` entry is missing, misspelled, or miscased. Org members are still listed in the file as a fallback, but the workflow guard is what actually holds.
+1
View File
@@ -0,0 +1 @@
AGENTS.md
+40
View File
@@ -51,3 +51,43 @@ body:
- OS:
validations:
required: true
- type: textarea
id: verification
attributes:
label: How You Verified This
description: We only take on bugs someone has actually reproduced. Show your work.
value: |
### What I Ran
The exact command or script, and where it ran.
### What I Saw
The real output, log line, or traceback. Paste it, do not describe it.
### Why This Is a Bug
What should have happened instead, and what says so: a docs link, a
docstring, a test, or the code itself.
### What I Ruled Out
Anything you checked that turned out not to be the cause.
validations:
required: true
- type: dropdown
id: ai_assistance
attributes:
label: AI Assistance
description: >-
This asks how the bug was found and confirmed, not how the text was
written. Drafting the write-up with AI is fine. We ask because it tells
us how much to trust the reproduction, not because it counts against you.
options:
- No AI involved
- AI helped me find it, and I reproduced it myself afterwards
- AI found and wrote this, and I have not reproduced it myself
validations:
required: true
+6 -3
View File
@@ -1,8 +1,11 @@
blank_issues_enabled: true
blank_issues_enabled: false
contact_links:
- name: Discord Community
- name: Question or general help
url: https://discord.gg/6PzXDgEjG5
about: Ask questions and discuss with the community
about: Ask on Discord. The issue tracker is for bugs and accepted work only.
- name: Documentation
url: https://docs.mem0.ai
about: Read the official mem0 documentation
- name: Report a security vulnerability
url: https://github.com/mem0ai/mem0/security/advisories/new
about: Report privately through a security advisory. Never open a public issue.
@@ -21,3 +21,17 @@ body:
How should the docs be improved?
validations:
required: true
- type: dropdown
id: ai_assistance
attributes:
label: AI Assistance
description: >-
This asks how the problem was found, not how the text was written.
Drafting the write-up with AI is fine.
options:
- No AI involved, I hit this reading the docs
- AI-assisted, but I checked the page myself
- AI found this, and I have not opened the page
validations:
required: true
@@ -36,3 +36,18 @@ body:
Any workarounds you've tried or other approaches considered.
validations:
required: true
- type: dropdown
id: ai_assistance
attributes:
label: AI Assistance
description: >-
This asks where the idea came from, not how the text was written.
Drafting the write-up with AI is fine. A request you hit yourself while
building something carries more weight than one a model suggested.
options:
- No AI involved, this is a need I hit myself
- AI-assisted, but the need is mine
- AI suggested this feature
validations:
required: true
+12
View File
@@ -14,6 +14,18 @@ Closes #<!-- issue number -->
- [ ] Refactor (no functional changes)
- [ ] Documentation update
## AI Assistance
<!-- This is about the code, not this description. Writing the description with AI is fine. -->
- [ ] No AI assistance
- [ ] AI-assisted (autocomplete, or I asked a model questions while writing this)
- [ ] AI-generated (an agent wrote most or all of this diff)
<!-- If you ticked either AI box, name the tool and what you checked yourself. -->
- [ ] **I can explain every line of this diff and how it interacts with the rest of the codebase, without asking an AI tool.**
## Breaking Changes
<!-- If this is a breaking change, describe what breaks and the migration path. Delete this section if not applicable. -->
+413
View File
@@ -0,0 +1,413 @@
# The list of vouched (or denounced) users for this repository.
#
# Only vouched users can open pull requests here. A denounced user (prefixed
# with a minus) is blocked outright.
#
# Vouch automatically allows two kinds of account without consulting this file:
# accounts ending in [bot], and repo collaborators with write or admin
# permission. Org membership on its own is NOT one of them, so
# vouch-check-pr.yml skips the check entirely for OWNER, MEMBER, and
# COLLABORATOR authors. mem0ai org members are listed below as well, but that
# workflow guard is what actually protects them: a missing, misspelled, or
# miscased entry here can never cause a member to be flagged.
#
# Syntax:
# - One handle per line (without @), sorted alphabetically.
# - Optionally specify platform: `platform:username` (e.g. `github:mitchellh`).
# - To denounce a user, prefix with minus: `-username`.
# - Optionally add a note after a space following the handle.
#
# Maintainers vouch by commenting "!vouch @username" on any issue, and denounce
# with "!denounce @username". The bot commits the change back to this file.
#
# Seeded on 2026-08-12 from every author with at least one merged pull request,
# then filtered: accounts with a merge rate at or below 16% across six or more
# attempts were dropped, since landing one change out of many is the signature
# of automated submission rather than contribution. Removal is not a ban. Any
# maintainer can !vouch these accounts back in.
1MikeMakuch
aaishikdutta
Aarkin7
abdullahirfann
AbdurNawaz
abhay-codes07
Abhineshhh
ac12644
acarbonetto
adh-wonolo
Aditya-Tripuraneni
aesher9o1
agumpandey
ahnedeee
ajmalmohad
AkisAya
akshat1423
akshseh
alessandropanzieri
alohays
aloktripathi1
amahuli03
amanagarwal042
Ameysr
amjadraza
anantoj
anchit-nishant
andrewghlee
andy-k-improving
anifort
anishesg
AnkushMalaker
AnnaSuSu
anujshandillya
ArchishmanSengupta
Arsh-mem0
ArthurHoward1
aryankhanna475
Ashu463
atahanyild
AtharvaJaiswal005
atkinsh
avp1598
axelray-dev
ayaangazali
aymenkrifa
barry166
being-abhi
berwinjoule
BillionClaw
bioshazard
bisla
bkidd1
blino
bmsvinci1729
boss-mao
Br1an67
brucewkz
cachho
caifeizhi
candidosales
cclauss
chaithanyak42
chinnuabey
ChiragArora31
ChrisFloofyKitsune
chrisqu777
clementantonyk
codexvn
Colsrch
CrepuscularIRIS
ctxlong
danielsiwiec
darkhaniop
davidatorres
deshraj
Dev-Khant
Devan019
deven298
devYRPauli
DhanushNehru
DhilipBinny
Dhravya
dimigerontaki
Diveyam-Mishra
divyansh-1009
Divyanshu9822
dog-last
DrJsPBs
dtee1
DumoeDss
e-biswas
Echo3ToEcho7
eldar702
eltociear
EnzoFanAccount
Esparon1
Fahmid-Arman
Failfail2603
FarukhS52
farzad528
felipeavilis
femto
fengjikui
fenilfaldu
fileames
Flyfoxs
fmercurio
FoliageOwO
fran3cc
frank-zsy
frederikb96
Freshield
freya0926
G26karthik
gabe-l-hart
gabrielstein-mem0
gajazlikovac
gasolin
gaurav0107
gauravagerwala
Genarojrsanchez
ghdcksgml1
GingerMoon
gmdorf
golemus
GongRzhe
GopalGB
Gyubin
haarishmk26
hackice20
halanm
hardik1408
Harin329
harshgupta-mem0
harshpandit007
hayescode
hcsum
he-yufeng
heng-ah
Hexecu
Himanshu-Sangshetti
hjlarry
HowieG
HrushiYadav
HScarb
huveewomg
Hybirdss
ianupamsingh
IgnazioDS
immuhammadfurqan
into-the-night
invincible04
Itz-Antaripa
ixchio
Jaco-Ren
Jai0401
JainamShah-22
Jainish-S
jarediaz
jeanibarz
Jerry-Terrasse
jessai2026
jesse-c
jfeng18
jferrettiboke
jjjojoj
joaomdmoura
JoeSL
johnwlockwood
jonasiwnl
josephchancey
juananpe
juaneloDev
junmo1215
Jupiter363
KapilM26
karthik-indla
KarthikeyaKollu
kartik-mem0
katarinasupe
ketangangal
kimnamu
kindertheo
kirex0
kirklin
kk2211
kmitul
koi646
kratos0718
krescent
Krishnachaitanyakc
kriszlazar
KushagraB424
l1anch1
lamost423
lan17
LeonieFreisinger
lh0x00
limboinf
liviaellen
longway-code
lsvishaal
LuciAkirami
lucifertrj
lvpx
ly-wang19
maamalama
maccuryj
mae5357
mahone3297
Malhis
maljazaery
manganeseheptoxide
manthanguptaa
mark-watson
Mark-Zeng
markmbain
matanco1
mauricioalarcon
maxvonhippel
me-tusharchandra
mezotv
MgeeeeK
mggger
mgoulart
microbluey
mikejgray
Mingxiangyu
Mini256
misrasaurabh1
mjzcng
mogith-pn
morgoth9808
moyueheng
mrbusche
Mrinank-Bhowmick
muhammed-mamun
MUZAMMILPERVAIZ
mvanhorn
naman09
NavyaAlapati13
neilbhutada
NightClover-code
nikhilsharma26500
NILAY1556
niv-hertz
NoahStapp
norrishuang
OfficialAbhinavSingh
officialasishkumar
OjusWiZard
okaditya84
omahs
OsamaNabih
oskarrough
p-tirth
Padarn
paipeline
ParseDark
parshvadaftari
Parteeksachdeva
parthshr370
parzival418
Paulie-Aditya
paurushmittal
pc9
Pecunia201
peterj
pragnyanramtha
PranavPuranik
PrashantDixit0
prateekchhikara
prathameshagrawal
pratikgajjar
PratikRai0101
Prikshit7766
Prithvi1994
QunBB
rafid001
raghavtyagii
rahulsharmavishwakarma
rajib76
rakheesingh
ranjithkumar8352
Rayhanpatel
reachAnushaKondam
Real5K
Rhythm-08
richawo
Rishiraj2594
RitwijParmar
RobinALG87
rocke2020
rodboev
rohitgr7
ron-42
roshan-shaik-ml
rst0070
rudra717
rudrajmehta-mem0
rupamoraczen
rupeshbansal
ryanrozich
SaharshPatel24
sahilyadav902
sahithreddy05
SakshiSrivastava2024
SamuelDevdas
sarkarsaurabh27
sdht0
seetharam-rajagopal
sergio-toro
SerSamgy
shafdev
shashank42
ShauryaaSharma
Sheharyar570
shenxiangzhuang
ShivamMenda
shlokkhemani
shraderdm
shrivastavanolo
shubhampal123
shuoli84
sidmohanty11
siroa
slobodaapl
soapun
soumil-rathi
spike-spiegel-21
srishti-git1110
SSDWGG
sssserrano
subhadip001
subhajit20
SudoAnirudh
sukkritsharmaofficial
sw8fbar
swarnaprakash
sxu75374
SZemse
taranjeet
techcontributor
tgabi333
theagenticguy
thomasgtaylor
tomasonjo
TommyZihao
TruptiAgrawal
turtletongue
Tushar-kalsi
Ukong0324
umran666
utkarsh240799
UzairNaeem3
V-Silpin
vatsalrathod16
vedant381
veeceey
vgvoleg
VictorECDSA
VikramIyer125
Vir-8
vsatyamuralikrishna
vuonghuuhung
WayneCao
whysosaket
wobushixiaoj
xiangpingjiang
XiaojuCH
xu-xiang
xyb
yashikabadaya
yashs33244
ygorth
youneshima
ytkimirti
YuriyTW
YusukeJustinNakajima
zaiddkhan
zegerhoogeboom
zinyando
Zlo7
Zncl2222
zzaym
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
}
base_version=$(git show "$BASE_SHA:pyproject.toml" 2>/dev/null | extract_version || echo "")
head_version=$(extract_version < pyproject.toml)
head_version=$(git show "$HEAD_SHA:pyproject.toml" | extract_version)
echo "Base version: ${base_version:-<unknown>}"
echo "Head version: $head_version"
+103
View File
@@ -0,0 +1,103 @@
name: PR Gate
on:
pull_request_target:
types: [opened, reopened, edited, ready_for_review]
concurrency:
group: pr-gate-${{ github.event.pull_request.number }}
cancel-in-progress: true
env:
GATE_EFFECTIVE_FROM: '2026-08-12T00:00:00Z'
permissions:
contents: read
pull-requests: write
issues: read
jobs:
gate:
if: >-
github.event.pull_request.draft == false &&
github.event.pull_request.user.type != 'Bot' &&
!contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association)
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const { owner, repo } = context.repo;
const effectiveFrom = process.env.GATE_EFFECTIVE_FROM;
if (effectiveFrom && Date.parse(pr.created_at) < Date.parse(effectiveFrom)) {
core.info(`Opened ${pr.created_at}, before the gate took effect ${effectiveFrom}. Skipped.`);
return;
}
const { data: current } = await github.rest.pulls.get({
owner, repo, pull_number: pr.number,
});
if (current.state !== 'open') {
core.info(`#${pr.number} is already ${current.state}. Skipped.`);
return;
}
const files = await github.paginate(github.rest.pulls.listFiles, {
owner, repo, pull_number: pr.number, per_page: 100,
});
if (files.length > 0 && files.every((file) => file.filename.startsWith('docs/'))) {
core.info('Docs-only PR, gate skipped');
return;
}
const { repository } = await github.graphql(
`query ($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
closingIssuesReferences(first: 20) {
nodes { number labels(first: 50) { nodes { name } } }
}
}
}
}`,
{ owner, repo, number: pr.number },
);
const accepted = repository.pullRequest.closingIssuesReferences.nodes
.filter((issue) => issue.labels.nodes.some((label) => label.name === 'accepted'))
.map((issue) => issue.number);
if (accepted.length > 0) {
core.info(`Accepted issue linked: #${accepted.join(', #')}`);
return;
}
const body = [
'Thanks for taking the time to open this.',
'',
'We only review pull requests that fix an issue we have already agreed to take on, so this one is closed for now.',
'**Closed does not mean rejected.** It means it is not in the queue yet, and reopening takes about a minute.',
'',
'To get it reviewed:',
'',
'1. Make sure an issue describes the problem, with the version you are on, a runnable reproduction, and the real output or traceback you saw.',
'2. Link it from this pull request description with `Closes #<number>`.',
'3. Ask a maintainer to label that issue `accepted`.',
'4. Reopen this pull request. The check runs again and it stays open.',
'',
'Already linked an accepted issue? Edit the description to include `Closes #<number>` and reopen. The check reruns automatically.',
'',
'Documentation-only changes skip this gate entirely.',
'',
'See [CONTRIBUTING.md](https://github.com/mem0ai/mem0/blob/main/CONTRIBUTING.md) for the full policy.',
].join('\n');
await github.rest.issues.createComment({
owner, repo, issue_number: pr.number, body,
});
await github.rest.pulls.update({
owner, repo, pull_number: pr.number, state: 'closed',
});
core.info(`Closed #${pr.number}: no accepted issue linked`);
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
set -euo pipefail
base_version=$(git show "$BASE_SHA:mem0-ts/package.json" 2>/dev/null | jq -r .version || echo "")
head_version=$(jq -r .version mem0-ts/package.json)
head_version=$(git show "$HEAD_SHA:mem0-ts/package.json" | jq -r .version)
echo "Base version: ${base_version:-<unknown>}"
echo "Head version: $head_version"
+27
View File
@@ -0,0 +1,27 @@
name: Vouch - Check PR
on:
pull_request_target:
types: [opened, reopened]
concurrency:
group: vouch-check-pr-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
jobs:
check:
if: >-
github.event.pull_request.user.type != 'Bot' &&
!contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association)
runs-on: ubuntu-latest
steps:
- uses: mitchellh/vouch/action/check-pr@d66fa29a64600490892131ad87597c30c91fcac4 # v1.5.0
with:
pr-number: ${{ github.event.pull_request.number }}
auto-close: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,42 @@
name: Vouch - Manage by Issue
on:
issue_comment:
types: [created]
concurrency:
group: vouch-manage
cancel-in-progress: false
permissions:
contents: write
issues: write
pull-requests: write
jobs:
manage:
if: contains(github.event.comment.body, '!vouch') || contains(github.event.comment.body, '!denounce') || contains(github.event.comment.body, '!unvouch')
runs-on: ubuntu-latest
steps:
- uses: actions/create-github-app-token@v3
id: app-token
with:
app-id: ${{ secrets.VOUCH_APP_ID }}
private-key: ${{ secrets.VOUCH_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
token: ${{ steps.app-token.outputs.token }}
- uses: mitchellh/vouch/action/manage-by-issue@d66fa29a64600490892131ad87597c30c91fcac4 # v1.5.0
with:
repo: ${{ github.repository }}
issue-id: ${{ github.event.issue.number }}
comment-id: ${{ github.event.comment.id }}
vouch-keyword: "!vouch"
denounce-keyword: "!denounce"
unvouch-keyword: "!unvouch"
pull-request: "true"
merge-immediately: "true"
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
+15
View File
@@ -0,0 +1,15 @@
{
"name": "mem0-plugins",
"version": "1",
"plugins": [
{
"id": "mem0",
"displayName": "Mem0",
"version": "0.1.0",
"description": "Persistent memory for Kimi Code. Remembers decisions, patterns, and preferences across sessions.",
"homepage": "https://mem0.ai",
"keywords": ["memory", "personalization", "mcp", "semantic-search"],
"source": "https://github.com/mem0ai/mem0/tree/main/integrations/mem0-plugin"
}
]
}
+106 -544
View File
@@ -1,593 +1,155 @@
# AGENTS.md
This file provides context for AI coding assistants (Claude Code, Cursor, GitHub Copilot, Codex, etc.) working with the Mem0 repository.
Context for AI coding assistants (Claude Code, Cursor, Copilot, Codex) working in the Mem0 repository.
## Project Overview
**Mem0** ("mem-zero") is a memory layer for AI agents: persistent, personalized memory through a hosted platform API and self-hosted open-source SDKs. Apache-2.0.
[Repository](https://github.com/mem0ai/mem0) · [Documentation](https://docs.mem0.ai)
**Mem0** ("mem-zero") is an intelligent memory layer for AI agents and assistants. It provides persistent, personalized memory via both a hosted platform API and self-hosted open-source SDKs.
This is a polyglot monorepo and **every package sets its own rules**. Read the `AGENTS.md` nearest the files you are editing before running any command. The linters, formatters, test runners, and line lengths genuinely differ per package, and using the wrong one fails CI or produces a diff full of noise.
- **Repository**: https://github.com/mem0ai/mem0
- **Documentation**: https://docs.mem0.ai
- **License**: Apache-2.0
## Do NOT
## Repository Structure
- Open a pull request without a signed CLA. It will not be reviewed. See [The CLA is not optional](#the-cla-is-not-optional).
- Modify anything in `.github/workflows/` without explicit maintainer approval. Publishing credentials are pinned to workflow filenames.
- Commit `.env` files, API keys, or credentials.
- Skip pre-commit hooks.
- Use npm or yarn in TypeScript packages. This repo is pnpm-only (Bun in `.opencode-plugin/`).
- Use `require()` in TypeScript. ES module `import` syntax only.
- Mix up linter configs. Root Python is ruff at line length **120**, `cli/python/` is ruff at **100**, `cli/node/` is Biome, `mem0-ts/` is Prettier, `integrations/vercel-ai-sdk/` is ESLint.
- Add Python dependencies to the core `dependencies` list in `pyproject.toml`. Use an optional group.
- Change a public API without updating `docs/` in the same pull request.
- Introduce a new framework or abstraction without discussion. Follow the patterns already in the file you are editing.
This is a **polyglot monorepo** containing Python and TypeScript packages, CLIs, servers, plugins, and documentation.
## Where to look
### Key Directories
| Editing | Read | Toolchain |
|---------|------|-----------|
| `mem0/` | [`mem0/AGENTS.md`](mem0/AGENTS.md) | hatch, ruff 120, pytest |
| `tests/` | [`tests/AGENTS.md`](tests/AGENTS.md) | pytest |
| `mem0-ts/` | [`mem0-ts/AGENTS.md`](mem0-ts/AGENTS.md) | pnpm, tsup, Prettier, jest |
| `cli/python/` | [`cli/python/AGENTS.md`](cli/python/AGENTS.md) | ruff **100**, pytest |
| `cli/node/` | [`cli/node/AGENTS.md`](cli/node/AGENTS.md) | pnpm, tsup, Biome, vitest |
| `integrations/` | [`integrations/AGENTS.md`](integrations/AGENTS.md) | varies per integration |
| `server/` | [`server/AGENTS.md`](server/AGENTS.md) | Docker Compose, FastAPI |
| `docs/` | [`docs/AGENTS.md`](docs/AGENTS.md) | Mintlify |
| `skills/` | [`skills/AGENTS.md`](skills/AGENTS.md) | markdown, size-budgeted |
| `.github/` | [`.github/AGENTS.md`](.github/AGENTS.md) | GitHub Actions |
| Directory | Description |
|-----------|-------------|
| `mem0/` | Core Python SDK (`mem0ai` on PyPI) — memory, LLMs, embeddings, vector stores, graphs, rerankers |
| `mem0-ts/` | TypeScript SDK (`mem0ai` on npm) — client + OSS memory |
| `cli/python/` | Python CLI (`mem0-cli` on PyPI) — Typer-based, entry point `mem0` |
| `cli/node/` | Node CLI (`@mem0/cli` on npm) — Commander-based, entry point `mem0` |
| `integrations/` | **Agent & editor integrations**, one directory per integration (see "Adding a New Integration") |
| `integrations/mem0-plugin/` | AI editor plugins (Claude Code, Cursor, Codex) — MCP server connection, lifecycle hooks, skills. Contains nested `.opencode-plugin/` (`@mem0/opencode-plugin`) |
| `integrations/openclaw/` | `@mem0/openclaw-mem0` — OpenClaw plugin for Claude Code / AI editors |
| `integrations/pi-agent-plugin/` | `@mem0/pi-agent-plugin` — Pi Agent plugin |
| `integrations/vercel-ai-sdk/` | `@mem0/vercel-ai-provider` — Vercel AI SDK memory provider |
| `integrations/n8n-nodes-mem0/` | `@mem0/n8n-nodes-mem0` — n8n community node; add / search / get / update / delete memories |
| `integrations/zapier-mem0/` | `@mem0/zapier` — Zapier Platform CLI app (deploys to Zapier, not npm); add / search / get / delete memories |
| `server/` | FastAPI REST server for self-hosted Mem0 (Docker: FastAPI + PostgreSQL/pgvector + Neo4j) |
| `skills/` | Claude Code skill definitions. Reference skills (SDK knowledge, always-on): `mem0/`, `mem0-cli/`, `mem0-vercel-ai-sdk/`. Pipeline skills (run on demand): `mem0-integrate/`, `mem0-test-integration/`, `mem0-oss-to-platform/` |
## Repository map
| Directory | What it is |
|-----------|------------|
| `mem0/` | Core Python SDK (`mem0ai` on PyPI): memory, LLMs, embeddings, vector stores, graphs, rerankers |
| `mem0-ts/` | TypeScript SDK (`mem0ai` on npm): hosted client + OSS memory |
| `cli/python/` | Python CLI (`mem0-cli` on PyPI), Typer-based, entry point `mem0` |
| `cli/node/` | Node CLI (`@mem0/cli` on npm), Commander-based, entry point `mem0` |
| `integrations/` | Agent and editor integrations, one self-contained directory each |
| `server/` | FastAPI REST server for self-hosted Mem0 (Docker: FastAPI + pgvector + Neo4j) |
| `skills/` | Claude Code skill definitions, published by raw URL |
| `docs/` | Documentation site (Mintlify) |
| `tests/` | Python SDK tests (pytest) |
| `evaluation/` | Submodule → [`mem0ai/memory-benchmarks`](https://github.com/mem0ai/memory-benchmarks) — benchmarking (LOCOMO, LongMemEval, BEAM) lives in that repo |
| `examples/` | Sample projects & runnable demos — apps, Chrome extension, multi-agent patterns, and Jupyter notebooks (`notebooks/`) |
| `examples/` | Sample apps, Chrome extension, multi-agent patterns, notebooks |
| `scripts/` | Repo-wide utilities, e.g. `check-llms-txt-coverage.py` |
| `evaluation/` | Submodule pinned to [`mem0ai/memory-benchmarks`](https://github.com/mem0ai/memory-benchmarks) |
| `pr-reviews/` | Pull request review materials |
| `scripts/` | Repo-wide utility scripts (e.g., `check-llms-txt-coverage.py` for docs/llms.txt sync) |
### Core Package Dependencies
```
mem0 (Python SDK) mem0-ts (TypeScript SDK)
├── mem0/memory/ ├── src/client/ (MemoryClient — hosted)
├── mem0/llms/ └── src/oss/ (Memory — self-hosted)
├── mem0/memory/ ├── src/client/ MemoryClient (hosted)
├── mem0/llms/ └── src/oss/ Memory (self-hosted)
├── mem0/embeddings/ ├── src/llms/
├── mem0/vector_stores/ ├── src/embeddings/
├── mem0/graphs/ ├── src/vector_stores/
└── mem0/reranker/ └── src/graphs/
cli/python/ ──▶ mem0ai (optional, for OSS mode)
cli/node/ ──▶ mem0ai (npm, for API calls)
integrations/vercel-ai-sdk/ ──▶ ai, @ai-sdk/* providers
integrations/openclaw/ ──▶ mem0ai (npm)
cli/python/ ──▶ mem0ai (optional, OSS mode)
cli/node/ ──▶ mem0ai (npm)
integrations/vercel-ai-sdk/ ──▶ ai, @ai-sdk/*
integrations/openclaw/ ──▶ mem0ai (npm)
```
## Development Setup
### Requirements
- **Python**: 3.9+ (3.10+ for CLI)
- **Node.js**: v18+ (v20 or v22 recommended)
- **pnpm**: v10+ (`npm install -g pnpm@10`) — used for all TypeScript packages
- **Hatch**: Python build/environment tool (`pip install hatch`)
- **Docker**: Required for `server/` development
### Initial Setup
## Setup
```bash
# Python SDK
hatch shell dev_py_3_11 # creates environment with all deps
pre-commit install # install git hooks
hatch shell dev_py_3_11 # Python: creates the env with all deps
pre-commit install # ruff + isort on commit
# TypeScript packages
cd mem0-ts && pnpm install # TS SDK
cd cli/node && pnpm install # Node CLI
cd integrations/vercel-ai-sdk && pnpm install # Vercel AI provider
cd integrations/openclaw && pnpm install # OpenClaw plugin
cd <ts-package> && pnpm install
```
## Build, Lint, and Test Commands
Requirements: Python 3.9+ (3.10+ for the CLI), Node 18+ (20 or 22 preferred), pnpm 10+, hatch, Docker for `server/`.
### Python SDK (`mem0/`)
## Conventions everywhere
- **Naming:** `snake_case.py`, `test_<module>.py`, `snake_case.ts`, `<module>.test.ts`, `kebab-case` for config and manifest files.
- **Python:** Pydantic v2 for models and config. Providers inherit a `base.py` abstract class; config lives in `configs.py`.
- **TypeScript:** strict mode, tsup builds, ES module imports.
- **Commits:** [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`).
- **Versions:** bump in `pyproject.toml` or `package.json`. Releases are cut by tag prefix; see [`.github/AGENTS.md`](.github/AGENTS.md).
## Benchmarking
Benchmarks (LOCOMO, LongMemEval, BEAM) live in [`mem0ai/memory-benchmarks`](https://github.com/mem0ai/memory-benchmarks). The in-repo `evaluation/` path is a submodule pinned to that repo's `main`:
```bash
# Environment setup (uses Hatch)
hatch shell dev_py_3_11 # or dev_py_3_9, dev_py_3_10, dev_py_3_12
# Linting and formatting
make lint # ruff check
make format # ruff format
make sort # isort mem0/
# Tests
make test # pytest tests/
make test-py-3.9 # test specific Python version (3.9–3.12)
# Build and publish
make build # hatch build
make publish # hatch publish
git submodule update --init evaluation
```
- **Python:** 3.9, 3.10, 3.11, 3.12
- **Linter/formatter:** Ruff (line length **120**)
- **Import sorting:** isort (`profile = "black"`)
- **Test framework:** pytest (with pytest-mock, pytest-asyncio)
- **Pre-commit hooks:** ruff + isort — run `pre-commit install` before committing
## What to ship with a change
### TypeScript SDK (`mem0-ts/`)
Guidelines, not rules. Trivial fixes need less; anything user-facing needs more.
```bash
cd mem0-ts
pnpm install
pnpm run build # tsup
pnpm run test # jest (all tests)
pnpm run test:unit # jest --coverage (unit tests only)
pnpm run test:integration # jest (integration tests, needs MEM0_API_KEY)
pnpm run test:ci # jest --coverage --ci (CI mode)
pnpm run test:watch # jest watch mode
```
| Change | Expect |
|--------|--------|
| **Bug fix** | A regression test that fails without the fix, written first. The fix. The relevant suite passing. The package's linter run. |
| **New feature** | Implementation following existing patterns, test coverage, `docs/` updates for public APIs, an example if the behavior is user-facing, and an `llms.txt` entry for any new `.mdx` page. |
| **New provider** | See [Adding a provider](mem0/AGENTS.md#adding-a-provider). |
| **New integration** | See [Adding an integration](integrations/AGENTS.md#adding-an-integration). |
| **Refactor** | Tests for changed behavior, existing tests still green. No docs needed for internal-only changes. |
- **Node:** 20, 22 (CI-tested)
- **Build:** tsup (CJS + ESM)
- **Test:** jest
- **Formatter:** prettier
Fix bugs at the root, not at the symptom. If a guard belongs in a shared function, put it there rather than in each caller.
### Python CLI (`cli/python/`)
## Contributing
```bash
cd cli/python
pip install -e ".[dev]" # dev install with ruff + pytest
ruff check . # lint
ruff format . # format
pytest # test
hatch build # build
```
Full guide: [`CONTRIBUTING.md`](CONTRIBUTING.md). Conduct: [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md).
- **Python:** 3.10+ (not 3.9)
- **Linter/formatter:** Ruff (line length **100** — different from root SDK)
- **Ruff rules:** E, F, I, W, UP, B, SIM, RUF (ignores E501, B008 for Typer patterns, SIM108)
- **Framework:** Typer + Rich + httpx
- **Entry point:** `mem0 = "mem0_cli.app:main"`
- **Source layout:** `src/mem0_cli/`
- **Optional dependency:** `mem0ai` (for OSS mode, via `[oss]` extra)
1. Open an issue **first** and wait for a maintainer to apply the `accepted` label. Every PR must link it with `Closes #<number>`. PRs without an accepted linked issue are closed automatically by the [PR Gate](.github/workflows/pr-gate.yml), with a reopen path. Documentation-only changes are exempt.
2. Fork, then branch from `main` (`feature/...`, `fix/...`).
3. Make the change: code, tests, docs, examples.
4. Run lint and tests for **every** package you touched.
5. Commit with Conventional Commits.
6. Open the PR against `main` and fill in [the template](.github/PULL_REQUEST_TEMPLATE.md). Do not paraphrase it; GitHub prefills it.
7. **Sign the CLA.**
### Node CLI (`cli/node/`)
### The CLA is not optional
```bash
cd cli/node
pnpm install
pnpm run build # tsup
pnpm run lint # biome check src/
pnpm run lint:fix # biome check --write src/
pnpm run typecheck # tsc --noEmit
pnpm run test # vitest run
pnpm run test:watch # vitest (watch mode)
pnpm run dev # tsx src/index.ts (development)
```
**A pull request from a contributor who has not signed the Contributor License Agreement is not accepted, not reviewed, and not merged.** This is not a formality applied at merge time. An unsigned pull request does not enter the review queue at all: maintainers do not read the diff, do not leave feedback, and do not discuss the approach. It sits until the CLA is signed, and it is closed if it goes stale.
- **Node:** 18+ required
- **Build:** tsup (ESM)
- **Linter:** Biome (not ESLint, not Ruff)
- **Test:** vitest (not jest)
- **Framework:** Commander + Chalk + ora + cli-table3
The `CLAassistant` bot comments on your first pull request with a link. Signing takes under a minute, is done once per GitHub account, and covers every contribution you make afterwards. Until it is signed the `license/cla` check stays red.
### Vercel AI SDK Provider (`integrations/vercel-ai-sdk/`)
If you are an agent opening a pull request on someone's behalf, tell them they must sign it themselves. Nobody else can sign for them, and the pull request goes nowhere until they do.
```bash
cd integrations/vercel-ai-sdk
pnpm install
pnpm run build # tsup
pnpm run lint # eslint
pnpm run type-check # tsc --noEmit
pnpm run prettier-check # prettier --check
pnpm run test # jest
pnpm run test:edge # vitest (edge runtime)
pnpm run test:node # vitest (node runtime)
```
### What gets a pull request closed
- **Build:** tsup (CJS + ESM)
- **Lint:** ESLint + Prettier
- **Test:** jest + vitest (edge/node configs)
Beyond the CLA and the accepted-issue gate, the [Contribution Conduct](CODE_OF_CONDUCT.md#contribution-conduct) section of the code of conduct is the enforceable form of this repo's anti-slop policy:
### OpenClaw Plugin (`integrations/openclaw/`)
- **Disclose AI use.** The PR template asks how the *code* was written; drafting the description with a model is fine. The disclosure is never held against you, it tells a reviewer where to look. Silence followed by a review comment you cannot answer is what costs everyone the afternoon.
- **Do not submit work you have not run.** A bug report means you reproduced it. A PR means you ran the tests.
- **Do not fabricate evidence.** Invented tracebacks, unmeasured benchmarks, tests that assert the implementation back at itself, descriptions that describe a different change than the diff makes.
- **Match your volume to your engagement.** Open changes at the rate you can discuss them.
- **Do not press for merges.** One polite follow-up after a reasonable wait is fine.
- **You must be able to explain every line of your diff** and how it interacts with the rest of the codebase, without asking an AI tool. This is the one rule that does not bend.
```bash
cd integrations/openclaw
pnpm install
pnpm run build # tsup
pnpm run test # vitest run
```
### Reference
- **Build:** tsup (ESM)
- **Test:** vitest (with Codecov in CI)
- **Plugin manifest:** `openclaw.plugin.json`
### Server (`server/`)
```bash
# Docker production build
cd server
make build # docker build -t mem0-api-server .
make run_local # docker run -p 8000:8000 with .env
# Docker Compose development (FastAPI + PostgreSQL/pgvector + Neo4j)
cd server
docker-compose up # starts all 3 services
# mem0 API: localhost:8888
# PostgreSQL: localhost:8432
# Neo4j HTTP: localhost:8474, Bolt: localhost:8687
```
- **Framework:** FastAPI with uvicorn (auto-reload in dev)
- **Services:** PostgreSQL with pgvector, Neo4j 5.x with APOC plugin
- **Hot reload:** Dev Dockerfile mounts `server/` and `mem0/` for live changes
### Documentation (`docs/`)
```bash
make docs # or: cd docs && mintlify dev
```
- **Framework:** Mintlify
- **API spec:** `docs/openapi.json`
- **Structure:** `api-reference/`, `open-source/`, `platform/`, `integrations/`, `cookbooks/`, `core-concepts/`
### Evaluation / Benchmarking
Benchmarking lives in the external [`mem0ai/memory-benchmarks`](https://github.com/mem0ai/memory-benchmarks) repo (LOCOMO + LongMemEval + BEAM). The in-repo `evaluation/` path is a **git submodule** pinned to that repo's `main` — populate it with `git submodule update --init evaluation` (or clone mem0 with `--recurse-submodules`), or clone the benchmarks repo standalone:
```bash
git clone https://github.com/mem0ai/memory-benchmarks.git
cd memory-benchmarks
pip install -r requirements.txt
# Run a benchmark (Mem0 Cloud; use docker compose for OSS)
python -m benchmarks.locomo.run --project-name my-test --backend cloud --mem0-api-key $MEM0_API_KEY
python -m benchmarks.longmemeval.run --project-name my-test --backend cloud --mem0-api-key $MEM0_API_KEY --all-questions
python -m benchmarks.beam.run --project-name my-test --backend cloud --mem0-api-key $MEM0_API_KEY --chat-sizes 100K --conversations 0-9
```
## Core APIs
### Python
| Function / Class | Purpose | Import |
|-----------------|---------|--------|
| `Memory` | Self-hosted memory (sync) | `from mem0 import Memory` |
| `AsyncMemory` | Self-hosted memory (async) | `from mem0 import AsyncMemory` |
| `MemoryClient` | Hosted platform client (sync) | `from mem0 import MemoryClient` |
| `AsyncMemoryClient` | Hosted platform client (async) | `from mem0 import AsyncMemoryClient` |
**Key `Memory` / `MemoryClient` methods:**
| Method | Purpose |
|--------|---------|
| `add(messages, *, user_id, agent_id, run_id, metadata)` | Store a new memory |
| `search(query, *, user_id, agent_id, run_id, limit, filters)` | Search memories |
| `get(memory_id)` | Retrieve a single memory by ID |
| `get_all(*, user_id, agent_id, run_id, limit)` | List all memories |
| `update(memory_id, data)` | Update a memory |
| `delete(memory_id)` | Delete a memory |
| `delete_all(*, user_id, agent_id, run_id)` | Delete all memories |
| `history(memory_id)` | Get change history for a memory |
### TypeScript
| Export | Purpose | Import |
|--------|---------|--------|
| `MemoryClient` | Hosted platform client | `import { MemoryClient } from 'mem0ai'` |
| `Memory` | Self-hosted OSS memory | `import { Memory } from 'mem0ai/oss'` |
## Import Patterns
### Python
| What | Import |
|------|--------|
| Core memory classes | `from mem0 import Memory, AsyncMemory` |
| Platform client | `from mem0 import MemoryClient, AsyncMemoryClient` |
| Configuration | `from mem0.configs.base import MemoryConfig` |
| LLM providers | `from mem0.llms.<provider> import <ProviderLLM>` |
| Embedding providers | `from mem0.embeddings.<provider> import <ProviderEmbedding>` |
| Vector store providers | `from mem0.vector_stores.<provider> import <ProviderVectorStore>` |
### TypeScript
| What | Import |
|------|--------|
| Hosted client | `import { MemoryClient } from 'mem0ai'` |
| OSS memory | `import { Memory } from 'mem0ai/oss'` |
| Specific providers (OSS) | `import { OpenAIEmbedding } from 'mem0ai/oss'` |
## Coding Standards
### File Naming Conventions
- **Python source files:** `snake_case.py` (e.g., `azure_openai.py`, `cohere_reranker.py`)
- **Python test files:** `test_<module>.py` (e.g., `test_memory.py`, `test_main.py`)
- **TypeScript source files:** `snake_case.ts` (e.g., `azure_ai_search.ts`)
- **TypeScript test files:** `<module>.test.ts` (e.g., `memory.test.ts`)
- **Config/manifest files:** `kebab-case` (e.g., `openclaw.plugin.json`, `jest.config.js`)
### Python Conventions
- **Provider pattern:** All providers (LLMs, embeddings, vector stores, graphs, rerankers) inherit from a `base.py` abstract class in their directory. Config classes live in `configs.py`.
- **Pydantic v2** for all data models and configuration.
- **Ruff** is the single linting and formatting tool — no black, no flake8.
- Root SDK: line length **120**
- Python CLI: line length **100** with extended rule set (UP, B, SIM, RUF)
- **isort** with `profile = "black"` for import sorting.
### TypeScript Conventions
- **Build:** tsup across all packages.
- **Package manager:** pnpm everywhere (no npm, no yarn).
- **TypeScript strict mode** across all packages.
- **Linting varies by package:**
| Package | Linter | Formatter | Test Framework |
|---------|--------|-----------|---------------|
| `mem0-ts/` | — | Prettier | jest |
| `cli/node/` | Biome | Biome | vitest |
| `integrations/vercel-ai-sdk/` | ESLint | Prettier | jest + vitest |
| `integrations/openclaw/` | — | — | vitest |
### Type Checking
Always run type checking after modifying TypeScript code:
```bash
cd <package> && pnpm run typecheck # or: tsc --noEmit
```
## Architecture
### Provider Pattern
The SDK uses a consistent plugin architecture across 5 categories. Each category has a `base.py` abstract class and concrete provider implementations:
| Category | Count | Examples |
|----------|-------|---------|
| **LLMs** | 24 | OpenAI, Anthropic, AWS Bedrock, Azure OpenAI, Gemini, Groq, Ollama, Together, DeepSeek, vLLM, LiteLLM, LM Studio, xAI |
| **Vector Stores** | 30 | Qdrant, Pinecone, Chroma, Weaviate, Milvus, MongoDB, Redis, Elasticsearch, pgvector, Supabase, Faiss, S3 Vectors |
| **Embeddings** | 15 | OpenAI, Azure OpenAI, Gemini, HuggingFace, FastEmbed, Together, AWS Bedrock, Ollama, Vertex AI |
| **Graph Stores** | 4 | Neo4j, Memgraph, Kuzu, Apache AGE |
| **Rerankers** | 5 | Cohere, HuggingFace, LLM-based, Sentence Transformer, Zero Entropy |
### Two Usage Modes
Self-hosted `Memory` / `AsyncMemory` classes and hosted-platform `MemoryClient` — both in Python and TypeScript.
### Graph Memory
Optional layer on top of vector memory for relationship-aware retrieval. Configured via the `graph` section of `MemoryConfig`.
### MCP Integration
Model Context Protocol support in multiple places:
- **Remote:** MCP server at `mcp.mem0.ai`
- **Plugin:** MCP tools in `integrations/mem0-plugin/` — 9 tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`
### Plugin & Skills System
- `integrations/mem0-plugin/` provides integrations for Claude Code, Cursor, and Codex via MCP server connections and lifecycle hooks for automatic memory capture.
- `skills/` contains structured skill definitions for AI agents, split into two categories:
- **Reference skills** (always-on SDK knowledge): `mem0` (Python + TS SDKs, framework integrations), `mem0-cli` (terminal workflows), `mem0-vercel-ai-sdk` (Vercel AI provider).
- **Pipeline skills** (run on demand): `mem0-integrate` wires Mem0 into an existing repo via a TDD pipeline; `mem0-test-integration` verifies what the integrator produced on the same branch (the two are loosely coupled via `.mem0-integration/` artifacts); `mem0-oss-to-platform` migrates an existing project from Mem0 OSS to the hosted Platform SDK (plan, then execute on approval).
### Adding a New Provider
To add a new LLM, embedding, vector store, or reranker provider:
1. Create `mem0/<category>/<provider_name>.py`
2. Inherit from the abstract base class in `mem0/<category>/base.py`
3. Add configuration to `mem0/<category>/configs.py` (if the category uses one)
4. Register the provider in `mem0/<category>/__init__.py`
5. Add tests in `tests/<category>/<provider_name>/`
6. Add any new dependencies to the appropriate optional group in `pyproject.toml` (never to core `dependencies`)
7. Follow the exact pattern of existing providers in the same category — match method signatures, error handling, and config structure
### Adding a New Integration
Agent/editor integrations live under `integrations/`. Each is a self-contained directory (its own `package.json`/lockfile, build, and tests). To add one:
1. Create `integrations/<name>/` and build the integration there.
2. If it publishes to a registry, set `repository.directory: "integrations/<name>"` in its `package.json` so npm provenance links to the correct subdirectory.
3. Add CI/CD under `.github/workflows/` (`<name>-checks.yml`, `<name>-cd.yml`). Use `integrations/<name>` in `paths:` triggers, `working-directory`, and `cache-dependency-path`. Register the release tag prefix in the `case` block in `release.yml` (keep the bare `v*` arm last). Keep workflow **filenames** stable — npm OIDC trusted publishing is pinned to repo + workflow filename.
4. If it is a Claude Code / editor marketplace plugin, register its path in the five `marketplace.json` files (root + `.claude-plugin/`, `.cursor-plugin/`, `.codex-plugin/`, `.agents/plugins/`).
5. Document it under `docs/integrations/` and add the page to `docs/docs.json` and `docs/llms.txt`.
6. Add rows to the "Key Directories" table and the CI/CD tables in this file.
## CI/CD
### CI Workflows (automated testing)
PR testing is orchestrated by a single entry point: **`ci-gate.yml` (CI Gate)** runs on every PR, detects which packages changed, and invokes only the relevant package workflows below as reusable workflows (`workflow_call`). Its final **`CI Gate`** job aggregates the results (skipped pipelines pass; failed or cancelled ones fail) and is the **only status check that needs to be required** in branch protection. Package workflows keep their own push-to-main and manual triggers; their `pull_request` triggers moved into the gate's path filters.
| Workflow | File | Standalone Triggers | Tests |
|----------|------|---------------------|-------|
| CI Gate | `ci-gate.yml` | All PRs | Routes to and aggregates the workflows below |
| Python SDK | `ci.yml` | Push to main | Ruff lint + pytest on Python 3.10, 3.11, 3.12 |
| TypeScript SDK | `ts-sdk-ci.yml` | Push to main (on `mem0-ts/`) | Prettier + build + jest on Node 20, 22 |
| Python CLI | `cli-python-ci.yml` | Push to main (on `cli/python/`), manual | Ruff lint + pytest + hatch build on Python 3.10, 3.11, 3.12 |
| Node CLI | `cli-node-ci.yml` | Push to main (on `cli/node/`), manual | Biome lint + tsc + vitest + tsup build on Node 20, 22 |
| OpenClaw | `openclaw-checks.yml` | Push to main (on `integrations/openclaw/`), manual | tsc + vitest (with Codecov) + tsup build on Node 20, 22 |
| Mem0 Plugin | `mem0-plugin-checks.yml` | Push to main (on `integrations/mem0-plugin/`, excluding `.opencode-plugin/`), manual | pytest + hook entry-point exec bits + JSON manifest validation on Python 3.10, 3.11, 3.12 |
| OpenCode Plugin | `opencode-plugin-checks.yml` | Push to main (on `integrations/mem0-plugin/.opencode-plugin/`), manual | Bun: tsc type-check + build + dist artifact check |
| Pi Agent Plugin | `pi-agent-plugin-checks.yml` | Push to main (on `integrations/pi-agent-plugin/`), manual | tsc + vitest + tsup build (dist artifact check) on Node 20, 22 |
| n8n Node | `n8n-nodes-mem0-checks.yml` | Push to main (on `integrations/n8n-nodes-mem0/`), manual | ESLint (n8n-nodes-base) + tsc build (dist artifact check) on Node 20 |
| Zapier App | `zapier-mem0-checks.yml` | Push to main (on `integrations/zapier-mem0/`), manual | build (tsc) + `zapier validate` + offline unit tests on Node 22 |
| docs llms.txt | `docs-llms-txt-check.yml` | Manual | `docs/llms.txt` coverage check |
When adding a new package CI workflow: give it `workflow_call` (plus `push`/`workflow_dispatch` as needed, but no `pull_request` trigger), then register it in `ci-gate.yml` — a path filter under the `changes` job, a call job, and an entry in the gate job's `needs` list.
### CD Workflows (automated publishing)
Publishing is routed through a single entry point: **`release.yml` (Release Router)** is the only workflow that listens to `release: published` events. It matches the release tag prefix and dispatches the corresponding package workflow via `workflow_dispatch`, so each release produces exactly one routed run (no skipped runs from the other pipelines).
| Workflow | File | Tag Prefix | Target |
|----------|------|------------|--------|
| Release Router | `release.yml` | (all releases) | dispatches the matching workflow below |
| Python SDK | `cd.yml` | `v*` | PyPI (`mem0ai`) |
| TypeScript SDK | `ts-sdk-cd.yml` | `ts-v*` | npm (`mem0ai`) |
| Python CLI | `cli-python-cd.yml` | `cli-v*` | PyPI (`mem0-cli`) |
| Node CLI | `cli-node-cd.yml` | `cli-node-v*` | npm (`@mem0/cli`) |
| Vercel AI SDK | `vercel-ai-cd.yml` | `vercel-ai-v*` | npm (`@mem0/vercel-ai-provider`) |
| OpenClaw | `openclaw-cd.yml` | `openclaw-v*` | npm (`@mem0/openclaw-mem0`) |
| OpenCode Plugin | `opencode-plugin-cd.yml` | `opencode-v*` | npm (`@mem0/opencode-plugin`) |
| Pi Agent Plugin | `pi-agent-plugin-cd.yml` | `pi-agent-v*` | npm (`@mem0/pi-agent-plugin`) |
| n8n Node | `n8n-nodes-mem0-cd.yml` | `n8n-nodes-mem0-v*` | npm (`@mem0/n8n-nodes-mem0`) |
- Package CD workflows are `workflow_dispatch`-only (inputs: `tag`, `prerelease`); they check out and build the given tag. Registry trusted-publisher settings stay pinned to each package's own workflow filename.
- All publishing uses **OIDC trusted publishing** — no tokens or secrets required.
- First publish of a new npm package must be done manually; OIDC works for subsequent versions.
- To re-publish a release (e.g. after a registry settings fix), do **not** delete/recreate the GitHub release — manually dispatch the package workflow instead: `gh workflow run <package>-cd.yml --ref refs/tags/<tag> -f tag=<tag>`.
- The **Zapier app** (`integrations/zapier-mem0`) deploys to Zapier's own platform, not npm, so it is **not** in the release router. Deploy it manually: `gh workflow run zapier-mem0-cd.yml --ref main` (requires the `ZAPIER_DEPLOY_KEY` secret).
- When adding a new package: add its CD workflow (`workflow_dispatch` with `tag`/`prerelease` inputs), then register its tag prefix in the `case` block in `release.yml`. Keep the bare `v*` arm last.
### Utility Workflows
| Workflow | File | Purpose |
|----------|------|---------|
| Issue Labeler | `issue-labeler.yml` | Automatic issue labeling |
| PR Labeler | `pr-labeler.yml` | Path-based PR labeling plus propagating labels from linked issues |
| Stale Bot | `stale.yml` | Marks stale issues and PRs |
| llms.txt Check | `docs-llms-txt-check.yml` | Blocks PRs touching `docs/**/*.mdx` when `docs/llms.txt` is out of sync. Fix locally with `python scripts/check-llms-txt-coverage.py --write`. |
## Task Completion Guidelines
These guidelines outline typical artifacts for different task types. Use judgment to adapt based on scope and context.
### Bug Fixes
1. **Unit tests**: Add tests that would fail without the fix (regression tests)
2. **Implementation**: Fix the bug
3. **Manual verification**: Run the relevant test suite to confirm the fix
4. **Lint**: Run the appropriate linter for the package you modified
### New Features
1. **Implementation**: Build the feature following existing patterns
2. **Unit tests**: Comprehensive test coverage for new functionality
3. **Documentation**: Update relevant docs in `docs/` for public APIs
4. **Examples**: Add usage examples if the feature introduces new user-facing behavior
5. **llms.txt**: Any new `.mdx` page under `docs/` must be linked in `docs/llms.txt` with a scope tag (`[Platform]` / `[OSS]` / `[Both]`) and a `Use when ...` description. The `docs-llms-txt-check.yml` workflow runs on every PR that touches docs and **fails the check** if the index is out of sync. To fix: run `python scripts/check-llms-txt-coverage.py --write` locally to scaffold placeholders under `## Unclassified - needs triage`, then replace the `[TODO: ...]` tags, rewrite descriptions as `Use when ...`, move entries into the right section, and delete the triage heading when empty.
### New Provider (LLM / Embedding / Vector Store / Reranker)
1. **Implementation**: Follow the "Adding a New Provider" steps above
2. **Tests**: Add unit tests matching the pattern of existing providers
3. **Configuration**: Add to the appropriate `configs.py` and `__init__.py`
4. **Dependencies**: Add to the correct optional group in `pyproject.toml`
5. **Documentation**: Add an integration guide in `docs/integrations/`
### Refactoring / Internal Changes
- Unit tests for any changed behavior
- No documentation needed for internal-only changes
- Ensure all existing tests still pass
### When to Deviate
These are guidelines, not rigid rules. Adjust based on:
- **Scope**: Trivial fixes (typos, comments) may not need tests
- **Visibility**: Internal changes may not need documentation
- **Context**: Some changes span multiple categories — use judgment
When uncertain about expected artifacts, ask for clarification.
## Contributing Guidelines
### Workflow
1. Fork and clone the repository.
2. Create a feature branch from `main` (e.g., `feature/my-new-feature`).
3. Make your changes — add tests, docs, and examples as appropriate.
4. Run linting and tests for every package you modified (see commands above).
5. Run `pre-commit install` on first setup — hooks run ruff + isort automatically.
6. Commit with a clear message following [Conventional Commits](https://www.conventionalcommits.org/) (e.g., `feat:`, `fix:`, `docs:`, `refactor:`).
7. Push and open a Pull Request against `main`.
### Pull Request Requirements
Every PR must follow the repo's PR template (`.github/PULL_REQUEST_TEMPLATE.md`):
1. **Linked Issue** — Reference the issue with `Closes #<number>`. If no issue exists, create one first or explain why in the description.
2. **Description** — Explain what the PR does and why it's needed.
3. **Type of Change** — Check the appropriate box:
- Bug fix / New feature / Breaking change / Refactor / Documentation update
4. **Breaking Changes** — If applicable, describe what breaks and the migration path.
5. **Test Coverage** — Check what applies:
- Added/updated unit tests
- Added/updated integration tests
- Tested manually (describe how)
- No tests needed (explain why)
6. **Checklist** — All must be checked before merge:
- [ ] Code follows the project's style guidelines
- [ ] Self-review performed
- [ ] Tests added that prove the fix/feature works
- [ ] New and existing tests pass locally
- [ ] Documentation updated if needed
### PR Description Template
```markdown
## Linked Issue
Closes #<!-- issue number -->
## Description
<!-- What does this PR do? Why is it needed? -->
## Type of Change
- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Refactor (no functional changes)
- [ ] Documentation update
## Breaking Changes
N/A
## Test Coverage
- [ ] I added/updated unit tests
- [ ] I added/updated integration tests
- [ ] I tested manually (describe below)
- [ ] No tests needed (explain why)
## Checklist
- [ ] My code follows the project's style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have added tests that prove my fix/feature works
- [ ] New and existing tests pass locally
- [ ] I have updated documentation if needed
```
### General Rules
- Follow existing code patterns — don't introduce new frameworks or abstractions without discussion.
- Version bumps go in `pyproject.toml` (Python) or `package.json` (TypeScript).
- For `server/` work, use Docker Compose for local development.
- Do NOT use `pip` or `conda` for dependency management — use `hatch` (see `docs/contributing/development.mdx`).
### Contributing Guides
| Task | Guide |
|------|-------|
| Code contributions | `docs/contributing/development.mdx` |
| Topic | File |
|-------|------|
| Contributor guide | [`CONTRIBUTING.md`](CONTRIBUTING.md) |
| Code of conduct | [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) |
| Security reports | [`SECURITY.md`](SECURITY.md) |
| Development setup | `docs/contributing/development.mdx` |
| Documentation contributions | `docs/contributing/documentation.mdx` |
| PR template | `.github/PULL_REQUEST_TEMPLATE.md` |
| Bug reports | `.github/ISSUE_TEMPLATE/bug_report.yml` |
| Feature requests | `.github/ISSUE_TEMPLATE/feature_request.yml` |
| Documentation issues | `.github/ISSUE_TEMPLATE/documentation_issue.yml` |
## Do NOT
- Modify CI/CD workflows without explicit approval.
- Add new Python dependencies to the core `dependencies` list in `pyproject.toml` without discussion — use optional dependency groups instead.
- Commit `.env` files, API keys, or credentials.
- Skip pre-commit hooks.
- Use npm or yarn in TypeScript packages — this repo uses pnpm exclusively.
- Use `require()` for imports in TypeScript — use ES module `import` syntax.
- Mix up linter configs: root Python SDK uses line-length 120, Python CLI uses 100, Node CLI uses Biome (not ESLint/Ruff).
- Change public APIs without updating documentation in `docs/`.
| Issue forms | `.github/ISSUE_TEMPLATE/` |
| Trust list (vouch) | `.github/VOUCHED.td` |
| CI/CD, gates, rulesets | [`.github/AGENTS.md`](.github/AGENTS.md) |
+181
View File
@@ -0,0 +1,181 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of
any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Contribution Conduct
Mem0 receives more contributions than any maintainer can read line by line. The
rules below exist so that the time we do have goes to people who are actually
trying to improve the project. They apply to issues, pull requests, discussions,
and reviews.
**Be honest about how the work was produced.** Using an AI tool to find a bug,
write a patch, or draft a description is fine and welcome. Not saying so is not.
Every issue form and the pull request template ask about AI, and the answer is
never held against you. It tells a reviewer where to look. An unanswered review
comment on code the author cannot explain is what costs us the afternoon.
**Do not submit work you have not verified.** A reported bug means you ran it and
saw it. A pull request means you ran the tests. Pasting a model's output, a
scanner result, or a plausible-looking patch and letting maintainers find out
whether it is real moves your work onto someone else's desk. Reports and patches
that turn out to be unverified are closed without a detailed response.
**Do not fabricate evidence.** Invented tracebacks, benchmark numbers you did not
measure, reproductions that were never run, tests that assert the implementation
back at itself, and descriptions that describe a different change than the diff
makes are all treated the same way, regardless of whether a person or a tool
produced them.
**Match your volume to your engagement.** Open changes at the rate you can
discuss them. A queue of open pull requests from one author, none of them
answered when questioned, is treated as automated submission and handled under
enforcement below, whatever the individual diffs look like.
**Do not press for merges.** Bumping a thread, tagging maintainers repeatedly,
asking in Discord or by direct message for a review, and reopening a closed pull
request without addressing why it was closed all take attention away from the
queue rather than moving your change through it. One polite follow-up after a
reasonable wait is fine.
**Do not contribute for a badge.** Changes made to raise a contribution count,
qualify for an event, or pad a profile, whitespace edits, README churn, and
mechanical reformatting bundled with nothing else, are closed on sight.
**Disagreement is fine, and closing is not a verdict.** Our pull request gate
closes changes that do not yet link an accepted issue. That is a queue decision,
not a judgment of you or your code, and reopening takes about a minute. Argue for
your change on its merits; that is a normal and welcome part of contributing.
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, including this
repository, our Discord, and our documentation, and also applies when an
individual is officially representing the community in public spaces. Examples of
representing our community include using an official email address, posting via
an official social media account, or acting as an appointed representative at an
online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the maintainers at **support@mem0.ai**. All complaints will be
reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community, or a first contribution that
breaches the Contribution Conduct rules above.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions, including a repeated pattern of unverified or automated submissions
after a first warning.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban. At this stage the account may be denounced in `.github/VOUCHED.td`, which
means new pull requests are flagged automatically.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
The Contribution Conduct section is specific to this repository.
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][mozilla].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][faq]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[mozilla]: https://github.com/mozilla/inclusion
[faq]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
+52 -2
View File
@@ -7,6 +7,12 @@ new features, documentation, examples, and integrations.
Mem0 is a polyglot monorepo, and this guide covers contributing to both the
**Python SDK** and the **TypeScript SDK** (and the rest of the repository).
By participating you agree to our [Code of Conduct](./CODE_OF_CONDUCT.md). Its
**Contribution Conduct** section is the enforceable form of the rules on this
page: disclose AI use, don't submit work you haven't run, don't fabricate
reproductions or benchmarks, keep your volume matched to your engagement, and
don't press for merges.
## Before You Start
### 1. Open an Issue First
@@ -23,9 +29,53 @@ in code.
- For anything beyond a trivial fix, wait for a maintainer to confirm the approach
before starting significant work.
Every pull request must link to an issue using `Closes #<issue-number>`.
A bug report needs a reproduction we can run, the version you are on, and the
real output or traceback you saw. Reports without those cannot be acted on and
get closed. A feature request needs the problem you hit and the workaround you
are living with, not just the API you would like.
### 2. Sign the Contributor License Agreement (CLA)
Every pull request must link to an issue using `Closes #<issue-number>`, and that
issue must carry the `accepted` label. A maintainer applies `accepted` once we
agree the change is one we want.
Pull requests that don't link an accepted issue are closed automatically by the
[PR Gate](./.github/workflows/pr-gate.yml). **Closed does not mean rejected.** It
means the change isn't in the queue yet. Once a maintainer labels the issue,
reopen the pull request and it stays open. Documentation-only changes skip the
gate entirely.
Security fixes are the one exception, and they don't go through public pull
requests at all. Follow the [Security Policy](./SECURITY.md) instead, which uses
a private advisory and a private fork so the vulnerability isn't disclosed before
the fix ships.
### 2. Understand Your Code
**You must be able to explain what your changes do and how they interact with
the rest of the codebase without the help of an AI tool.** This is the one rule
we will not bend on.
Using AI to write code is fine. Most of us do. You can build real understanding
by interrogating an agent about this codebase until you grasp the edge cases and
the blast radius of your change. What is not fine is opening a pull request for
a diff you cannot defend in review.
Disclose it in the pull request template and say what you checked yourself.
We ask about the code, not the write-up: using AI to draft the pull request
description is fine. We ask because it tells reviewers where to look, not
because it counts against you. An honest "an agent wrote this, here is what I
verified" is welcome. Silence, followed by a review comment you cannot answer,
is what wastes everyone's time.
Signs your pull request will be closed:
- Invented APIs, config keys, or providers that don't exist in this repo.
- Tests that assert the implementation back at itself rather than the behaviour.
- A description that describes a different change than the diff makes.
- Sweeping unrelated reformatting bundled with a small fix.
- You cannot answer a direct question about your own diff.
### 3. Sign the Contributor License Agreement (CLA)
**We cannot accept or merge any pull request until you have signed our Contributor
License Agreement (CLA).**
+6
View File
@@ -26,6 +26,12 @@ following as you can:
- Clear, step-by-step reproduction instructions
- The security impact and a proof of concept, if available
- Any suggested fix or mitigation
- Whether an AI tool was involved in finding or writing up the report
Reports generated by an AI tool are welcome, but only once you have run the
reproduction yourself and confirmed the impact is real. A scan result or model
output pasted in without that step is not a vulnerability report, and we close
those without a detailed response so we can spend the time on real ones.
## Response Process
+41
View File
@@ -0,0 +1,41 @@
# Node CLI (`cli/node/`)
The `@mem0/cli` package on npm. Commander-based, entry point `mem0`.
## Commands
```bash
pnpm install
pnpm run build # tsup (ESM)
pnpm run lint # biome check src/
pnpm run lint:fix # biome check --write src/
pnpm run typecheck # tsc --noEmit
pnpm run test # vitest run
pnpm run test:watch
pnpm run dev # tsx src/index.ts
```
pnpm only. Never npm, never yarn.
## Conventions
> **Biome, not ESLint. vitest, not jest.** `mem0-ts/` uses Prettier + jest and
> `integrations/vercel-ai-sdk/` uses ESLint + jest. Running those tools here produces
> spurious diffs. Every toolchain in this repo is per-package.
- **Node 18+** required.
- **Build:** tsup, ESM output only.
- **Linter and formatter:** Biome, configured in `biome.json`.
- **Tests:** vitest.
- **TypeScript strict mode.** ES module `import` syntax only, never `require()`.
Run `pnpm run typecheck` after every change.
## Dependencies
Commander + Chalk + ora + cli-table3, and `mem0ai` (npm) for API calls.
## CI and release
- CI: `cli-node-ci.yml`, Biome + tsc + vitest + tsup build on Node 20 and 22.
- Release: tag prefix `cli-node-v*` dispatches `cli-node-cd.yml`, publishing to npm over OIDC.
+1
View File
@@ -0,0 +1 @@
AGENTS.md
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@mem0/cli",
"version": "0.2.11",
"version": "0.2.12",
"description": "The official CLI for mem0 — the memory layer for AI agents",
"type": "module",
"bin": {
+1
View File
@@ -15,6 +15,7 @@ export interface AddOptions {
infer?: boolean;
expires?: string;
customInstructions?: string;
agentCustomInstructions?: string;
customCategories?: Record<string, string>[];
structuredDataSchema?: Record<string, unknown>;
timestamp?: number;
+2
View File
@@ -153,6 +153,8 @@ export class PlatformBackend implements Backend {
if (opts.expires) payload.expiration_date = opts.expires;
if (opts.customInstructions)
payload.custom_instructions = opts.customInstructions;
if (opts.agentCustomInstructions)
payload.agent_custom_instructions = opts.agentCustomInstructions;
if (opts.customCategories)
payload.custom_categories = opts.customCategories;
if (opts.structuredDataSchema)
+2
View File
@@ -53,6 +53,7 @@ export async function cmdAdd(
expires?: string;
categories?: string;
customInstructions?: string;
agentCustomInstructions?: string;
customCategories?: string;
structuredDataSchema?: string;
timestamp?: number;
@@ -153,6 +154,7 @@ export async function cmdAdd(
infer: opts.infer !== false,
expires: opts.expires,
customInstructions: opts.customInstructions,
agentCustomInstructions: opts.agentCustomInstructions,
customCategories: customCats,
structuredDataSchema: schema,
timestamp: opts.timestamp,
+10 -1
View File
@@ -36,7 +36,16 @@ const COMMAND_GROUPS: { panel: string; commands: string[] }[] = [
},
{
panel: "Management",
commands: ["init", "status", "import", "help", "entity", "event", "config"],
commands: [
"init",
"status",
"version",
"import",
"help",
"entity",
"event",
"config",
],
},
];
+21 -3
View File
@@ -95,6 +95,10 @@ async function getBackendOnly(
return (await getBackendAndConfig(apiKey, baseUrl)).backend;
}
function printVersion(): void {
console.log(` ${colors.brand("◆ Mem0")} CLI v${CLI_VERSION}`);
}
function checkAgentMode(): boolean {
const rootOpts = program.opts();
const isAgent = !!(rootOpts.json || rootOpts.agent);
@@ -154,7 +158,7 @@ program
.enablePositionalOptions()
.option("--version", "Show version and exit.")
.on("option:version", () => {
console.log(` ${colors.brand("◆ Mem0")} CLI v${CLI_VERSION}`);
printVersion();
process.exit(0);
})
.option("--json", "Output as JSON for agent/programmatic use.")
@@ -328,6 +332,10 @@ program
"--custom-instructions <text>",
"Custom instructions for fact extraction.",
)
.option(
"--agent-custom-instructions <text>",
"Extraction instructions for agent-scoped memories, overriding the project setting.",
)
.option(
"--custom-categories <json>",
"Custom categories as a JSON array of {name: description} objects.",
@@ -383,7 +391,10 @@ program
)
.option("--rerank", "Enable reranking (Platform only).", false)
.option("--keyword", "Use keyword search.", false)
.option("--filter <json>", "Advanced filter expression (JSON).")
.option(
"--filter <json>",
'Advanced filter as JSON: {"AND": [...]} or {"OR": [...]}, e.g. {"AND": [{"categories": {"in": ["work"]}}]}.',
)
.option("--fields <list>", "Specific fields to return (comma-separated).")
.option("--show-expired", "Include expired memories.", false)
.option(
@@ -400,7 +411,7 @@ program
.option("--base-url <url>", "Override API base URL.")
.addHelpText(
"after",
'\nExamples:\n $ mem0 search "preferences" --user-id alice\n $ mem0 search "tools" -u alice -o json -k 5\n $ echo "preferences" | mem0 search -u alice',
'\nExamples:\n $ mem0 search "preferences" --user-id alice\n $ mem0 search "tools" -u alice -o json -k 5\n $ echo "preferences" | mem0 search -u alice\n $ mem0 search "invoices" -u alice --filter \'{"AND": [{"categories": {"in": ["work"]}}]}\'',
)
.action(async (query, opts) => {
let resolvedQuery = query;
@@ -819,6 +830,13 @@ program
});
});
program
.command("version")
.description("Show version and exit.")
.action(() => {
printVersion();
});
program
.command("import <filePath>")
.description("Import memories from a JSON file.")
+15 -2
View File
@@ -44,11 +44,17 @@ describe("CLI Integration — help and version", () => {
expect(result.stdout).toContain("search");
});
it("prints the version with --version, and has no version subcommand", () => {
it("prints the version with --version", () => {
const flag = run(["--version"]);
expect(flag.exitCode).toBe(0);
expect(flag.stdout).toContain("Mem0");
expect(run(["version"]).exitCode).not.toBe(0);
});
it("version subcommand output matches --version output byte-for-byte", () => {
const flag = run(["--version"]);
const cmd = run(["version"]);
expect(cmd.exitCode).toBe(0);
expect(cmd.stdout).toBe(flag.stdout);
});
it.each([["help", "--json"], ["--json", "help"], ["--agent", "help"]])(
@@ -129,6 +135,13 @@ describe("CLI Integration — help and version", () => {
expect(result.stdout).toContain("--rerank");
});
it("search help documents the --filter JSON shape with an example", () => {
const result = run(["search", "--help"]);
expect(result.exitCode).toBe(0);
expect(result.stdout).toContain("AND");
expect(result.stdout).toContain("categories");
});
it("list help has --category flag", () => {
const result = run(["list", "--help"]);
expect(result.exitCode).toBe(0);
+1
View File
@@ -50,6 +50,7 @@ const ADD_MAPPING: Record<string, string[]> = {
metadata: ["--metadata"],
expiration_date: ["--expires"],
custom_instructions: ["--custom-instructions"],
agent_custom_instructions: ["--agent-custom-instructions"],
custom_categories: ["--custom-categories"],
infer: ["--no-infer"],
immutable: ["--immutable"],
+5
View File
@@ -84,6 +84,7 @@ describe("PlatformBackend option-parity payloads (MEM-5893)", () => {
metadata: { source: "test" },
expires: "2099-01-01",
customInstructions: "Extract only preferences.",
agentCustomInstructions: "Extract only tool outcomes.",
customCategories: [{ prefs: "user preferences" }],
structuredDataSchema: { type: "object" },
timestamp: 1700000000,
@@ -91,6 +92,9 @@ describe("PlatformBackend option-parity payloads (MEM-5893)", () => {
const payload = spy.mock.calls[0][2].json;
expect(payload.custom_instructions).toBe("Extract only preferences.");
expect(payload.agent_custom_instructions).toBe(
"Extract only tool outcomes.",
);
expect(payload.custom_categories).toEqual([{ prefs: "user preferences" }]);
expect(payload.structured_data_schema).toEqual({ type: "object" });
expect(payload.timestamp).toBe(1700000000);
@@ -109,6 +113,7 @@ describe("PlatformBackend option-parity payloads (MEM-5893)", () => {
const payload = spy.mock.calls[0][2].json;
expect(payload).not.toHaveProperty("custom_instructions");
expect(payload).not.toHaveProperty("agent_custom_instructions");
expect(payload).not.toHaveProperty("custom_categories");
expect(payload).not.toHaveProperty("structured_data_schema");
expect(payload).not.toHaveProperty("timestamp");
+47
View File
@@ -0,0 +1,47 @@
# Python CLI (`cli/python/`)
The `mem0-cli` package on PyPI. Typer-based, entry point `mem0`.
## Commands
```bash
pip install -e ".[dev]" # dev install: ruff + pytest
ruff check . # lint
ruff format . # format
pytest # test
hatch build # build
```
## Conventions
> **Line length is 100 here, not 120.** The root Python SDK uses 120. Running the root
> `make format` over this directory reformats every file and fails CI. Use the local
> `ruff` invocations above.
- **Python 3.10+.** Not 3.9, unlike the root SDK.
- **Ruff** with an extended rule set: `E`, `F`, `I`, `W`, `UP`, `B`, `SIM`, `RUF`.
Ignores `E501` (formatter handles it), `B008` (required by Typer's argument defaults),
and `SIM108`.
- **Ruff format:** double quotes, space indent, `docstring-code-format = true`.
- **isort** first-party is `mem0_cli` only.
- **pytest** for tests.
- Target version pinned to `py310`.
## Layout
```
cli/python/
├── src/mem0_cli/ package source (src layout)
└── tests/
```
Entry point: `mem0 = "mem0_cli.app:main"`.
## Dependencies
Typer + Rich + httpx. `mem0ai` is **optional**, exposed through the `[oss]` extra for OSS mode. Do not promote it to a required dependency.
## CI and release
- CI: `cli-python-ci.yml`, ruff + pytest + `hatch build` on Python 3.10, 3.11, 3.12.
- Release: tag prefix `cli-v*` dispatches `cli-python-cd.yml`, publishing to PyPI over OIDC.
+1
View File
@@ -0,0 +1 @@
AGENTS.md
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "mem0-cli"
version = "0.2.10"
version = "0.2.11"
description = "The official CLI for mem0 — the memory layer for AI agents"
readme = "README.md"
license = "Apache-2.0"
+1 -1
View File
@@ -1,3 +1,3 @@
"""mem0 CLI — the command-line interface for the mem0 memory layer."""
__version__ = "0.2.10"
__version__ = "0.2.11"
+29 -2
View File
@@ -278,6 +278,11 @@ def add(
custom_instructions: str | None = typer.Option(
None, "--custom-instructions", help="Custom instructions for fact extraction."
),
agent_custom_instructions: str | None = typer.Option(
None,
"--agent-custom-instructions",
help="Extraction instructions for agent-scoped memories, overriding the project setting.",
),
custom_categories: str | None = typer.Option(
None,
"--custom-categories",
@@ -327,6 +332,7 @@ def add(
expires=expires,
categories=categories,
custom_instructions=custom_instructions,
agent_custom_instructions=agent_custom_instructions,
custom_categories=custom_categories,
structured_data_schema=structured_data_schema,
timestamp=timestamp,
@@ -365,7 +371,11 @@ def search(
False, "--keyword", help="Use keyword search.", rich_help_panel="Search"
),
filter_json: str | None = typer.Option(
None, "--filter", help="Advanced filter expression (JSON).", rich_help_panel="Search"
None,
"--filter",
help='Advanced filter as JSON: {"AND": [...]} or {"OR": [...]}, '
'e.g. {"AND": [{"categories": {"in": ["work"]}}]}.',
rich_help_panel="Search",
),
fields: str | None = typer.Option(
None,
@@ -408,6 +418,7 @@ def search(
mem0 search "preferences" --user-id alice
mem0 search "tools" -u alice -o json -k 5
echo "preferences" | mem0 search -u alice
mem0 search "invoices" -u alice --filter '{"AND": [{"categories": {"in": ["work"]}}]}'
"""
from mem0_cli.commands.memory import cmd_search
@@ -1078,6 +1089,18 @@ def status(
)
@app.command(rich_help_panel="Management")
def version() -> None:
"""Show version and exit.
Example:
mem0 version
"""
from mem0_cli.commands.utils import cmd_version
cmd_version()
@app.command("import", rich_help_panel="Management")
def import_cmd(
file_path: str = typer.Argument(..., help="JSON file to import."),
@@ -1139,6 +1162,7 @@ def _build_help_json() -> dict:
"--expires": "Expiration date (YYYY-MM-DD).",
"--categories": "Not supported on add, use --custom-categories instead.",
"--custom-instructions": "Custom instructions for fact extraction.",
"--agent-custom-instructions": "Extraction instructions for agent-scoped memories, overriding the project setting.",
"--custom-categories": "Custom categories as a JSON array of {name: description} objects.",
"--structured-data-schema": "Schema for structured data extraction, as JSON.",
"--timestamp": "Unix timestamp for the memory.",
@@ -1158,7 +1182,10 @@ def _build_help_json() -> dict:
"--threshold": "Minimum similarity score (default: 0.3).",
"--rerank": "Enable reranking (Platform only).",
"--keyword": "Use keyword search instead of semantic.",
"--filter": "Advanced filter expression (JSON).",
"--filter": (
'Advanced filter as JSON: {"AND": [...]} or {"OR": [...]}, '
'e.g. {"AND": [{"categories": {"in": ["work"]}}]}.'
),
"--fields": "Specific fields to return (comma-separated).",
"--show-expired": "Include expired memories.",
"--reference-date": "Reference date for relative queries (YYYY-MM-DD or unix timestamp).",
+1
View File
@@ -26,6 +26,7 @@ class Backend(ABC):
infer: bool = True,
expires: str | None = None,
custom_instructions: str | None = None,
agent_custom_instructions: str | None = None,
custom_categories: list[dict] | None = None,
structured_data_schema: dict | None = None,
timestamp: int | None = None,
@@ -88,6 +88,7 @@ class PlatformBackend(Backend):
infer: bool = True,
expires: str | None = None,
custom_instructions: str | None = None,
agent_custom_instructions: str | None = None,
custom_categories: list[dict] | None = None,
structured_data_schema: dict | None = None,
timestamp: int | None = None,
@@ -117,6 +118,8 @@ class PlatformBackend(Backend):
payload["expiration_date"] = expires
if custom_instructions:
payload["custom_instructions"] = custom_instructions
if agent_custom_instructions:
payload["agent_custom_instructions"] = agent_custom_instructions
if custom_categories:
payload["custom_categories"] = custom_categories
if structured_data_schema:
@@ -77,6 +77,7 @@ def cmd_add(
expires: str | None,
categories: str | None,
custom_instructions: str | None = None,
agent_custom_instructions: str | None = None,
custom_categories: str | None = None,
structured_data_schema: str | None = None,
timestamp: int | None = None,
@@ -166,6 +167,7 @@ def cmd_add(
infer=not no_infer,
expires=expires,
custom_instructions=custom_instructions,
agent_custom_instructions=agent_custom_instructions,
custom_categories=custom_cats,
structured_data_schema=schema,
timestamp=timestamp,
+12 -1
View File
@@ -91,7 +91,12 @@ class TestCLIIntegration:
flag = _run(["--version"])
assert flag.returncode == 0
assert __version__ in flag.stdout
assert _run(["version"]).returncode != 0
def test_version_subcommand_matches_flag_byte_for_byte(self):
flag = _run(["--version"])
cmd = _run(["version"])
assert cmd.returncode == 0
assert cmd.stdout == flag.stdout
@pytest.mark.parametrize(
"args",
@@ -127,6 +132,12 @@ class TestCLIIntegration:
assert result.returncode == 0
assert "top-k" in result.stdout
def test_search_help_documents_filter_json_shape(self):
result = _run(["search", "--help"])
assert result.returncode == 0
assert "AND" in result.stdout
assert "categories" in result.stdout
def test_list_help(self):
result = _run(["list", "--help"])
assert result.returncode == 0
+1
View File
@@ -38,6 +38,7 @@ ADD_MAPPING: dict[str, list[str]] = {
"metadata": ["metadata"],
"expiration_date": ["expires"],
"custom_instructions": ["custom_instructions"],
"agent_custom_instructions": ["agent_custom_instructions"],
"custom_categories": ["custom_categories"],
"infer": ["no_infer"],
"immutable": ["immutable"],
@@ -22,12 +22,14 @@ class TestAddOptions:
metadata={"source": "test"},
expires="2099-01-01",
custom_instructions="Extract only preferences.",
agent_custom_instructions="Extract only tool outcomes.",
custom_categories=[{"prefs": "user preferences"}],
structured_data_schema={"type": "object"},
timestamp=1700000000,
)
payload = mock_request.call_args.kwargs["json"]
assert payload["custom_instructions"] == "Extract only preferences."
assert payload["agent_custom_instructions"] == "Extract only tool outcomes."
assert payload["custom_categories"] == [{"prefs": "user preferences"}]
assert payload["structured_data_schema"] == {"type": "object"}
assert payload["timestamp"] == 1700000000
@@ -40,6 +42,7 @@ class TestAddOptions:
backend.add(content="hello", user_id="alice")
payload = mock_request.call_args.kwargs["json"]
assert "custom_instructions" not in payload
assert "agent_custom_instructions" not in payload
assert "custom_categories" not in payload
assert "structured_data_schema" not in payload
assert "timestamp" not in payload
+49
View File
@@ -0,0 +1,49 @@
# Documentation (`docs/`)
Mintlify site published at https://docs.mem0.ai.
## Commands
```bash
make docs # from repo root
cd docs && mintlify dev
```
## Structure
| Path | Contents |
|------|----------|
| `api-reference/` | Platform REST endpoints |
| `open-source/` | Self-hosted SDK guides |
| `platform/` | Hosted platform guides |
| `integrations/` | One page per integration |
| `core-concepts/` | Memory model, graph memory, scoping |
| `cookbooks/` | End-to-end recipes |
| `contributing/` | Contributor guides |
| `docs.json` | Navigation tree |
| `openapi.json` | Platform API spec |
| `llms.txt` | Scope-tagged index for agents |
## Adding a page
Every new `.mdx` page needs three things, or CI fails:
1. The page itself under the right section.
2. A navigation entry in `docs.json`.
3. A line in `llms.txt` with a scope tag (`[Platform]`, `[OSS]`, or `[Both]`) and a description that starts with `Use when ...`.
`docs-llms-txt-check.yml` runs on every PR touching `docs/**/*.mdx` and **blocks the merge** when `llms.txt` is out of sync. To fix:
```bash
python scripts/check-llms-txt-coverage.py --write
```
That scaffolds placeholders under `## Unclassified - needs triage`. Then replace each `[TODO: ...]` tag, rewrite the descriptions as `Use when ...`, move entries into the correct section, and delete the triage heading once it is empty.
## Conventions
- Frontmatter needs `title`, `description`, and usually `icon`.
- Mintlify components (`<Note>`, `<Card>`, `<Tabs>`, `<CodeGroup>`) are available; prefer them over raw HTML.
- Code samples must be runnable. If a sample calls a public SDK method, it has to match the real signature.
- Documentation-only PRs are exempt from the `accepted`-issue requirement in the PR gate, but not from the CLA.
- Any change to a public SDK signature has to update the matching page here in the same PR.
+1
View File
@@ -0,0 +1 @@
AGENTS.md
@@ -95,6 +95,12 @@ client.project.update(
custom_instructions="..."
)
# Separate extraction instructions for agent-scoped memories
# (see /platform/features/custom-instructions)
client.project.update(
agent_custom_instructions="..."
)
# Use the input language for memory storage and retrieval
client.project.update(multilingual=True)
+144
View File
@@ -7,6 +7,43 @@ mode: "wide"
<Tabs>
<Tab title="Python">
<Update label="2026-08-11" description="v2.0.18">
**Bug Fixes:**
- **Core:** Percent-escape `%`, `&`, and `=` in `user_id`, `agent_id`, and `run_id` when building the session scope key for the recent-conversation buffer, so the key stays unambiguous for ids containing those characters. Ordinary ids keep their existing key; an id already containing `%`, `&`, or `=` maps to a new key, so its buffer starts empty once and refills on the next `add()`. Stored memories are unaffected ([#6892](https://github.com/mem0ai/mem0/pull/6892))
- **Vector Stores:** Raise `ValueError` when a PGVector `in`/`nin` filter value is not a list. A string value was previously iterated character by character into the generated `= ANY(...)` array (so `{"user_id": {"in": "alice"}}` matched `a`, `l`, `i`, `c`, `e`), and a non-iterable value raised a bare `TypeError` from deep inside filter building ([#6879](https://github.com/mem0ai/mem0/pull/6879))
- **Vector Stores:** Reject `index_accuracy=0` in the Oracle AI Vector Search config. The range check sat behind a truthiness test, so `0` skipped validation entirely and was passed through to `WITH TARGET ACCURACY 0` instead of raising ([#6848](https://github.com/mem0ai/mem0/pull/6848))
- **Vector Stores:** Close the Oracle connection or pool that Mem0 opened when initialization fails. A client version check, a database version check, or a `create_col()` error previously propagated with the connection still open, leaking it for the life of the process. A caller-supplied `client` is left untouched ([#6839](https://github.com/mem0ai/mem0/pull/6839))
</Update>
<Update label="2026-08-05" description="v2.0.17">
**New Features:**
- **Client:** Add `agent_custom_instructions` to `project.update()`/`update_project()` (sync and async) and to the `ProjectUpdateOptions` and `AddMemoryOptions` typed models. It sets a second extraction instruction set that applies only to agent-scoped memories: an add passing `agent_id` without `user_id` uses it, one passing both splits by attribution, and while it is unset `custom_instructions` continues to apply to every memory ([#6809](https://github.com/mem0ai/mem0/pull/6809))
</Update>
<Update label="2026-08-04" description="v2.0.16">
**New Features:**
- **Client:** Add `reference_date`, `latest_only`, and `keyword_search` to `SearchMemoryOptions`, and `latest_only` to `GetAllMemoryOptions`, keeping the Python client's typed options in sync with the Platform API and the CLIs ([#6696](https://github.com/mem0ai/mem0/pull/6696))
**Bug Fixes:**
- **Core:** Stop `add()` metadata from setting a memory's identity scope. `_build_filters_and_metadata()` now strips `user_id`, `agent_id`, `run_id`, and `actor_id` from caller-supplied `metadata` before building the creation template, so metadata can no longer place a memory into a scope that was never passed through the entity params ([#6656](https://github.com/mem0ai/mem0/pull/6656))
- **Vector Stores:** Validate Upstash filter keys and values in `search()`, `keyword_search()`, and `list()`. Filter keys must match a safe identifier pattern, values must be `str`/`int`/`float`/`bool`, and string values containing a double quote or backslash are now rejected instead of being interpolated unescaped into the generated query string ([#5981](https://github.com/mem0ai/mem0/pull/5981))
- **Embeddings:** `FastEmbedEmbedding.embed()` now converts its result with `.tolist()` before returning, so callers get a plain `List[float]` instead of a numpy array ([#6770](https://github.com/mem0ai/mem0/pull/6770))
- **Embeddings:** `HuggingFaceEmbedding` now passes `api_key` to the OpenAI-compatible client when `huggingface_base_url` is set. The configured key was previously dropped, so the client fell back to `OPENAI_API_KEY` from the environment or raised `OpenAIError` at construction when that was unset ([#6770](https://github.com/mem0ai/mem0/pull/6770))
- **Embeddings:** Replace Ollama's interactive `pip install` prompt on import with a plain `ImportError`. Importing `mem0.embeddings.ollama` without the `ollama` package previously blocked on stdin and then called `sys.exit(1)`, killing the host process instead of raising ([#6770](https://github.com/mem0ai/mem0/pull/6770))
- **Core:** `remove_code_blocks()` now returns an empty string for `None` input instead of raising `AttributeError` ([#6770](https://github.com/mem0ai/mem0/pull/6770))
- **Core:** `parse_vision_messages()` now chains the original exception (`raise ... from e`) when an image download fails, so the root cause is preserved in the traceback ([#6770](https://github.com/mem0ai/mem0/pull/6770))
- **Core:** `process_telemetry_filters(None)` now returns `([], {})`, matching the two-value tuple every caller unpacks, instead of `{}` ([#6770](https://github.com/mem0ai/mem0/pull/6770))
- **Core:** `LlmFactory.create()` no longer mutates the caller's config dict in place via `.update(kwargs)`; the merge now builds a new dict ([#6770](https://github.com/mem0ai/mem0/pull/6770))
- **Rerankers:** The Cohere, HuggingFace, SentenceTransformer, and Zero Entropy rerankers' failure-fallback path no longer mutates the caller's document dicts in place when stamping `rerank_score`; it now falls back on copies ([#6770](https://github.com/mem0ai/mem0/pull/6770))
- **Vector Stores:** Remove `logging.basicConfig()` calls from the MongoDB and Vertex AI Vector Search providers, so selecting either provider no longer reconfigures the host application's root logger as a side effect ([#6770](https://github.com/mem0ai/mem0/pull/6770))
</Update>
<Update label="2026-08-01" description="v2.0.15">
**Bug Fixes:**
@@ -1169,6 +1206,44 @@ See the [OSS v2 to v3 migration guide](https://docs.mem0.ai/migration/oss-v2-to-
<Tab title="TypeScript">
<Update label="2026-08-11" description="v3.1.6">
**New Features:**
- **Vector Stores:** Add an Oracle AI Vector Search vector store (`oracledb`) to the OSS SDK, with pooled connections, `HNSW`/`IVF` indexes, an optional `indexAccuracy` target, JSON payload filtering, and six selectable distance metrics ([#6690](https://github.com/mem0ai/mem0/pull/6690))
**Bug Fixes:**
- **Core:** Percent-escape `%`, `&`, and `=` in `userId`, `agentId`, and `runId` when building the session scope key for the recent-conversation buffer, so the key stays unambiguous for ids containing those characters. Ordinary ids keep their existing key; an id already containing `%`, `&`, or `=` maps to a new key, so its buffer starts empty once and refills on the next `add()`. Stored memories are unaffected ([#6892](https://github.com/mem0ai/mem0/pull/6892))
- **Vector Stores:** Close and clear the Oracle pool that Mem0 created when `initialize()` fails, and reset the cached init promise so the next call retries instead of replaying the rejection forever. A caller-supplied `client` is left untouched ([#6839](https://github.com/mem0ai/mem0/pull/6839))
- **Vector Stores:** Validate Oracle `insert()` batches before touching the database: `ids` and `payloads` must match `vectors` in length, so a short array can no longer write rows with `undefined` ids or silently drop payloads ([#6839](https://github.com/mem0ai/mem0/pull/6839))
**Improvements:**
- **Vector Stores:** Cut Oracle round trips. `insert()` now sends the whole batch through one `executeMany()` with explicit `bindDefs` instead of one `INSERT` per vector, `list()` reads the total from a `COUNT(*) OVER ()` window in the same statement instead of issuing a second count query, and an unfiltered `search()` adds the `VECTOR_INDEX_TRANSFORM` hint so the vector index is used ([#6835](https://github.com/mem0ai/mem0/pull/6835))
**Security:**
- **Dependencies:** Patched 8 high and 18 medium severity dependency vulnerabilities across the pnpm workspace via `pnpm.overrides` (`undici`, `brace-expansion`, `ip-address`) ([#6847](https://github.com/mem0ai/mem0/pull/6847))
</Update>
<Update label="2026-08-05" description="v3.1.5">
**New Features:**
- **Client:** Add `agentCustomInstructions` to `PromptUpdatePayload`, `AddMemoryOptions`, and `ProjectResponse`. It sets a second extraction instruction set that applies only to agent-scoped memories: an add passing `agentId` without `userId` uses it, one passing both splits by attribution, and while it is unset `customInstructions` continues to apply to every memory ([#6809](https://github.com/mem0ai/mem0/pull/6809))
</Update>
<Update label="2026-08-04" description="v3.1.4">
**New Features:**
- **Client:** Add `referenceDate` and `keywordSearch` to `SearchMemoryOptions`, keeping the TypeScript client's typed search options in sync with the Platform API ([#6696](https://github.com/mem0ai/mem0/pull/6696))
**Bug Fixes:**
- **Client:** Take the `/v1/ping/` identity/telemetry call off the request critical path. Every method previously did `if (this.telemetryId === "") await this.ping();`, blocking the first call on each client instance on a network round trip; the ping now resolves in the background through a shared, credentials-keyed promise cache (FIFO-capped at 50 entries), so concurrent clients on the same host/API key share one ping instead of issuing one each, and a failed ping is not cached so the process can retry ([#6788](https://github.com/mem0ai/mem0/pull/6788))
- **Client:** `deleteUsers()` now issues its per-entity DELETE requests through the shared `fetch()`-based helper instead of the axios instance, which defaulted to `keepAlive: false`. Deleting every user, agent, app, and run now reuses pooled connections instead of paying a fresh TCP/TLS handshake per entity ([#6788](https://github.com/mem0ai/mem0/pull/6788))
- **Memory (OSS):** Stop `add()` metadata from setting or overwriting a memory's identity scope. Metadata now runs through the same `stripIdentityKeys()` helper as `update()`, so `user_id`/`agent_id`/`run_id` (snake_case or camelCase) and `actor_id` passed in metadata can no longer place a memory into a scope the caller didn't request through `userId`/`agentId`/`runId`/`filters` ([#6377](https://github.com/mem0ai/mem0/pull/6377))
- **Vector Stores:** Fix Redis `search()` and `list()` building an invalid, empty RediSearch filter expression when `filters` was an empty object or contained only null/undefined values. The shared `buildRedisFilterExpr()` helper now falls back to `"*"` (match all) instead of joining zero conditions into `""` ([#6014](https://github.com/mem0ai/mem0/pull/6014))
</Update>
<Update label="2026-08-01" description="v3.1.3">
**New Features:**
@@ -1748,6 +1823,26 @@ See the [TypeScript SDK migration guide](https://docs.mem0.ai/migration/ts-v2-to
<Tab title="CLI">
<Update label="2026-08-04" description="Python v0.2.11 / Node v0.2.12">
**New Features:**
- **`add`:** New `--custom-instructions`, `--custom-categories`, `--structured-data-schema`, and `--timestamp` flags, matching the Platform `/v3/memories/add/` payload fields (Python and Node [#6696](https://github.com/mem0ai/mem0/pull/6696))
- **`search`:** New `--show-expired`, `--reference-date`, and `--latest-only` flags, forwarded to `/v3/memories/search/` as `show_expired`, `reference_date`, and `latest_only` (Python and Node [#6696](https://github.com/mem0ai/mem0/pull/6696))
- **`list`:** New `--show-expired` and `--latest-only` flags (Python and Node [#6696](https://github.com/mem0ai/mem0/pull/6696))
- **`update`:** New `--expires` and `--timestamp` flags (Python and Node [#6696](https://github.com/mem0ai/mem0/pull/6696))
- **`delete`:** New `--delete-linked` flag to also delete memories linked to the target memory (Python and Node [#6696](https://github.com/mem0ai/mem0/pull/6696))
**Bug Fixes:**
- **`help --json`:** Emit JSON automatically under agent mode (`--agent`), not only when `--json` is passed explicitly. Python checks `is_agent_mode()` and now renders through `console.print_json()` instead of a plain `console.print(json.dumps(...))` call; Node also checks the root `--agent` flag in addition to the subcommand's `--json` flag (Python and Node [#6773](https://github.com/mem0ai/mem0/pull/6773))
**Changes:**
- **`add`:** `--categories` is no longer forwarded on `add`. The `/v3/memories/add/` payload has no `categories` field (only `custom_categories`), so the CLI was sending a key the endpoint does not accept. Passing the flag now exits 1 with a message pointing to `--custom-categories` (Python and Node [#6696](https://github.com/mem0ai/mem0/pull/6696))
**Security:**
- **Dependencies (Node):** Tighten the `postcss` pnpm override from `<8.5.10 → >=8.5.10` to `<8.5.18 → >=8.5.18 <9.0.0`, closing a newer CVE range the previous floor didn't cover, as part of a wider dependency patch sweep across the pnpm workspaces ([#6639](https://github.com/mem0ai/mem0/pull/6639))
</Update>
<Update label="2026-07-13" description="Python v0.2.10 / Node v0.2.11">
**Bug Fixes:**
@@ -1913,6 +2008,19 @@ A full-featured command-line interface for Mem0, available in both Python and No
<Tabs>
<Tab title="Mem0 Plugin">
<Update label="2026-08-04" description="mem0-plugin v0.2.14">
**Fixes:**
- **Settings loading no longer crashes on a malformed `settings.json`:** If `~/.mem0/settings.json` parsed as valid JSON but wasn't an object (a list or a bare string, for example), `load_settings()` called `.items()` on it and raised. `resolve_config()` guards only against `ImportError`, so the failure escaped into every hook that resolves identity, not just setup. Settings loading now keeps the defaults instead. Setup also stopped claiming it "Created" the settings file when one already existed; it only prints that when it actually wrote one. Shared across Claude Code, Cursor, Codex, and Antigravity.
**New Features:**
- **Unknown settings key warning:** Setup now flags keys in `settings.json` that the plugin doesn't recognize, so a typo'd setting no longer fails silently.
**Removed:**
- Dropped the `mem0_doc_search` "openmemory" section now that OpenMemory has been removed from the docs site, so the skill no longer links to pages that don't exist.
</Update>
<Update label="2026-07-14" description="mem0-plugin v0.2.13">
**Fixes:**
@@ -2252,6 +2360,19 @@ Initial release of the Mem0 plugin for Claude Code and Cursor, followed by Codex
<Tab title="Antigravity">
<Update label="2026-08-04" description="Antigravity plugin v0.1.6">
**Fixes:**
- **Settings loading no longer crashes on a malformed `settings.json`:** If `~/.mem0/settings.json` parsed as valid JSON but wasn't an object, every hook that resolves identity previously raised, not just setup. It now keeps the defaults instead, and setup only reports it "Created" the settings file when it actually wrote one.
**Improvements:**
- **Unknown settings key warning:** Setup now flags keys in `settings.json` it doesn't recognize instead of ignoring them silently.
**Removed:**
- Dropped the doc-search skill's "openmemory" section now that OpenMemory has been removed from the docs site.
</Update>
<Update label="2026-07-14" description="Antigravity plugin v0.1.5">
**Fixes:**
@@ -2722,6 +2843,21 @@ Existing memories written by the previous versions are not rewritten. If your me
<Tab title="n8n">
<Update label="2026-08-05" description="n8n-nodes-mem0 v0.1.3">
**Changes:**
- **License changed to MIT:** The published `@mem0/n8n-nodes-mem0` package is now MIT (was Apache-2.0). n8n's Creator Portal requires verified community nodes to be MIT, and the failing license check was the blocker for verification. The rest of the mem0 repo stays Apache-2.0 ([#6804](https://github.com/mem0ai/mem0/pull/6804))
- **Themed icons:** The node and credential icons now declare `{ light, dark }` variants instead of a single icon, clearing the remaining `icon-prefer-themed-variants` warnings from the Creator Portal scan. No functional changes ([#6804](https://github.com/mem0ai/mem0/pull/6804))
</Update>
<Update label="2026-08-04" description="n8n-nodes-mem0 v0.1.2">
**Changes:**
- **Package contact:** `author.email` in the published package is now `integrations@mem0.ai` (was `founders@mem0.ai`), so npm and n8n Creator Portal correspondence reaches the integrations team directly. No functional changes ([#6791](https://github.com/mem0ai/mem0/pull/6791))
</Update>
<Update label="2026-07-30" description="n8n-nodes-mem0 v0.1.1">
**Changes:**
@@ -2751,6 +2887,14 @@ Existing memories written by the previous versions are not rewritten. If your me
<Tab title="Zapier">
<Update label="2026-08-04" description="Zapier app v0.1.1">
**Bug Fixes:**
- **Add Memory:** **User ID** is now a required field. Mem0 rejects a write that carries no entity ID, so a Zap left blank failed at the API instead of in the editor. If you scoped memories only by Agent ID or Run ID, set a User ID as well ([#6790](https://github.com/mem0ai/mem0/pull/6790))
- **Deployment:** Add a root `index.js` that re-exports the compiled app from `dist/`, and point `main` at it. Zapier's Lambda wrapper loads `<root>/index.js` and ignores the `package.json` `main` field, so the deployed app could not resolve its entry point ([#6789](https://github.com/mem0ai/mem0/pull/6789))
</Update>
<Update label="2026-07-29" description="Zapier app v0.1.0">
**Initial release** of the Mem0 Zapier app, built on the Zapier Platform CLI ([#6518](https://github.com/mem0ai/mem0/pull/6518))
+1 -1
View File
@@ -97,4 +97,4 @@ Here's a comprehensive list of all parameters that can be used across different
## Supported Embedding Models
For detailed information on configuring specific embedders, please visit the [Embedding Models](./models) section. There you'll find information for each supported embedder with provider-specific usage examples and configuration details.
For detailed information on configuring specific embedders, please visit the [Embedding Models](./overview) section. There you'll find information for each supported embedder with provider-specific usage examples and configuration details.
+1 -1
View File
@@ -133,4 +133,4 @@ Here's a comprehensive list of all parameters that can be used across different
## Supported LLMs
For detailed information on configuring specific LLMs, please visit the [LLMs](./models) section. There you'll find information for each supported LLM with provider-specific usage examples and configuration details.
For detailed information on configuring specific LLMs, please visit the [LLMs](./overview) section. There you'll find information for each supported LLM with provider-specific usage examples and configuration details.
@@ -78,6 +78,38 @@ await memory.add(messages, { userId: 'alice', metadata: { category: 'movies' } }
The TypeScript provider calls the Bedrock [Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html), a single uniform interface across the current Bedrock model families. Streaming and `InvokeModel`-only models are not supported yet.
</Note>
### Application inference profiles
Bedrock resolves the model family from the model identifier. An application inference profile ARN ends in an opaque ID, so there is nothing to resolve from. Set `provider_override` (Python) / `providerOverride` (TypeScript) when your model is one:
<CodeGroup>
```python Python
config = {
"llm": {
"provider": "aws_bedrock",
"config": {
"model": "arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123xyz",
"provider_override": "anthropic",
}
}
}
```
```typescript TypeScript
const config = {
llm: {
provider: 'aws_bedrock',
config: {
model: 'arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123xyz',
providerOverride: 'anthropic',
},
},
};
```
</CodeGroup>
Without it, initialization raises `Unknown provider in model` (Python: `ValueError`; TypeScript: `Error`). Plain model IDs and cross-region inference profiles such as `us.anthropic.claude-sonnet-4-20250514-v1:0` still resolve automatically and need no override.
### Config
All available parameters for the `aws_bedrock` config are present in [Master List of All Params in Config](../config).
+2 -2
View File
@@ -123,10 +123,10 @@ Here's a comprehensive list of all parameters that can be used across different
Each vector database has its own specific configuration requirements. To customize the config for your chosen vector store:
1. Identify the vector database you want to use from [supported vector databases](./dbs).
1. Identify the vector database you want to use from [supported vector databases](./overview).
2. Refer to the `Config` section in the respective vector database's documentation.
3. Include only the relevant parameters for your chosen database in the `config` dictionary.
## Supported Vector Databases
For detailed information on configuring specific vector databases, please visit the [Supported Vector Databases](./dbs) section. There you'll find individual pages for each supported vector store with provider-specific usage examples and configuration details.
For detailed information on configuring specific vector databases, please visit the [Supported Vector Databases](./overview) section. There you'll find individual pages for each supported vector store with provider-specific usage examples and configuration details.
+123 -21
View File
@@ -3,17 +3,25 @@ title: "Oracle AI Vector Search"
description: "Use Oracle Database AI Vector Search as a vector store in Mem0 for semantic and relational queries."
---
{/* Copyright (c) 2026, Oracle and/or its affiliates. */}
[Oracle AI Vector Search](https://www.oracle.com/database/ai-vector-search/) stores embeddings in an Oracle table using the native `VECTOR` data type, so you can combine semantic search over unstructured data with relational queries over business data in a single database.
### Requirements
- Oracle Database 23.4 or later, with a user that can create tables and vector indexes
- The `python-oracledb` driver. In thick mode, Oracle Client 23.4 or later is also required.
- The `python-oracledb` or `node-oracledb` driver. In thick mode, Oracle Client 23.4 or later is also required.
```bash
<CodeGroup>
```bash Python
pip install oracledb
```
```bash TypeScript
npm install oracledb
```
</CodeGroup>
### Usage
<CodeGroup>
@@ -47,11 +55,58 @@ messages = [
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from "mem0ai/oss";
const config = {
vectorStore: {
provider: "oracledb",
config: {
collectionName: "mem0",
embeddingModelDims: 1536,
connectionParams: {
user: "mem0_user",
password: "your-password",
connectString: "localhost:1521/FREEPDB1",
},
},
},
};
const memory = new Memory(config);
const messages = [
{
role: "user",
content: "I'm planning to watch a movie tonight. Any recommendations?",
},
{
role: "assistant",
content: "How about thriller movies? They can be quite engaging.",
},
{
role: "user",
content: "I'm not a big fan of thriller movies but I love sci-fi movies.",
},
{
role: "assistant",
content:
"Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future.",
},
];
await memory.add(messages, {
userId: "alice",
metadata: { category: "movies" },
});
```
</CodeGroup>
To reuse a connection or pool you already manage, pass it as `client` instead of `connection_params`:
To reuse a connection or pool you already manage, pass it as `client` instead of the connection parameters:
```python
<CodeGroup>
```python Python
import oracledb
pool = oracledb.create_pool(user="mem0_user", password="your-password", dsn="localhost:1521/FREEPDB1")
@@ -64,33 +119,52 @@ config = {
}
```
```typescript TypeScript
import oracledb from "oracledb";
const pool = await oracledb.createPool({
user: "mem0_user",
password: "your-password",
connectString: "localhost:1521/FREEPDB1",
});
const config = {
vectorStore: {
provider: "oracledb",
config: { client: pool },
},
};
```
</CodeGroup>
### Config
Here are the parameters available for configuring Oracle AI Vector Search:
| Parameter | Description | Default Value |
| --- | --- | --- |
| `connection_params` | Connection settings passed to `python-oracledb`, such as `user`, `password` and `dsn`. See the [connection handling guide](https://python-oracledb.readthedocs.io/en/latest/user_guide/connection_handling.html). | `None` |
| `use_connection_pool` | Create a connection pool from `connection_params` instead of a single connection | `True` |
| `client` | An existing `oracledb.Connection` or `oracledb.ConnectionPool` to use instead of building one from `connection_params` | `None` |
| `collection_name` | Name of the Oracle table that stores vectors and payloads | `mem0` |
| `embedding_model_dims` | Dimension of your embedding vectors, must be greater than 0 | `1536` |
| `distance_metric` | Distance function used for indexing and search: `COSINE`, `EUCLIDEAN`, `EUCLIDEAN_SQUARED`, `DOT`, `HAMMING` or `MANHATTAN` | `COSINE` |
| `do_create_index` | Whether to create a vector index on the collection | `True` |
| `index_type` | Vector index type: `HNSW` or `IVF` | `HNSW` |
| `index_name` | Name of the vector index | `<collection_name>_VEC_IDX` |
| `index_parameters` | Index tuning parameters. For `HNSW`: `neighbors`, `efconstruction`. For `IVF`: `neighbor partitions`, `samples_per_partition`, `min_vectors_per_partition`. | `None` |
| `index_accuracy` | Target index accuracy from 1 to 100, applied as `WITH TARGET ACCURACY <n>` | `None` |
| Python | TypeScript | Description | Default Value |
| --- | --- | --- | --- |
| `connection_params` | `connectionParams` | Connection settings passed to the Oracle driver, such as `user`, `password` and `dsn` (`connectString` in TypeScript). See the [Python](https://python-oracledb.readthedocs.io/en/latest/user_guide/connection_handling.html) or [Node.js](https://node-oracledb.readthedocs.io/en/latest/user_guide/connection_handling.html) connection handling guide. | `None` |
| `use_connection_pool` | `useConnectionPool` | Create a connection pool from the connection parameters instead of a single connection | `True` |
| `client` | `client` | An existing Oracle connection or pool to use instead of building one from the connection parameters | `None` |
| `collection_name` | `collectionName` | Name of the Oracle table that stores vectors and payloads | `mem0` |
| `embedding_model_dims` | `embeddingModelDims` | Dimension of your embedding vectors, must be greater than 0 | `1536` |
| `distance_metric` | `distanceMetric` | Distance function used for indexing and search: `COSINE`, `EUCLIDEAN`, `EUCLIDEAN_SQUARED`, `DOT`, `HAMMING` or `MANHATTAN` | `COSINE` |
| `do_create_index` | `doCreateIndex` | Whether to create a vector index on the collection | `True` |
| `index_type` | `indexType` | Vector index type: `HNSW` or `IVF` | `HNSW` |
| `index_name` | `indexName` | Name of the vector index | `<collection_name>_VEC_IDX` |
| `index_parameters` | `indexParameters` | Index tuning parameters. For `HNSW`: `neighbors`, `efconstruction`. For `IVF`: `neighbor partitions`, `samples_per_partition`, `min_vectors_per_partition`. | `None` |
| `index_accuracy` | `indexAccuracy` | Target index accuracy from 1 to 100, applied as `WITH TARGET ACCURACY <n>` | `None` |
<Note>
When you pass a pre-built `client`, Mem0 uses it as-is and ignores `connection_params` and `use_connection_pool`. Mem0 does not close a client it did not create.
When you pass a pre-built `client`, Mem0 uses it as-is and ignores the connection parameters and pooling options. Mem0 does not close a client it did not create.
</Note>
### Vector indexes
Set the index type with `index_type` and tune it with `index_parameters`:
```python
<CodeGroup>
```python Python
config = {
"vector_store": {
"provider": "oracledb",
@@ -104,6 +178,25 @@ config = {
}
```
```typescript TypeScript
const config = {
vectorStore: {
provider: "oracledb",
config: {
connectionParams: {
user: "mem0_user",
password: "your-password",
connectString: "localhost:1521/FREEPDB1",
},
indexType: "HNSW",
indexParameters: { neighbors: 32, efconstruction: 200 },
indexAccuracy: 95,
},
},
};
```
</CodeGroup>
For the full list of supported options, see the Oracle [`CREATE VECTOR INDEX`](https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/create-vector-index.html) reference.
### Search scores
@@ -121,14 +214,23 @@ Filters run against the JSON `payload` column and support:
| Comparison | `{"score": {"gte": 0.5}}`, also `eq`, `ne`, `gt`, `lt`, `lte` |
| Membership | `{"category": {"in": ["movies", "books"]}}`, also `nin` |
| String matching | `{"title": {"contains": "sci-fi"}}`, also `icontains` for case-insensitive |
| Logical groups | `{"AND": [...]}`, `{"OR": [...]}`, `{"NOT": [...]}` |
| Logical groups | `{"AND": [...]}`, `{"OR": [...]}`, `{"NOT": [...]}`, also `$and`, `$or`, `$not` |
Multiple fields at the top level are combined with `AND`:
```python
<CodeGroup>
```python Python
m.search(
"movie recommendations",
user_id="alice",
filters={"category": {"in": ["movies", "books"]}, "rating": {"gte": 4}},
)
```
```typescript TypeScript
await memory.search("movie recommendations", {
userId: "alice",
filters: { category: { in: ["movies", "books"] }, rating: { gte: 4 } },
});
```
</CodeGroup>
+1 -1
View File
@@ -10,7 +10,7 @@ Mem0 includes built-in support for various popular databases. Memory can utilize
See the list of supported vector databases below.
<Note>
The following vector databases are supported in the Python implementation. The TypeScript implementation currently supports Qdrant, Redis, PGVector, Supabase, LangChain, Azure AI Search, Vectorize, Amazon S3 Vectors, Milvus, Neptune Analytics, and an in-memory store.
The following vector databases are supported in the Python implementation. The TypeScript implementation currently supports Qdrant, Redis, PGVector, Supabase, LangChain, Oracle AI Vector Search, Azure AI Search, Vectorize, Amazon S3 Vectors, Milvus, Neptune Analytics, and an in-memory store.
</Note>
<CardGroup cols={3}>
+24 -2
View File
@@ -14,7 +14,8 @@ Follow the steps below for a smooth contribution process.
<Note>
For the complete contributor checklist, see
[CONTRIBUTING.md](https://github.com/mem0ai/mem0/blob/main/CONTRIBUTING.md) in
the repository root.
the repository root. By participating you agree to our
[Code of Conduct](https://github.com/mem0ai/mem0/blob/main/CODE_OF_CONDUCT.md).
</Note>
## Before You Start
@@ -30,7 +31,28 @@ change, avoid duplicate work, and agree on the approach before you write code.
or [feature request](https://github.com/mem0ai/mem0/issues/new?template=feature_request.yml).
- For anything beyond a trivial fix, wait for a maintainer to confirm the approach.
Every pull request must link to an issue using `Closes #<issue-number>`.
Every pull request must link to an issue using `Closes #<issue-number>`, and that
issue must carry the `accepted` label. A maintainer applies `accepted` once we
agree the change is worth making. Pull requests that do not link an accepted
issue are closed automatically, with instructions to reopen once the label is
applied. Documentation-only changes are exempt.
<Note>
Closed does not mean rejected. Getting the label and reopening takes about a
minute, and the check reruns on reopen.
</Note>
### Show Your Work
Both issue forms ask how you verified the problem: what you ran, the real output
you saw, and why it is a bug rather than expected behavior. Reports without that
are hard to act on and usually sit unanswered.
They also ask whether AI was involved. That question is about how the problem was
found and confirmed, not about how the text was written: drafting the write-up
with a model is fine. The same applies to pull requests, where the AI disclosure
covers the code in the diff. We ask because it tells reviewers where to look, not
because it counts against you.
### 2. Sign the Contributor License Agreement (CLA)
+3
View File
@@ -3,6 +3,9 @@ title: Personalized AI Tutor
description: "Keep student progress and preferences persistent across tutoring sessions."
---
<Info icon="server">
**Works with:** Mem0 OSS (`Memory`)
</Info>
You can create a personalized AI Tutor using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
@@ -3,6 +3,9 @@ title: Self-Hosted AI Companion
description: "Run Mem0 end-to-end on your machine using Ollama-powered LLMs and embedders."
---
<Info icon="server">
**Works with:** Mem0 OSS (`Memory`)
</Info>
Mem0 can be utilized entirely locally by leveraging Ollama for both the embedding model and the language model (LLM). This guide will walk you through the necessary steps and provide the complete code to get you started.
@@ -3,6 +3,9 @@ title: Build a Node.js Companion
description: "Build a JavaScript fitness coach that remembers user goals run after run."
---
<Info icon="server">
**Works with:** Mem0 OSS (`Memory`)
</Info>
You can create a personalized AI Companion using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
@@ -3,6 +3,9 @@ title: Interactive Memory Demo
description: "Spin up the showcase companion app to see Mem0 memories in action."
---
<Info icon="cloud">
**Works with:** Mem0 Platform
</Info>
You can create a personalized AI Companion using Mem0. This guide will walk you through the necessary steps and provide the complete setup instructions to get you started.
@@ -3,6 +3,9 @@ title: Smart Travel Assistant
description: "Plan itineraries that remember traveler preferences across trips."
---
<Info icon="server">
**Works with:** Mem0 OSS (`Memory`)
</Info>
Create a personalized AI Travel Assistant using Mem0. This guide provides step-by-step instructions and the complete code to get you started.
@@ -3,6 +3,9 @@ title: Voice-First AI Companion
description: "Pair the OpenAI Agents SDK with Mem0 to build a voice assistant that remembers."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
This guide demonstrates how to combine OpenAI's Agents SDK for voice applications with Mem0's memory capabilities to create a voice assistant that remembers user preferences and past interactions.
@@ -3,6 +3,9 @@ title: Research Assistant for YouTube
description: "Layer personalized context over any video using the Mem0 YouTube assistant."
---
<Info icon="cloud">
**Works with:** Mem0 Platform
</Info>
Enhance your YouTube experience with Mem0's YouTube Assistant, a Chrome extension that brings AI-powered chat directly to your YouTube videos. Get instant, personalized answers about video content while leveraging your own knowledge and memories, all without leaving the page.
@@ -3,6 +3,9 @@ title: Build a Companion with Mem0
description: "Spin up a fitness coach that remembers goals, adapts tone, and keeps sessions personal."
---
<Info icon="layer-group">
**Works with:** Mem0 OSS (`Memory`) and Mem0 Platform (`MemoryClient`)
</Info>
Essentially, creating a companion out of LLMs is as simple as a loop. But these loops work great for one type of character without personalization and fall short as soon as you restart the chat.
@@ -3,6 +3,9 @@ title: Control Memory Ingestion
description: "Filter speculation, enforce formats, and gate low-confidence data before it persists."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
AI assistants plugged with memory systems face a problem - they often store everything. Not every conversation needs to be remembered, and not every detail should go to the memory store. Without proper controls, memory systems accumulate unreliable data.
@@ -3,6 +3,10 @@ title: Partition Memories by Entity
description: Keep memories separate by tagging each write and query with user, agent, app, and session identifiers.
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
Nora runs a travel service. When she stored all memories in one bucket, a recruiter's nut allergy accidentally appeared in a traveler's dinner reservation. Let's fix this by properly separating memories for different users, agents, and applications.
<Info icon="clock">
@@ -3,6 +3,9 @@ title: Export Stored Memories
description: "Retrieve, review, and migrate user memories with structured exports."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
Mem0 is a dynamic memory store that gives you full control over your data. Along with storing memories, it gives you the ability to retrieve, export, and migrate your data whenever you need.
@@ -169,20 +172,20 @@ export_job = client.create_memory_export(
)
print(f"Export ID: {export_job['id']}")
print(f"Status: {export_job['status']}")
print(f"Message: {export_job['message']}")
```
**Output:**
```
Export ID: exp_abc123
Status: processing
Export ID: 550e8400-e29b-41d4-a716-446655440000
Message: Memory export request received. The export will be ready in a few seconds.
```
<Info>
**Export initiated:** Status is "processing". Large exports may take a few seconds. Poll with `get_memory_export()` until status changes to "completed" before downloading data.
**Export initiated:** The export runs asynchronously and is usually ready within a few seconds. Retry `get_memory_export()` with the returned ID until it stops returning a "no export found" error.
</Info>
### Step 3: Download the export
@@ -193,7 +196,7 @@ export_data = client.get_memory_export(
memory_export_id=export_job['id']
)
print(export_data['data'])
print(export_data)
```
@@ -216,7 +219,7 @@ export_by_filters = client.get_memory_export(
filters={"user_id": "dev"}
)
print(export_by_filters['data'])
print(export_by_filters)
```
@@ -240,7 +243,7 @@ export_with_instructions = client.create_memory_export(
```
<Tip>
Always check export status before downloading. Call `get_memory_export()` in a loop with a short delay until `status == "completed"`. Attempting to download while still processing returns incomplete data.
If the export is still processing, `get_memory_export()` returns a 404 with `{"error": "No memory export request found"}`. Retry after a short delay until the call succeeds instead of polling a status field.
</Tip>
---
@@ -3,6 +3,9 @@ title: Tag and Organize Memories
description: "Let Mem0 auto-categorize support data so teams retrieve the right facts fast."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
When you have large volumes of memory data, sorting it during post-processing becomes difficult. What if your memory store understood the importance of creating tags and buckets without a lot of effort?
@@ -3,6 +3,9 @@ title: Persistent Eliza Characters
description: "Bring persistent personality to Eliza OS agents using Mem0."
---
<Info icon="cloud">
**Works with:** Mem0 Platform
</Info>
You can create a personalized Eliza OS Character using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
@@ -3,6 +3,10 @@ title: "Gemini 3 with Mem0 MCP"
description: "Create snappy, smart, memory-aware agents by pairing Gemini 3 with Mem0 MCP server."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (MCP server)
</Info>
Gemini 3, when paired with Mem0's cloud MCP server, works in synergy to create snappy, smart, memory-aware agents.
<Callout type="info" icon="sparkles" color="#8B5CF6">
@@ -3,6 +3,9 @@ title: Multi-Agent Collaboration
description: "Share a persistent memory layer across collaborating LlamaIndex agents."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`Mem0Memory.from_client`)
</Info>
<Snippet file="blank-notif.mdx" />
@@ -3,6 +3,9 @@ title: ReAct Agents with Memory
description: "Teach a ReAct agent to store and recall context via Mem0."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`Mem0Memory.from_client`)
</Info>
Create a ReAct Agent with LlamaIndex which uses Mem0 as the memory store.
@@ -78,7 +81,7 @@ from llama_index.core.agent import FunctionCallingAgent
agent = FunctionCallingAgent.from_tools(
[call_tool, email_tool, order_food_tool],
llm=llm,
memory=memory_from_client, # or memory_from_config
memory=memory_from_client,
verbose=True,
)
```
@@ -161,7 +164,7 @@ agent = FunctionCallingAgent.from_tools(
[call_tool, email_tool, order_food_tool],
llm=llm,
# memory is provided
memory=memory_from_client, # or memory_from_config
memory=memory_from_client,
verbose=True,
)
response = agent.chat("I am feeling hungry, order me something and send me the bill")
@@ -3,6 +3,9 @@ title: Visual Memory Retrieval
description: "Store and recall visual context alongside text conversations."
---
<Info icon="cloud">
**Works with:** Mem0 Platform
</Info>
Enhance your AI interactions with Mem0's multimodal capabilities. Mem0 now supports image understanding, allowing for richer context and more natural interactions across supported AI platforms.
@@ -3,6 +3,9 @@ title: Memory-Powered Agent SDK
description: "Expose Mem0 memories as callable tools inside OpenAI agent workflows."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
Integrate Mem0's memory capabilities with OpenAI's Agents SDK to create AI agents with persistent memory. You can create agents that remember past conversations and use that context to provide better responses.
@@ -3,6 +3,9 @@ title: Bedrock with Persistent Memory
description: "Pair Mem0 with AWS Bedrock and OpenSearch for a managed stack."
---
<Info icon="server">
**Works with:** Mem0 OSS (`Memory`)
</Info>
This example demonstrates how to configure and use the `mem0ai` SDK with **AWS Bedrock** and **OpenSearch Service (AOSS)** for persistent memory capabilities in Python.
@@ -3,6 +3,9 @@ title: Healthcare Coach with ADK
description: "Guide patients with an assistant that remembers history across ADK sessions."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
This example demonstrates how to build a healthcare assistant that remembers patient information across conversations using Google ADK and Mem0.
@@ -123,7 +126,7 @@ Now we'll create our main agent with all the tools:
# Create the agent
healthcare_agent = Agent(
name="healthcare_assistant",
model="gemini-1.5-flash", # Using Gemini for healthcare assistant
model="gemini-2.0-flash", # Using Gemini for healthcare assistant
description="Healthcare assistant that helps patients with health information and appointment scheduling.",
instruction="""You are a helpful Healthcare Assistant with memory capabilities.
+4 -1
View File
@@ -3,10 +3,13 @@ title: Persistent Mastra Agents
description: "Extend Mastra agents with persistent memories powered by Mem0."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`@mastra/mem0`)
</Info>
In this example you'll learn how to use Mem0 to add long-term memory capabilities to [Mastra's agent](https://mastra.ai/) via tool-use. This memory integration can work alongside Mastra's [agent memory features](https://mastra.ai/docs/agents/01-agent-memory).
You can find the complete example code in the [Mastra repository](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-mem0).
The complete example code, from installing the integration to wiring it into a Mastra agent, is shown below. Mem0's integration is published on npm as [`@mastra/mem0`](https://www.npmjs.com/package/@mastra/mem0).
## Overview
@@ -3,6 +3,9 @@ title: Memory as OpenAI Tool
description: "Wire Mem0 memories into OpenAI's inbuilt function-calling flow."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
Integrate Mem0’s memory capabilities with OpenAI’s Inbuilt Tools to create AI agents with persistent memory.
@@ -3,12 +3,14 @@ title: Search with Personal Context
description: "Blend Tavily's realtime results with personal context stored in Mem0."
---
<Info icon="cloud">
**Works with:** Mem0 Platform (`MemoryClient`)
</Info>
Imagine asking a search assistant for "coffee shops nearby" and instead of generic results, it shows remote-work-friendly cafes with great WiFi in your city because it remembers you mentioned working remotely before. Or when you search for "lunchbox ideas for kids" it knows you have a 7-year-old daughter and recommends peanut-free options that align with her allergy.
That's what we are going to build today, a Personalized Search Assistant powered by Mem0 for memory and [Tavily](https://tavily.com) for real-time search.
## Why Personalized Search
Most assistants treat every query like they've never seen you before. That means repeating yourself about your location, diet, or preferences, and getting results that feel generic.
@@ -3,6 +3,9 @@ title: Content Creation Workflow
description: "Store voice guidelines once and apply them across every draft."
---
<Info icon="layer-group">
**Works with:** Mem0 OSS (`Memory`) and Mem0 Platform (`MemoryClient`)
</Info>
This guide demonstrates how to leverage **Mem0** to streamline content writing by applying your unique writing style and preferences using persistent memory.
+3 -8
View File
@@ -3,11 +3,12 @@ title: Multi-Session Research Agent
description: "Run multi-session investigations that remember past findings and preferences."
---
<Info icon="cloud">
**Works with:** Mem0 Platform
</Info>
Deep Research is an intelligent agent that synthesizes large amounts of online data and completes complex research tasks, customized to your unique preferences and insights. Built on Mem0's technology, it enhances AI-driven online exploration with personalized memories.
You can check out the GitHub repository here: [Personalized Deep Research](https://github.com/mem0ai/personalized-deep-research/tree/mem0)
## Overview
Deep Research leverages Mem0's memory capabilities to:
@@ -61,12 +62,6 @@ Watch Deep Research in action:
- **Technical Research**: Technology evaluation, solution comparison
- **Business Research**: Strategic planning, opportunity analysis
## Try It Out
> To try it yourself, clone the repository and follow the instructions in the README to run it locally or deploy it.
- [Personalized Deep Research GitHub](https://github.com/mem0ai/personalized-deep-research/tree/mem0)
---
<CardGroup cols={2}>
@@ -3,6 +3,9 @@ title: Automated Email Intelligence
description: "Capture, categorize, and recall inbox threads using persistent memories."
---
<Info icon="layer-group">
**Works with:** Mem0 OSS (`Memory`) and Mem0 Platform (`MemoryClient`)
</Info>
This guide demonstrates how to build an intelligent email processing system using Mem0's memory capabilities. You'll learn how to store, categorize, retrieve, and analyze emails to create a smart email management solution.
@@ -3,6 +3,9 @@ title: Memory-Powered Support Agent
description: "Build a support assistant that keeps past tickets and resolutions at its fingertips."
---
<Info icon="server">
**Works with:** Mem0 OSS (`Memory`)
</Info>
You can create a personalized Customer Support AI Agent using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
@@ -3,6 +3,9 @@ title: Collaborative Task Assistant
description: "Coordinate multi-user projects with shared memories and roles."
---
<Info icon="server">
**Works with:** Mem0 OSS (`Memory`)
</Info>
## Overview
+50
View File
@@ -13,6 +13,56 @@ With Mem0, you can create stateful LLM-based applications such as chatbots, virt
Here are some examples of how Mem0 can be integrated into various applications:
## Pick by compatibility
Every cookbook opens with a **Works with** badge naming the SDK surface it uses. Pick your setup below to see only the cookbooks that run on it. Three cookbooks work on both and appear under either tab.
<Tabs>
<Tab title="Self-hosted OSS">
Ten cookbooks run on the open-source `Memory` class, with no Mem0 Platform account.
| Cookbook | Category | Works with |
| --- | --- | --- |
| [Personalized AI Tutor](/cookbooks/companions/ai-tutor) | Companions | OSS only |
| [Build a Node.js Companion](/cookbooks/companions/nodejs-companion) | Companions | OSS only |
| [Self-Hosted AI Companion](/cookbooks/companions/local-companion-ollama) | Companions | OSS only |
| [Smart Travel Assistant](/cookbooks/companions/travel-assistant) | Companions | OSS only |
| [Build a Companion with Mem0](/cookbooks/essentials/building-ai-companion) | Essentials | OSS and Platform |
| [Bedrock with Persistent Memory](/cookbooks/integrations/aws-bedrock) | Integrations | OSS only |
| [Automated Email Intelligence](/cookbooks/operations/email-automation) | Operations | OSS and Platform |
| [Collaborative Task Assistant](/cookbooks/operations/team-task-agent) | Operations | OSS only |
| [Content Creation Workflow](/cookbooks/operations/content-writing) | Operations | OSS and Platform |
| [Memory-Powered Support Agent](/cookbooks/operations/support-inbox) | Operations | OSS only |
</Tab>
<Tab title="Hosted Platform">
Twenty-one cookbooks run on the hosted Platform, using `MemoryClient` or the Mem0 MCP server with a `MEM0_API_KEY`.
| Cookbook | Category | Works with |
| --- | --- | --- |
| [Interactive Memory Demo](/cookbooks/companions/quickstart-demo) | Companions | Platform only |
| [Research Assistant for YouTube](/cookbooks/companions/youtube-research) | Companions | Platform only |
| [Voice-First AI Companion](/cookbooks/companions/voice-companion-openai) | Companions | Platform only |
| [Build a Companion with Mem0](/cookbooks/essentials/building-ai-companion) | Essentials | OSS and Platform |
| [Control Memory Ingestion](/cookbooks/essentials/controlling-memory-ingestion) | Essentials | Platform only |
| [Export Stored Memories](/cookbooks/essentials/exporting-memories) | Essentials | Platform only |
| [Partition Memories by Entity](/cookbooks/essentials/entity-partitioning-playbook) | Essentials | Platform only |
| [Tag and Organize Memories](/cookbooks/essentials/tagging-and-organizing-memories) | Essentials | Platform only |
| [Gemini 3 with Mem0 MCP](/cookbooks/frameworks/gemini-3-with-mem0-mcp) | Frameworks | Platform only |
| [Multi-Agent Collaboration](/cookbooks/frameworks/llamaindex-multiagent) | Frameworks | Platform only |
| [Persistent Eliza Characters](/cookbooks/frameworks/eliza-os-character) | Frameworks | Platform only |
| [ReAct Agents with Memory](/cookbooks/frameworks/llamaindex-react) | Frameworks | Platform only |
| [Visual Memory Retrieval](/cookbooks/frameworks/multimodal-retrieval) | Frameworks | Platform only |
| [Healthcare Coach with ADK](/cookbooks/integrations/healthcare-google-adk) | Integrations | Platform only |
| [Memory as OpenAI Tool](/cookbooks/integrations/openai-tool-calls) | Integrations | Platform only |
| [Memory-Powered Agent SDK](/cookbooks/integrations/agents-sdk-tool) | Integrations | Platform only |
| [Persistent Mastra Agents](/cookbooks/integrations/mastra-agent) | Integrations | Platform only |
| [Search with Personal Context](/cookbooks/integrations/tavily-search) | Integrations | Platform only |
| [Automated Email Intelligence](/cookbooks/operations/email-automation) | Operations | OSS and Platform |
| [Content Creation Workflow](/cookbooks/operations/content-writing) | Operations | OSS and Platform |
| [Multi-Session Research Agent](/cookbooks/operations/deep-research) | Operations | Platform only |
</Tab>
</Tabs>
## Start here
The most popular cookbooks to get going fast:
+3 -3
View File
@@ -46,7 +46,7 @@ When new messages arrive, Mem0 extracts durable facts and stores them with the i
1. **Context lookup.** Mem0 checks related existing memories so it can avoid storing the same fact again.
2. **Fact extraction.** An LLM extracts preferences, decisions, plans, and other details your agent can reuse.
3. **Deduplication and embedding.** Redundant facts are removed, then each memory is embedded for semantic search.
4. **Entity linking.** When configured, Mem0 links people, places, organizations, and concepts across memories.
4. **Entity extraction.** Mem0 pulls out the people, places, organizations, and concepts each memory mentions and stores them for entity matching at search time. On Platform these entities also become the nodes of [Graph Memory](/platform/features/graph-memory).
The automatic extraction path is additive. If a user says, "I moved from Austin to Seattle," Mem0 can store the new fact without silently rewriting the old one. Use explicit `update` or `delete` operations when your application needs to correct or remove a memory.
@@ -61,7 +61,7 @@ When you call `search`, Mem0 ranks stored memories against your query and filter
| **Entity** | Boosts memories linked to entities in the query | Questions about a person, project, or account |
| **Temporal** | Scores candidates on time metadata extracted at write time against the query's temporal intent | Temporal questions ("when did...", current state, recency) |
Platform retrieval fuses these signals in the managed service. OSS retrieval depends on your configured vector store, optional reranker, and graph store.
Platform retrieval fuses these signals in the managed service, where the entity signal is powered by built-in [Graph Memory](/platform/features/graph-memory). OSS retrieval depends on your configured vector store and optional reranker, and boosts on entity overlap alone: it has no graph memory.
<Note>
Always scope searches with filters such as `user_id`, `agent_id`, or `run_id`. This keeps memories from different users, agents, or sessions from mixing.
@@ -75,7 +75,7 @@ Mem0 stores different parts of a memory in stores built for different lookup pat
|---|---|---|
| **SQL database** | Facts and metadata | The source of truth for each memory |
| **Vector database** | Embeddings | Semantic similarity search |
| **Entity or graph store** | Entities and relationships | Relationship-aware retrieval when graph memory is enabled |
| **Entity store** | Entities extracted from memory text | Boosts memories sharing entities with the query. On Platform it also backs [Graph Memory](/platform/features/graph-memory) |
On Mem0 Platform, these stores are managed for you. In OSS, you choose and operate the backing stores through your configuration.
+10 -1
View File
@@ -85,7 +85,8 @@
"platform/features/advanced-retrieval",
"platform/advanced-memory-operations",
"platform/features/custom-instructions",
"platform/features/memory-decay"
"platform/features/memory-decay",
"platform/features/dream"
]
},
{
@@ -610,6 +611,10 @@
]
},
"redirects": [
{
"source": "/open-source/features/reranking",
"destination": "/open-source/features/reranker-search"
},
{
"source": "/platform/features/contextual-add",
"destination": "/core-concepts/memory-operations/add"
@@ -1034,6 +1039,10 @@
"source": "/features/graph-memory",
"destination": "/platform/features/graph-memory"
},
{
"source": "/open-source/features/graph-memory",
"destination": "/platform/features/graph-memory"
},
{
"source": "/features/:slug",
"destination": "/platform/features/:slug"
-17
View File
@@ -34,15 +34,11 @@ npx flowise start
2. In this example, we use the **Conversation Chain** template.
3. Replace the default **Buffer Memory** with **Mem0 Memory**.
![Flowise Memory Integration](https://raw.githubusercontent.com/FlowiseAI/FlowiseDocs/main/en/.gitbook/assets/mem0/flowise-flow.png)
### 2. Obtain Your Mem0 API Key
1. Navigate to the <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-flowise" rel="nofollow">Mem0 API Key dashboard</a>.
2. Generate or copy your existing Mem0 API Key.
![Mem0 API Key](https://raw.githubusercontent.com/FlowiseAI/FlowiseDocs/main/en/.gitbook/assets/mem0/api-key.png)
### 3. Configure Mem0 Credentials
1. Enter the **Mem0 API Key** in the Mem0 Credentials section.
@@ -57,11 +53,6 @@ npx flowise start
}
```
<figure>
<img src="https://raw.githubusercontent.com/FlowiseAI/FlowiseDocs/main/en/.gitbook/assets/mem0/creds.png" alt="Mem0 Credentials" />
<figcaption>Configure API Credentials</figcaption>
</figure>
## Memory Features
### 1. Basic Memory Storage
@@ -72,8 +63,6 @@ Test your memory configuration:
2. Run a test chat and store some information
3. Verify the stored memories in the <a href="https://app.mem0.ai/dashboard/requests?utm_source=oss&utm_medium=integration-flowise" rel="nofollow">Mem0 Dashboard</a>
![Flowise Test Chat](https://raw.githubusercontent.com/FlowiseAI/FlowiseDocs/main/en/.gitbook/assets/mem0/flowise-chat-1.png)
### 2. Memory Retention
Validate memory persistence:
@@ -82,14 +71,10 @@ Validate memory persistence:
2. Ask a question about previously stored information
3. Confirm that the AI remembers the context
![Testing Memory Retention](https://raw.githubusercontent.com/FlowiseAI/FlowiseDocs/main/en/.gitbook/assets/mem0/flowise-chat-2.png)
## Advanced Configuration
### Memory Settings
![Mem0 Settings](https://raw.githubusercontent.com/FlowiseAI/FlowiseDocs/main/en/.gitbook/assets/mem0/settings.png)
Available settings include:
1. **Search Only Mode**: Enable memory retrieval without creating new memories
@@ -108,8 +93,6 @@ Additional settings available in <a href="https://app.mem0.ai/dashboard/project-
1. **Custom Instructions**: Define memory extraction rules
2. **Expiration Date**: Set automatic memory cleanup periods
![Mem0 Project Settings](https://raw.githubusercontent.com/FlowiseAI/FlowiseDocs/main/en/.gitbook/assets/mem0/mem0-settings.png)
## Best Practices
1. **User Identification**: Use consistent `user_id` values for reliable memory retrieval
+1 -1
View File
@@ -6,7 +6,7 @@ description: "Use Mem0 as a memory store in LlamaIndex with support for ReAct an
LlamaIndex supports Mem0 as a [memory store](https://llamahub.ai/l/memory/llama-index-memory-mem0). In this guide, we'll show you how to use it.
<Note type="info">
[**Mem0Memory**](https://docs.llamaindex.ai/en/stable/examples/memory/Mem0Memory/) now supports **ReAct** and **FunctionCalling** agents.
[**Mem0Memory**](https://developers.llamaindex.ai/python/examples/memory/mem0memory/) now supports **ReAct** and **FunctionCalling** agents.
</Note>
### Installation
+42 -42
View File
@@ -56,8 +56,8 @@ client.add(
)
# Read
client.search("What does Alice like to do?", user_id="alice")
client.get_all(user_id="alice")
client.search("What does Alice like to do?", filters={"user_id": "alice"})
client.get_all(filters={"user_id": "alice"})
client.get(memory_id="<id>")
# Update
@@ -86,8 +86,8 @@ await client.add(
);
// Read
await client.search("What does Alice like to do?", { user_id: "alice" });
await client.getAll({ user_id: "alice" });
await client.search("What does Alice like to do?", { filters: { user_id: "alice" } });
await client.getAll({ filters: { user_id: "alice" } });
await client.get("<memory_id>");
// Update
@@ -113,8 +113,8 @@ m = Memory() # needs OPENAI_API_KEY; see components/ for custom providers
m.add("I love hiking on weekends", user_id="alice")
# Read
m.search("What does Alice like to do?", user_id="alice")
m.get_all(user_id="alice")
m.search("What does Alice like to do?", filters={"user_id": "alice"})
m.get_all(filters={"user_id": "alice"})
m.get(memory_id="<id>")
# Update
@@ -140,8 +140,8 @@ const memory = new Memory();
await memory.add("I love hiking on weekends", { userId: "alice" });
// Read
await memory.search("What does Alice like to do?", { userId: "alice" });
await memory.getAll({ userId: "alice" });
await memory.search("What does Alice like to do?", { filters: { user_id: "alice" } });
await memory.getAll({ filters: { user_id: "alice" } });
await memory.get("<memory_id>");
// Update
@@ -164,7 +164,7 @@ npm list mem0ai --depth 0 2>/dev/null | grep mem0ai
mem0 --version # Python or Node CLI, whichever is on PATH
```
If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_format: "v1.1"`), route them through the matching migration guide in the Platform section before quoting current docs. If no Mem0 package is installed, recommend `pip install mem0ai` or `npm install mem0ai` and the corresponding quickstart above.
If the user is on a pre-current major (Python < 2, TS < 3, or a Platform call still passing `output_format`, `api_version`, `async_mode`, or `enable_graph`, all removed in the current major), route them through the matching migration guide in the Platform section before quoting current docs. If no Mem0 package is installed, recommend `pip install mem0ai` or `npm install mem0ai` and the corresponding quickstart above.
## Getting Started
@@ -177,14 +177,14 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
- [Platform CLI](https://docs.mem0.ai/platform/cli) [Platform]: Use when the user wants to manage Platform memories from the terminal.
- [Mem0 MCP Server](https://docs.mem0.ai/platform/mem0-mcp) [Platform]: Use when connecting memory to AI coding tools over MCP.
- [Open Source Overview](https://docs.mem0.ai/open-source/overview) [OSS]: Use when the user needs full infra control and custom provider wiring.
- [Open Source Configuration](https://docs.mem0.ai/open-source/configuration) [OSS]: Use when configuring `Memory` - LLM, embedder, vector store, graph store.
- [Open Source Configuration](https://docs.mem0.ai/open-source/configuration) [OSS]: Use when configuring `Memory` - LLM, embedder, vector store, reranker.
- [Open Source Python Quickstart](https://docs.mem0.ai/open-source/python-quickstart) [OSS]: Use for the first self-hosted Python integration.
- [Open Source Node.js Quickstart](https://docs.mem0.ai/open-source/node-quickstart) [OSS]: Use for the first self-hosted Node integration.
- [Self-Hosted Setup](https://docs.mem0.ai/open-source/setup) [OSS]: Use when standing up the bundled REST server and dashboard via Docker Compose, including auth, API keys, and the setup wizard.
## Core Concepts
- [How Mem0 Works](https://docs.mem0.ai/core-concepts/how-it-works) [Both]: Use when explaining the end-to-end pipeline: extraction (ADD-only distillation), storage across vector/graph/history stores, and multi-signal retrieval.
- [How Mem0 Works](https://docs.mem0.ai/core-concepts/how-it-works) [Both]: Use when explaining the end-to-end pipeline: extraction (ADD-only distillation), storage across vector/entity/history stores, and multi-signal retrieval.
- [Memory Types](https://docs.mem0.ai/core-concepts/memory-types) [Both]: Use when explaining working, factual, episodic, and semantic memory distinctions.
- [Memory Operations - Add](https://docs.mem0.ai/core-concepts/memory-operations/add) [Both]: Use when explaining how `add()` extracts facts, resolves conflicts, and writes to both stores.
- [Memory Operations - Search](https://docs.mem0.ai/core-concepts/memory-operations/search) [Both]: Use when explaining how queries are processed and ranked.
@@ -207,6 +207,7 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
- [Temporal Reasoning](https://docs.mem0.ai/platform/features/temporal-reasoning) [Platform]: Use when time-aware searches like last week, upcoming, or right now need better result ordering.
- [Custom Instructions](https://docs.mem0.ai/platform/features/custom-instructions) [Platform]: Use when tailoring what Mem0 extracts and stores on Platform.
- [Memory Decay](https://docs.mem0.ai/platform/features/memory-decay) [Platform]: Use when search results should boost recently-reinforced memories and dampen stale ones. Opt in per project; applies at search time and never filters candidates out.
- [Dream](https://docs.mem0.ai/platform/features/dream) [Platform]: Use when long-lived user memory should stay coherent on its own - synthesizing recurring patterns, superseding outdated facts, and merging duplicates in the background. Synthesis is opt-in (Pro+); Supersede and Merge are always on.
- [Advanced Memory Operations](https://docs.mem0.ai/platform/advanced-memory-operations) [Platform]: Use when basic CRUD is not enough - batch ops, complex filters, workflows.
### Features - Data Management
@@ -234,7 +235,6 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
- [Open Source Features Overview](https://docs.mem0.ai/open-source/features/overview) [OSS]: Use when surveying OSS-only capabilities.
- [Metadata Filtering](https://docs.mem0.ai/open-source/features/metadata-filtering) [OSS]: Use when filtering by custom metadata fields in self-hosted.
- [Reranker Search](https://docs.mem0.ai/open-source/features/reranker-search) [OSS]: Use when improving OSS search quality with a reranker.
- [Reranking](https://docs.mem0.ai/open-source/features/reranking) [OSS]: Use when configuring reranking end-to-end in OSS.
- [Async Memory](https://docs.mem0.ai/open-source/features/async-memory) [OSS]: Use when the self-hosted app needs `AsyncMemory`.
- [OSS Multimodal Support (features)](https://docs.mem0.ai/open-source/features/multimodal-support) [OSS]: Use when handling images and PDFs self-hosted (feature guide).
- [Custom Instructions (OSS)](https://docs.mem0.ai/open-source/features/custom-instructions) [OSS]: Use when tailoring extraction prompts in OSS.
@@ -246,46 +246,46 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
- [Integrations Overview](https://docs.mem0.ai/integrations) [Both]: Use when surveying every available integration.
### Agent Frameworks
- [LangChain](https://docs.mem0.ai/integrations/langchain) [Both]: Use when the user is on LangChain.
- [LangGraph](https://docs.mem0.ai/integrations/langgraph) [Both]: Use when building stateful multi-actor LangGraph apps.
- [LangChain Tools](https://docs.mem0.ai/integrations/langchain-tools) [Both]: Use when Mem0 should be exposed as a LangChain tool.
- [LangChain](https://docs.mem0.ai/integrations/langchain) [Platform]: Use when the user is on LangChain.
- [LangGraph](https://docs.mem0.ai/integrations/langgraph) [Platform]: Use when building stateful multi-actor LangGraph apps.
- [LangChain Tools](https://docs.mem0.ai/integrations/langchain-tools) [Platform]: Use when Mem0 should be exposed as a LangChain tool.
- [LlamaIndex](https://docs.mem0.ai/integrations/llama-index) [Both]: Use when layering memory on a LlamaIndex RAG app.
- [CrewAI](https://docs.mem0.ai/integrations/crewai) [Both]: Use when building CrewAI multi-agent systems.
- [AutoGen](https://docs.mem0.ai/integrations/autogen) [Both]: Use when the user is on Microsoft AutoGen.
- [Agno](https://docs.mem0.ai/integrations/agno) [Both]: Use when the user is on Agno.
- [CrewAI](https://docs.mem0.ai/integrations/crewai) [Platform]: Use when building CrewAI multi-agent systems.
- [AutoGen](https://docs.mem0.ai/integrations/autogen) [Platform]: Use when the user is on Microsoft AutoGen.
- [Agno](https://docs.mem0.ai/integrations/agno) [Platform]: Use when the user is on Agno.
- [Camel AI](https://docs.mem0.ai/integrations/camel-ai) [Both]: Use when the user is on Camel AI.
- [ChatDev](https://docs.mem0.ai/integrations/chatdev) [Both]: Use when the user is on ChatDev.
- [ChatDev](https://docs.mem0.ai/integrations/chatdev) [Platform]: Use when the user is on ChatDev.
- [Hermes](https://docs.mem0.ai/integrations/hermes) [Both]: Use when the user is on Hermes.
- [Pi Agent](https://docs.mem0.ai/integrations/pi-agent) [Platform]: Use when adding persistent memory to Pi Agent with the Mem0 plugin.
- [OpenAI Agents SDK](https://docs.mem0.ai/integrations/openai-agents-sdk) [Both]: Use when the user is on the OpenAI Agents SDK.
- [Google AI ADK](https://docs.mem0.ai/integrations/google-ai-adk) [Both]: Use when the user is on Google's Agent Development Kit.
- [Mastra](https://docs.mem0.ai/integrations/mastra) [Both]: Use when the user is on Mastra (TypeScript).
- [OpenAI Agents SDK](https://docs.mem0.ai/integrations/openai-agents-sdk) [Platform]: Use when the user is on the OpenAI Agents SDK.
- [Google AI ADK](https://docs.mem0.ai/integrations/google-ai-adk) [Platform]: Use when the user is on Google's Agent Development Kit.
- [Mastra](https://docs.mem0.ai/integrations/mastra) [Platform]: Use when the user is on Mastra (TypeScript).
- [OpenClaw](https://docs.mem0.ai/integrations/openclaw) [Both]: Use when wiring Mem0 into Claude Code or editors via OpenClaw.
- [Vercel AI SDK](https://docs.mem0.ai/integrations/vercel-ai-sdk) [Both]: Use when the user is on the Vercel AI SDK.
### AI Coding Tools
- [Claude Code](https://docs.mem0.ai/integrations/claude-code) [Both]: Use when wiring memory into Claude Code.
- [Cursor](https://docs.mem0.ai/integrations/cursor) [Both]: Use when wiring memory into Cursor.
- [Codex](https://docs.mem0.ai/integrations/codex) [Both]: Use when wiring memory into Codex / other editor assistants.
- [OpenCode](https://docs.mem0.ai/integrations/opencode) [Both]: Use when wiring memory into OpenCode.
- [Antigravity](https://docs.mem0.ai/integrations/antigravity) [Both]: Use when wiring memory into Google Antigravity.
- [Cursor](https://docs.mem0.ai/integrations/cursor) [Platform]: Use when wiring memory into Cursor.
- [Codex](https://docs.mem0.ai/integrations/codex) [Platform]: Use when wiring memory into Codex / other editor assistants.
- [OpenCode](https://docs.mem0.ai/integrations/opencode) [Platform]: Use when wiring memory into OpenCode.
- [Antigravity](https://docs.mem0.ai/integrations/antigravity) [Platform]: Use when wiring memory into Google Antigravity.
### Voice & Real-time
- [LiveKit](https://docs.mem0.ai/integrations/livekit) [Both]: Use when building real-time voice/video with memory.
- [Pipecat](https://docs.mem0.ai/integrations/pipecat) [Both]: Use when the voice pipeline is Pipecat.
- [ElevenLabs](https://docs.mem0.ai/integrations/elevenlabs) [Both]: Use when voice synthesis uses ElevenLabs.
- [LiveKit](https://docs.mem0.ai/integrations/livekit) [Platform]: Use when building real-time voice/video with memory.
- [Pipecat](https://docs.mem0.ai/integrations/pipecat) [Platform]: Use when the voice pipeline is Pipecat.
- [ElevenLabs](https://docs.mem0.ai/integrations/elevenlabs) [Platform]: Use when voice synthesis uses ElevenLabs.
### Cloud & Infrastructure
- [AWS Bedrock](https://docs.mem0.ai/integrations/aws-bedrock) [Both]: Use when the user is on AWS Bedrock managed AI services.
- [AWS Bedrock](https://docs.mem0.ai/integrations/aws-bedrock) [OSS]: Use when the user is on AWS Bedrock managed AI services.
### Developer Tools
- [Dify](https://docs.mem0.ai/integrations/dify) [Both]: Use when the user is on Dify LLMOps.
- [Flowise](https://docs.mem0.ai/integrations/flowise) [Both]: Use when the user is on Flowise no-code.
- [Dify](https://docs.mem0.ai/integrations/dify) [Platform]: Use when the user is on Dify LLMOps.
- [Flowise](https://docs.mem0.ai/integrations/flowise) [Platform]: Use when the user is on Flowise no-code.
- [n8n](https://docs.mem0.ai/integrations/n8n) [Both]: Use when the user builds workflows or AI agents in n8n.
- [Zapier](https://docs.mem0.ai/integrations/zapier) [Both]: Use when the user automates workflows with Zapier.
- [AgentOps](https://docs.mem0.ai/integrations/agentops) [Both]: Use when tracking agent observability with memory metadata.
- [Respan](https://docs.mem0.ai/integrations/respan) [Both]: Use when monitoring Mem0 with Respan (formerly Keywords AI) LLM observability.
- [Raycast](https://docs.mem0.ai/integrations/raycast) [Both]: Use when the user wants quick memory access via Raycast.
- [Respan](https://docs.mem0.ai/integrations/respan) [OSS]: Use when monitoring Mem0 with Respan (formerly Keywords AI) LLM observability.
- [Raycast](https://docs.mem0.ai/integrations/raycast) [Platform]: Use when the user wants quick memory access via Raycast.
## Cookbooks
@@ -317,10 +317,10 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
### Integration Examples
- [Agents SDK Tool](https://docs.mem0.ai/cookbooks/integrations/agents-sdk-tool) [Platform]: Use when exposing Mem0 as a tool in OpenAI Agents SDK.
- [OpenAI Tool Calls](https://docs.mem0.ai/cookbooks/integrations/openai-tool-calls) [Platform]: Use when hooking Mem0 into OpenAI function calling.
- [Mastra Agent](https://docs.mem0.ai/cookbooks/integrations/mastra-agent) [Both]: Use when the agent is built in Mastra.
- [Healthcare Google ADK](https://docs.mem0.ai/cookbooks/integrations/healthcare-google-adk) [Both]: Use when the domain is medical and the framework is Google ADK.
- [AWS Bedrock](https://docs.mem0.ai/cookbooks/integrations/aws-bedrock) [Both]: Use when deploying with AWS managed model services.
- [Tavily Search](https://docs.mem0.ai/cookbooks/integrations/tavily-search) [Both]: Use when the agent layers web search on memory.
- [Mastra Agent](https://docs.mem0.ai/cookbooks/integrations/mastra-agent) [Platform]: Use when the agent is built in Mastra.
- [Healthcare Google ADK](https://docs.mem0.ai/cookbooks/integrations/healthcare-google-adk) [Platform]: Use when the domain is medical and the framework is Google ADK.
- [AWS Bedrock](https://docs.mem0.ai/cookbooks/integrations/aws-bedrock) [OSS]: Use when deploying with AWS managed model services.
- [Tavily Search](https://docs.mem0.ai/cookbooks/integrations/tavily-search) [Platform]: Use when the agent layers web search on memory.
### Framework Examples
- [LlamaIndex React](https://docs.mem0.ai/cookbooks/frameworks/llamaindex-react) [Both]: Use when building a React UI with LlamaIndex and memory.
@@ -409,10 +409,10 @@ The `integrations/mem0-plugin/` directory provides MCP server connection, lifecy
Editor-specific setup docs (already listed above under `## Integrations > AI Coding Tools`):
- `integrations/claude-code` [Both]
- `integrations/cursor` [Both]
- `integrations/codex` [Both]
- `integrations/opencode` [Both]
- `integrations/antigravity` [Both]
- `integrations/cursor` [Platform]
- `integrations/codex` [Platform]
- `integrations/opencode` [Platform]
- `integrations/antigravity` [Platform]
- `integrations/openclaw` [Both]
### MCP Endpoints
+26 -29
View File
@@ -1,6 +1,6 @@
---
title: "Open Source: Migrating to the New Memory Algorithm"
description: "Guide for self-hosted Mem0 users to upgrade to the new memory algorithm with ADD-only extraction, hybrid search, and entity linking."
description: "Guide for self-hosted Mem0 users to upgrade to the new memory algorithm with ADD-only extraction, hybrid search, and entity-aware retrieval."
icon: "arrow-right"
iconType: "solid"
---
@@ -15,7 +15,8 @@ The new Mem0 release redesigns both extraction and retrieval, and cleans up the
- **Extraction**: Single-pass ADD-only (one LLM call, no UPDATE/DELETE)
- **Retrieval**: Multi-signal hybrid search (semantic + BM25 keyword + entity matching)
- **Entity linking**: Automatic entity extraction and cross-memory linking
- **Entity matching**: Automatic entity extraction feeds a third scoring signal in hybrid search, boosting memories that share entities with the query
- **Graph memory moved to Platform**: The external graph store integration is removed from OSS; graph memory is now a built-in, always-on [Mem0 Platform feature](/platform/features/graph-memory)
- **SDK cleanup**: Deprecated parameters removed, naming conventions standardized
- **API surface aligned with Platform**: Entity IDs now follow the same convention across OSS and Platform: top-level kwargs for `add()` / `delete_all()`, inside `filters` for `search()` / `get_all()`
@@ -37,7 +38,7 @@ These changes produce a **+20 point improvement on LoCoMo** (71.4 → 91.6) and
| `add()` events | Returns `ADD`, `UPDATE`, `DELETE` | Returns `ADD` only | Update code expecting UPDATE/DELETE |
| Custom extraction prompt | `custom_fact_extraction_prompt` | `custom_instructions` | Rename in config |
| Custom update prompt | `custom_update_memory_prompt` | Deprecated | Use `custom_instructions` instead |
| Graph memory | `enable_graph` + `graph_store` in config | Removed | Graph store support has been removed entirely |
| Graph memory | `enable_graph` + `graph_store` in config | Removed | Graph memory is removed from OSS. It's a built-in, always-on [Mem0 Platform feature](/platform/features/graph-memory) |
| Qdrant client | `>=1.9.1` | `>=1.12.0` | Update dependency |
| Upstash client | `>=0.1.0` | `>=0.6.0` | Update dependency |
@@ -53,8 +54,8 @@ These changes produce a **+20 point improvement on LoCoMo** (71.4 → 91.6) and
| `messages` in `add()` | Could be `null` / `undefined` | Required: throws on null/undefined | Always pass a string or array |
| Payload key for lemmatized text | `text_lemmatized` (snake_case) | `textLemmatized` (camelCase) | TS-only internal field. If you share a vector store collection between Python and TS SDKs, lemma-based BM25 will not resolve across languages: keep collections language-scoped. |
| Custom prompt | `customPrompt` | `customInstructions` | Rename in config |
| Graph memory | `enableGraph` + `graphStore` in config | Removed | Graph store support has been removed entirely |
| Default graph config | Neo4j default config applied | No default graph config | Graph store config is no longer used |
| Graph memory | `enableGraph` + `graphStore` in config | Removed | Graph memory is removed from OSS. It's a built-in, always-on [Mem0 Platform feature](/platform/features/graph-memory) |
| Default graph config | Neo4j default config applied | No default graph config | Graph store config is no longer read; OSS has no built-in graph config to fall back to |
### Python Client SDK
@@ -104,7 +105,7 @@ These changes produce a **+20 point improvement on LoCoMo** (71.4 → 91.6) and
</Tabs>
<Info>
The Python `[nlp]` extra installs [spaCy](https://spacy.io/) for entity extraction and keyword lemmatization. Without it, Mem0 still works but falls back to semantic-only search (no entity linking, no BM25 lemmatization).
The Python `[nlp]` extra installs [spaCy](https://spacy.io/) for entity extraction and keyword lemmatization. Without it, Mem0 still works but falls back to semantic-only search (no entity matching, no BM25 lemmatization).
</Info>
<Warning>
@@ -135,7 +136,7 @@ pip install fastembed
config = {
"custom_instructions": "Focus on user preferences", # [OK] New name
# custom_update_memory_prompt removed: use custom_instructions
# enable_graph and graph_store removed: graph store support has been removed
# enable_graph and graph_store removed: graph memory is now a Mem0 Platform feature
}
```
</Tab>
@@ -154,7 +155,7 @@ pip install fastembed
// After
const config = {
customInstructions: "Focus on user preferences", // [OK] New name
// enableGraph and graphStore removed: graph store support has been removed
// enableGraph and graphStore removed: graph memory is now a Mem0 Platform feature
};
```
</Tab>
@@ -320,35 +321,31 @@ pip install "qdrant-client>=1.12.0"
pip install "upstash-vector>=0.6.0"
```
### 6. Entity Store Setup
### 6. Entity Matching Store Setup
The new algorithm automatically creates a parallel entity store collection named `{your_collection}_entities`. No manual setup is required: it's created on first use.
The new algorithm automatically creates a parallel collection named `{your_collection}_entities` to power entity matching, the third signal in hybrid search. No manual setup is required: it's created on first use. This is separate from and unrelated to graph memory, which is a Mem0 Platform feature.
<Warning>
Make sure your vector store user/credentials have permission to create new collections. If you're using a managed vector database with restricted permissions, pre-create the `{collection_name}_entities` collection with the same embedding dimensions as your main collection.
</Warning>
## Graph Memory: Now Built-In
## Graph Memory: Platform Only
External graph **store** support has been removed from the open-source SDK and replaced by **built-in graph memory** (entity linking), which runs natively with no external dependencies.
Graph memory is removed from the open-source SDK. It is not being replaced by an OSS equivalent: graph memory is a **Mem0 Platform** feature, built in and always on, with no external graph database required. See [Graph Memory](/platform/features/graph-memory) for what it does on Platform.
**What was removed:**
**What was removed from OSS:**
- `enable_graph` / `enableGraph` config flag
- `graph_store` / `graphStore` configuration block (Neo4j, Memgraph, Kuzu, Apache AGE, Neptune)
- All external graph store code paths (~4000 lines)
**What replaces it:**
Mem0 now builds the graph itself. It extracts entities (proper nouns, quoted text, compound noun phrases) from every memory during the add pipeline and stores them in a parallel collection (`{collection}_entities`) inside your existing vector store. Memories that share an entity are linked, and at search time entities from the query are matched against this collection to boost connected memories. The boost is folded into the combined `score` on each result.
- `graph_store` / `graphStore` configuration block
- All external graph store drivers (Neo4j, Memgraph, Kuzu, Apache AGE, Neptune) and their code paths (~4000 lines)
**Migration:**
- Remove `enable_graph` / `enableGraph` from your config
- Remove the `graph_store` / `graphStore` block: it is no longer read
- Uninstall external graph drivers (neo4j, memgraph, etc.) if you were using them only for Mem0
- No data migration is required. Built-in graph memory activates automatically on the next `add()` call.
- If you need graph memory, use [Mem0 Platform](/platform/features/graph-memory) instead of self-hosted OSS
<Warning>
The old `relations` field on search results (populated by the external graph store) is no longer returned. Entity connections are now applied through retrieval ranking rather than exposed as a separate, directly traversable structure. If your application read or traversed the `relations` array, you will need to redesign that part against the new API.
The old `relations` field on search results (populated by the external graph store) is no longer returned in OSS. OSS has no graph memory replacement, so there is nothing to populate this field with. If your application read or traversed the `relations` array, either move to Mem0 Platform to keep that data or redesign that part against the new OSS retrieval API.
</Warning>
## How the New Algorithm Works
@@ -362,7 +359,7 @@ Input conversation
→ Batch embed extracted memories
→ Hash-based deduplication (MD5, prevents exact duplicates)
→ Batch insert into vector store
→ Entity extraction + linking
→ Entity extraction (for entity matching)
```
The previous algorithm used two LLM calls: one to extract candidate facts, one to decide ADD/UPDATE/DELETE actions against existing memories. The new algorithm collapses this into a single call that only adds. The model spends its capacity on understanding the input rather than diffing against existing state.
@@ -375,7 +372,7 @@ Query
→ Parallel scoring:
1. Semantic search (vector similarity)
2. BM25 keyword search (normalized term matching)
3. Entity matching (entity graph boost)
3. Entity matching (entity overlap boost)
→ Score fusion → Top-K selection
```
@@ -408,8 +405,8 @@ The new features degrade gracefully when optional dependencies are missing:
| Missing Dependency | Impact | Search Still Works? |
|---|---|---|
| spaCy (`mem0ai[nlp]`) | No entity extraction, no BM25 lemmatization | Yes (semantic-only) |
| `fastembed` (Qdrant) | No BM25 keyword search | Yes (semantic + entity) |
| Entity store unavailable | No entity boosting | Yes (semantic + BM25) |
| `fastembed` (Qdrant) | No BM25 keyword search | Yes (semantic + entity matching) |
| Entity matching store unavailable | No entity matching boost | Yes (semantic + BM25) |
You always get semantic search. Hybrid search features layer on top when available.
@@ -449,13 +446,13 @@ These parameters have been removed across all SDKs. Remove them from your code:
**Config:** `custom_update_memory_prompt` → deprecated, use `custom_instructions`
**Config:** `enable_graph` + `graph_store` → removed (graph store support removed entirely)
**Config:** `enable_graph` + `graph_store` → removed (graph memory is now a [Mem0 Platform feature](/platform/features/graph-memory))
### TypeScript OSS: Removed/renamed parameters
**Config:** `customPrompt` → renamed to `customInstructions`
**Config:** `enableGraph` + `graphStore` → removed (graph store support removed entirely)
**Config:** `enableGraph` + `graphStore` → removed (graph memory is now a [Mem0 Platform feature](/platform/features/graph-memory))
**search():** `limit` → renamed to `topK`
@@ -521,9 +518,9 @@ If spaCy is not installed at all, install the NLP extras:
pip install "mem0ai[nlp]"
```
### Entity store collection creation fails
### Entity matching store collection creation fails
The entity store tries to create a `{collection_name}_entities` collection automatically. If your vector database has restricted permissions, pre-create this collection with the same embedding dimensions as your main collection.
The entity matching store tries to create a `{collection_name}_entities` collection automatically. If your vector database has restricted permissions, pre-create this collection with the same embedding dimensions as your main collection.
### Score values are different from before
+3 -3
View File
@@ -4,7 +4,7 @@ description: "Configure Mem0 OSS in Python or TypeScript with your own LLM, embe
icon: "sliders"
---
Mem0 OSS works out of the box with OpenAI defaults. Point it at your own LLM, embedder, and vector store by passing a config when you create `Memory`. The Python SDK also supports a reranker and graph memory.
Mem0 OSS works out of the box with OpenAI defaults. Point it at your own LLM, embedder, vector store, and reranker by passing a config when you create `Memory`.
<Info>
**Prerequisites**
@@ -90,11 +90,11 @@ Set your provider keys as environment variables:
```bash
export OPENAI_API_KEY="..."
export COHERE_API_KEY="..." # Python reranker only
export COHERE_API_KEY="..." # Cohere reranker only
```
<Note>
The TypeScript OSS SDK configures the LLM, embedder, vector store, and history store. Reranker and graph memory are Python-only today.
The TypeScript OSS SDK configures the LLM, embedder, vector store, history store, and reranker. Graph memory is not part of OSS in either language: it is a built-in [Mem0 Platform feature](/platform/features/graph-memory).
</Note>
Prefer a config file? Load YAML into Python's `from_config`:
@@ -53,7 +53,7 @@ const memory = new Memory({
});
const results = await memory.search("What are my food preferences?", {
filters: { userId: "alice" },
filters: { user_id: "alice" },
rerank: true,
});
```
@@ -86,7 +86,7 @@ const memory = new Memory({
});
const results = await memory.search("What movies do I like?", {
filters: { userId: "alice" },
filters: { user_id: "alice" },
rerank: true,
});
```
@@ -108,7 +108,7 @@ const memory = new Memory({
});
const results = await memory.search("What movies do I like?", {
filters: { userId: "alice" },
filters: { user_id: "alice" },
rerank: true,
});
```
-6
View File
@@ -1,6 +0,0 @@
---
title: Reranking
description: 'Redirect to the canonical reranker-enhanced search guide.'
---
<Redirect href="/open-source/features/reranker-search" />
+1 -1
View File
@@ -43,7 +43,7 @@ await memory.add(messages, { userId: "alice", metadata: { category: "movie_recom
<Step title="Search memories">
```ts
const results = await memory.search("What do you know about me?", { filters: { userId: "alice" } });
const results = await memory.search("What do you know about me?", { filters: { user_id: "alice" } });
console.log(results);
```
+73 -3
View File
@@ -1218,6 +1218,15 @@
},
"description": "Number of items per page. Default: 100."
},
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"maximum": 200
},
"description": "Maximum number of memories to return. Maximum accepted value: 200. Ignored when both `page` and `page_size` are supplied."
},
{
"name": "start_date",
"in": "query",
@@ -1261,6 +1270,7 @@
},
"metadata": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "User-supplied metadata attached to the memory."
},
@@ -1288,6 +1298,7 @@
},
"structured_attributes": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "System-derived temporal breakdown of the memory's creation time (e.g. year, month, day_of_week)."
},
@@ -1346,6 +1357,7 @@
},
"metadata": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "User-supplied metadata attached to the memory."
},
@@ -1373,6 +1385,7 @@
},
"structured_attributes": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "System-derived temporal breakdown of the memory's creation time (e.g. year, month, day_of_week)."
},
@@ -1413,14 +1426,47 @@
},
"400": {
"description": "Bad Request.",
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"type": "array",
"description": "Returned when none of the required filters (app_id, user_id, agent_id, run_id) is supplied.",
"items": {
"type": "string"
},
"example": [
"One of the filters: app_id, user_id, agent_id, run_id is required!"
]
},
{
"type": "object",
"description": "Returned when the `limit` query parameter is invalid.",
"properties": {
"error": {
"type": "string"
}
},
"example": {
"error": "limit must be <= 200"
}
}
]
}
}
}
},
"404": {
"description": "Not Found.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"detail": {
"type": "string",
"example": "One of the filters: app_id, user_id, agent_id, run_id is required!"
"example": "Invalid page."
}
}
}
@@ -1774,6 +1820,7 @@
},
"metadata": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Additional metadata associated with the memory"
},
@@ -1802,6 +1849,7 @@
},
"structured_attributes": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "System-derived temporal breakdown of the memory's creation time (e.g. year, month, day_of_week)."
},
@@ -2563,6 +2611,7 @@
},
"metadata": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "User-supplied metadata attached to the memory."
},
@@ -2575,6 +2624,7 @@
},
"structured_attributes": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "System-derived temporal breakdown of the memory's creation time (e.g. year, month, day_of_week)."
},
@@ -2734,6 +2784,10 @@
"type": "string",
"description": "Project-level instructions that guide extraction for this call."
},
"agent_custom_instructions": {
"type": "string",
"description": "Extraction instructions for agent-scoped memories, overriding the project-level setting for this call. Applied when `agent_id` is sent without `user_id`; when both are sent it governs the assistant-attributed memories while `custom_instructions` governs the rest."
},
"custom_categories": {
"type": "array",
"description": "Category catalog for this call. Replaces the project-level list rather than merging with it. Omit to fall back to the project list, then the default catalog.",
@@ -2979,7 +3033,7 @@
}
],
"nullable": true,
"description": "Optional query anchor time for relative temporal interpretation. Accepts Unix epoch, YYYY-MM-DD, or ISO datetime."
"description": "Date and time to simulate the search from. Accepts a Unix epoch, YYYY-MM-DD, or ISO datetime."
},
"fields": {
"type": "array",
@@ -3082,6 +3136,7 @@
},
"metadata": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "User-supplied metadata attached to the memory."
},
@@ -3380,6 +3435,7 @@
},
"metadata": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Additional metadata associated with the memory"
},
@@ -3408,6 +3464,7 @@
},
"structured_attributes": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "System-derived temporal breakdown of the memory's creation time (e.g. year, month, day_of_week)."
},
@@ -3571,6 +3628,7 @@
},
"metadata": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Additional metadata associated with the memory"
},
@@ -3599,6 +3657,7 @@
},
"structured_attributes": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "System-derived temporal breakdown of the memory's creation time (e.g. year, month, day_of_week)."
},
@@ -5750,6 +5809,11 @@
},
"description": "Custom instructions for memory processing in this project"
},
"agent_custom_instructions": {
"type": "string",
"nullable": true,
"description": "Extraction instructions for agent-scoped memories. Falls back to `custom_instructions` when unset. Send an empty string to clear it."
},
"custom_categories": {
"type": "array",
"items": {
@@ -7376,6 +7440,12 @@
"type": "string",
"nullable": true
},
"agent_custom_instructions": {
"description": "Extraction instructions that apply only to agent-scoped memories. Used when `agent_id` is sent without `user_id`; when both are sent it governs the assistant-attributed memories while `custom_instructions` governs the rest. Falls back to `custom_instructions` when unset.",
"title": "Agent custom instructions",
"type": "string",
"nullable": true
},
"immutable": {
"description": "Whether the memory is immutable.",
"title": "Immutable",
+3 -2
View File
@@ -143,6 +143,7 @@ Search memories using natural language.
```bash
mem0 search "dietary restrictions" --user-id alice
mem0 search "preferred tools" --user-id alice --output json --top-k 5
mem0 search "invoices" --user-id alice --filter '{"AND": [{"categories": {"in": ["work"]}}]}'
```
| Flag | Description |
@@ -155,7 +156,7 @@ mem0 search "preferred tools" --user-id alice --output json --top-k 5
| `--threshold` | Minimum similarity score (default: 0.3) |
| `--rerank` | Enable reranking |
| `--keyword` | Use keyword search instead of semantic |
| `--filter` | Advanced filter expression (JSON) |
| `--filter` | Advanced filter as JSON: `{"AND": [...]}` or `{"OR": [...]}`, e.g. `{"AND": [{"categories": {"in": ["work"]}}]}` |
| `--fields` | Return only the named fields |
| `--show-expired` | Include expired memories |
| `--reference-date` | Reference date for relative queries (`YYYY-MM-DD` or Unix timestamp) |
@@ -471,7 +472,7 @@ These two flags belong to `mem0` itself, so they go **before** the command name:
|------|-------------|
| `--json` | Enable agent mode: structured JSON envelope output, no colors or spinners |
| `--agent` | Alias for `--json` |
| `--version` | Print the CLI version and exit |
| `--version` | Print the CLI version and exit. `mem0 version` does the same thing as a regular subcommand |
<Warning>
On `init` only, `--agent` means something different. `mem0 init --agent` creates an Agent Mode account (see [Sign up as an agent](/platform/agent-signup)); it does not switch the output to JSON. To get JSON from `init`, put the flag first: `mem0 --json init`.
+18 -4
View File
@@ -99,16 +99,23 @@ results = client.search(
### Recommended Configurations
`rerank` is the only lever here that changes result *order*. `filters`, `top_k`, and `threshold` change *which* memories come back, not how they're ordered. The two functions below send the same query and filters; the only difference is the `rerank` flag.
<CodeGroup>
```python Python
# Basic search - good for exploration
# Fast path - use for exploratory search, or anywhere the user scans a list
# of results instead of trusting result #1 (dashboards, "show me everything
# about X" style queries). No reranking overhead.
def quick_search(query, user_id):
return client.search(
query=query,
filters={"user_id": user_id},
)
# Reranked search - good when result order matters
# Precision path - use when only the top result reaches the user, e.g. an
# agent that injects a single fact into a prompt. Reranking (see above)
# re-scores every match and moves the closest one to position 1, at the
# cost of ~150-200ms added latency.
def standard_search(query, user_id):
return client.search(
query=query,
@@ -118,14 +125,19 @@ def standard_search(query, user_id):
```
```javascript JavaScript
// Basic search - good for exploration
// Fast path - use for exploratory search, or anywhere the user scans a list
// of results instead of trusting result #1 (dashboards, "show me everything
// about X" style queries). No reranking overhead.
function quickSearch(query, userId) {
return client.search(query, {
filters: { user_id: userId },
});
}
// Reranked search - good when result order matters
// Precision path - use when only the top result reaches the user, e.g. an
// agent that injects a single fact into a prompt. Reranking (see above)
// re-scores every match and moves the closest one to position 1, at the
// cost of ~150-200ms added latency.
function standardSearch(query, userId) {
return client.search(query, {
filters: { user_id: userId },
@@ -135,6 +147,8 @@ function standardSearch(query, userId) {
```
</CodeGroup>
**What changes in the response:** both calls return the same fields on each memory (see the [Search Memories API reference](/api-reference/memory/search-memories) for the full response shape). The only difference is the *order* of the `results` array, the same effect shown in the [Reranking example above](#reranking): `quick_search` returns results ranked by raw similarity, `standard_search` returns the reranked order.
## Best Practices
### Do
+1 -1
View File
@@ -75,7 +75,7 @@ print(response)
```
</CodeGroup>
This "Updated custom categories" message is specific to a PATCH-style partial update, which is what `client.project.update()` sends. Calling the raw API with a full PUT instead returns a generic `{"message": "Project updated successfully."}`, regardless of which fields changed.
Treat the `message` string as informational. The project endpoint accepts `PATCH` only, and its documented response is the generic `{"message": "Project updated successfully"}`. Confirm an update by reading the field back, as in the next step, rather than by matching on the message.
### 2. Confirm the active catalog
@@ -95,6 +95,100 @@ Exclude:
- [Irrelevant information]
```
## Agent Custom Instructions
`custom_instructions` applies to every memory your project extracts, no matter whose it is. But what is worth remembering about an agent is rarely what is worth remembering about a user: an agent's useful memories are things like which tools fail, which retry strategies work, and how a given environment behaves, not personal preferences.
`agent_custom_instructions` is an optional second set of extraction rules that applies only to agent-scoped memories.
Available from Python SDK `v2.0.17` and TypeScript SDK `v3.1.5`. Upgrade first if you are on an earlier release.
Set it on the project alongside `custom_instructions`:
<CodeGroup>
```python Python
client.project.update(
custom_instructions="Extract the user's preferences, goals, and constraints.",
agent_custom_instructions=(
"Extract operational lessons for the agent:\n"
"- Tools that failed and the error returned\n"
"- Retry or fallback strategies that worked\n"
"- Environment quirks worth recalling on the next run\n\n"
"Exclude: user preferences, personal details."
),
)
```
```javascript JavaScript
await client.updateProject({
customInstructions: "Extract the user's preferences, goals, and constraints.",
agentCustomInstructions: `Extract operational lessons for the agent:
- Tools that failed and the error returned
- Retry or fallback strategies that worked
- Environment quirks worth recalling on the next run
Exclude: user preferences, personal details.`,
});
```
</CodeGroup>
### Which instructions apply
Which set governs an `add()` call depends on the entity IDs you pass with it:
| The add call passes | Instructions applied |
|---------------------|----------------------|
| `user_id` only | `custom_instructions` |
| `agent_id` only | `agent_custom_instructions` |
| `user_id` **and** `agent_id` | `agent_custom_instructions` govern the memories attributed to the assistant; `custom_instructions` govern the rest |
`agent_custom_instructions` is unset by default. While it is unset, `custom_instructions` applies to every memory, so projects that don't set it behave exactly as they did before.
### Overriding for a single call
Both fields are also accepted per request, overriding the project setting for that `add()` only:
<CodeGroup>
```python Python
client.add(
messages,
filters={"agent_id": "support-agent"},
agent_custom_instructions="Only remember which tools errored and why.",
)
```
```javascript JavaScript
await client.add(messages, {
agentId: "support-agent",
agentCustomInstructions: "Only remember which tools errored and why.",
});
```
</CodeGroup>
### Reading and clearing
<CodeGroup>
```python Python
# Read the current value
response = client.project.get(fields=["agent_custom_instructions"])
print(response["agent_custom_instructions"])
# Clear it; agent memories fall back to custom_instructions
client.project.update(agent_custom_instructions="")
```
```javascript JavaScript
// Read the current value
const response = await client.getProject({
fields: ["agentCustomInstructions"],
});
console.log(response.agentCustomInstructions);
// Clear it; agent memories fall back to customInstructions
await client.updateProject({ agentCustomInstructions: "" });
```
</CodeGroup>
## Real-World Examples
<Tabs>
+164
View File
@@ -0,0 +1,164 @@
---
title: Dream
description: "Dream keeps a user's memory clean over time by distilling recurring patterns, retiring outdated facts, and merging duplicates in the background."
---
# Dream
As an application talks to the same user over weeks and months, their memory grows. Some of that growth is signal, meaning new facts worth keeping. A lot of it is noise: the same preference stated three different ways, an old fact that a newer one has quietly replaced, or a set of small observations that only mean something when you look at them together.
**Dream** is the background layer that keeps a user's memory coherent as it grows. It continuously reviews each user's memories and does three things. It synthesizes higher-order patterns, supersedes outdated facts, and merges duplicates. The result is that what you read back stays sharp instead of drifting into a pile of overlapping, stale entries.
<Info>
**Dream matters when…**
- Your users interact with your product over a long period and accumulate a lot of memories.
- You want retrieval to return the *current* truth about a user, not a mix of old and new contradictory facts.
- You want higher-level insights ("this user consistently prefers X") without writing your own summarization layer.
</Info>
## The three actions of Dream
Dream is made of three independent actions. Two of them, Supersede and Merge, keep memory clean and run automatically for everyone. The third, Synthesis, produces new insight and is a toggle you turn on per project.
| Action | What it does | When it runs | Availability |
|---|---|---|---|
| **Synthesis** | Distills a user's memories into higher-order **pattern memories** | On a schedule, in the background | Opt-in (Pro and above) |
| **Supersede** | Marks an older fact as outdated when a newer one contradicts it | As memories are added | Always on, all plans |
| **Merge** | Folds a duplicate into a single canonical memory | As memories are added | Always on, all plans |
### Synthesis
Over time a user's memories often *imply* something larger than any single entry. Ten separate notes about early-morning meetings, workout logs, and coffee orders together say "this user is an early riser." **Synthesis** finds those recurring threads and writes them back as new **pattern memories**: concise, higher-order facts that capture what the individual memories only hint at.
- Pattern memories are added *alongside* your existing memories, never in place of them. The source memories stay exactly where they are.
- Each pattern memory keeps a link back to the specific memories it was distilled from, so an insight is always traceable to its evidence.
- Synthesis is additive and idempotent. Re-running it will not create duplicate patterns for the same underlying evidence.
**Example.** These four memories accumulate for the same user over time:
- *"User runs approximately 40 kilometers per week and is currently training for a marathon."*
- *"User lifts weights at the gym three times a week, primarily focusing on legs and back."*
- *"User tracks all workouts using a Garmin Forerunner watch."*
- *"User's goal for 2026 is to run a sub-4-hour marathon."*
Synthesis distills them into one pattern memory, kept alongside the originals:
> *"User follows a structured fitness routine that includes weekly long runs (≈40 km), regular leg-and-back strength training, tracks workouts with a Garmin device, and pursues progressive marathon time goals."*
Each source memory stays exactly where it was, and the new pattern links back to all of them as its evidence.
<Note>
Synthesis only considers memories created **after** you enable it for a project. Turning it on sets a forward boundary, so historical memories aren't reprocessed in bulk on day one. Everything added from that point on is eligible.
</Note>
<Note>
Synthesis only looks at memories scoped to a **`user_id` alone**. Memories that also carry another entity (an `agent_id`, `run_id`, or `app_id`) are left out of a user's synthesis run. This keeps each run tied to a single user's own memories and avoids cross-referencing across agents, runs, or apps. So a memory has to be user-scoped, with no other entity attached, to be eligible for a pattern.
</Note>
### Supersede
When a user tells you something that **contradicts** an earlier memory ("I moved to Berlin" after an earlier "I live in Lisbon"), Dream marks the older memory as **superseded** and links it to the newer fact that replaced it. Superseded memories are not deleted and not hidden by default. A normal `search` or `get` still returns them alongside your active memories, badged as superseded, so you keep the full history. When you want only the current truth, ask for it explicitly with `latest_only=true` (see [How reads change](#how-reads-change-with-dream) below). Supersede runs automatically as part of adding memories, on every plan.
**Example.** The user has an existing memory *"User drives a 2019 Subaru Outback."* Later they mention selling it, producing a new memory *"User sold their 2019 Subaru Outback and bought a Tesla Model 3."* Dream marks the Subaru memory as superseded and links it to the newer one. A default `search` returns both: the Tesla memory as active, and the Subaru one labelled superseded. Passing `latest_only=true` returns only *"User sold their 2019 Subaru Outback and bought a Tesla Model 3."*
### Merge
When a new memory is effectively a **duplicate** of one you already have, Dream keeps a single canonical memory instead of two near-identical copies. When a duplicate is stored as its own memory, Dream marks it **merged** and links it to the canonical one. The merged record is hidden from reads by default (you get the one canonical memory), retained rather than deleted, and surfaced with `include_merged=true`. Merge runs automatically as memories are added, on every plan, and keeps your memory set compact without you deduplicating by hand.
In practice, most exact or near-duplicate restatements of a fact you already have are recognised and deduplicated as the memory is added. No second copy is created, so you simply keep the one memory. A distinct `merged` record appears when a fuller version of an existing fact arrives and folds the barer one in.
**Example.** The user has an existing memory *"User has a dog named Rex."* Later they mention *"My dog Rex is a 3-year-old golden retriever."* The richer statement is stored and Dream marks the barer *"User has a dog named Rex"* as **merged** into it. A default read returns the single canonical memory *"User's dog Rex is a 3-year-old golden retriever"*, and `include_merged=true` also returns the merged original.
<Info>
**Nothing Dream does is destructive.** Superseded and merged memories are retained, never erased. Every change is recorded and reviewable, so you always know why a memory was retired or combined.
</Info>
## How reads change with Dream
Dream doesn't change the shape of your `add`, `search`, or `get` calls, so you don't touch your application code. What it changes is *which* memories a read returns by default, and it gives you two flags to widen or narrow that set:
| Read mode | Active | Superseded | Merged |
|---|:---:|:---:|:---:|
| **Default** (`search` / `get`) | ✓ | ✓ | ✗ |
| **`latest_only=true`** | ✓ | — | — |
| **`include_merged=true`** | ✓ | ✓ | ✓ |
- **By default**, a read returns active plus superseded memories (superseded ones are still there, labelled as history) and hides merged duplicates. Synthesized pattern memories are returned alongside these too.
- **`latest_only=true`** narrows the result to active memories only, meaning the current truth, with superseded and merged both excluded. Use this when you want the cleanest possible snapshot of the user right now.
- **`include_merged=true`** returns everything, including the merged duplicates, when you need the complete picture.
## Enabling Dream
Supersede and Merge require no setup. They're always on for every project on every plan.
Synthesis is opt-in per project:
1. Open the **[Dream settings for your project](https://app.mem0.ai/dashboard/dream)** in the Mem0 dashboard.
2. Toggle **Synthesis** on.
Synthesis is a per-project setting, so you can enable it for one project and compare against another with it off. You can turn it off at any time. Doing so is fully reversible and leaves every existing memory (including already-synthesized patterns) untouched.
From the [Dream page](https://app.mem0.ai/dashboard/dream) you can also review what Dream has done: recent synthesis runs, the patterns produced and their source memories, and the memories that were superseded or merged.
## Plan availability
| Capability | Free | Starter | Pro | Enterprise |
|---|:---:|:---:|:---:|:---:|
| **Supersede** (outdated facts flagged) | ✓ | ✓ | ✓ | ✓ |
| **Merge** (duplicates folded, hidden by default) | ✓ | ✓ | ✓ | ✓ |
| **Synthesis** (pattern memories written) | — | — | ✓ | ✓ |
| **Dream dashboard** (runs, activity) | — | — | ✓ | ✓ |
Synthesis requires a **Pro plan or higher**. Enterprise plans also get a faster, configurable schedule (see below).
## How often Dream runs, and what delay to expect
Different actions run on different clocks, so the delay you should expect depends on which action.
### Supersede & Merge, as memories are added
Supersede and Merge are part of the memory-addition pipeline. They're evaluated when a memory is added, so an outdated fact is superseded or a duplicate is merged as part of that add being processed, on the same timescale as the memory becoming searchable. There's no separate schedule to wait for.
### Synthesis, on a schedule in the background
Synthesis runs as a scheduled background job per user, not on every add. Two conditions gate it:
- **Enough to work with:** a user must have at least **20** memories before Synthesis considers them. Below that threshold there isn't a meaningful pattern to distill yet.
- **Cadence elapsed:** each user is re-synthesized at most once per cadence window.
| Plan | Synthesis cadence (per user) |
|---|---|
| Pro | Every **7 days** |
| Enterprise | **Daily** (and configurable) |
Because Synthesis is processed in batches in the background, **expect new pattern memories to appear within roughly 24 hours of a scheduled run**, not instantly. In practice, the end-to-end delay from crossing a cadence window to seeing new patterns is up to about a day. This background design is deliberate: it keeps Synthesis from adding any latency to your live `add` and `search` calls.
<Warning>
Synthesis is **not** real-time. If you enable it today, the first pattern memories for an eligible user will appear on the next scheduled run for that user (governed by the cadence above), and can take up to ~24 hours to complete once that run starts. Supersede and Merge, by contrast, keep pace with your adds.
</Warning>
## FAQ
**Does Dream delete any of my memories?**
No. Nothing Dream does is destructive. Superseded memories stay visible in default reads (labelled as history), merged duplicates are hidden by default but retained, and synthesized patterns are added alongside your existing memories, never in place of them. Every change is reviewable from the dashboard.
**How do I get only the current facts, without the superseded ones?**
Pass `latest_only=true` on your read. Superseded and merged memories are both excluded, leaving only active memories. By default (no flag) superseded memories are included so you keep the full history.
**Do I need to change my code to use Dream?**
No. Supersede and Merge are always on, and enabling Synthesis is a project setting. Your `add`, `search`, and `get` calls are unchanged. Dream shapes the memory set behind the same API.
**Will Synthesis reprocess all my old memories when I turn it on?**
No. Enabling Synthesis sets a forward boundary, so only memories created after you turn it on are eligible. This avoids a bulk reprocess of your entire history on day one.
**Why don't I see pattern memories immediately after enabling Synthesis?**
Synthesis runs on a schedule (every 7 days on Pro, daily on Enterprise) and only for users with at least 20 memories. Patterns appear on the next scheduled run for an eligible user and can take up to ~24 hours to complete once that run starts.
**Which memories does Synthesis include?**
Only memories scoped to a `user_id` on its own. If a memory also carries an `agent_id`, `run_id`, or `app_id`, it's excluded from that user's synthesis run. This keeps each run confined to a single user's memories and prevents any cross-referencing across agents, runs, or apps. Supersede and Merge are not affected by this and run across your memories as usual.
**Are synthesized pattern memories traceable?**
Yes. Every pattern memory links back to the specific source memories it was distilled from, so you can always see the evidence behind an insight from the Dream dashboard.
**Can I turn Synthesis off?**
Yes, at any time, per project. Turning it off is fully reversible and leaves all existing memories, including already-synthesized patterns, untouched.
+8 -8
View File
@@ -64,7 +64,7 @@ client.project.update(decay=True)
```
```javascript JavaScript
await client.project.update({ decay: true });
await client.updateProject({ decay: true });
```
```bash cURL
@@ -75,32 +75,32 @@ curl -X PATCH https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PR
```
```json Response
{ "message": "Updated decay" }
{ "message": "Project updated successfully" }
```
</CodeGroup>
### 2. Confirm the state
`decay` is returned on every project read; there is currently no way to narrow the response to just this field, so read the full project object and pick out `decay`.
`decay` is returned on every project read. To fetch only this field, use `?fields=decay`.
<CodeGroup>
```python Python
response = client.project.get()
response = client.project.get(fields=["decay"])
print(response["decay"])
```
```javascript JavaScript
const response = await client.project.get();
const response = await client.getProject({ fields: ["decay"] });
console.log(response.decay);
```
```bash cURL
curl "https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PROJECT_ID/" \
curl "https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PROJECT_ID/?fields=decay" \
-H "Authorization: Token $MEM0_API_KEY"
```
```json Response
{ "decay": true, "...": "full project object" }
{ "decay": true }
```
</CodeGroup>
@@ -114,7 +114,7 @@ client.project.update(decay=False)
```
```javascript JavaScript
await client.project.update({ decay: false });
await client.updateProject({ decay: false });
```
```bash cURL
+45 -104
View File
@@ -1,139 +1,80 @@
---
title: Temporal Reasoning
description: "Time-aware memory retrieval for Mem0 Platform v3 so queries like 'last week', 'upcoming', and 'right now' return the right memories."
description: "Boost memories whose dates match the time in a search."
badge: "v3"
---
Some memories matter because of **when** they happened, not just because they sound similar. Temporal Reasoning lets Mem0 Platform v3 understand time-aware queries and return the most contextually appropriate results.
Temporal Reasoning gives a ranking boost to memories whose event dates match the time in a search. Event dates are when something described in a memory happened or will happen. It runs automatically on Mem0 Platform v3.
<Info>
**Use Temporal Reasoning when…**
- Users ask questions like "what happened last week?" or "what do I have coming up?"
- Your app stores both past events and future plans for the same person
- You want time-aware retrieval without building your own date-parsing layer
</Info>
It is not available in the OSS SDK.
<Warning>
Temporal Reasoning is a **Mem0 Platform v3** feature. It is not available on OSS memory stores or older Platform endpoints.
</Warning>
Dates from new memories usually affect search within a few seconds.
## Configure access
## Time-aware searches
Confirm your `MEM0_API_KEY` is set and that you are using the v3 Platform client:
Queries can include expressions such as `yesterday`, `last week`, `tomorrow`, `currently`, and `as of March 2025`. Mem0 compares them with dates and date ranges found in stored memories.
```python
from mem0 import MemoryClient
## Example
client = MemoryClient(api_key="your-api-key")
```
Suppose a user has these memories:
## How it works
- "Yesterday I met Maya at the Orion conference in Paris."
- "Last week I met Maya at the Orion conference in Tokyo."
- "Last year I met Maya at the Orion conference in Lisbon."
When a memory describes an event, a future plan, or an ongoing state, Temporal Reasoning recognizes the time context so the right results surface at search time.
A query like `what did I do last week?` should return a completed past event: not an upcoming appointment and not a stable fact that hasn't changed. Temporal Reasoning handles that distinction automatically.
### Memory types Temporal Reasoning handles
| Type | What it represents | Example |
| --- | --- | --- |
| Dated occurrence | Something that happened at a known time | "I finished the Q1 review on March 10, 2025." |
| Future plan | A future commitment or scheduled item | "I have a dentist appointment on March 18, 2025." |
| Ongoing state | A fact that remains true over time | "I am the product lead at Acme Corp." |
| Relationship | A durable connection between people or entities | "Priya manages Jordan." |
| Preference | A stable preference or habit | "I prefer morning meetings." |
Results come back in the normal search response shape: Temporal Reasoning affects ranking, not the response format.
## Configure it
Temporal Reasoning is enabled by default for all v3 searches and writes. There is no per-request toggle.
Two parameters give you precise control when you need it:
- `observation_date` (or `observation_datetime`, which takes priority when both are set) on `add()`: anchors an imported memory to the time it actually happened. Pair with `timezone` when resolving a date-only value.
- `timestamp` on `add()`: a Unix epoch that sets the memory's creation time. When present it takes priority over `observation_datetime` and `observation_date` as the anchor Temporal Reasoning ranks against, so pass only the one you want to win.
- `reference_date` on `search()`: resolves relative phrases like `last week` against a fixed point in time
Searching for `Which city did I meet Maya in at the Orion conference last week?` gives the Tokyo memory a temporal boost and ranks it first.
<CodeGroup>
```python Python
from mem0 import MemoryClient
client = MemoryClient(api_key="your-api-key")
client.add(
[{"role": "user", "content": "I finished the Q1 review on March 10, 2025."}],
user_id="jordan",
observation_date="2025-03-10",
)
results = client.search(
"what did I do last week?",
filters={"user_id": "jordan"},
"Which city did I meet Maya in at the Orion conference last week?",
filters={"user_id": "maya-demo"},
)
```
```javascript JavaScript
const results = await client.search(
"Which city did I meet Maya in at the Orion conference last week?",
{ filters: { user_id: "maya-demo" } }
);
```
</CodeGroup>
Search returns the usual memory results, reordered using the temporal boost.
## Search from a specific time
Use `reference_date` to simulate searching at a specific date and time. Mem0 treats it as the current time for that search.
<CodeGroup>
```python Python
results = client.search(
"What happened last week?",
filters={"user_id": "user-123"},
reference_date="2025-03-21T00:00:00Z",
)
```
```javascript JavaScript
import { MemoryClient } from "mem0ai";
const client = new MemoryClient({ apiKey: "your-api-key" });
await client.add(
[{ role: "user", content: "I finished the Q1 review on March 10, 2025." }],
{
userId: "jordan",
observationDate: "2025-03-10",
}
);
const results = await client.search("what did I do last week?", {
filters: { user_id: "jordan" },
const results = await client.search("What happened last week?", {
filters: { user_id: "user-123" },
referenceDate: "2025-03-21T00:00:00Z",
});
```
</CodeGroup>
<Tip>
`reference_date` is especially useful in automated tests and demos because it makes relative phrases like `last week` resolve consistently every time.
</Tip>
## Parameters
## Supported query patterns
| Action | Python | TypeScript | Purpose |
| --- | --- | --- | --- |
| Add memories | `timestamp` | `timestamp` | Preserve the original time of an imported conversation. |
| Search memories | `reference_date` | `referenceDate` | Simulate searching at a specific date and time. |
<AccordionGroup>
<Accordion title="Historical questions">
Examples: `last week`, `last month`, `in March 2025`, `on 2025-03-10`
</Accordion>
<Accordion title="Upcoming questions">
Examples: `upcoming`, `next week`, `tomorrow`, `what do I have coming up?`
</Accordion>
<Accordion title="Current-state questions">
Examples: `right now`, `currently`, `where do I work now?`
</Accordion>
<Accordion title="As-of questions">
Examples: `as of March 2025`, `where was I living as of 2024?`
</Accordion>
<Accordion title="Duration questions">
Examples: `how long have I lived here?`, `since when have I worked there?`
</Accordion>
</AccordionGroup>
## Verify the feature is working
- Run a temporal search with a time-aware query (e.g., "what did I do last week?") and confirm the memory that fits the time window ranks first.
- Use `reference_date` in test queries so relative phrases resolve consistently across runs.
- For backfilled data, pass `timestamp` on `add()` to confirm the memory reflects the right point in time.
## Best practices
- Use explicit dates in source conversations when events or plans matter temporally.
- Pass `observation_date` (or `observation_datetime`) during historical imports so the ingestion time does not become the only time anchor. Do not also pass `timestamp` on those calls, since it overrides both as the ranking anchor.
- Scope searches with `filters` so time-aware ranking operates inside the right user boundary.
- Use `reference_date` in automated tests and reproducible demos.
For all search inputs and returned fields, see the [Search Memories API reference](/api-reference/memory/search-memories).
<CardGroup cols={1}>
<Card title="Memory Timestamps" icon="calendar" href="/platform/features/timestamp">
Anchor imported memories to when they actually happened.
Preserve the original time of imported memories.
</Card>
</CardGroup>

Some files were not shown because too many files have changed in this diff Show More