Compare commits

..
Author SHA1 Message Date
mintlify[bot]andGitHub 44dc74d78f docs: expand short frontmatter descriptions for SEO 2026-06-26 10:32:06 +00:00
KartikandGitHub d258b638ef docs: document FastEmbed embedder + missing org/project API endpoints (#5852) 2026-06-26 16:00:12 +05:30
Harsh Vardhan GuptaandGitHub bbbfcfea07 fix(deps): bump undici to >=6.27.0 (CVE-2026-12151) (#5861) 2026-06-26 15:32:09 +05:30
KartikandGitHub fbef369b91 docs(open-source): fix OSS feature docs for v3 SDK (#5847) 2026-06-26 14:14:33 +05:30
KartikandGitHub a7ed68e697 docs(integrations): fix retired model IDs, v3 response shapes & vercel deps (#5842) 2026-06-26 13:59:33 +05:30
KartikandGitHub 8a92cf0306 docs(integrations): sync agent-plugin hook tables with actual hooks.json (#5839) 2026-06-26 13:58:28 +05:30
0fbbb2f525 feat(memory): expose expiration controls in client docs (#5874)
Co-authored-by: Soumil Rathi <soumilrathi@gmail.com>
2026-06-25 17:14:33 -07:00
818c2981b7 feat(ts-sdk): add MiniMax LLM provider (#5858)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-25 17:01:50 +05:30
Rod BoevandGitHub 1f66aadfa3 fix(openclaw): normalize Windows skill-loader URLs before fileURLToPath (#5679) 2026-06-25 16:36:11 +05:30
Hrushikesh YadavandGitHub b91c745fbc fix: apply remove_code_blocks() to LangChain path in async _create_procedural_memory (#5711) 2026-06-25 16:34:28 +05:30
Muhammad FurqanandGitHub af70668308 fix(reranker): score HuggingFace reranker with sigmoid, not min-max (#5715) 2026-06-25 16:18:02 +05:30
890473f891 fix(core): validate and trim entity IDs in delete_all() (#5735)
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-25 16:14:30 +05:30
Hrushikesh YadavandGitHub d2ff83cf72 fix(redis): use .get() for hash/created_at in insert() to handle entity payloads (#5709) 2026-06-25 16:13:44 +05:30
Rod BoevandGitHub 0e02effaf7 fix(notices): derive scale counts for Redis and search backends (#5687) 2026-06-25 16:04:44 +05:30
9269a0ad6e feat(ts-sdk): add LiteLLM as LLM provider (#5830)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-25 15:52:46 +05:30
Hrushikesh YadavandGitHub 3d06006f36 fix(valkey): escape special chars in FT.SEARCH tag filter values (#5750) 2026-06-25 15:20:13 +05:30
Rod BoevandGitHub 6bb1d328ad fix(mem0-ts): support pgvector connection strings and ssl (#5789) 2026-06-25 11:57:37 +05:30
Taranjeet SinghandGitHub ac296f7534 docs: make example code fences copy-safe (#5833) 2026-06-24 22:19:40 -07:00
KartikandGitHub ac8f862ff7 fix(mem0-plugin): store files_touched as a list to stop double JSON-encoding (#5806) 2026-06-25 09:06:11 +05:30
b33fa5427c fix(memory): align entity extraction precision (#5829)
Making the entity extraction function cleaner


Co-authored-by: Soumil Rathi <soumilrathi@gmail.com>
2026-06-24 15:48:37 -07:00
Ashutosh KasudhanandGitHub 5d573dd2ae docs: added typescript support to deepseek provider (#5723) 2026-06-24 20:55:14 +05:30
KartikandGitHub 98dbf90864 chore: update changelog, bump SDK versions to Python 2.0.8 and TypeScript 3.0.10 (#5825) 2026-06-24 20:21:06 +05:30
David ShraderandGitHub 6ddf1669f4 fix(vector_stores): point fastembed-missing warning at mem0ai[extras] (#5622) 2026-06-24 14:47:02 +05:30
David ShraderandGitHub d3d2e89fd5 fix(llms): skip JSON response_format for Groq compound models (#5513) 2026-06-24 14:42:22 +05:30
XiaojuandGitHub 43175d85f2 fix: preserve empty Azure AI Search update values (#5524)
Signed-off-by: Xiaoju <xiaojuchh@gmail.com>
2026-06-24 14:41:55 +05:30
KartikandGitHub 661ecb9f0f docs(hermes): update for v3 API, OSS self-hosted mode, and new tools (#5807) 2026-06-24 11:59:13 +05:30
冯基魁andGitHub 09f181c577 fix(server): fetch filtered dashboard memories beyond default page (#5753) 2026-06-24 11:49:06 +05:30
3497f26a00 fix: add auto_refresh option for OpenSearch Serverless compatibility (#3893)
Co-authored-by: Zaid Malhis <Malhis@users.noreply.github.com>
2026-06-24 11:48:52 +05:30
BartokandGitHub e9c0547423 fix(ts-sdk): preserve customCategories names through key conversion (#5741) 2026-06-24 11:15:19 +05:30
Yash SinghandGitHub 25bc1b7426 fix(memory): guard against malformed image_url in parse_vision_messages (#5631) 2026-06-24 11:10:36 +05:30
Hrushikesh YadavandGitHub fee344db85 fix(chroma): wrap scalar vector_id in list for delete() (#5703) 2026-06-24 10:54:36 +05:30
BartokandGitHub b611f69381 fix(chroma): wrap update() ids/embeddings/metadatas in lists (#5757) 2026-06-24 10:54:15 +05:30
Muhammad FurqanandGitHub c2862831db fix(reranker): log reranking failures instead of swallowing them silently (#5717) 2026-06-24 10:44:37 +05:30
홍찬희andGitHub 1678e682ee fix(ts-sdk): check message.role instead of content for system messages (#3921) 2026-06-23 17:18:00 +05:30
BartokandGitHub ced4af681f fix(claude-plugin): rerank auto-injected memory context by default (#5690) 2026-06-23 16:52:35 +05:30
Hrushikesh YadavandGitHub 565db27121 fix(milvus,baidu): sanitize filter values to prevent expression injection (#5746) 2026-06-23 16:51:05 +05:30
Hrushikesh YadavandGitHub c0ac9f81fa fix(milvus): wrap scalar vector_id in list for delete() (#5704) 2026-06-23 16:48:47 +05:30
Yash SinghandGitHub 879c68555c fix(memory): return attributed_to from get/get_all/search (#5629) 2026-06-23 16:43:30 +05:30
Abhishek ChauhanandGitHub c2e723352e fix(ts-oss): return attributedTo from get/search/getAll (#5675) 2026-06-23 16:42:57 +05:30
Hrushikesh YadavandGitHub 716f021df8 fix(pinecone): map all comparison operators in _create_filter() (#5707) 2026-06-23 16:38:28 +05:30
Jiangtian FengandGitHub 7fa996261d perf: batch BM25 sparse encoding in Qdrant insert (#5592) 2026-06-23 16:29:16 +05:30
Yash SinghandGitHub 87bd2d91e0 fix(llms): preserve reasoning fields in base-to-provider config conversion (#5638) 2026-06-23 16:27:43 +05:30
Yash SinghandGitHub 15a930dac2 fix(llms): pass configured anthropic_base_url to the Anthropic client (#5626) 2026-06-23 16:26:22 +05:30
BartokandGitHub fa9abc77a6 fix(ts-oss): honor configured baseURL in AnthropicLLM (#5740) 2026-06-23 16:25:51 +05:30
Hrushikesh YadavandGitHub 4e448269bc fix(mongodb): reject dict filter values to prevent NoSQL operator injection (#5748) 2026-06-22 18:09:01 +05:30
Hrushikesh YadavandGitHub 29d131f7aa fix(chroma): return None instead of {} from _generate_where_clause for empty filters (#5713) 2026-06-22 12:05:28 +05:30
BartokandGitHub 42fe129330 fix(opensearch): return [[]] from list() error path to honor list() contract (#5727) 2026-06-22 11:58:37 +05:30
Hrushikesh YadavandGitHub bd5996f41e fix(pinecone): return [[]] from list() error path instead of dict (#5706) 2026-06-22 11:57:52 +05:30
BartokandGitHub 299c423213 fix(faiss): return [[]] for uninitialized index to honor list() contract (#5725) 2026-06-22 11:57:06 +05:30
Hrushikesh YadavandGitHub ce0531a13e fix(mongodb): wrap list() return in outer list to match interface contract (#5729) 2026-06-22 11:54:16 +05:30
513b56159f fix(embeddings): forward embedding_dims to Titan V2 in AWS Bedrock embedder (#5671)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 11:49:23 +05:30
Yash SinghandGitHub 1676b3168d fix(server): return 404/400 instead of 502 for not-found and invalid input (#5634) 2026-06-22 11:47:48 +05:30
Davide LeopardiandGitHub 8a786bf72d fix(azure): stop mutating and corrupting caller messages in content rewrite (#5731) 2026-06-22 11:45:46 +05:30
Yash SinghandGitHub a48f34cf77 fix(vector_stores): deep-copy Redis DEFAULT_FIELDS so instances keep distinct dims (#5633) 2026-06-22 11:29:25 +05:30
Hrushikesh YadavandGitHub 650b734b1b fix: reset() only drops history table, leaving stale messages (#5541) 2026-06-22 11:28:17 +05:30
youneshimaandGitHub 871a1de7d2 docs: fix add memory v3 behavior (#5694) 2026-06-21 12:18:58 -07:00
e615cc66de docs: rebrand Keywords AI integration to Respan (#5098)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-20 23:10:15 +05:30
Harsh Vardhan GuptaandGitHub ca86a164bd fix(pi-agent-plugin): resolve undici CVE-2026-9697 / CVE-2026-9678 (#5669) 2026-06-19 16:21:18 +05:30
2ac3f3956a fix(cli): pass telemetry context via stdin instead of argv (#5668)
Co-authored-by: JunghwanNA <70629228+shaun0927@users.noreply.github.com>
2026-06-19 13:57:53 +05:30
7a9f03af3f fix(llms,embeddings): repair HTTP proxy support (httpx>=0.28) and preserve proxies in LlmFactory (#5447)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-19 13:45:21 +05:30
Yash SinghandGitHub 48f1d6f010 fix(reranker): clamp out-of-range LLM scores instead of mis-parsing them (#5635) 2026-06-19 12:49:50 +05:30
Yash SinghandGitHub f0ccd99924 fix(vertex): pass required vectors arg in list and similarity search (#5627) 2026-06-19 12:44:48 +05:30
c5971193a2 fix(vector_stores): return None from Redis.get() for missing IDs (#5625)
Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-19 12:25:24 +05:30
Yash SinghandGitHub ff53fd60b7 fix(graph): keep distinct entities that share a substring prefix (#5630) 2026-06-19 12:23:15 +05:30
Yash SinghandGitHub ffa334537a fix(client): check HTTP status before parsing ping response in _validate_api_key (#5639) 2026-06-19 12:19:13 +05:30
Yash SinghandGitHub bd7ce2c13c fix(vector_stores): drop stray print in Weaviate list_cols (#5637) 2026-06-19 12:07:10 +05:30
Yash SinghandGitHub 5d767219ff fix(reranker): export all five rerankers from package root (#5636) 2026-06-19 12:06:12 +05:30
HaochenandGitHub 6b744845c3 fix(oss-ts): preserve message roles in extraction input so assistant facts aren't attributed to the user (#5643) 2026-06-19 09:17:52 +05:30
Yash SinghandGitHub 5b4478458b fix(server): return 404 not 500 for malformed api key id on revoke (#5640) 2026-06-18 17:45:05 +05:30
BartokandGitHub 1751e7bff9 fix(ts-oss): reject empty/blank messages in Memory.add() to prevent hallucinated memories (#5545) 2026-06-18 17:36:19 +05:30
7ae6a8c36a fix(memory): guard entity embed_batch count mismatch in v3 add pipeline (#5604)
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-18 17:22:44 +05:30
1dcee153b9 fix(deps): patch js-yaml, ai, python-dotenv vulnerabilities (CVE-2026-53550, CVE-2025-48985, CVE-2026-28684) (#5641)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:13:15 +05:30
Md. Mamun HossainandGitHub 4065e846f6 fix(ts-sdk): prevent hallucinated memories on empty messages payload … (#5613) 2026-06-18 17:01:02 +05:30
Hrushikesh YadavandGitHub 466249113c fix: async delete_all race condition corrupts entity store linked_memory_ids (#5553) 2026-06-18 16:57:03 +05:30
Alok TripathiandGitHub 3e2ae734e7 feat(embeddings): add native embed_batch to 5 embedders (LMStudio, Together, HuggingFace, VertexAI, GoogleGenAI) (#5609) 2026-06-18 16:46:31 +05:30
96b31c4bc0 fix(form-data): upgrade to >=4.0.6 across pnpm workspaces (CVE-2026-12143) (#5618)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:44:05 +05:30
Rocke DongandGitHub 0117d5838b fix(server): use 127.0.0.1 in dashboard healthcheck to avoid IPv6 localhost resolution (#5612) 2026-06-18 11:53:06 +05:30
Abhishek ChauhanandGitHub 42a3b4043c fix(ts-sdk): preserve user metadata keys across the case-conversion round-trip (#5515) 2026-06-18 11:35:20 +05:30
KartikandGitHub 158e9111cb chore: update changelog, bump SDK versions to Python 2.0.7 and TypeScript 3.0.9 (#5615) 2026-06-17 21:45:28 +05:30
9ed1983b85 refactor(opencode): use existing mem0 SDK instead of delegating to MCP, load skills properly instead of dumping them in .opencode (#5323)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-17 21:18:39 +05:30
703e8a035d fix: FAISS filtered search drops over-fetched candidates before filtering (#5453)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-17 16:34:27 +05:30
Hrushikesh YadavandGitHub 7ed2faab84 fix: api_error_handler silently drops return values from async methods (#5540) 2026-06-17 14:46:08 +05:30
Abhishek ChauhanandGitHub 0d66d3d127 fix(ts-sdk): preserve user-defined schema keys in createMemoryExport (#5594) 2026-06-17 14:40:33 +05:30
137b7519f7 fix(embeddings): honor aws_session_token in AWS Bedrock embeddings (#5566)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:36:33 +05:30
e34f5835bd feat(embeddings): add native embed_batch to OllamaEmbedding (#5415)
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-17 14:12:53 +05:30
Yash Raj PandeyandGitHub f122eb7c65 fix(weaviate): pass embedding dims in reset() so it does not crash (#5570) 2026-06-17 13:29:13 +05:30
mintlify[bot]GitHubmintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
a5123b8a5e docs: tighten Graph Memory description for SEO (#5603)
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
2026-06-17 05:10:38 +00:00
rudrajmehta-mem0andGitHub 6aa9bffa55 docs: reinstate graph memory terminology (native entity linking) (#5601) 2026-06-16 21:22:55 -07:00
d772f9a961 feat: support Gemini via Vertex AI as LLM provider (#4030)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-16 16:59:06 +05:30
7c841a2bce fix(redis): do not crash on empty or None filters in search and list (#5446)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-16 16:10:57 +05:30
Hrushikesh YadavandGitHub 6a6dfb4935 fix(huggingface): use self.config instead of raw config parameter (#5538) 2026-06-16 15:51:27 +05:30
Hrushikesh YadavandGitHub 8b370def80 fix: AsyncMemory.reset() does not reset entity store (#5535) 2026-06-16 15:50:30 +05:30
Hrushikesh YadavandGitHub d46464282c fix(pinecone): hybrid search crashes when filters is None (#5533) 2026-06-16 15:49:26 +05:30
Hrushikesh YadavandGitHub bb4a239cb1 fix(mongodb): reset() passes wrong argument to create_col() (#5532) 2026-06-16 15:48:45 +05:30
Hrushikesh YadavandGitHub e30f0d91fe fix(weaviate): reset() crashes with missing vector_size argument (#5531) 2026-06-16 15:45:47 +05:30
Hrushikesh YadavandGitHub 9f34e858c7 fix(ollama): json format mutates caller's messages list in-place (#5539) 2026-06-16 15:37:22 +05:30
BartokandGitHub 94bbc13de0 fix(memory): skip messages without a content key in message parsers (#5575) 2026-06-16 15:29:53 +05:30
Hrushikesh YadavandGitHub a2f01a8fcc fix: async delete_all aborts on first error, leaving partial deletion (#5529) 2026-06-16 11:59:33 +05:30
Hrushikesh YadavandGitHub 30d172e826 fix: omit None config values from Gemini GenerateContentConfig (#5528) 2026-06-16 11:54:42 +05:30
bb69b036b5 fix(vector_stores): return None from get() for missing IDs (milvus/weaviate/supabase) (#5562)
Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
2026-06-16 11:52:59 +05:30
b55c51e004 fix(anthropic): tool_choice format and tool response parsing (#5537)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-15 17:28:45 +05:30
4492e75d04 fix(deps): bump esbuild >=0.28.1 across all npm packages (#5563)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 17:04:11 +05:30
Hrushikesh YadavandGitHub 4d949022f2 fix: preserve custom metadata fields during memory update (#5480) 2026-06-15 16:29:44 +05:30
3ef034a9e4 fix(vector_stores): return None from ChromaDB.get() for missing IDs (#5561)
Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
2026-06-15 16:11:03 +05:30
Yash SinghandGitHub b90e3c0b76 fix(reranker): respect config.top_k in Cohere and ZeroEntropy fallback paths (#5560) 2026-06-15 16:10:00 +05:30
a8eeddde64 fix(llms): honor reasoning-model params in AzureOpenAIStructuredLLM (#5548)
Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
2026-06-15 16:07:19 +05:30
Hrushikesh YadavandGitHub 09a9e34382 fix(litellm): function-calling check blocks all calls on non-tool models (#5536) 2026-06-15 15:59:46 +05:30
66c4394b40 fix(pyproject): rename vector_stores extra to vector-stores for PEP 503/508 compliance (#4934)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-15 12:38:23 +05:30
32575a65fc fix(llms): honor reasoning-model params in OpenAIStructuredLLM (#5458)
Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-15 12:36:15 +05:30
Yash SinghandGitHub 66901d7393 fix(llms): accept and forward **kwargs in Together/LangChain/Sarvam providers (#5556) 2026-06-15 12:23:04 +05:30
Hrushikesh YadavandGitHub a1eefc31bc fix(bedrock): use dict literal instead of set in AI21 response parse default (#5527) 2026-06-15 12:09:34 +05:30
Davide LeopardiandGitHub de471799d1 fix(llms): send max_completion_tokens for the GPT-5 family across providers (#5547) 2026-06-15 12:04:19 +05:30
Rod BoevandGitHub 3951ad4705 fix(openclaw): reduce skills-mode triage prompt footprint (#5502) 2026-06-15 11:18:39 +05:30
KartikandGitHub 9315e3036f chore: retire in-repo evaluation/ in favor of mem0ai/memory-benchmarks (#5520) 2026-06-14 00:43:02 +05:30
KartikandGitHub b3ede5b7c0 chore: update changelog, bump SDK and package versions to 3.0.8 and 2.0.6 (#5522) 2026-06-13 20:59:53 +05:30
youneshimaandGitHub 3553fc79dd feat(memory): add OSS-to-Platform notices (#5494) 2026-06-13 18:34:20 +05:30
KartikandGitHub f322cf82b9 chore: consolidate cookbooks/ into an indexed examples/ directory (#5517) 2026-06-13 18:25:50 +05:30
KartikandGitHub 73c975ba68 chore: bump version to 0.1.3, update mem0ai to ^3.0.7, and adjust CHANGELOG (#5521) 2026-06-13 18:10:50 +05:30
KartikandGitHub 931d579ba5 chore(openclaw): release v1.0.13 and backfill v1.0.12 changelog (#5519) 2026-06-13 17:59:04 +05:30
KartikandGitHub f4773a0baf fix(mem0-plugin): accurate per-editor telemetry attribution + OpenCode telemetry (#5518) 2026-06-13 16:48:29 +05:30
KartikandGitHub 06d33f6cc4 fix: relax flaky entity boost parallelism timing threshold (#5511) 2026-06-12 21:07:47 +05:30
Hrushikesh YadavandGitHub 8f3b60f3e1 fix: prevent crash in parse_vision_messages when vision is disabled (#5487) 2026-06-12 20:41:18 +05:30
Harsh Vardhan GuptaandGitHub a6e27dcc9c fix(@mem0/community): upgrade @langchain/community to ^1.1.18 (CVE-2026-27795, CVE-2026-26019) (#5510) 2026-06-12 20:07:03 +05:30
Yufeng HeandGitHub 4f10c986b5 fix: expose Qdrant https option (#5380) 2026-06-12 20:06:26 +05:30
821152bd14 Fix OpenClaw Mem0 custom categories payload (#5345)
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-12 19:48:53 +05:30
f48b133101 feat(skills): add mem0-oss-to-platform migration skill (#5455)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-12 19:48:37 +05:30
1d56f85705 fix(cli): resolve Windows environment compatibility issues in python CLI tests (#5464)
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-12 19:40:26 +05:30
Hrushikesh YadavandGitHub ced852033b fix: return 400 instead of 502 for invalid search filters (#5482) 2026-06-12 19:35:24 +05:30
Yufeng HeandGitHub b9ad8fa8b2 fix(openclaw): skip runtime setup during metadata registration (#5383) 2026-06-12 19:32:59 +05:30
e3f5ce7b41 fix: use valid S3 entity index names (#5416)
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-12 19:22:32 +05:30
KartikandGitHub f681889b14 fix(pi-agent-plugin): make command results visible and relevance-filtered (#5504) 2026-06-12 19:13:31 +05:30
KartikandGitHub b5ec46be5b fix(plugin): guard bare $USER refs in on_session_start.sh for Windows (#5492) 2026-06-12 19:13:19 +05:30
168ad358d5 fix(deps): resolve all open MEDIUM Dependabot alerts (npm overrides + Python pins) (#5489)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 15:15:26 +05:30
2c796d144f refactor: consolidate agent/editor plugins under integrations/ (#5491)
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-12 10:31:35 +05:30
c676c2c458 fix(dashboard): pin pnpm to 10.34.2 so docker build works on node:20-alpine (#5483)
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-11 22:45:52 +05:30
b36847622d fix(langchain): search() crashes with TypeError when score is None (#5072)
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-11 22:34:06 +05:30
Hrushikesh YadavandGitHub 32c8849044 fix: remove dead _process_config method in Memory and AsyncMemory (#5486) 2026-06-11 22:26:53 +05:30
Hrushikesh YadavandGitHub 2dd2872c08 fix: use 'is not None' instead of truthiness for vector/payload in pgvector update (#5488) 2026-06-11 22:12:38 +05:30
cf268da19d fix(demo): guard against undefined data in useMemories hook (v2 async response) (#5029)
Co-authored-by: Kartik <kartik.labhshetwar@mem0.ai>
2026-06-11 21:50:35 +05:30
Sense_wangandGitHub 7a5df64746 fix: allow dashboard refresh cookie on http deployments (#5026) 2026-06-11 21:29:54 +05:30
4c41f6deeb fix(vector-stores): index Valkey 'memory' field as TEXT not TAG (#5443)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-06-11 21:28:42 +05:30
Hrushikesh YadavandGitHub f84aa1eb31 fix: implement $not filter support in ChromaDB vector store (#5485) 2026-06-11 20:12:39 +05:30
Saket AryanandGitHub 9226ee2229 ci: aggregate all PR testing behind a single required CI Gate workflow (#5476) 2026-06-11 15:24:51 +05:30
614 changed files with 27661 additions and 15360 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
"name": "mem0",
"source": {
"source": "local",
"path": "./mem0-plugin"
"path": "./integrations/mem0-plugin"
},
"policy": {
"installation": "AVAILABLE",
+2 -2
View File
@@ -10,9 +10,9 @@
"plugins": [
{
"name": "mem0",
"source": "./mem0-plugin",
"source": "./integrations/mem0-plugin",
"description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search to Claude workflows.",
"version": "0.2.9"
"version": "0.2.11"
}
]
}
+1 -1
View File
@@ -8,7 +8,7 @@
"name": "mem0",
"source": {
"source": "local",
"path": "./mem0-plugin"
"path": "./integrations/mem0-plugin"
},
"policy": {
"installation": "AVAILABLE",
+2 -2
View File
@@ -10,9 +10,9 @@
"plugins": [
{
"name": "mem0",
"source": "./mem0-plugin",
"source": "./integrations/mem0-plugin",
"description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search.",
"version": "0.2.9"
"version": "0.2.11"
}
]
}
+171
View File
@@ -0,0 +1,171 @@
name: CI Gate
# Single required status check for all PRs.
#
# Path-filtered CI workflows can't be marked as required in branch
# protection: on a PR that doesn't touch their paths they never report, and
# the required check hangs at "Expected" forever. This gate solves that. It
# runs on every PR, detects which packages changed, calls only the relevant
# package CI workflows (as reusable workflows), and the final "CI Gate" job
# reports the aggregate result — success when every invoked pipeline passed
# (skipped pipelines are fine), failure when any failed.
#
# Branch protection should require exactly one status check: "CI Gate".
#
# Package CI workflows keep their own push-to-main and workflow_dispatch
# triggers; only their pull_request triggers moved here. To wire in a new
# package: add a filter under the `changes` job, a call job that `uses:` the
# package workflow, and list the call job in the gate's `needs`.
on:
pull_request:
concurrency:
group: ci-gate-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: read
jobs:
changes:
name: Detect changed packages
runs-on: ubuntu-latest
outputs:
python_sdk: ${{ steps.filter.outputs.python_sdk }}
ts_sdk: ${{ steps.filter.outputs.ts_sdk }}
cli_python: ${{ steps.filter.outputs.cli_python }}
cli_node: ${{ steps.filter.outputs.cli_node }}
openclaw: ${{ steps.filter.outputs.openclaw }}
opencode_plugin: ${{ steps.filter.outputs.opencode_plugin }}
pi_agent_plugin: ${{ steps.filter.outputs.pi_agent_plugin }}
docs_llms_txt: ${{ steps.filter.outputs.docs_llms_txt }}
steps:
- uses: dorny/paths-filter@v3
id: filter
with:
# Each filter mirrors the package workflow's old pull_request
# paths, plus the package workflow file itself and this gate file
# (changing either must re-exercise the pipeline).
filters: |
python_sdk:
- 'mem0/**'
- 'tests/**'
- 'pyproject.toml'
- '.github/workflows/ci.yml'
- '.github/workflows/ci-gate.yml'
ts_sdk:
- 'mem0-ts/**'
- '.github/workflows/ts-sdk-ci.yml'
- '.github/workflows/ci-gate.yml'
cli_python:
- 'cli/python/**'
- '.github/workflows/cli-python-ci.yml'
- '.github/workflows/ci-gate.yml'
cli_node:
- 'cli/node/**'
- '.github/workflows/cli-node-ci.yml'
- '.github/workflows/ci-gate.yml'
openclaw:
- 'integrations/openclaw/**'
- '.github/workflows/openclaw-checks.yml'
- '.github/workflows/ci-gate.yml'
opencode_plugin:
- 'integrations/mem0-plugin/.opencode-plugin/**'
- '.github/workflows/opencode-plugin-checks.yml'
- '.github/workflows/ci-gate.yml'
pi_agent_plugin:
- 'integrations/pi-agent-plugin/**'
- '.github/workflows/pi-agent-plugin-checks.yml'
- '.github/workflows/ci-gate.yml'
docs_llms_txt:
- 'docs/**/*.mdx'
- 'docs/llms.txt'
- 'scripts/check-llms-txt-coverage.py'
- 'scripts/llms-txt-ignore.txt'
- '.github/workflows/docs-llms-txt-check.yml'
- '.github/workflows/ci-gate.yml'
python-sdk:
name: Python SDK
needs: changes
if: needs.changes.outputs.python_sdk == 'true'
uses: ./.github/workflows/ci.yml
secrets: inherit
ts-sdk:
name: TypeScript SDK
needs: changes
if: needs.changes.outputs.ts_sdk == 'true'
uses: ./.github/workflows/ts-sdk-ci.yml
secrets: inherit
cli-python:
name: Python CLI
needs: changes
if: needs.changes.outputs.cli_python == 'true'
uses: ./.github/workflows/cli-python-ci.yml
secrets: inherit
cli-node:
name: Node CLI
needs: changes
if: needs.changes.outputs.cli_node == 'true'
uses: ./.github/workflows/cli-node-ci.yml
secrets: inherit
openclaw:
name: OpenClaw
needs: changes
if: needs.changes.outputs.openclaw == 'true'
uses: ./.github/workflows/openclaw-checks.yml
secrets: inherit
opencode-plugin:
name: OpenCode Plugin
needs: changes
if: needs.changes.outputs.opencode_plugin == 'true'
uses: ./.github/workflows/opencode-plugin-checks.yml
secrets: inherit
pi-agent-plugin:
name: Pi Agent Plugin
needs: changes
if: needs.changes.outputs.pi_agent_plugin == 'true'
uses: ./.github/workflows/pi-agent-plugin-checks.yml
secrets: inherit
docs-llms-txt:
name: docs llms.txt
needs: changes
if: needs.changes.outputs.docs_llms_txt == 'true'
uses: ./.github/workflows/docs-llms-txt-check.yml
secrets: inherit
gate:
name: CI Gate
needs:
- changes
- python-sdk
- ts-sdk
- cli-python
- cli-node
- openclaw
- opencode-plugin
- pi-agent-plugin
- docs-llms-txt
if: always()
runs-on: ubuntu-latest
steps:
- name: Evaluate pipeline results
env:
NEEDS: ${{ toJSON(needs) }}
run: |
echo "$NEEDS" | jq -r 'to_entries[] | "\(.key): \(.value.result)"'
failed=$(echo "$NEEDS" | jq -r '[to_entries[] | select(.value.result == "failure" or .value.result == "cancelled") | .key] | join(", ")')
if [ -n "$failed" ]; then
echo "::error::Failing pipelines: $failed"
exit 1
fi
echo "All pipelines relevant to this change passed."
+3 -1
View File
@@ -1,9 +1,11 @@
name: ci
# On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main runs remain standalone.
on:
push:
branches: [main]
pull_request:
workflow_call:
jobs:
changelog_check:
+3 -4
View File
@@ -1,5 +1,7 @@
name: CLI Node CI
# On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main and manual runs remain standalone.
on:
workflow_dispatch:
push:
@@ -7,10 +9,7 @@ on:
paths:
- 'cli/node/**'
- '.github/workflows/cli-node-ci.yml'
pull_request:
paths:
- 'cli/node/**'
- '.github/workflows/cli-node-ci.yml'
workflow_call:
jobs:
lint:
+3 -4
View File
@@ -1,5 +1,7 @@
name: CLI Python CI
# On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main and manual runs remain standalone.
on:
workflow_dispatch:
push:
@@ -7,10 +9,7 @@ on:
paths:
- 'cli/python/**'
- '.github/workflows/cli-python-ci.yml'
pull_request:
paths:
- 'cli/python/**'
- '.github/workflows/cli-python-ci.yml'
workflow_call:
jobs:
lint:
+3 -6
View File
@@ -6,13 +6,10 @@ name: docs - llms.txt check
# python scripts/check-llms-txt-coverage.py # read-only
# python scripts/check-llms-txt-coverage.py --write # scaffold placeholders
# On PRs this is invoked by ci-gate.yml (the single required check);
# manual runs remain standalone.
on:
pull_request:
paths:
- 'docs/**/*.mdx'
- 'docs/llms.txt'
- 'scripts/check-llms-txt-coverage.py'
- 'scripts/llms-txt-ignore.txt'
workflow_call:
workflow_dispatch: {}
permissions:
+2 -2
View File
@@ -25,7 +25,7 @@ jobs:
id-token: write
defaults:
run:
working-directory: openclaw
working-directory: integrations/openclaw
steps:
- uses: actions/checkout@v4
with:
@@ -42,7 +42,7 @@ jobs:
node-version: '22'
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
cache-dependency-path: openclaw/pnpm-lock.yaml
cache-dependency-path: integrations/openclaw/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
+16 -17
View File
@@ -1,16 +1,15 @@
name: openclaw checks
# On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main and manual runs remain standalone.
on:
workflow_dispatch:
push:
branches: [main]
paths:
- 'openclaw/**'
- '.github/workflows/openclaw-checks.yml'
pull_request:
paths:
- 'openclaw/**'
- 'integrations/openclaw/**'
- '.github/workflows/openclaw-checks.yml'
workflow_call:
jobs:
lint:
@@ -28,13 +27,13 @@ jobs:
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: openclaw/pnpm-lock.yaml
cache-dependency-path: integrations/openclaw/pnpm-lock.yaml
- name: Install dependencies
run: cd openclaw && pnpm install --frozen-lockfile
run: cd integrations/openclaw && pnpm install --frozen-lockfile
- name: Type check
run: cd openclaw && pnpm exec tsc --noEmit
run: cd integrations/openclaw && pnpm exec tsc --noEmit
test:
runs-on: ubuntu-latest
@@ -54,20 +53,20 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
cache-dependency-path: openclaw/pnpm-lock.yaml
cache-dependency-path: integrations/openclaw/pnpm-lock.yaml
- name: Install dependencies
run: cd openclaw && pnpm install --frozen-lockfile
run: cd integrations/openclaw && pnpm install --frozen-lockfile
- name: Run tests with coverage
run: cd openclaw && pnpm exec vitest run --coverage
run: cd integrations/openclaw && pnpm exec vitest run --coverage
- name: Upload coverage to Codecov
if: matrix.node-version == 20
uses: codecov/codecov-action@v4
with:
flags: openclaw
directory: openclaw/coverage
directory: integrations/openclaw/coverage
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -86,15 +85,15 @@ jobs:
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: openclaw/pnpm-lock.yaml
cache-dependency-path: integrations/openclaw/pnpm-lock.yaml
- name: Install dependencies
run: cd openclaw && pnpm install --frozen-lockfile
run: cd integrations/openclaw && pnpm install --frozen-lockfile
- name: Build
run: cd openclaw && pnpm build
run: cd integrations/openclaw && pnpm build
- name: Verify dist output exists
run: |
test -f openclaw/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
test -f openclaw/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
test -f integrations/openclaw/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
test -f integrations/openclaw/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
id-token: write
defaults:
run:
working-directory: mem0-plugin/.opencode-plugin
working-directory: integrations/mem0-plugin/.opencode-plugin
steps:
- uses: actions/checkout@v4
with:
+5 -6
View File
@@ -1,23 +1,22 @@
name: opencode-plugin checks
# On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main and manual runs remain standalone.
on:
workflow_dispatch:
push:
branches: [main]
paths:
- 'mem0-plugin/.opencode-plugin/**'
- '.github/workflows/opencode-plugin-checks.yml'
pull_request:
paths:
- 'mem0-plugin/.opencode-plugin/**'
- 'integrations/mem0-plugin/.opencode-plugin/**'
- '.github/workflows/opencode-plugin-checks.yml'
workflow_call:
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: mem0-plugin/.opencode-plugin
working-directory: integrations/mem0-plugin/.opencode-plugin
steps:
- uses: actions/checkout@v4
+2 -2
View File
@@ -25,7 +25,7 @@ jobs:
id-token: write
defaults:
run:
working-directory: pi-agent-plugin
working-directory: integrations/pi-agent-plugin
steps:
- uses: actions/checkout@v4
with:
@@ -42,7 +42,7 @@ jobs:
node-version: '22'
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
cache-dependency-path: pi-agent-plugin/pnpm-lock.yaml
cache-dependency-path: integrations/pi-agent-plugin/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
+17 -18
View File
@@ -1,16 +1,15 @@
name: pi-agent-plugin checks
# On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main and manual runs remain standalone.
on:
workflow_dispatch:
push:
branches: [main]
paths:
- 'pi-agent-plugin/**'
- '.github/workflows/pi-agent-plugin-checks.yml'
pull_request:
paths:
- 'pi-agent-plugin/**'
- 'integrations/pi-agent-plugin/**'
- '.github/workflows/pi-agent-plugin-checks.yml'
workflow_call:
jobs:
lint:
@@ -28,13 +27,13 @@ jobs:
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: pi-agent-plugin/pnpm-lock.yaml
cache-dependency-path: integrations/pi-agent-plugin/pnpm-lock.yaml
- name: Install dependencies
run: cd pi-agent-plugin && pnpm install --frozen-lockfile
run: cd integrations/pi-agent-plugin && pnpm install --frozen-lockfile
- name: Type check
run: cd pi-agent-plugin && pnpm exec tsc --noEmit
run: cd integrations/pi-agent-plugin && pnpm exec tsc --noEmit
test:
runs-on: ubuntu-latest
@@ -54,13 +53,13 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
cache-dependency-path: pi-agent-plugin/pnpm-lock.yaml
cache-dependency-path: integrations/pi-agent-plugin/pnpm-lock.yaml
- name: Install dependencies
run: cd pi-agent-plugin && pnpm install --frozen-lockfile
run: cd integrations/pi-agent-plugin && pnpm install --frozen-lockfile
- name: Run tests
run: cd pi-agent-plugin && pnpm exec vitest run
run: cd integrations/pi-agent-plugin && pnpm exec vitest run
build:
runs-on: ubuntu-latest
@@ -77,17 +76,17 @@ jobs:
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: pi-agent-plugin/pnpm-lock.yaml
cache-dependency-path: integrations/pi-agent-plugin/pnpm-lock.yaml
- name: Install dependencies
run: cd pi-agent-plugin && pnpm install --frozen-lockfile
run: cd integrations/pi-agent-plugin && pnpm install --frozen-lockfile
- name: Build
run: cd pi-agent-plugin && pnpm build
run: cd integrations/pi-agent-plugin && pnpm build
- name: Verify dist output exists
run: |
test -f pi-agent-plugin/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
test -f pi-agent-plugin/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
test -f pi-agent-plugin/dist/entry.js || (echo "Build output missing: dist/entry.js" && exit 1)
test -f pi-agent-plugin/dist/entry.d.ts || (echo "Build output missing: dist/entry.d.ts" && exit 1)
test -f integrations/pi-agent-plugin/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
test -f integrations/pi-agent-plugin/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
test -f integrations/pi-agent-plugin/dist/entry.js || (echo "Build output missing: dist/entry.js" && exit 1)
test -f integrations/pi-agent-plugin/dist/entry.d.ts || (echo "Build output missing: dist/entry.d.ts" && exit 1)
+3 -3
View File
@@ -1,14 +1,14 @@
name: TypeScript SDK CI
# On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main runs remain standalone.
on:
push:
branches: [main]
paths:
- 'mem0-ts/**'
- '.github/workflows/ts-sdk-ci.yml'
pull_request:
paths:
- 'mem0-ts/**'
workflow_call:
jobs:
check_changes:
+2 -2
View File
@@ -25,7 +25,7 @@ jobs:
id-token: write
defaults:
run:
working-directory: vercel-ai-sdk
working-directory: integrations/vercel-ai-sdk
steps:
- uses: actions/checkout@v4
with:
@@ -42,7 +42,7 @@ jobs:
node-version: '22'
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
cache-dependency-path: vercel-ai-sdk/pnpm-lock.yaml
cache-dependency-path: integrations/vercel-ai-sdk/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
+2
View File
@@ -189,3 +189,5 @@ eval/
qdrant_storage/
.crossnote
testing.ipynb
.weave/
+4
View File
@@ -0,0 +1,4 @@
[submodule "evaluation"]
path = evaluation
url = https://github.com/mem0ai/memory-benchmarks
branch = main
+59 -40
View File
@@ -12,7 +12,7 @@ This file provides context for AI coding assistants (Claude Code, Cursor, GitHub
## Repository Structure
This is a **polyglot monorepo** containing Python and TypeScript packages, CLIs, servers, plugins, documentation, and evaluation tooling.
This is a **polyglot monorepo** containing Python and TypeScript packages, CLIs, servers, plugins, and documentation.
### Key Directories
@@ -22,17 +22,18 @@ This is a **polyglot monorepo** containing Python and TypeScript packages, CLIs,
| `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` |
| `vercel-ai-sdk/` | `@mem0/vercel-ai-provider` — Vercel AI SDK memory provider |
| `openclaw/` | `@mem0/openclaw-mem0` — OpenClaw plugin for Claude Code / AI editors |
| `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 |
| `server/` | FastAPI REST server for self-hosted Mem0 (Docker: FastAPI + PostgreSQL/pgvector + Neo4j) |
| `openmemory/` | Self-hosted memory platform — `api/` (FastAPI + Alembic + MCP server) and `ui/` (Next.js 15 + React 19) |
| `mem0-plugin/` | AI editor plugins (Claude Code, Cursor, Codex) — MCP server connection, lifecycle hooks, skills |
| `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/` |
| `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/` |
| `docs/` | Documentation site (Mintlify) |
| `tests/` | Python SDK tests (pytest) |
| `evaluation/` | Benchmarking framework — LOCOMO evals, experiment runner, score generation |
| `examples/` | Sample projects — demo apps, Chrome extension, multi-agent patterns |
| `cookbooks/` | Jupyter notebooks — customer support chatbot, AutoGen integration |
| `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/`) |
| `pr-reviews/` | Pull request review materials |
| `scripts/` | Repo-wide utility scripts (e.g., `check-llms-txt-coverage.py` for docs/llms.txt sync) |
@@ -49,8 +50,8 @@ mem0 (Python SDK) mem0-ts (TypeScript SDK)
cli/python/ ──▶ mem0ai (optional, for OSS mode)
cli/node/ ──▶ mem0ai (npm, for API calls)
vercel-ai-sdk/ ──▶ ai, @ai-sdk/* providers
openclaw/ ──▶ mem0ai (npm)
integrations/vercel-ai-sdk/ ──▶ ai, @ai-sdk/* providers
integrations/openclaw/ ──▶ mem0ai (npm)
```
## Development Setup
@@ -73,8 +74,8 @@ pre-commit install # install git hooks
# TypeScript packages
cd mem0-ts && pnpm install # TS SDK
cd cli/node && pnpm install # Node CLI
cd vercel-ai-sdk && pnpm install # Vercel AI provider
cd openclaw && pnpm install # OpenClaw plugin
cd integrations/vercel-ai-sdk && pnpm install # Vercel AI provider
cd integrations/openclaw && pnpm install # OpenClaw plugin
```
## Build, Lint, and Test Commands
@@ -162,10 +163,10 @@ pnpm run dev # tsx src/index.ts (development)
- **Test:** vitest (not jest)
- **Framework:** Commander + Chalk + ora + cli-table3
### Vercel AI SDK Provider (`vercel-ai-sdk/`)
### Vercel AI SDK Provider (`integrations/vercel-ai-sdk/`)
```bash
cd vercel-ai-sdk
cd integrations/vercel-ai-sdk
pnpm install
pnpm run build # tsup
pnpm run lint # eslint
@@ -180,10 +181,10 @@ pnpm run test:node # vitest (node runtime)
- **Lint:** ESLint + Prettier
- **Test:** jest + vitest (edge/node configs)
### OpenClaw Plugin (`openclaw/`)
### OpenClaw Plugin (`integrations/openclaw/`)
```bash
cd openclaw
cd integrations/openclaw
pnpm install
pnpm run build # tsup
pnpm run test # vitest run
@@ -245,18 +246,19 @@ make docs # or: cd docs && mintlify dev
- **API spec:** `docs/openapi.json`
- **Structure:** `api-reference/`, `open-source/`, `platform/`, `integrations/`, `cookbooks/`, `core-concepts/`
### Evaluation (`evaluation/`)
### 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
cd evaluation
make run-mem0-add # Run mem0 add experiments
make run-mem0-search # Run mem0 search experiments
make run-mem0-plus-add # With graph memory
make run-mem0-plus-search # With graph memory
make run-rag # RAG baseline
make run-full-context # Full context baseline
make run-langmem # LangMem comparison
make run-openai # OpenAI comparison
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
@@ -342,8 +344,8 @@ make run-openai # OpenAI comparison
|---------|--------|-----------|---------------|
| `mem0-ts/` | — | Prettier | jest |
| `cli/node/` | Biome | Biome | vitest |
| `vercel-ai-sdk/` | ESLint | Prettier | jest + vitest |
| `openclaw/` | — | — | vitest |
| `integrations/vercel-ai-sdk/` | ESLint | Prettier | jest + vitest |
| `integrations/openclaw/` | — | — | vitest |
### Type Checking
@@ -381,14 +383,14 @@ Model Context Protocol support in multiple places:
- **Remote:** MCP server at `mcp.mem0.ai`
- **Local:** MCP server in `openmemory/api/` (FastAPI-based)
- **Plugin:** MCP tools in `mem0-plugin/` — 9 tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`
- **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
- `mem0-plugin/` provides integrations for Claude Code, Cursor, and Codex via MCP server connections and lifecycle hooks for automatic memory capture.
- `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.
- **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
@@ -402,19 +404,36 @@ To add a new LLM, embedding, vector store, or reranker provider:
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)
| Workflow | File | Triggers | Tests |
|----------|------|----------|-------|
| Python SDK | `ci.yml` | Push to main, PRs on `mem0/`, `tests/`, `pyproject.toml` | Ruff lint + pytest on Python 3.10, 3.11, 3.12 |
| TypeScript SDK | `ts-sdk-ci.yml` | Push to main, PRs on `mem0-ts/` | Prettier + build + jest on Node 20, 22 |
| Python CLI | `cli-python-ci.yml` | Push to `cli/python/`, PRs, manual | Ruff lint + pytest + hatch build on Python 3.10, 3.11, 3.12 |
| Node CLI | `cli-node-ci.yml` | Push to `cli/node/`, PRs, manual | Biome lint + tsc + vitest + tsup build on Node 20, 22 |
| OpenClaw | `openclaw-checks.yml` | Push to `openclaw/`, PRs, manual | tsc + vitest (with Codecov) + tsup build on Node 20, 22 |
| OpenCode Plugin | `opencode-plugin-checks.yml` | Push to `mem0-plugin/.opencode-plugin/`, PRs, manual | Bun: tsc type-check + build + dist artifact check |
| Pi Agent Plugin | `pi-agent-plugin-checks.yml` | Push to `pi-agent-plugin/`, PRs, manual | tsc + vitest + tsup build (dist artifact check) on Node 20, 22 |
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 |
| 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 |
| 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)
+2 -1
View File
@@ -1026,7 +1026,8 @@ def get_user_preferences(user_id: str):
### AutoGen Integration
```python
from cookbooks.helper.mem0_teachability import Mem0Teachability
# Mem0Teachability lives in examples/notebooks/helper/ — see examples/notebooks/mem0-autogen.ipynb
from helper.mem0_teachability import Mem0Teachability
from mem0 import Memory
# Add memory capability to AutoGen agents
+2 -1
View File
@@ -186,9 +186,10 @@ npx skills add https://github.com/mem0ai/mem0 --skill mem0-vercel-ai-sdk
```bash
npx skills add https://github.com/mem0ai/mem0 --skill mem0-integrate
npx skills add https://github.com/mem0ai/mem0 --skill mem0-test-integration
npx skills add https://github.com/mem0ai/mem0 --skill mem0-oss-to-platform
```
Use `/mem0-integrate` to wire Mem0 into an existing repo via a test-first pipeline, then `/mem0-test-integration` to verify. See the [skills catalog](./skills/) or [Vibecoding with Mem0](https://docs.mem0.ai/vibecoding) for the full picture.
Use `/mem0-integrate` to wire Mem0 into an existing repo via a test-first pipeline, then `/mem0-test-integration` to verify. Use `/mem0-oss-to-platform` to migrate an existing project from Mem0 OSS to the hosted Platform SDK. See the [skills catalog](./skills/) or [Vibecoding with Mem0](https://docs.mem0.ai/vibecoding) for the full picture.
### Basic Usage
+9
View File
@@ -5,6 +5,15 @@ All notable changes to `@mem0/cli` are documented here.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.9] — 2026-06-19
### Security
- Telemetry no longer passes the Mem0 API key to its child process via
command-line arguments. The context is now sent over stdin, so the key is no
longer visible in the process list (`ps`, `/proc/<pid>/cmdline`, Activity
Monitor). Fixes #4862.
## [0.2.8] — 2026-06-01
### Security
+11 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@mem0/cli",
"version": "0.2.8",
"version": "0.2.9",
"description": "The official CLI for mem0 — the memory layer for AI agents",
"type": "module",
"bin": {
@@ -44,5 +44,15 @@
"vitest": "^4.1.0",
"@biomejs/biome": "^1.7.0",
"@types/node": "^20.0.0"
},
"pnpm": {
"overrides": {
"jws@4.0.0": "4.0.1",
"langsmith@<0.6.0": "^0.6.0",
"tar-fs@>=2.0.0 <2.1.4": "^2.1.4",
"picomatch@<2.3.2": "^2.3.2",
"postcss@<8.5.10": ">=8.5.10",
"esbuild": ">=0.28.1"
}
}
}
+132 -415
View File
@@ -9,6 +9,8 @@ overrides:
langsmith@<0.6.0: ^0.6.0
tar-fs@>=2.0.0 <2.1.4: ^2.1.4
picomatch@<2.3.2: ^2.3.2
postcss@<8.5.10: '>=8.5.10'
esbuild: '>=0.28.1'
importers:
@@ -38,7 +40,7 @@ importers:
version: 20.19.37
tsup:
specifier: ^8.0.0
version: 8.5.1(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)
version: 8.5.1(postcss@8.5.15)(tsx@4.21.0)(typescript@5.9.3)
tsx:
specifier: ^4.7.0
version: 4.21.0
@@ -76,28 +78,24 @@ packages:
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@biomejs/cli-linux-arm64@1.9.4':
resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@biomejs/cli-linux-x64-musl@1.9.4':
resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
libc: [musl]
'@biomejs/cli-linux-x64@1.9.4':
resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@biomejs/cli-win32-arm64@1.9.4':
resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==}
@@ -115,314 +113,158 @@ packages:
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
'@esbuild/aix-ppc64@0.25.12':
resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
'@esbuild/aix-ppc64@0.28.1':
resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/aix-ppc64@0.27.4':
resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.25.12':
resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
'@esbuild/android-arm64@0.28.1':
resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm64@0.27.4':
resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.25.12':
resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
'@esbuild/android-arm@0.28.1':
resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-arm@0.27.4':
resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.25.12':
resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
'@esbuild/android-x64@0.28.1':
resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/android-x64@0.27.4':
resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.25.12':
resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
'@esbuild/darwin-arm64@0.28.1':
resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-arm64@0.27.4':
resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.25.12':
resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
'@esbuild/darwin-x64@0.28.1':
resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/darwin-x64@0.27.4':
resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.25.12':
resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
'@esbuild/freebsd-arm64@0.28.1':
resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-arm64@0.27.4':
resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.25.12':
resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
'@esbuild/freebsd-x64@0.28.1':
resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/freebsd-x64@0.27.4':
resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.25.12':
resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
'@esbuild/linux-arm64@0.28.1':
resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm64@0.27.4':
resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.25.12':
resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
'@esbuild/linux-arm@0.28.1':
resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-arm@0.27.4':
resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.25.12':
resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
'@esbuild/linux-ia32@0.28.1':
resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-ia32@0.27.4':
resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.25.12':
resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
'@esbuild/linux-loong64@0.28.1':
resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-loong64@0.27.4':
resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.25.12':
resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
'@esbuild/linux-mips64el@0.28.1':
resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-mips64el@0.27.4':
resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.25.12':
resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
'@esbuild/linux-ppc64@0.28.1':
resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-ppc64@0.27.4':
resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.25.12':
resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
'@esbuild/linux-riscv64@0.28.1':
resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-riscv64@0.27.4':
resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.25.12':
resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
'@esbuild/linux-s390x@0.28.1':
resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-s390x@0.27.4':
resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.25.12':
resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
'@esbuild/linux-x64@0.28.1':
resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/linux-x64@0.27.4':
resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-arm64@0.25.12':
resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
'@esbuild/netbsd-arm64@0.28.1':
resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-arm64@0.27.4':
resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-x64@0.25.12':
resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
'@esbuild/netbsd-x64@0.28.1':
resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/netbsd-x64@0.27.4':
resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.25.12':
resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
'@esbuild/openbsd-arm64@0.28.1':
resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-arm64@0.27.4':
resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.25.12':
resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
'@esbuild/openbsd-x64@0.28.1':
resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/openbsd-x64@0.27.4':
resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/openharmony-arm64@0.25.12':
resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
'@esbuild/openharmony-arm64@0.28.1':
resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
'@esbuild/openharmony-arm64@0.27.4':
resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
'@esbuild/sunos-x64@0.25.12':
resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
'@esbuild/sunos-x64@0.28.1':
resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/sunos-x64@0.27.4':
resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.25.12':
resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
'@esbuild/win32-arm64@0.28.1':
resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-arm64@0.27.4':
resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.25.12':
resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
'@esbuild/win32-ia32@0.28.1':
resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-ia32@0.27.4':
resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.25.12':
resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
'@esbuild/win32-x64@0.27.4':
resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==}
'@esbuild/win32-x64@0.28.1':
resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -474,79 +316,66 @@ packages:
resolution: {integrity: sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.60.0':
resolution: {integrity: sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==}
cpu: [arm]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.60.0':
resolution: {integrity: sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.60.0':
resolution: {integrity: sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-loong64-gnu@4.60.0':
resolution: {integrity: sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==}
cpu: [loong64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-loong64-musl@4.60.0':
resolution: {integrity: sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==}
cpu: [loong64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-ppc64-gnu@4.60.0':
resolution: {integrity: sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-ppc64-musl@4.60.0':
resolution: {integrity: sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==}
cpu: [ppc64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-riscv64-gnu@4.60.0':
resolution: {integrity: sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-riscv64-musl@4.60.0':
resolution: {integrity: sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-s390x-gnu@4.60.0':
resolution: {integrity: sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.60.0':
resolution: {integrity: sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.60.0':
resolution: {integrity: sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==}
cpu: [x64]
os: [linux]
libc: [musl]
'@rollup/rollup-openbsd-x64@4.60.0':
resolution: {integrity: sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==}
@@ -657,7 +486,7 @@ packages:
resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
peerDependencies:
esbuild: '>=0.18'
esbuild: '>=0.28.1'
cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
@@ -737,13 +566,8 @@ packages:
es-module-lexer@2.1.0:
resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==}
esbuild@0.25.12:
resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
engines: {node: '>=18'}
hasBin: true
esbuild@0.27.4:
resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==}
esbuild@0.28.1:
resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==}
engines: {node: '>=18'}
hasBin: true
@@ -829,8 +653,8 @@ packages:
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
nanoid@3.3.12:
resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
@@ -871,7 +695,7 @@ packages:
engines: {node: '>= 18'}
peerDependencies:
jiti: '>=1.21.0'
postcss: '>=8.0.9'
postcss: '>=8.5.10'
tsx: ^4.8.1
yaml: ^2.4.2
peerDependenciesMeta:
@@ -884,8 +708,8 @@ packages:
yaml:
optional: true
postcss@8.5.8:
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
postcss@8.5.15:
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
engines: {node: ^10 || ^12 || >=14}
readdirp@4.1.2:
@@ -997,7 +821,7 @@ packages:
peerDependencies:
'@microsoft/api-extractor': ^7.36.0
'@swc/core': ^1
postcss: ^8.4.12
postcss: '>=8.5.10'
typescript: '>=4.5.0'
peerDependenciesMeta:
'@microsoft/api-extractor':
@@ -1163,160 +987,82 @@ snapshots:
'@colors/colors@1.5.0':
optional: true
'@esbuild/aix-ppc64@0.25.12':
'@esbuild/aix-ppc64@0.28.1':
optional: true
'@esbuild/aix-ppc64@0.27.4':
'@esbuild/android-arm64@0.28.1':
optional: true
'@esbuild/android-arm64@0.25.12':
'@esbuild/android-arm@0.28.1':
optional: true
'@esbuild/android-arm64@0.27.4':
'@esbuild/android-x64@0.28.1':
optional: true
'@esbuild/android-arm@0.25.12':
'@esbuild/darwin-arm64@0.28.1':
optional: true
'@esbuild/android-arm@0.27.4':
'@esbuild/darwin-x64@0.28.1':
optional: true
'@esbuild/android-x64@0.25.12':
'@esbuild/freebsd-arm64@0.28.1':
optional: true
'@esbuild/android-x64@0.27.4':
'@esbuild/freebsd-x64@0.28.1':
optional: true
'@esbuild/darwin-arm64@0.25.12':
'@esbuild/linux-arm64@0.28.1':
optional: true
'@esbuild/darwin-arm64@0.27.4':
'@esbuild/linux-arm@0.28.1':
optional: true
'@esbuild/darwin-x64@0.25.12':
'@esbuild/linux-ia32@0.28.1':
optional: true
'@esbuild/darwin-x64@0.27.4':
'@esbuild/linux-loong64@0.28.1':
optional: true
'@esbuild/freebsd-arm64@0.25.12':
'@esbuild/linux-mips64el@0.28.1':
optional: true
'@esbuild/freebsd-arm64@0.27.4':
'@esbuild/linux-ppc64@0.28.1':
optional: true
'@esbuild/freebsd-x64@0.25.12':
'@esbuild/linux-riscv64@0.28.1':
optional: true
'@esbuild/freebsd-x64@0.27.4':
'@esbuild/linux-s390x@0.28.1':
optional: true
'@esbuild/linux-arm64@0.25.12':
'@esbuild/linux-x64@0.28.1':
optional: true
'@esbuild/linux-arm64@0.27.4':
'@esbuild/netbsd-arm64@0.28.1':
optional: true
'@esbuild/linux-arm@0.25.12':
'@esbuild/netbsd-x64@0.28.1':
optional: true
'@esbuild/linux-arm@0.27.4':
'@esbuild/openbsd-arm64@0.28.1':
optional: true
'@esbuild/linux-ia32@0.25.12':
'@esbuild/openbsd-x64@0.28.1':
optional: true
'@esbuild/linux-ia32@0.27.4':
'@esbuild/openharmony-arm64@0.28.1':
optional: true
'@esbuild/linux-loong64@0.25.12':
'@esbuild/sunos-x64@0.28.1':
optional: true
'@esbuild/linux-loong64@0.27.4':
'@esbuild/win32-arm64@0.28.1':
optional: true
'@esbuild/linux-mips64el@0.25.12':
'@esbuild/win32-ia32@0.28.1':
optional: true
'@esbuild/linux-mips64el@0.27.4':
optional: true
'@esbuild/linux-ppc64@0.25.12':
optional: true
'@esbuild/linux-ppc64@0.27.4':
optional: true
'@esbuild/linux-riscv64@0.25.12':
optional: true
'@esbuild/linux-riscv64@0.27.4':
optional: true
'@esbuild/linux-s390x@0.25.12':
optional: true
'@esbuild/linux-s390x@0.27.4':
optional: true
'@esbuild/linux-x64@0.25.12':
optional: true
'@esbuild/linux-x64@0.27.4':
optional: true
'@esbuild/netbsd-arm64@0.25.12':
optional: true
'@esbuild/netbsd-arm64@0.27.4':
optional: true
'@esbuild/netbsd-x64@0.25.12':
optional: true
'@esbuild/netbsd-x64@0.27.4':
optional: true
'@esbuild/openbsd-arm64@0.25.12':
optional: true
'@esbuild/openbsd-arm64@0.27.4':
optional: true
'@esbuild/openbsd-x64@0.25.12':
optional: true
'@esbuild/openbsd-x64@0.27.4':
optional: true
'@esbuild/openharmony-arm64@0.25.12':
optional: true
'@esbuild/openharmony-arm64@0.27.4':
optional: true
'@esbuild/sunos-x64@0.25.12':
optional: true
'@esbuild/sunos-x64@0.27.4':
optional: true
'@esbuild/win32-arm64@0.25.12':
optional: true
'@esbuild/win32-arm64@0.27.4':
optional: true
'@esbuild/win32-ia32@0.25.12':
optional: true
'@esbuild/win32-ia32@0.27.4':
optional: true
'@esbuild/win32-x64@0.25.12':
optional: true
'@esbuild/win32-x64@0.27.4':
'@esbuild/win32-x64@0.28.1':
optional: true
'@jridgewell/gen-mapping@0.3.13':
@@ -1491,9 +1237,9 @@ snapshots:
widest-line: 4.0.1
wrap-ansi: 8.1.0
bundle-require@5.1.0(esbuild@0.27.4):
bundle-require@5.1.0(esbuild@0.28.1):
dependencies:
esbuild: 0.27.4
esbuild: 0.28.1
load-tsconfig: 0.2.5
cac@6.7.14: {}
@@ -1546,63 +1292,34 @@ snapshots:
es-module-lexer@2.1.0: {}
esbuild@0.25.12:
esbuild@0.28.1:
optionalDependencies:
'@esbuild/aix-ppc64': 0.25.12
'@esbuild/android-arm': 0.25.12
'@esbuild/android-arm64': 0.25.12
'@esbuild/android-x64': 0.25.12
'@esbuild/darwin-arm64': 0.25.12
'@esbuild/darwin-x64': 0.25.12
'@esbuild/freebsd-arm64': 0.25.12
'@esbuild/freebsd-x64': 0.25.12
'@esbuild/linux-arm': 0.25.12
'@esbuild/linux-arm64': 0.25.12
'@esbuild/linux-ia32': 0.25.12
'@esbuild/linux-loong64': 0.25.12
'@esbuild/linux-mips64el': 0.25.12
'@esbuild/linux-ppc64': 0.25.12
'@esbuild/linux-riscv64': 0.25.12
'@esbuild/linux-s390x': 0.25.12
'@esbuild/linux-x64': 0.25.12
'@esbuild/netbsd-arm64': 0.25.12
'@esbuild/netbsd-x64': 0.25.12
'@esbuild/openbsd-arm64': 0.25.12
'@esbuild/openbsd-x64': 0.25.12
'@esbuild/openharmony-arm64': 0.25.12
'@esbuild/sunos-x64': 0.25.12
'@esbuild/win32-arm64': 0.25.12
'@esbuild/win32-ia32': 0.25.12
'@esbuild/win32-x64': 0.25.12
esbuild@0.27.4:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.4
'@esbuild/android-arm': 0.27.4
'@esbuild/android-arm64': 0.27.4
'@esbuild/android-x64': 0.27.4
'@esbuild/darwin-arm64': 0.27.4
'@esbuild/darwin-x64': 0.27.4
'@esbuild/freebsd-arm64': 0.27.4
'@esbuild/freebsd-x64': 0.27.4
'@esbuild/linux-arm': 0.27.4
'@esbuild/linux-arm64': 0.27.4
'@esbuild/linux-ia32': 0.27.4
'@esbuild/linux-loong64': 0.27.4
'@esbuild/linux-mips64el': 0.27.4
'@esbuild/linux-ppc64': 0.27.4
'@esbuild/linux-riscv64': 0.27.4
'@esbuild/linux-s390x': 0.27.4
'@esbuild/linux-x64': 0.27.4
'@esbuild/netbsd-arm64': 0.27.4
'@esbuild/netbsd-x64': 0.27.4
'@esbuild/openbsd-arm64': 0.27.4
'@esbuild/openbsd-x64': 0.27.4
'@esbuild/openharmony-arm64': 0.27.4
'@esbuild/sunos-x64': 0.27.4
'@esbuild/win32-arm64': 0.27.4
'@esbuild/win32-ia32': 0.27.4
'@esbuild/win32-x64': 0.27.4
'@esbuild/aix-ppc64': 0.28.1
'@esbuild/android-arm': 0.28.1
'@esbuild/android-arm64': 0.28.1
'@esbuild/android-x64': 0.28.1
'@esbuild/darwin-arm64': 0.28.1
'@esbuild/darwin-x64': 0.28.1
'@esbuild/freebsd-arm64': 0.28.1
'@esbuild/freebsd-x64': 0.28.1
'@esbuild/linux-arm': 0.28.1
'@esbuild/linux-arm64': 0.28.1
'@esbuild/linux-ia32': 0.28.1
'@esbuild/linux-loong64': 0.28.1
'@esbuild/linux-mips64el': 0.28.1
'@esbuild/linux-ppc64': 0.28.1
'@esbuild/linux-riscv64': 0.28.1
'@esbuild/linux-s390x': 0.28.1
'@esbuild/linux-x64': 0.28.1
'@esbuild/netbsd-arm64': 0.28.1
'@esbuild/netbsd-x64': 0.28.1
'@esbuild/openbsd-arm64': 0.28.1
'@esbuild/openbsd-x64': 0.28.1
'@esbuild/openharmony-arm64': 0.28.1
'@esbuild/sunos-x64': 0.28.1
'@esbuild/win32-arm64': 0.28.1
'@esbuild/win32-ia32': 0.28.1
'@esbuild/win32-x64': 0.28.1
estree-walker@3.0.3:
dependencies:
@@ -1671,7 +1388,7 @@ snapshots:
object-assign: 4.1.1
thenify-all: 1.6.0
nanoid@3.3.11: {}
nanoid@3.3.12: {}
object-assign@4.1.1: {}
@@ -1707,16 +1424,16 @@ snapshots:
mlly: 1.8.2
pathe: 2.0.3
postcss-load-config@6.0.1(postcss@8.5.8)(tsx@4.21.0):
postcss-load-config@6.0.1(postcss@8.5.15)(tsx@4.21.0):
dependencies:
lilconfig: 3.1.3
optionalDependencies:
postcss: 8.5.8
postcss: 8.5.15
tsx: 4.21.0
postcss@8.5.8:
postcss@8.5.15:
dependencies:
nanoid: 3.3.11
nanoid: 3.3.12
picocolors: 1.1.1
source-map-js: 1.2.1
@@ -1837,18 +1554,18 @@ snapshots:
ts-interface-checker@0.1.13: {}
tsup@8.5.1(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3):
tsup@8.5.1(postcss@8.5.15)(tsx@4.21.0)(typescript@5.9.3):
dependencies:
bundle-require: 5.1.0(esbuild@0.27.4)
bundle-require: 5.1.0(esbuild@0.28.1)
cac: 6.7.14
chokidar: 4.0.3
consola: 3.4.2
debug: 4.4.3
esbuild: 0.27.4
esbuild: 0.28.1
fix-dts-default-cjs-exports: 1.0.1
joycon: 3.1.1
picocolors: 1.1.1
postcss-load-config: 6.0.1(postcss@8.5.8)(tsx@4.21.0)
postcss-load-config: 6.0.1(postcss@8.5.15)(tsx@4.21.0)
resolve-from: 5.0.0
rollup: 4.60.0
source-map: 0.7.6
@@ -1857,7 +1574,7 @@ snapshots:
tinyglobby: 0.2.15
tree-kill: 1.2.2
optionalDependencies:
postcss: 8.5.8
postcss: 8.5.15
typescript: 5.9.3
transitivePeerDependencies:
- jiti
@@ -1867,7 +1584,7 @@ snapshots:
tsx@4.21.0:
dependencies:
esbuild: 0.27.4
esbuild: 0.28.1
get-tsconfig: 4.13.7
optionalDependencies:
fsevents: 2.3.3
@@ -1882,10 +1599,10 @@ snapshots:
vite@6.4.3(@types/node@20.19.37)(tsx@4.21.0):
dependencies:
esbuild: 0.25.12
esbuild: 0.28.1
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
postcss: 8.5.8
postcss: 8.5.15
rollup: 4.60.0
tinyglobby: 0.2.15
optionalDependencies:
+2
View File
@@ -10,3 +10,5 @@ overrides:
langsmith@<0.6.0: ^0.6.0
tar-fs@>=2.0.0 <2.1.4: ^2.1.4
picomatch@<2.3.2: ^2.3.2
"postcss@<8.5.10": ">=8.5.10"
"esbuild": ">=0.28.1"
+5 -5
View File
@@ -145,11 +145,11 @@ export function captureEvent(
anonDistinctIdToAlias: anonIdToAlias,
};
const child = spawn(
process.execPath,
[SENDER_SCRIPT, JSON.stringify(context)],
{ detached: true, stdio: "ignore" },
);
const child = spawn(process.execPath, [SENDER_SCRIPT], {
detached: true,
stdio: ["pipe", "ignore", "ignore"],
});
child.stdin?.end(JSON.stringify(context));
child.unref();
} catch {
/* silently swallow */
+28 -2
View File
@@ -1,7 +1,8 @@
/**
* Standalone telemetry sender — runs as a detached child process.
*
* Usage: node telemetry-sender.cjs '<json context>'
* Usage: node telemetry-sender.cjs (JSON context is read from stdin; a single
* argv argument is still accepted as a legacy fallback)
*
* This script is spawned by telemetry.captureEvent() and runs independently
* of the parent CLI process. It:
@@ -19,6 +20,31 @@
const https = require("https");
const fs = require("fs");
function loadContext() {
return new Promise((resolve, reject) => {
if (process.argv[2]) {
try {
resolve(JSON.parse(process.argv[2]));
} catch (err) {
reject(err);
}
return;
}
let data = "";
process.stdin.setEncoding("utf8");
process.stdin.on("data", (chunk) => (data += chunk));
process.stdin.on("end", () => {
try {
resolve(JSON.parse(data));
} catch (err) {
reject(err);
}
});
process.stdin.on("error", reject);
});
}
function httpsRequest(url, method, headers, body) {
return new Promise((resolve, reject) => {
const u = new URL(url);
@@ -108,7 +134,7 @@ async function sendIdentifyEvent(ctx, payload, anonId) {
}
async function main() {
const ctx = JSON.parse(process.argv[2]);
const ctx = await loadContext();
const payload = ctx.payload;
if (ctx.needsEmail && ctx.mem0ApiKey) {
+59
View File
@@ -0,0 +1,59 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const mockLoadConfig = vi.fn();
const mockSaveConfig = vi.fn();
const mockSpawn = vi.fn();
vi.mock("../src/config.js", () => ({
CONFIG_FILE: "/tmp/mem0-config.json",
loadConfig: mockLoadConfig,
saveConfig: mockSaveConfig,
}));
vi.mock("node:child_process", () => ({
spawn: mockSpawn,
}));
describe("captureEvent", () => {
beforeEach(() => {
vi.resetModules();
mockLoadConfig.mockReset();
mockSaveConfig.mockReset();
mockSpawn.mockReset();
delete process.env.MEM0_TELEMETRY;
});
it("pipes the telemetry context through stdin instead of argv", async () => {
mockLoadConfig.mockReturnValue({
platform: {
apiKey: "m0-node-secret",
baseUrl: "https://api.mem0.ai",
userEmail: "",
},
telemetry: {
anonymousId: "cli-anon-node",
},
});
const stdin = { end: vi.fn() };
const child = { stdin, unref: vi.fn() };
mockSpawn.mockReturnValue(child);
const { captureEvent } = await import("../src/telemetry.js");
captureEvent("node_test_event", { case: "stdin-secret" });
expect(mockSpawn).toHaveBeenCalledTimes(1);
const [execPath, args, options] = mockSpawn.mock.calls[0];
expect(execPath).toBe(process.execPath);
expect(args).toHaveLength(1);
expect(String(args[0])).toContain("telemetry-sender.cjs");
expect(JSON.stringify(args)).not.toContain("m0-node-secret");
expect(options).toMatchObject({ detached: true, stdio: ["pipe", "ignore", "ignore"] });
expect(stdin.end).toHaveBeenCalledTimes(1);
const payload = JSON.parse(stdin.end.mock.calls[0][0]);
expect(payload.mem0ApiKey).toBe("m0-node-secret");
expect(payload.payload.event).toBe("node_test_event");
expect(child.unref).toHaveBeenCalledTimes(1);
});
});
+6
View File
@@ -8,4 +8,10 @@ export default defineConfig({
define: {
__CLI_VERSION__: JSON.stringify(pkg.version),
},
test: {
// Integration tests spawn the CLI via `npx tsx` (15s subprocess
// timeout); the first spawn in a file pays a cold-start cost that can
// exceed vitest's 5s default on CI runners.
testTimeout: 30_000,
},
});
+13
View File
@@ -5,6 +5,19 @@ All notable changes to `mem0-cli` (Python) are documented here.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.8] — 2026-06-19
### Security
- Telemetry no longer passes the Mem0 API key to its child process via
command-line arguments. The context is now sent over stdin, so the key is no
longer visible in the process list (`ps`, `/proc/<pid>/cmdline`, Activity
Monitor). Fixes #4862.
### Fixed
- `__version__` now matches the packaged version (was stale at 0.2.4).
## [0.2.7] — 2026-05-20
### Added
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "mem0-cli"
version = "0.2.7"
version = "0.2.8"
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.4"
__version__ = "0.2.8"
+9 -2
View File
@@ -137,12 +137,19 @@ def capture_event(
"anon_distinct_id_to_alias": anon_id_to_alias,
}
subprocess.Popen(
[sys.executable, "-m", "mem0_cli.telemetry_sender", json.dumps(context)],
child = subprocess.Popen(
[sys.executable, "-m", "mem0_cli.telemetry_sender"],
stdin=subprocess.PIPE,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True,
close_fds=True,
text=True,
)
if child.stdin:
with contextlib.suppress(Exception):
child.stdin.write(json.dumps(context))
with contextlib.suppress(Exception):
child.stdin.close()
except Exception:
pass
+13 -2
View File
@@ -1,6 +1,7 @@
"""Standalone telemetry sender — runs as a detached subprocess.
Usage: python -m mem0_cli.telemetry_sender '<json context>'
Usage: python -m mem0_cli.telemetry_sender (JSON context is read from stdin;
a single argv argument is still accepted as a legacy fallback)
This module is spawned by telemetry.capture_event() and runs independently
of the parent CLI process. It:
@@ -20,8 +21,18 @@ import sys
import urllib.request
def _load_context() -> dict:
"""Load telemetry context from stdin, falling back to argv for compatibility."""
raw = ""
if not sys.stdin.isatty():
raw = sys.stdin.read().strip()
if not raw and len(sys.argv) > 1:
raw = sys.argv[1]
return json.loads(raw)
def main() -> None:
ctx = json.loads(sys.argv[1])
ctx = _load_context()
payload = ctx["payload"]
if ctx.get("needs_email") and ctx.get("mem0_api_key"):
+6 -3
View File
@@ -32,12 +32,13 @@ def _run(args: list[str], home_dir: str | None = None) -> subprocess.CompletedPr
if key.startswith("MEM0_"):
del env[key]
env.pop("FORCE_COLOR", None)
env["PYTHONIOENCODING"] = "utf-8"
if home_dir:
env["HOME"] = home_dir
result = subprocess.run(
[sys.executable, "-m", "mem0_cli", *args],
capture_output=True,
text=True,
encoding="utf-8",
env=env,
timeout=15,
)
@@ -99,12 +100,13 @@ class TestArgvPreprocessing:
result = subprocess.run(
[sys.executable, "-m", "mem0_cli", "init", "--agent"],
capture_output=True,
text=True,
encoding="utf-8",
env={
**{k: v for k, v in os.environ.items() if not k.startswith("MEM0_")},
"HOME": clean_home,
"MEM0_BASE_URL": "http://127.0.0.1:1", # blackhole
"FORCE_COLOR": "0",
"PYTHONIOENCODING": "utf-8",
},
timeout=15,
)
@@ -133,12 +135,13 @@ class TestJsonEnvelopeParity:
result = subprocess.run(
[sys.executable, "-m", "mem0_cli", "init", "--agent", "--json"],
capture_output=True,
text=True,
encoding="utf-8",
env={
**{k: v for k, v in os.environ.items() if not k.startswith("MEM0_")},
"HOME": clean_home,
"MEM0_BASE_URL": "http://127.0.0.1:1",
"FORCE_COLOR": "0",
"PYTHONIOENCODING": "utf-8",
},
timeout=15,
)
+2 -1
View File
@@ -49,6 +49,7 @@ def _run(
if key.startswith("MEM0_"):
del env[key]
env.pop("FORCE_COLOR", None)
env["PYTHONIOENCODING"] = "utf-8"
if home_dir:
env["HOME"] = home_dir
if env_override:
@@ -56,7 +57,7 @@ def _run(
result = subprocess.run(
[sys.executable, "-m", "mem0_cli", *args],
capture_output=True,
text=True,
encoding="utf-8",
env=env,
)
return subprocess.CompletedProcess(
+7 -7
View File
@@ -8,8 +8,8 @@ from io import StringIO
from unittest.mock import patch
import pytest
from click.exceptions import Exit as ClickExit
from rich.console import Console
from typer import Exit as TyperExit
from mem0_cli.commands.config_cmd import (
cmd_config_get,
@@ -181,7 +181,7 @@ class TestAddCommand:
patch("mem0_cli.commands.memory.console", console),
patch("mem0_cli.commands.memory.err_console", err_console),
patch("mem0_cli.commands.memory._stdin_is_piped", return_value=False),
pytest.raises((SystemExit, ClickExit)),
pytest.raises((SystemExit, TyperExit)),
):
cmd_add(
mock_backend,
@@ -206,7 +206,7 @@ class TestAddCommand:
with (
patch("mem0_cli.commands.memory.console", console),
patch("mem0_cli.commands.memory.err_console", err_console),
pytest.raises((SystemExit, ClickExit)),
pytest.raises((SystemExit, TyperExit)),
):
cmd_add(
mock_backend,
@@ -764,7 +764,7 @@ class TestImportCommand:
with (
patch("mem0_cli.commands.utils.console", console),
patch("mem0_cli.commands.utils.err_console", err_console),
pytest.raises((SystemExit, ClickExit)),
pytest.raises((SystemExit, TyperExit)),
):
cmd_import(mock_backend, "/nonexistent/file.json", user_id=None, agent_id=None)
@@ -801,7 +801,7 @@ class TestEntitiesListCommand:
with (
patch("mem0_cli.commands.entities.console", console),
patch("mem0_cli.commands.entities.err_console", err_console),
pytest.raises((SystemExit, ClickExit)),
pytest.raises((SystemExit, TyperExit)),
):
cmd_entities_list(mock_backend, "invalid", output="table")
@@ -944,7 +944,7 @@ class TestEntitiesDeleteCommand:
with (
patch("mem0_cli.commands.entities.console", console),
patch("mem0_cli.commands.entities.err_console", err_console),
pytest.raises((SystemExit, ClickExit)),
pytest.raises((SystemExit, TyperExit)),
):
cmd_entities_delete(
mock_backend,
@@ -1308,7 +1308,7 @@ class TestAgentMode:
patch("mem0_cli.commands.memory.console", console),
patch("mem0_cli.commands.memory.err_console", err_console),
patch("sys.stdout", captured_stdout),
pytest.raises((SystemExit, ClickExit)),
pytest.raises((SystemExit, TyperExit)),
):
cmd_get(mock_backend, "bad-id", output="text")
+2 -1
View File
@@ -67,7 +67,8 @@ class TestConfig:
from mem0_cli.config import CONFIG_FILE
mode = os.stat(CONFIG_FILE).st_mode & 0o777
assert mode == 0o600
if os.name != "nt":
assert mode == 0o600
def test_defaults_save_and_load(self, isolate_config):
config = Mem0Config()
+80
View File
@@ -0,0 +1,80 @@
"""Tests for telemetry subprocess secret handling."""
from __future__ import annotations
import io
import json
import subprocess
import sys
from mem0_cli.config import Mem0Config, save_config
from mem0_cli.telemetry import capture_event
from mem0_cli.telemetry_sender import _load_context
class _CaptureStdin:
def __init__(self):
self.buffer = ""
self.closed = False
def write(self, value: str) -> None:
self.buffer += value
def close(self) -> None:
self.closed = True
class _DummyProcess:
def __init__(self):
self.stdin = _CaptureStdin()
def test_capture_event_writes_context_to_stdin_not_argv(isolate_config, monkeypatch):
config = Mem0Config()
config.platform.api_key = "m0-test-secret"
config.telemetry.anonymous_id = "cli-anon-test"
save_config(config)
captured: dict[str, object] = {}
proc = _DummyProcess()
def fake_popen(args, **kwargs):
captured["args"] = args
captured["kwargs"] = kwargs
return proc
monkeypatch.setattr("mem0_cli.telemetry.subprocess.Popen", fake_popen)
capture_event("unit_test_event", {"case": "stdin-secret"})
argv = captured["args"]
assert argv == [sys.executable, "-m", "mem0_cli.telemetry_sender"]
assert all("m0-test-secret" not in arg for arg in argv)
kwargs = captured["kwargs"]
assert kwargs["stdin"] == subprocess.PIPE
assert kwargs["text"] is True
ctx = json.loads(proc.stdin.buffer)
assert ctx["mem0_api_key"] == "m0-test-secret"
assert ctx["payload"]["event"] == "unit_test_event"
assert proc.stdin.closed
def test_load_context_reads_from_stdin(monkeypatch):
monkeypatch.setattr("sys.argv", ["telemetry_sender"])
monkeypatch.setattr("sys.stdin", io.StringIO('{"payload": {"event": "stdin"}}'))
ctx = _load_context()
assert ctx["payload"]["event"] == "stdin"
def test_load_context_falls_back_to_argv(monkeypatch):
monkeypatch.setattr("sys.argv", ["telemetry_sender", '{"payload": {"event": "argv"}}'])
monkeypatch.setattr("sys.stdin", io.StringIO(""))
ctx = _load_context()
assert ctx["payload"]["event"] == "argv"
@@ -50,6 +50,7 @@ Provide conversation messages for Mem0 to extract memories from. At least one en
| `app_id` | string | No* | Associates the memory with an app. |
| `metadata` | object | Optional | Custom key/value metadata (e.g., `{"topic": "preferences"}`). |
| `infer` | boolean (default `true`) | Optional | Set to `false` to skip inference and store the provided text as-is. |
| `expiration_date` | string | Optional | Date in `YYYY-MM-DD` format. The memory is visible through this date and hidden by default after it passes. |
> \* At least one entity ID (`user_id`, `agent_id`, `app_id`, or `run_id`) is required.
@@ -83,3 +84,11 @@ The request is queued for background processing. The response contains an `event
<Info>
Poll the event status via `GET /v1/event/{event_id}/`. Status will be `SUCCEEDED` or `FAILED` once processing completes.
</Info>
<Info>
Memories with `expiration_date` remain stored after they expire. Search and get-all hide them by default; pass `show_expired: true` to include them.
</Info>
<Info>
Python uses `expiration_date`; TypeScript uses `expirationDate`.
</Info>
@@ -6,6 +6,10 @@ openapi: post /v3/memories/
List memories scoped by filters with paginated results. Entity IDs (`user_id`, `agent_id`, `app_id`, `run_id`) **must** be passed inside the `filters` object — top-level entity IDs are rejected with 400.
Expired memories are hidden by default. Pass `show_expired: true` to include memories whose `expiration_date` has passed.
Python uses `show_expired`; TypeScript uses `showExpired`.
The `filters` object supports complex logical operations (AND, OR, NOT) and comparison operators:
- `in`: Matches any of the values specified
@@ -32,6 +36,7 @@ memories = client.get_all(
}
]
},
show_expired=False,
page=1,
page_size=50
)
@@ -46,12 +51,14 @@ memories = client.get_all(
{
"id": "f4cbdb08-7062-4f3e-8eb2-9f5c80dfe64c",
"memory": "Alex is planning a trip to San Francisco from July 1st to July 10th",
"expiration_date": null,
"created_at": "2024-07-01T12:00:00Z",
"updated_at": "2024-07-01T12:00:00Z"
},
{
"id": "a2b8c3d4-5e6f-7g8h-9i0j-1k2l3m4n5o6p",
"memory": "Alex prefers vegetarian restaurants",
"expiration_date": null,
"created_at": "2024-07-05T15:30:00Z",
"updated_at": "2024-07-05T15:30:00Z"
}
@@ -8,6 +8,10 @@ Relevance-ranked hybrid search across stored memories. V3 uses multi-signal retr
Entity IDs (`user_id`, `agent_id`, `app_id`, `run_id`) **must** be passed inside the `filters` object — top-level entity IDs are rejected with 400. At least one entity ID is required.
Expired memories are hidden by default. Pass `show_expired: true` to include memories whose `expiration_date` has passed.
Python uses `show_expired`; TypeScript uses `showExpired`.
The `filters` object supports complex logical operations (AND, OR, NOT) and comparison operators:
- `in`: Matches any of the values specified
- `gte`: Greater than or equal to
@@ -30,6 +34,7 @@ The `filters` object supports complex logical operations (AND, OR, NOT) and comp
```python Platform API Example
related_memories = client.search(
query="What are Alice's hobbies?",
show_expired=False,
filters={
"OR": [
{
@@ -54,6 +59,7 @@ related_memories = client.search(
"category": "hobbies"
},
"score": 0.82,
"expiration_date": null,
"created_at": "2024-07-26T10:29:36.630547-07:00",
"updated_at": null,
"categories": ["hobbies"]
+11 -2
View File
@@ -1,5 +1,14 @@
---
title: 'Update Memory'
description: "Update the content or metadata of a single memory by its unique ID using the PUT endpoint."
description: "Update the content, metadata, timestamp, or expiration date of a single memory by its unique ID using the PUT endpoint."
openapi: put /v1/memories/{memory_id}/
---
---
Use this endpoint to update mutable memory fields. To make a memory expire, set `expiration_date` to a `YYYY-MM-DD` date. To make it permanent again, send `expiration_date: null`.
```python
client.update("mem_123", expiration_date="2030-01-31")
client.update("mem_123", expiration_date=None)
```
TypeScript uses `expirationDate`.
@@ -0,0 +1,5 @@
---
title: "Remove Organization Member"
description: "Remove a member from a Mem0 organization by revoking their access and clearing their assigned role."
openapi: "delete /api/v1/orgs/organizations/{org_id}/members/"
---
@@ -0,0 +1,5 @@
---
title: "Update Organization Member"
description: "Update the role assigned to an existing member of a Mem0 organization to change their permissions."
openapi: "put /api/v1/orgs/organizations/{org_id}/members/"
---
@@ -0,0 +1,5 @@
---
title: "Remove Project Member"
description: "Remove a member from a Mem0 project to revoke their access and unassign their project-level role."
openapi: "delete /api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/"
---
@@ -0,0 +1,5 @@
---
title: "Update Project Member"
description: "Update the role assigned to an existing member of a Mem0 project to change their project-level permissions."
openapi: "put /api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/"
---
@@ -0,0 +1,5 @@
---
title: "Update Project"
description: "Update settings and configuration for an existing Mem0 project, including name and project-level options."
openapi: "patch /api/v1/orgs/organizations/{org_id}/projects/{project_id}/"
---
+2 -2
View File
@@ -46,9 +46,9 @@ Ground-up rewrite of the memory pipeline with 20+ point benchmark improvements:
- **~3-4x fewer tokens** — Under 7K tokens per retrieval vs 25K+ for full-context approaches
- **ADD-only extraction** — Memories accumulate; nothing is overwritten or deleted
- **Hybrid retrieval** — Semantic + BM25 keyword + entity boost, scored in parallel
- **Entity linking** — Entities extracted, embedded, and linked across memories
- **Graph memory (built-in)**: entities extracted, embedded, and linked across memories, with no external graph store required
Breaking changes: Graph memory removed from OSS, `search()` defaults changed, deprecated params removed. See [migration guide](/migration/oss-v2-to-v3).
Breaking changes: external graph stores removed from OSS (replaced by built-in graph memory), `search()` defaults changed, deprecated params removed. See [migration guide](/migration/oss-v2-to-v3).
</Update>
+33
View File
@@ -4,6 +4,39 @@ description: "Release notes for the OpenClaw plugin and agent harness."
mode: "wide"
---
<Update label="2026-06-12" description="v1.0.13">
**Fixes:**
- **Custom categories payload:** `customCategories` (a `Record<string, string>` map) is now converted via the new `customCategoryMapToList()` helper into the `Array<Record<string, string>>` shape the Mem0 SDK expects on `add` calls — previously the raw object was passed as `custom_categories` and silently ignored ([#5345](https://github.com/mem0ai/mem0/pull/5345))
- **Skip runtime setup during metadata registration:** `register()` now detects `registrationMode === "cli-metadata"`, registers only the CLI commands, and returns early — avoiding backend initialization, service/tool registration, and hook installation during OpenClaw's metadata-only registration pass ([#5383](https://github.com/mem0ai/mem0/pull/5383))
**Security:**
- Bumped `mem0ai` from `3.0.3` to `3.0.7` (latest Node SDK) — includes the transitive axios CVE remediation shipped in `3.0.6` ([#5460](https://github.com/mem0ai/mem0/pull/5460))
- Added pnpm override `uuid@<11.1.1` → `>=11.1.1` to resolve an open MEDIUM Dependabot alert ([#5489](https://github.com/mem0ai/mem0/pull/5489))
**Improvements:**
- **Repo consolidation:** Plugin moved from repo-root `openclaw/` to `integrations/openclaw/`; `package.json` `repository.directory` updated to match so npm provenance links to the correct subdirectory ([#5491](https://github.com/mem0ai/mem0/pull/5491))
**Tests:**
- Added `customCategoryMapToList` unit tests and a `PlatformProvider` test asserting `custom_categories` is passed to the Mem0 SDK as a list ([#5345](https://github.com/mem0ai/mem0/pull/5345))
- Added a regression test asserting `cli-metadata` registration registers only CLI commands and triggers no runtime side effects ([#5383](https://github.com/mem0ai/mem0/pull/5383))
</Update>
<Update label="2026-06-02" description="v1.0.12">
**Docs:**
- **Agent Mode onboarding:** README now documents an autonomous setup path for AI agents — `mem0 init --agent --json` mints an evaluation Mem0 API key with no email, OTP, or browser and exports it as `MEM0_API_KEY` for `openclaw mem0 init`; a human owner can later run `mem0 init --email <email>` to claim ownership without disrupting the agent ([#5123](https://github.com/mem0ai/mem0/pull/5123))
**Security:**
- Added pnpm overrides to remediate advisories in transitive dependencies: `langsmith@<0.6.0` → `^0.6.0`, `picomatch@<2.3.2` → `^2.3.2`, `vite` → `^8.0.5`, and `@qdrant/js-client-rest` → `^1.18.0` ([#5294](https://github.com/mem0ai/mem0/pull/5294))
**Dependencies:**
- Bumped `mem0ai` from `3.0.2` to `3.0.3` ([#5212](https://github.com/mem0ai/mem0/pull/5212))
- Bumped dev dependencies `@vitest/coverage-v8` and `vitest` from `^4.0.18` to `^4.1.7`; added `vite@^8.0.5` and `@qdrant/js-client-rest@^1.18.0` ([#5294](https://github.com/mem0ai/mem0/pull/5294))
</Update>
<Update label="2026-04-29" description="v1.0.11">
**New Features:**
+1 -1
View File
@@ -25,7 +25,7 @@ mode: "wide"
<Update label="2026-04-16" description="">
**Improvements:**
- **UI:** Removed Graph Memory tab, page, and all references from dashboard, sidebar, project settings, playground, and billing
- **UI:** Removed the legacy external-graph-store visualization tab, page, and its references from dashboard, sidebar, project settings, playground, and billing
</Update>
+161 -3
View File
@@ -7,6 +7,116 @@ mode: "wide"
<Tabs>
<Tab title="Python">
<Update label="2026-06-24" description="v2.0.9">
**Bug Fixes:**
- **Memory (OSS):** Improve entity extraction precision by avoiding sentence-start common noun noise, preserving useful topic phrases, and exact-deduplicating entity links before semantic matching ([#5829](https://github.com/mem0ai/mem0/pull/5829))
</Update>
<Update label="2026-06-24" description="v2.0.8">
**New Features:**
- **Embeddings:** Add native `embed_batch` to five embedders — LM Studio, Together, HuggingFace, Vertex AI, and Google GenAI — for batched embedding requests ([#5609](https://github.com/mem0ai/mem0/pull/5609))
**Bug Fixes:**
- **Core:** Guard against malformed `image_url` entries in `parse_vision_messages` to prevent crashes ([#5631](https://github.com/mem0ai/mem0/pull/5631))
- **Core:** Return `attributed_to` from `get()`, `get_all()`, and `search()` ([#5629](https://github.com/mem0ai/mem0/pull/5629))
- **Core:** Fix `reset()` only dropping the history table and leaving stale messages behind ([#5541](https://github.com/mem0ai/mem0/pull/5541))
- **Core:** Guard against an entity `embed_batch` count mismatch in the v3 add pipeline ([#5604](https://github.com/mem0ai/mem0/pull/5604))
- **Core:** Fix an async `delete_all` race condition that corrupted the entity store's `linked_memory_ids` ([#5553](https://github.com/mem0ai/mem0/pull/5553))
- **LLMs:** Skip the JSON `response_format` for Groq compound models that reject it ([#5513](https://github.com/mem0ai/mem0/pull/5513))
- **LLMs:** Preserve reasoning fields during base-to-provider config conversion ([#5638](https://github.com/mem0ai/mem0/pull/5638))
- **LLMs:** Pass the configured `anthropic_base_url` to the Anthropic client ([#5626](https://github.com/mem0ai/mem0/pull/5626))
- **LLMs:** Stop the Azure provider from mutating and corrupting caller messages during content rewrite ([#5731](https://github.com/mem0ai/mem0/pull/5731))
- **LLMs & Embeddings:** Repair HTTP proxy support for `httpx>=0.28` and preserve `proxies` in `LlmFactory` ([#5447](https://github.com/mem0ai/mem0/pull/5447))
- **Embeddings:** Forward `embedding_dims` to Titan V2 in the AWS Bedrock embedder ([#5671](https://github.com/mem0ai/mem0/pull/5671))
- **Rerankers:** Log reranking failures instead of swallowing them silently ([#5717](https://github.com/mem0ai/mem0/pull/5717))
- **Rerankers:** Clamp out-of-range LLM scores instead of mis-parsing them ([#5635](https://github.com/mem0ai/mem0/pull/5635))
- **Rerankers:** Export all five rerankers from the package root ([#5636](https://github.com/mem0ai/mem0/pull/5636))
- **Vector Stores:** Point the FastEmbed-missing warning at `mem0ai[extras]` ([#5622](https://github.com/mem0ai/mem0/pull/5622))
- **Vector Stores:** Preserve empty Azure AI Search update values ([#5524](https://github.com/mem0ai/mem0/pull/5524))
- **Vector Stores:** Add an `auto_refresh` option for OpenSearch Serverless compatibility ([#3893](https://github.com/mem0ai/mem0/pull/3893))
- **Vector Stores:** Wrap a scalar `vector_id` in a list for Chroma `delete()` ([#5703](https://github.com/mem0ai/mem0/pull/5703))
- **Vector Stores:** Wrap Chroma `update()` ids, embeddings, and metadatas in lists ([#5757](https://github.com/mem0ai/mem0/pull/5757))
- **Vector Stores:** Wrap a scalar `vector_id` in a list for Milvus `delete()` ([#5704](https://github.com/mem0ai/mem0/pull/5704))
- **Vector Stores:** Map all comparison operators in the Pinecone `_create_filter()` ([#5707](https://github.com/mem0ai/mem0/pull/5707))
- **Vector Stores:** Return `None` instead of `{}` from Chroma `_generate_where_clause` for empty filters ([#5713](https://github.com/mem0ai/mem0/pull/5713))
- **Vector Stores:** Return `[[]]` from the OpenSearch `list()` error path to honor the `list()` contract ([#5727](https://github.com/mem0ai/mem0/pull/5727))
- **Vector Stores:** Return `[[]]` from the Pinecone `list()` error path instead of a dict ([#5706](https://github.com/mem0ai/mem0/pull/5706))
- **Vector Stores:** Return `[[]]` for an uninitialized FAISS index to honor the `list()` contract ([#5725](https://github.com/mem0ai/mem0/pull/5725))
- **Vector Stores:** Wrap the MongoDB `list()` return in an outer list to match the interface contract ([#5729](https://github.com/mem0ai/mem0/pull/5729))
- **Vector Stores:** Deep-copy Redis `DEFAULT_FIELDS` so instances keep distinct dims ([#5633](https://github.com/mem0ai/mem0/pull/5633))
- **Vector Stores:** Pass the required `vectors` arg in Vertex AI `list()` and similarity search ([#5627](https://github.com/mem0ai/mem0/pull/5627))
- **Vector Stores:** Return `None` from Redis `get()` for missing IDs ([#5625](https://github.com/mem0ai/mem0/pull/5625))
- **Vector Stores:** Drop a stray `print` in Weaviate `list_cols` ([#5637](https://github.com/mem0ai/mem0/pull/5637))
- **Graph:** Keep distinct entities that share a substring prefix ([#5630](https://github.com/mem0ai/mem0/pull/5630))
- **Client:** Check the HTTP status before parsing the ping response in `_validate_api_key` ([#5639](https://github.com/mem0ai/mem0/pull/5639))
- **Server:** Fetch filtered dashboard memories beyond the default page ([#5753](https://github.com/mem0ai/mem0/pull/5753))
- **Server:** Return 404/400 instead of 502 for not-found and invalid input ([#5634](https://github.com/mem0ai/mem0/pull/5634))
- **Server:** Return 404 instead of 500 for a malformed API key id on revoke ([#5640](https://github.com/mem0ai/mem0/pull/5640))
- **Server:** Use `127.0.0.1` in the dashboard healthcheck to avoid IPv6 localhost resolution ([#5612](https://github.com/mem0ai/mem0/pull/5612))
**Improvements:**
- **Vector Stores:** Batch BM25 sparse encoding in Qdrant insert ([#5592](https://github.com/mem0ai/mem0/pull/5592))
**Security:**
- **Vector Stores:** Sanitize Milvus and Baidu filter values to prevent expression injection ([#5746](https://github.com/mem0ai/mem0/pull/5746))
- **Vector Stores:** Reject dict filter values in MongoDB to prevent NoSQL operator injection ([#5748](https://github.com/mem0ai/mem0/pull/5748))
</Update>
<Update label="2026-06-17" description="v2.0.7">
**New Features:**
- **LLMs:** Add Gemini via Vertex AI as LLM provider ([#4030](https://github.com/mem0ai/mem0/pull/4030))
- **Embeddings:** Add native `embed_batch` to `OllamaEmbedding` for batched embedding requests ([#5415](https://github.com/mem0ai/mem0/pull/5415))
**Bug Fixes:**
- **Core:** Fix `api_error_handler` silently dropping return values from async methods ([#5540](https://github.com/mem0ai/mem0/pull/5540))
- **Core:** Fix `AsyncMemory.reset()` not resetting the entity store ([#5535](https://github.com/mem0ai/mem0/pull/5535))
- **Core:** Fix `async delete_all` aborting on first error, leaving partial deletion ([#5529](https://github.com/mem0ai/mem0/pull/5529))
- **Core:** Skip messages without a `content` key in message parsers to prevent `KeyError` crashes ([#5575](https://github.com/mem0ai/mem0/pull/5575))
- **Core:** Preserve custom metadata fields during memory update ([#5480](https://github.com/mem0ai/mem0/pull/5480))
- **LLMs:** Fix Anthropic `tool_choice` format and tool response parsing ([#5537](https://github.com/mem0ai/mem0/pull/5537))
- **LLMs:** Fix Ollama `json` format mutating the caller's messages list in-place ([#5539](https://github.com/mem0ai/mem0/pull/5539))
- **LLMs:** Omit `None` config values from Gemini `GenerateContentConfig` to prevent validation errors ([#5528](https://github.com/mem0ai/mem0/pull/5528))
- **LLMs:** Honor reasoning-model params in `AzureOpenAIStructuredLLM` ([#5548](https://github.com/mem0ai/mem0/pull/5548))
- **LLMs:** Honor reasoning-model params in `OpenAIStructuredLLM` ([#5458](https://github.com/mem0ai/mem0/pull/5458))
- **LLMs:** Send `max_completion_tokens` for the GPT-5 family across all providers ([#5547](https://github.com/mem0ai/mem0/pull/5547))
- **LLMs:** Accept and forward `**kwargs` in Together, LangChain, and Sarvam providers ([#5556](https://github.com/mem0ai/mem0/pull/5556))
- **LLMs:** Fix Bedrock AI21 response parse default using `dict` literal instead of `set` ([#5527](https://github.com/mem0ai/mem0/pull/5527))
- **LLMs:** Fix LiteLLM function-calling check blocking all calls on non-tool models ([#5536](https://github.com/mem0ai/mem0/pull/5536))
- **LLMs:** Fix HuggingFace provider using `self.config` instead of raw `config` parameter ([#5538](https://github.com/mem0ai/mem0/pull/5538))
- **Embeddings:** Honor `aws_session_token` in AWS Bedrock embeddings ([#5566](https://github.com/mem0ai/mem0/pull/5566))
- **Rerankers:** Respect `config.top_k` in Cohere and ZeroEntropy fallback paths ([#5560](https://github.com/mem0ai/mem0/pull/5560))
- **Vector Stores:** Fix FAISS filtered search dropping over-fetched candidates before filtering ([#5453](https://github.com/mem0ai/mem0/pull/5453))
- **Vector Stores:** Fix Weaviate `reset()` crashing with missing `vector_size` argument ([#5531](https://github.com/mem0ai/mem0/pull/5531))
- **Vector Stores:** Pass embedding dims in Weaviate `reset()` to avoid re-init crash ([#5570](https://github.com/mem0ai/mem0/pull/5570))
- **Vector Stores:** Fix MongoDB `reset()` passing wrong argument to `create_col()` ([#5532](https://github.com/mem0ai/mem0/pull/5532))
- **Vector Stores:** Fix Pinecone hybrid search crashing when `filters` is `None` ([#5533](https://github.com/mem0ai/mem0/pull/5533))
- **Vector Stores:** Fix Redis crashing on empty or `None` filters in `search()` and `list()` ([#5446](https://github.com/mem0ai/mem0/pull/5446))
- **Vector Stores:** Return `None` from `get()` for missing IDs in Milvus, Weaviate, and Supabase ([#5562](https://github.com/mem0ai/mem0/pull/5562))
- **Vector Stores:** Return `None` from ChromaDB `get()` for missing IDs ([#5561](https://github.com/mem0ai/mem0/pull/5561))
</Update>
<Update label="2026-06-13" description="v2.0.6">
**New Features:**
- **Memory:** Add a contextual OSS-to-Platform notices system that surfaces occasional, situation-aware messages (first run, scale/performance thresholds, slow queries, and when temporal/decay features are relevant) pointing to the corresponding Mem0 Platform capabilities; disable via `MEM0_TELEMETRY=false` ([#5494](https://github.com/mem0ai/mem0/pull/5494))
**Bug Fixes:**
- **Memory:** Prevent a crash in `parse_vision_messages` when vision support is disabled ([#5487](https://github.com/mem0ai/mem0/pull/5487))
- **Vector Stores:** Expose the `https` option on the Qdrant vector store configuration so TLS endpoints can be targeted explicitly ([#5380](https://github.com/mem0ai/mem0/pull/5380))
- **Vector Stores:** Use valid S3 Vectors entity index names, fixing index operations that failed on invalid names ([#5416](https://github.com/mem0ai/mem0/pull/5416))
- **Vector Stores:** Fix `search()` crashing with a `TypeError` in the LangChain vector store when a result score is `None` ([#5072](https://github.com/mem0ai/mem0/pull/5072))
- **Vector Stores:** Use `is not None` instead of a truthiness check for vector/payload in the PGVector `update()` path, so valid empty/zero values are no longer skipped ([#5488](https://github.com/mem0ai/mem0/pull/5488))
- **Vector Stores:** Index the Valkey `memory` field as `TEXT` rather than `TAG` so full-text search behaves correctly ([#5443](https://github.com/mem0ai/mem0/pull/5443))
- **Vector Stores:** Implement `$not` filter support in the ChromaDB vector store ([#5485](https://github.com/mem0ai/mem0/pull/5485))
</Update>
<Update label="2026-06-10" description="v2.0.5">
**New Features:**
@@ -98,8 +208,8 @@ mode: "wide"
- **`messages` in `Memory.add()` rejects invalid types:** Passing `None` or non-`(str | dict | list)` values raises `Mem0ValidationError` (`error_code="VALIDATION_003"`) ([#4843](https://github.com/mem0ai/mem0/pull/4843))
- **`qdrant-client>=1.12.0` required** — Upgrade from `>=1.9.1` ([#4805](https://github.com/mem0ai/mem0/pull/4805))
- **`org_id` and `project_id` removed** — Removed from `MemoryClient` constructor and all method signatures ([#4740](https://github.com/mem0ai/mem0/pull/4740))
- **Graph Memory Removed (OSS):** `mem0/memory/graph_memory.py`, `memgraph_memory.py`, `kuzu_memory.py`, `apache_age_memory.py`, and `mem0/graphs/` (Neo4j / Memgraph / Kuzu / Apache AGE / Neptune drivers) deleted — ~4,000 lines. Graph memory is no longer supported in the OSS SDK; graph drivers (neo4j, memgraph, kuzu, etc.) can be uninstalled. Use the Platform API for graph features. Remove `enable_graph` and `graph_store` from your config ([#4805](https://github.com/mem0ai/mem0/pull/4805))
- **`enable_graph` removed from Client SDK** — Graph memory is now a project-level setting on the Platform. Remove `enable_graph` from `MemoryClient.add()` / `search()` / `get_all()` / `update_project()` calls ([#4776](https://github.com/mem0ai/mem0/pull/4776))
- **External Graph Store Removed (OSS):** `mem0/memory/graph_memory.py`, `memgraph_memory.py`, `kuzu_memory.py`, `apache_age_memory.py`, and `mem0/graphs/` (Neo4j / Memgraph / Kuzu / Apache AGE / Neptune drivers) deleted, about 4,000 lines. The external graph store integration is no longer part of the OSS SDK; graph drivers (neo4j, memgraph, kuzu, etc.) can be uninstalled. Graph memory now runs natively as built-in entity linking. Remove `enable_graph` and `graph_store` from your config ([#4805](https://github.com/mem0ai/mem0/pull/4805))
- **`enable_graph` removed from Client SDK:** Graph memory now runs automatically and no longer needs a flag. Remove `enable_graph` from `MemoryClient.add()` / `search()` / `get_all()` / `update_project()` calls ([#4776](https://github.com/mem0ai/mem0/pull/4776))
- **`custom_fact_extraction_prompt` renamed to `custom_instructions`** — Update config and memory module references ([#4740](https://github.com/mem0ai/mem0/pull/4740))
- **Typed option classes** — Added Pydantic v2 typed classes: `AddMemoryOptions`, `SearchMemoryOptions`, `GetAllMemoryOptions`, `DeleteAllMemoryOptions`, `UpdateMemoryOptions`, `ProjectUpdateOptions` ([#4740](https://github.com/mem0ai/mem0/pull/4740))
@@ -960,6 +1070,54 @@ See the [OSS v1 to v2 migration guide](https://docs.mem0.ai/migration/oss-v1-to-
<Tab title="TypeScript">
<Update label="2026-06-24" description="v3.0.11">
**Bug Fixes:**
- **Memory (OSS):** Align entity extraction with Python by reducing generic entity noise, preserving useful topic phrases, and exact-deduplicating entity links before semantic matching ([#5829](https://github.com/mem0ai/mem0/pull/5829))
</Update>
<Update label="2026-06-24" description="v3.0.10">
**Bug Fixes:**
- **Memory (OSS):** Guard against malformed `image_url` entries in `parseVisionMessages` to prevent crashes ([#5631](https://github.com/mem0ai/mem0/pull/5631))
- **Memory (OSS):** Return `attributedTo` from `get()`, `search()`, and `getAll()` ([#5675](https://github.com/mem0ai/mem0/pull/5675))
- **Memory (OSS):** Preserve message roles in the extraction input so assistant facts aren't attributed to the user ([#5643](https://github.com/mem0ai/mem0/pull/5643))
- **Memory (OSS):** Reject empty or blank messages in `Memory.add()` to prevent hallucinated memories ([#5545](https://github.com/mem0ai/mem0/pull/5545))
- **Memory (OSS):** Check `message.role` instead of `content` when detecting system messages ([#3921](https://github.com/mem0ai/mem0/pull/3921))
- **LLMs:** Honor the configured `baseURL` in `AnthropicLLM` ([#5740](https://github.com/mem0ai/mem0/pull/5740))
- **Client:** Preserve `customCategories` names through key conversion ([#5741](https://github.com/mem0ai/mem0/pull/5741))
- **Client:** Prevent hallucinated memories on an empty messages payload ([#5613](https://github.com/mem0ai/mem0/pull/5613))
- **Client:** Preserve user metadata keys across the case-conversion round-trip ([#5515](https://github.com/mem0ai/mem0/pull/5515))
**Security:**
- **Dependencies:** Upgrade `form-data` to `>=4.0.6` across pnpm workspaces to remediate CVE-2026-12143 ([#5618](https://github.com/mem0ai/mem0/pull/5618))
</Update>
<Update label="2026-06-17" description="v3.0.9">
**Bug Fixes:**
- **LLMs:** Fix Anthropic `tool_choice` format — was incorrectly sent as a bare string `"auto"` (rejected by the API); now correctly sent as `{ type: "auto" }`. Also fixes tool response parsing: `tool_use` blocks are now parsed into `toolCalls` objects instead of throwing. Updated default model to `claude-sonnet-4-6` and default `max_tokens` to `2000` to match the Python provider. Added `temperature`, `topP`, and `maxTokens` to `LLMConfig` so Anthropic params can be configured ([#5537](https://github.com/mem0ai/mem0/pull/5537))
- **Memory (OSS):** Preserve custom metadata fields during `update()` — fields such as `category`, `priority`, and other user-defined keys were previously dropped on update; the existing payload is now spread before applying the new data ([#5480](https://github.com/mem0ai/mem0/pull/5480))
- **Client:** Preserve user-defined schema keys in `createMemoryExport` ([#5594](https://github.com/mem0ai/mem0/pull/5594))
**Security:**
- **Dependencies:** Bump `esbuild` to `>=0.28.1` across all npm packages via pnpm overrides to remediate upstream vulnerability ([#5563](https://github.com/mem0ai/mem0/pull/5563))
</Update>
<Update label="2026-06-13" description="v3.0.8">
**New Features:**
- **Memory:** Add a contextual OSS-to-Platform notices system that surfaces occasional, situation-aware messages (first run, scale/performance thresholds, slow queries, and when temporal/decay features are relevant) pointing to the corresponding Mem0 Platform capabilities; disable via `MEM0_TELEMETRY=false` ([#5494](https://github.com/mem0ai/mem0/pull/5494))
**Security:**
- **Dependencies:** Upgrade `@langchain/community` to `^1.1.18` to remediate CVE-2026-27795 and CVE-2026-26019 ([#5510](https://github.com/mem0ai/mem0/pull/5510))
- **Dependencies:** Resolve all open MEDIUM Dependabot alerts via pnpm overrides ([#5489](https://github.com/mem0ai/mem0/pull/5489))
</Update>
<Update label="2026-06-10" description="v3.0.7">
**New Features:**
@@ -1039,7 +1197,7 @@ See the [OSS v1 to v2 migration guide](https://docs.mem0.ai/migration/oss-v1-to-
- **Default model:** `gpt-5-mini` is now the default in `OpenAI`, `OpenAIStructured`, and `Azure` LLM providers ([#4829](https://github.com/mem0ai/mem0/pull/4829))
**Breaking Changes:**
- **Graph Memory Removed (OSS):** `graph_memory.ts` (675 lines), `graphs/tools.ts` (267 lines), `graphs/utils.ts` (116 lines), `graphs/configs.ts` (30 lines) deleted. Graph memory is no longer supported in the OSS SDK — use Platform API for graph features ([#4805](https://github.com/mem0ai/mem0/pull/4805))
- **External Graph Store Removed (OSS):** `graph_memory.ts` (675 lines), `graphs/tools.ts` (267 lines), `graphs/utils.ts` (116 lines), `graphs/configs.ts` (30 lines) deleted. The external graph store integration is no longer part of the OSS SDK; graph memory now runs natively as built-in entity linking ([#4805](https://github.com/mem0ai/mem0/pull/4805))
- **camelCase Parameters (Client SDK):** All user-facing parameters converted from snake_case to camelCase. Mapping is transparent at API boundary via `camelToSnakeKeys()` / `snakeToCamelKeys()` ([#4776](https://github.com/mem0ai/mem0/pull/4776))
```typescript
// Before
@@ -0,0 +1,50 @@
---
title: "FastEmbed"
description: "Configure FastEmbed as an embedding provider in Mem0 to generate embeddings locally using ONNX-based models without a GPU."
---
You can use FastEmbed to run embedding models locally in Mem0. FastEmbed is an ONNX-based embedding library that runs efficiently on CPU without requiring a GPU or an external API key.
### Installation
```bash
pip install fastembed
```
### Usage
<CodeGroup>
```python Python
import os
from mem0 import Memory
os.environ["OPENAI_API_KEY"] = "your_api_key" # For LLM
config = {
"embedder": {
"provider": "fastembed",
"config": {
"model": "thenlper/gte-large"
}
}
}
m = Memory.from_config(config)
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."}
]
m.add(messages, user_id="john")
```
</CodeGroup>
### Config
Here are the parameters available for configuring FastEmbed embedder:
| Parameter | Description | Default Value |
| --- | --- | --- |
| `model` | The name of the FastEmbed model to use | `thenlper/gte-large` |
| `embedding_dims` | Dimensions of the embedding model (auto-derived from the model if not set) | `None` |
+28 -1
View File
@@ -7,7 +7,8 @@ To use DeepSeek LLM models, you have to set the `DEEPSEEK_API_KEY` environment v
## Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -36,6 +37,32 @@ messages = [
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'deepseek',
config: {
apiKey: process.env.DEEPSEEK_API_KEY || '',
model: 'deepseek-chat',
temperature: 0.2,
maxTokens: 2000,
top_p: 1.0,
},
},
};
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>
You can also configure the API base URL in the config:
```python
+31 -1
View File
@@ -4,9 +4,12 @@ description: "Use LiteLLM as an LLM provider in Mem0 to access over 100 language
---
[Litellm](https://litellm.vercel.app/docs/) is compatible with over 100 large language models (LLMs), all using a standardized input/output format. You can explore the [available models](https://litellm.vercel.app/docs/providers) to use with Litellm. Ensure you set the `API_KEY` for the model you choose to use.
In the TypeScript SDK, run LiteLLM as a [proxy server](https://docs.litellm.ai/docs/simple_proxy) (an OpenAI-compatible endpoint) and point Mem0 at it via `LITELLM_API_BASE` (defaults to `http://localhost:4000`).
## Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -33,6 +36,33 @@ messages = [
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
// Point Mem0 at your LiteLLM proxy. apiKey defaults to "sk-anything"
// (the proxy handles real auth); baseURL defaults to http://localhost:4000.
const config = {
llm: {
provider: 'litellm',
config: {
apiKey: process.env.LITELLM_API_KEY || 'sk-anything',
baseURL: process.env.LITELLM_API_BASE || 'http://localhost:4000',
model: 'gpt-5-mini',
},
},
};
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>
## Config
All available parameters for the `litellm` config are present in [Master List of All Params in Config](../config).
+45 -2
View File
@@ -7,7 +7,8 @@ To use MiniMax LLM models, you have to set the `MINIMAX_API_KEY` environment var
## Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -36,9 +37,37 @@ messages = [
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'minimax',
config: {
apiKey: process.env.MINIMAX_API_KEY || '',
model: 'MiniMax-M2.7',
temperature: 0.2,
maxTokens: 2000,
topP: 1.0,
},
},
};
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>
You can also configure the API base URL in the config:
```python
<CodeGroup>
```python Python
config = {
"llm": {
"provider": "minimax",
@@ -51,6 +80,20 @@ config = {
}
```
```typescript TypeScript
const config = {
llm: {
provider: 'minimax',
config: {
model: 'MiniMax-M2.7',
baseURL: 'https://your-custom-endpoint.com',
apiKey: 'your-api-key', // alternatively to using the environment variable
},
},
};
```
</CodeGroup>
## Config
All available parameters for the `minimax` config are present in [Master List of All Params in Config](../config).
-226
View File
@@ -1,226 +0,0 @@
---
title: LLM as Reranker
description: "Use any LLM as a flexible reranker in Mem0 with custom prompts and domain-specific scoring logic."
---
<Warning>
**This page has been superseded.** Please see [LLM Reranker](/components/rerankers/models/llm_reranker) for the complete and up-to-date documentation on using LLMs for reranking.
</Warning>
LLM-based reranker provides maximum flexibility by using any Large Language Model to score document relevance. This approach allows for custom prompts and domain-specific scoring logic.
## Supported LLM Providers
Any LLM provider supported by Mem0 can be used for reranking:
- **OpenAI**: GPT-4, GPT-3.5-turbo, etc.
- **Anthropic**: Claude models
- **Together**: Open-source models
- **Groq**: Fast inference
- **Ollama**: Local models
- And more...
## Configuration
```python Python
from mem0 import Memory
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "my_memories",
"path": "./chroma_db"
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini"
}
},
"reranker": {
"provider": "llm",
"config": {
"model": "gpt-4o-mini",
"provider": "openai",
"api_key": "your-openai-api-key", # or set OPENAI_API_KEY
"top_k": 5,
"temperature": 0.0
}
}
}
memory = Memory.from_config(config)
```
## Custom Scoring Prompt
You can provide a custom prompt for relevance scoring:
```python Python
custom_prompt = """You are a relevance scoring assistant. Rate how well this document answers the query.
Query: "{query}"
Document: "{document}"
Score from 0.0 to 1.0 where:
- 1.0: Perfect match, directly answers the query
- 0.8-0.9: Highly relevant, good match
- 0.6-0.7: Moderately relevant, partial match
- 0.4-0.5: Slightly relevant, limited useful information
- 0.0-0.3: Not relevant or no useful information
Provide only a single numerical score between 0.0 and 1.0."""
config["reranker"]["config"]["scoring_prompt"] = custom_prompt
```
## Usage Example
```python Python
import os
from mem0 import Memory
# Set API key
os.environ["OPENAI_API_KEY"] = "your-api-key"
# Initialize memory with LLM reranker
config = {
"vector_store": {"provider": "chroma"},
"llm": {"provider": "openai", "config": {"model": "gpt-4o-mini"}},
"reranker": {
"provider": "llm",
"config": {
"model": "gpt-4o-mini",
"provider": "openai",
"temperature": 0.0
}
}
}
memory = Memory.from_config(config)
# Add memories
messages = [
{"role": "user", "content": "I'm learning Python programming"},
{"role": "user", "content": "I find object-oriented programming challenging"},
{"role": "user", "content": "I love hiking in national parks"}
]
memory.add(messages, user_id="david")
# Search with LLM reranking
results = memory.search("What programming topics is the user studying?", filters={"user_id": "david"})
for result in results['results']:
print(f"Memory: {result['memory']}")
print(f"Vector Score: {result['score']:.3f}")
print(f"Rerank Score: {result['rerank_score']:.3f}")
print()
```
```text Output
Memory: I'm learning Python programming
Vector Score: 0.856
Rerank Score: 0.920
Memory: I find object-oriented programming challenging
Vector Score: 0.782
Rerank Score: 0.850
```
## Domain-Specific Scoring
Create specialized scoring for your domain:
```python Python
medical_prompt = """You are a medical relevance expert. Score how relevant this medical record is to the clinical query.
Clinical Query: "{query}"
Medical Record: "{document}"
Consider:
- Clinical relevance and accuracy
- Patient safety implications
- Diagnostic value
- Treatment relevance
Score from 0.0 to 1.0. Provide only the numerical score."""
config = {
"reranker": {
"provider": "llm",
"config": {
"model": "gpt-4o-mini",
"provider": "openai",
"scoring_prompt": medical_prompt,
"temperature": 0.0
}
}
}
```
## Multiple LLM Providers
Use different LLM providers for reranking:
```python Python
# Using Anthropic Claude
anthropic_config = {
"reranker": {
"provider": "llm",
"config": {
"model": "claude-3-haiku-20240307",
"provider": "anthropic",
"temperature": 0.0
}
}
}
# Using local Ollama model
ollama_config = {
"reranker": {
"provider": "llm",
"config": {
"model": "llama2:7b",
"provider": "ollama",
"temperature": 0.0
}
}
}
```
## Configuration Parameters
| Parameter | Description | Type | Default |
|-----------|-------------|------|---------|
| `model` | LLM model to use for scoring | `str` | `"gpt-4o-mini"` |
| `provider` | LLM provider name | `str` | `"openai"` |
| `api_key` | API key for the LLM provider | `str` | `None` |
| `top_k` | Maximum documents to return | `int` | `None` |
| `temperature` | Temperature for LLM generation | `float` | `0.0` |
| `max_tokens` | Maximum tokens for LLM response | `int` | `100` |
| `scoring_prompt` | Custom prompt template | `str` | Default prompt |
## Advantages
- **Maximum Flexibility**: Custom prompts for any use case
- **Domain Expertise**: Leverage LLM knowledge for specialized domains
- **Interpretability**: Understand scoring through prompt engineering
- **Multi-criteria**: Score based on multiple relevance factors
## Considerations
- **Latency**: Higher latency than specialized rerankers
- **Cost**: LLM API costs per reranking operation
- **Consistency**: May have slight variations in scoring
- **Prompt Engineering**: Requires careful prompt design
## Best Practices
1. **Temperature**: Use 0.0 for consistent scoring
2. **Prompt Design**: Be specific about scoring criteria
3. **Token Efficiency**: Keep prompts concise to reduce costs
4. **Caching**: Cache results for repeated queries when possible
5. **Fallback**: Handle API errors gracefully
+35 -37
View File
@@ -21,49 +21,47 @@ from mem0 import Memory
load_dotenv()
config = {
"vector_store": {
"provider": "pgvector",
"config": {
"connection_string": os.environ["DATABASE_URL"],
"collection_name": "memories",
"embedding_model_dims": 1536,
"hnsw": True,
},
},
"vector_store": {
"provider": "pgvector",
"config": {
"connection_string": os.environ["DATABASE_URL"],
"collection_name": "memories",
"embedding_model_dims": 1536,
"hnsw": True,
},
},
}
m = Memory.from_config(config)
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."},
{"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."},
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
results = m.search(
"What movies should I recommend?",
filters={"user_id": "alice"},
"What movies should I recommend?",
filters={"user_id": "alice"},
)
print(results)
```
````
```typescript TypeScript
import "dotenv/config";
import { Memory } from "mem0ai/oss";
const databaseUrl = new URL(process.env.DATABASE_URL!);
const m = new Memory({
vectorStore: {
provider: "pgvector",
config: {
user: decodeURIComponent(databaseUrl.username),
password: decodeURIComponent(databaseUrl.password),
host: databaseUrl.hostname,
port: Number(databaseUrl.port || 5432),
dbname: databaseUrl.pathname.slice(1) || "neondb",
connectionString: process.env.DATABASE_URL!,
ssl: {
rejectUnauthorized: false,
},
collectionName: "memories",
dimension: 1536,
embeddingModelDims: 1536,
@@ -89,7 +87,8 @@ const results = await m.search("What movies should I recommend?", {
});
console.log(results);
```
````
</CodeGroup>
## SQL Migration
@@ -116,20 +115,19 @@ DATABASE_URL=postgresql://user:password@ep-example.us-east-2.aws.neon.tech/neond
| `sslmode` | PostgreSQL SSL mode. Use `require` for Neon. | Driver default |
</Tab>
<Tab title="TypeScript">
The current Mem0 TypeScript `pgvector` adapter takes individual Postgres fields,
so parse `DATABASE_URL` before creating `Memory`.
Use the Neon `DATABASE_URL` directly with `connectionString`. Set `ssl` if your runtime needs an explicit TLS config object.
| Parameter | Description | Default |
| -------------------- | ---------------------------------------------- | -------------- |
| `connectionString` | Neon Postgres connection string. | Required |
| `ssl` | Optional TLS settings passed directly to `pg`. | Driver default |
| `collectionName` | Name for the vector collection. | `memories` |
| `dimension` | Vector dimension for Mem0 config. | Auto-detected |
| `embeddingModelDims` | Embedding model dimensions for table creation. | Required |
| `hnsw` | Enables HNSW indexing. | `false` |
**TLS note:** `ssl: true` is sufficient for most Neon connections since Neon uses valid certificates. Use `ssl: { rejectUnauthorized: false }` only when connecting through Neon's connection pooler on certain edge runtimes (e.g. Cloudflare Workers) that require it, or when your environment does not trust the Neon CA chain.
| Parameter | Description | Default |
| --- | --- | --- |
| `user` | Database user. | Required |
| `password` | Database password. | Required |
| `host` | Database host. | Required |
| `port` | Database port. | `5432` |
| `dbname` | Database name. | `vector_store` |
| `collectionName` | Name for the vector collection. | `memories` |
| `dimension` | Vector dimension for Mem0 config. | Auto-detected |
| `embeddingModelDims` | Embedding model dimensions for table creation. | Required |
| `hnsw` | Enables HNSW indexing. | `false` |
</Tab>
</Tabs>
@@ -56,6 +56,30 @@ config = {
}
```
### Configuration Options
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `collection_name` | string | required | Name of the OpenSearch index |
| `host` | string | required | OpenSearch endpoint URL |
| `port` | int | 9200 | Port number |
| `http_auth` | object | None | Authentication credentials (e.g., AWSV4SignerAuth) |
| `embedding_model_dims` | int | 1536 | Dimension of embedding vectors |
| `use_ssl` | bool | False | Enable SSL/TLS connection |
| `verify_certs` | bool | False | Verify SSL certificates |
| `auto_refresh` | bool | False | Automatically refresh index after insert. OpenSearch refreshes every ~1 second by default, so this is rarely needed. |
<Note>
The defaults above match a local OpenSearch instance. The AWS OpenSearch Serverless
example earlier on this page intentionally overrides them with `port=443`, `use_ssl=True`,
and `verify_certs=True`, which are required when connecting to a Serverless collection.
</Note>
<Note>
For **AWS OpenSearch Serverless**, keep `auto_refresh=False` (the default).
The `indices.refresh()` API is not supported on Serverless collections.
</Note>
### Add Memories
```python
+50 -45
View File
@@ -2,6 +2,7 @@
title: "pgvector"
description: "Use pgvector as a vector store in Mem0 for PostgreSQL-based vector similarity search with open-source simplicity."
---
[pgvector](https://github.com/pgvector/pgvector) is an open-source vector similarity search extension for Postgres. After connecting to Postgres, run `CREATE EXTENSION IF NOT EXISTS vector;` to create the vector extension.
### Usage
@@ -14,41 +15,38 @@ from mem0 import Memory
os.environ["OPENAI_API_KEY"] = "sk-xx"
config = {
"vector_store": {
"provider": "pgvector",
"config": {
"user": "test",
"password": "123",
"host": "127.0.0.1",
"port": "5432",
}
}
"vector_store": {
"provider": "pgvector",
"config": {
"user": "test",
"password": "123",
"host": "127.0.0.1",
"port": "5432",
},
}
}
m = Memory.from_config(config)
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."}
{"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."},
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
````
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
import { Memory } from "mem0ai/oss";
const config = {
vectorStore: {
provider: 'pgvector',
provider: "pgvector",
config: {
collectionName: 'memories',
collectionName: "memories",
embeddingModelDims: 1536,
user: 'test',
password: '123',
host: '127.0.0.1',
port: 5432,
dbname: 'vector_store', // Optional; TypeScript OSS defaults to `vector_store` when omitted
connectionString: "postgresql://test:123@localhost:5432/vector_store",
diskann: false, // Optional, requires pgvectorscale extension
hnsw: false, // Optional, for HNSW indexing
},
@@ -57,37 +55,44 @@ const config = {
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."}
]
{ 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>
### Config
Here are the parameters available for configuring pgvector:
| Parameter | Description | Default Value |
| --- | --- | --- |
| `dbname` | The name of the database | `postgres` |
| `collection_name` | The name of the collection | `mem0` |
| `embedding_model_dims` | Dimensions of the embedding model | `1536` |
| `user` | User name to connect to the database | `None` |
| `password` | Password to connect to the database | `None` |
| `host` | The host where the Postgres server is running | `None` |
| `port` | The port where the Postgres server is running | `None` |
| `diskann` | Whether to use diskann for vector similarity search (requires pgvectorscale) | `True` |
| `hnsw` | Whether to use hnsw for vector similarity search | `False` |
| `sslmode` | SSL mode for PostgreSQL connection (e.g., 'require', 'prefer', 'disable') | `None` |
| `connection_string` | PostgreSQL connection string (overrides individual connection parameters) | `None` |
| `connection_pool` | psycopg2 connection pool object (overrides connection string and individual parameters) | `None` |
| Parameter | SDK | Description | Default Value |
| -------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
| `connectionString` | TypeScript OSS | PostgreSQL connection string for direct connections. When set, Mem0 connects to the target database directly and skips the bootstrap `postgres` database flow. | `None` |
| `ssl` | TypeScript OSS | SSL option passed directly to `pg`, either `true` or an SSL config object, for both `connectionString` and split-field connections. | `None` |
| `dbname` | TypeScript OSS | Split-field database name. This is only used when `connectionString` is absent. | `vector_store` |
| `collectionName` | TypeScript OSS | Collection name. | `memories` |
| `embeddingModelDims` | TypeScript OSS | Dimensions of the embedding model. | Required |
| `user` | TypeScript OSS + Python | Database user for split-field connections. | `None` |
| `password` | TypeScript OSS + Python | Database password for split-field connections. | `None` |
| `host` | TypeScript OSS + Python | Database host for split-field connections. | `None` |
| `port` | TypeScript OSS + Python | Database port for split-field connections. | `None` |
| `diskann` | TypeScript OSS + Python | Whether to use DiskANN for vector similarity search, requires pgvectorscale. | `False` |
| `hnsw` | TypeScript OSS + Python | Whether to use HNSW for vector similarity search. | TypeScript OSS: `False`, Python: `True` |
| `connection_string` | Python only | PostgreSQL connection string, overrides individual connection parameters. | `None` |
| `sslmode` | Python only | SSL mode for PostgreSQL connections, such as `require`, `prefer`, or `disable`. | `None` |
| `connection_pool` | Python only | psycopg connection pool object, overrides connection string and individual connection parameters. | `None` |
**Note (TypeScript OSS):** If you omit `dbname`, the TypeScript client uses the database name `vector_store`. Python defaults to `postgres` for `dbname`, as in the table above.
**TypeScript OSS:** Use `connectionString` plus optional `ssl` for managed Postgres setups. If you omit `connectionString`, Mem0 falls back to split fields and uses `dbname`, `user`, `password`, `host`, `port`, and optional `ssl`.
**Python:** The Python SDK uses snake_case keys such as `connection_string`, `sslmode`, `collection_name`, and `embedding_model_dims`.
**Python connection priority**:
**Note**: The connection parameters have the following priority:
1. `connection_pool` (highest priority)
2. `connection_string`
3. Individual connection parameters (`user`, `password`, `host`, `port`, `sslmode`)
3. Individual connection parameters (`user`, `password`, `host`, `port`, `sslmode`)
+2 -1
View File
@@ -76,6 +76,7 @@ Let's see the available parameters for the `qdrant` config:
| `path` | Path for the qdrant database | `/tmp/qdrant` |
| `url` | Full URL for the qdrant server | `None` |
| `api_key` | API key for the qdrant server | `None` |
| `https` | Whether to force HTTPS on or off. `None` lets the client decide; set `False` for plain HTTP Qdrant with API key authentication. | `None` |
| `on_disk` | For enabling persistent storage | `False` |
</Tab>
<Tab title="TypeScript">
@@ -90,4 +91,4 @@ Let's see the available parameters for the `qdrant` config:
| `apiKey` | API key for the Qdrant server | `None` |
| `onDisk` | For enabling persistent storage | `False` |
</Tab>
</Tabs>
</Tabs>
+5 -5
View File
@@ -17,7 +17,7 @@ Some benchmarks today — particularly smaller ones like LoCoMo and LongMemEval
## Architecture Overview
Mem0's memory system operates across two phases — **extraction** (writing) and **retrieval** (reading) — with an entity linking layer connecting them.
Mem0's memory system operates across two phases, **extraction** (writing) and **retrieval** (reading), with a graph memory layer (entity linking) connecting them.
### Memory Extraction (Distillation)
@@ -27,14 +27,14 @@ When new conversations arrive, the extraction pipeline processes them through fi
2. **Context Lookup** — Find related existing memories to avoid duplicates
3. **Distill Memories** — Single-pass LLM extraction produces ADD-only facts from input + context
4. **Deduplicate + Embed** — Hash-based deduplication, then vectorize new memories
5. **Entity Linking** — Identify entities (proper nouns, quoted text, compound noun phrases) and link them across memories
5. **Graph Memory (Entity Linking)**: Identify entities (proper nouns, quoted text, compound noun phrases) and link them across memories into a graph
Memories are distributed across three storage layers, each tuned for a specific retrieval pattern:
| Store | Contents | Purpose |
|---|---|---|
| **Vector Database** | Memory text, embeddings, metadata (timestamps, hash, categories, attributed_to) | Primary fact storage + semantic retrieval |
| **Entity Store** | Entities + embeddings + linked memory IDs | Entity-based retrieval boost |
| **Graph / Entity Store** | Entities + embeddings + linked memory IDs | Graph connections across memories + entity-based retrieval boost |
| **SQL Database** | History log (ADD events) + rolling message window | Audit trail + extraction dedup context |
<Info>
@@ -76,7 +76,7 @@ The combined score outperformed every individual signal across every category te
*Mean tokens: 6,956*
The two largest gains are **temporal queries (+29.6)** and **multi-hop reasoning (+23.1)**. Both categories directly test the ADD-only architecture (preserving temporal context) and entity linking (connecting facts across memories).
The two largest gains are **temporal queries (+29.6)** and **multi-hop reasoning (+23.1)**. Both categories directly test the ADD-only architecture (preserving temporal context) and graph memory / entity linking (connecting facts across memories).
### LongMemEval
@@ -345,7 +345,7 @@ When evaluating memory systems, keep these considerations in mind:
<Card title="Research" icon="flask" href="https://mem0.ai/research">
Published research papers and technical reports
</Card>
<Card title="Blog Post" icon="newspaper" href="https://mem0.ai/blog/new-algorithm">
<Card title="Blog Post" icon="newspaper" href="https://mem0.ai/blog/the-token-efficient-memory-algorithm-now-has-temporal-reasoning">
Detailed writeup of the new algorithm design and results
</Card>
<Card title="Platform Migration" icon="arrow-right" href="/migration/platform-v2-to-v3">
+11 -11
View File
@@ -21,7 +21,7 @@ Adding memory is how Mem0 captures useful details from a conversation so your ag
- **Messages** – The ordered list of user/assistant turns you send to `add`.
- **Infer** – Controls whether Mem0 extracts structured memories (`infer=True`, default) or stores raw messages.
- **Metadata** – Optional filters (e.g., `{"category": "movie_recommendations"}`) that improve retrieval later.
- **User / Session identifiers** – `user_id`, `agent_id`, or `run_id` that scope the memory for future searches.
- **User / Session identifiers** – `user_id`, `agent_id`, `app_id`, or `run_id` that scope the memory for future searches.
## How does it work?
@@ -30,22 +30,22 @@ Mem0 offers two flows:
- **Mem0 Platform** – Fully managed API with dashboard and scaling.
- **Mem0 Open Source** – Local SDK that you run in your own environment.
Both flows take the same payload and pass it through the same pipeline.
Both flows take the same payload and add memories through an additive pipeline.
<Steps>
<Step title="Information extraction">
Mem0 sends the messages through an LLM that pulls out key facts, decisions, or preferences to remember.
</Step>
<Step title="Conflict resolution">
Existing memories are checked for duplicates or contradictions so the latest truth wins.
<Step title="Additive storage">
New memories are added without overwriting or deleting existing memories.
</Step>
<Step title="Storage">
The resulting memories land in managed vector storage so future searches return them quickly.
<Step title="Retrieval">
Future searches rank the most relevant memories for the query.
</Step>
</Steps>
<Warning>
Duplicate protection only runs during that conflict-resolution step when you let Mem0 infer memories (`infer=True`, the default). If you switch to `infer=False`, Mem0 stores your payload exactly as provided, so duplicates will land. Mixing both modes for the same fact will save it twice.
When you switch to `infer=False`, Mem0 stores your payload exactly as provided, so duplicates can land. Mixing both modes for the same fact can save it twice.
</Warning>
You trigger this pipeline with a single `add` call—no manual orchestration needed.
@@ -80,13 +80,13 @@ const messages = [
];
await client.add(messages, {
user_id: "alice",
userId: "alice",
});
```
</CodeGroup>
<Info icon="check">
Expect a `memory_id` (or list of IDs) in the response. Check the Mem0 dashboard to confirm the new entry under the correct user.
Expect a `status: "PENDING"` response with an `event_id`. Poll `GET /v1/event/{event_id}/` to confirm completion.
</Info>
## Add with Mem0 Open Source
@@ -138,7 +138,7 @@ const result = memory.add(messages, {
</Tip>
<Warning>
If you do choose `infer=False`, keep it consistent. Raw inserts skip conflict resolution, so a later `infer=True` call with the same content will create a second memory instead of updating the first.
If you do choose `infer=False`, keep it consistent. Raw inserts skip inference, so a later `infer=True` call with the same content can create a second memory.
</Warning>
## When Should You Add Memory?
@@ -167,7 +167,7 @@ For full list of supported fields, required formats, and advanced options, see t
| Capability | Mem0 Platform | Mem0 OSS |
| --- | --- | --- |
| Conflict resolution | Automatic with dashboard visibility | SDK handles merges locally; you control storage |
| Add behavior | ADD-only; memories accumulate | ADD-only; you control storage |
| Rate limits | Managed quotas per workspace | Limited by your hardware and provider APIs |
| Dashboard visibility | Yes — inspect memories visually | Inspect via CLI, logs, or custom UI |
+14 -7
View File
@@ -71,6 +71,7 @@
"pages": [
"platform/features/v2-memory-filters",
"platform/features/entity-scoped-memory",
"platform/features/graph-memory",
"platform/features/async-client",
"platform/features/multimodal-support",
"platform/features/custom-categories",
@@ -272,7 +273,8 @@
"components/embedders/models/lmstudio",
"components/embedders/models/together",
"components/embedders/models/langchain",
"components/embedders/models/aws_bedrock"
"components/embedders/models/aws_bedrock",
"components/embedders/models/fastembed"
]
}
]
@@ -440,7 +442,7 @@
"integrations/flowise",
"integrations/langchain-tools",
"integrations/agentops",
"integrations/keywords",
"integrations/respan",
"integrations/raycast"
]
}
@@ -532,6 +534,8 @@
"api-reference/organization/get-org",
"api-reference/organization/get-org-members",
"api-reference/organization/add-org-member",
"api-reference/organization/update-org-member",
"api-reference/organization/remove-org-member",
"api-reference/organization/delete-org"
]
},
@@ -544,6 +548,9 @@
"api-reference/project/get-project",
"api-reference/project/get-project-members",
"api-reference/project/add-project-member",
"api-reference/project/update-project",
"api-reference/project/update-project-member",
"api-reference/project/remove-project-member",
"api-reference/project/delete-project"
]
},
@@ -623,6 +630,10 @@
]
},
"redirects": [
{
"source": "/components/rerankers/models/llm",
"destination": "/components/rerankers/models/llm_reranker"
},
{
"source": "/migration/breaking-changes",
"destination": "/"
@@ -647,10 +658,6 @@
"source": "/open-source/features/custom-fact-extraction-prompt",
"destination": "/open-source/features/custom-instructions"
},
{
"source": "/platform/features/graph-memory",
"destination": "/migration/oss-v2-to-v3"
},
{
"source": "/cookbooks/essentials/choosing-memory-architecture-vector-vs-graph",
"destination": "/migration/oss-v2-to-v3"
@@ -1025,7 +1032,7 @@
},
{
"source": "/features/graph-memory",
"destination": "/migration/oss-v2-to-v3"
"destination": "/platform/features/graph-memory"
},
{
"source": "/features/:slug",
+6 -4
View File
@@ -309,19 +309,21 @@ Here are the available integrations for Mem0:
</Card>
<Card
title="Keywords AI"
title="Respan"
icon={
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
viewBox="0 0 200 200"
fill="none"
>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.07513 1.1863C9.21663 1.07722 9.39144 1.01009 9.56624 1.01009C9.83261 1.01009 10.0823 1.12756 10.2405 1.33734L15.0101 7.4964V12.4136L16.4335 13.8401C16.7582 14.1673 16.7582 14.7043 16.4335 15.0316C16.1089 15.3588 15.5762 15.3588 15.2515 15.0316L13.3453 13.1016V8.07538L8.92529 2.36944V2.36105C8.64228 2.00024 8.70887 1.4716 9.07513 1.1863ZM18.976 14.4133C18.8344 14.3778 18.7003 14.3042 18.5894 14.1925L16.9163 12.5059C16.7249 12.3129 16.6416 12.0528 16.6749 11.8094V6.88385H16.6499L11.8553 0.691225C11.7282 0.529117 11.6716 0.333133 11.6803 0.140562C11.134 0.0481292 10.5726 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20C13.9387 20 17.3456 17.7229 18.976 14.4133Z" fill="currentColor"></path>
<path d="M2.00635 190.234V9.76584H53.3558V29.5101H26.7223V170.562H53.3558V190.234H2.00635Z" fill="currentColor"></path>
<path d="M120.692 160.902C116.383 160.902 112.691 159.387 109.612 156.357C106.535 153.327 105.02 149.633 105.067 145.277C105.02 141.016 106.535 137.37 109.612 134.34C112.691 131.309 116.383 129.794 120.692 129.794C124.859 129.794 128.481 131.309 131.559 134.34C134.684 137.37 136.27 141.016 136.317 145.277C136.27 148.166 135.512 150.793 134.045 153.161C132.624 155.528 130.73 157.422 128.362 158.842C126.042 160.216 123.486 160.902 120.692 160.902Z" fill="currentColor"></path>
<path d="M197.993 9.76584V190.234H146.643V170.562H173.278V29.5101H146.643V9.76584H197.993Z" fill="currentColor"></path>
</svg>
}
href="/integrations/keywords"
href="/integrations/respan"
>
Build AI applications with persistent memory and comprehensive LLM observability.
</Card>
+1 -1
View File
@@ -73,7 +73,7 @@ client = MemoryClient()
# Define the agent
agent = Agent(
name="Personal Agent",
model=OpenAIChat(id="gpt-4"),
model=OpenAIChat(id="gpt-5-mini"),
description="You are a helpful personal agent that helps me with day to day activities."
"You can process both text and images.",
markdown=True
+2 -1
View File
@@ -28,7 +28,7 @@ echo 'export MEM0_API_KEY="m0-your-api-key"' >> ~/.bashrc && source ~/.bashrc
```bash
# Install the plugin (MCP server, hooks, scripts)
npx degit mem0ai/mem0/mem0-plugin ~/.gemini/config/plugins/mem0
npx degit mem0ai/mem0/integrations/mem0-plugin ~/.gemini/config/plugins/mem0
```
This installs the MCP server, lifecycle hooks, and shared scripts.
@@ -65,6 +65,7 @@ The plugin uses the same shell scripts as Claude Code, Cursor, and Codex — hoo
| **User prompt** | `UserPromptSubmit` | Searches relevant memories before each message |
| **Pre-tool** | `PreToolUse` | Blocks MEMORY.md writes, enforces `user_id`/`app_id` on mem0 tools |
| **Post-tool** | `PostToolUse` | Tracks stats, scans bash errors for related memories |
| **Stop** | `Stop` | Stores a session summary when the session ends |
## Troubleshooting
+2 -2
View File
@@ -43,7 +43,7 @@ OPENAI_API_KEY = os.environ.get('OPENAI_API_KEY')
memory_client = MemoryClient()
agent = ConversableAgent(
"chatbot",
llm_config={"config_list": [{"model": "gpt-4", "api_key": OPENAI_API_KEY}]},
llm_config={"config_list": [{"model": "gpt-5-mini", "api_key": OPENAI_API_KEY}]},
code_execution_config=False,
human_input_mode="NEVER",
)
@@ -99,7 +99,7 @@ For more complex scenarios, you can create multiple agents:
manager = ConversableAgent(
"manager",
system_message="You are a manager who helps in resolving complex customer issues.",
llm_config={"config_list": [{"model": "gpt-4", "api_key": OPENAI_API_KEY}]},
llm_config={"config_list": [{"model": "gpt-5-mini", "api_key": OPENAI_API_KEY}]},
human_input_mode="NEVER"
)
+5 -3
View File
@@ -64,7 +64,7 @@ Add the Mem0 MCP server directly with a single command:
npx mcp-add \
--name mem0-mcp \
--type http \
--url "https://mcp.mem0.ai/mcp" \
--url "https://mcp.mem0.ai/mcp/" \
--clients "claude code"
```
@@ -138,11 +138,13 @@ When installed via the plugin marketplace, Mem0 hooks into Claude Code's lifecyc
| Hook | Event | What it does |
|------|-------|-------------|
| **Setup** | `Setup` | Installs the mem0 SDK and dependencies (runs on init and maintenance) |
| **Session start** | `SessionStart` | Loads prior memories and displays status banner |
| **User prompt** | `UserPromptSubmit` | Searches relevant memories before each message; skips short prompts |
| **Pre-tool** | `PreToolUse` | Blocks MEMORY.md writes, enforces `user_id`/`app_id` on mem0 tool calls |
| **Pre-tool (3 handlers)** | `PreToolUse` | Blocks MEMORY.md writes; enforces `user_id`/`app_id` on mem0 tool calls; scans files being read for relevant memory context |
| **Post-tool** | `PostToolUse` | Tracks stats, scans bash errors for related memories |
| **Pre-compact** | `PreCompact` | Stores a session summary before context compaction |
| **Stop** | `Stop` | Stores a session summary when the session ends |
| **Pre-compact** | `PreCompact` | Stores a summary before the context is compacted |
## Example Workflow
+24 -10
View File
@@ -41,7 +41,17 @@ Install the full plugin including MCP server, lifecycle hooks, and SDK skill.
codex plugin marketplace add mem0ai/mem0
```
2. Restart Codex, open the Plugin Directory, browse the **Mem0 Plugins** marketplace, and install **Mem0**.
2. Install the plugin:
```bash
codex plugin add mem0@mem0-plugins
```
Or, in the app: restart Codex, open the Plugin Directory, browse the **Mem0 Plugins** marketplace, and install **Mem0**.
<Note>
Step 1 is required for the app UI. Mem0 isn't in OpenAI's curated directory yet, so **without `codex plugin marketplace add`, Mem0 won't appear in the Codex app's Plugin Directory** — searching for it returns nothing. Adding the marketplace surfaces it (under **Created by you**) and makes it installable.
</Note>
<Info>
Do not combine with Option B. The plugin manifest auto-registers the `mem0` MCP server, so adding both will create a duplicate registration.
@@ -49,27 +59,30 @@ Install the full plugin including MCP server, lifecycle hooks, and SDK skill.
### Option B — Direct MCP
The fastest way to connect Codex to Mem0 — no plugin, no marketplace. Add to `~/.codex/config.toml`:
The fastest way to connect Codex to Mem0 — no plugin, no marketplace. Add the MCP server with a single command:
```bash
codex mcp add mem0 --url https://mcp.mem0.ai/mcp/ --bearer-token-env-var MEM0_API_KEY
```
Or add it manually to `~/.codex/config.toml`:
```toml
[mcp_servers.mem0]
url = "https://mcp.mem0.ai/mcp"
url = "https://mcp.mem0.ai/mcp/"
bearer_token_env_var = "MEM0_API_KEY"
```
Make sure `MEM0_API_KEY` is exported in the shell you launch Codex from, then restart Codex.
<Info>
Codex's `codex mcp add` CLI only supports stdio MCP servers. Because Mem0's MCP is HTTP/streamable, you configure it by editing `config.toml` directly (or via the **Plugins → Connect to a custom MCP → Streamable HTTP** UI in the Codex app).
</Info>
This gives you the MCP tools but not the lifecycle hooks or SDK skill.
### Managing the Plugin
```bash
codex plugin marketplace upgrade # pull latest plugin versions
codex plugin marketplace remove mem0-plugins # unregister the marketplace
codex plugin remove mem0@mem0-plugins # uninstall the plugin (keeps the marketplace)
codex plugin marketplace remove mem0-plugins # unregister the marketplace entirely
```
To update, run `codex plugin marketplace upgrade` to pull the latest from the Mem0 repo.
@@ -110,9 +123,10 @@ When installed via the plugin marketplace, Mem0 hooks into Codex's lifecycle to
|------|-------|-------------|
| **Session start** | `SessionStart` | Loads prior memories and displays status banner |
| **User prompt** | `UserPromptSubmit` | Searches relevant memories before each message |
| **Pre-tool** | `PreToolUse` | Blocks MEMORY.md writes, enforces `user_id`/`app_id` on mem0 tool calls |
| **Pre-tool (3 handlers)** | `PreToolUse` | Blocks MEMORY.md writes; enforces `user_id`/`app_id` on mem0 tool calls; scans files being read for relevant memory context |
| **Post-tool** | `PostToolUse` | Tracks stats, scans bash errors for related memories |
| **Pre-compact** | `PreCompact` | Stores a session summary before context compaction |
| **Stop** | `Stop` | Stores a session summary when the session ends |
| **Pre-compact** | `PreCompact` | Stores a summary before the context is compacted |
## Example Workflow
+4 -3
View File
@@ -47,7 +47,7 @@ The fastest way to get started. Click the link below to install the Mem0 MCP ser
npx mcp-add \
--name mem0-mcp \
--type http \
--url "https://mcp.mem0.ai/mcp" \
--url "https://mcp.mem0.ai/mcp/" \
--clients "cursor"
```
@@ -108,9 +108,10 @@ When installed via the Cursor Marketplace, Mem0 hooks into Cursor's lifecycle:
|------|-------|-------------|
| **Session start** | `sessionStart` | Loads prior memories and displays status banner |
| **User prompt** | `beforeSubmitPrompt` | Searches relevant memories before each message; skips short prompts |
| **Pre-tool (2 handlers)** | `preToolUse` | Blocks MEMORY.md writes, enforces `user_id`/`app_id` on mem0 tool calls |
| **Pre-tool (3 handlers)** | `preToolUse` | Blocks MEMORY.md writes; enforces `user_id`/`app_id` on mem0 tool calls; scans files being read for relevant memory context |
| **Post-tool (2 handlers)** | `postToolUse` | Tracks stats, scans bash errors for related memories |
| **Pre-compact** | `preCompact` | Stores a session summary before context compaction |
| **Stop** | `stop` | Stores a session summary when the session ends |
| **Pre-compact** | `preCompact` | Stores a summary before the context is compacted |
## Example Workflow
+54 -55
View File
@@ -100,12 +100,12 @@ This section:
Initialize both the ElevenLabs and Mem0 clients:
```python
# Initialize ElevenLabs client
client = ElevenLabs(api_key=API_KEY)
# Initialize ElevenLabs client
client = ElevenLabs(api_key=API_KEY)
# Initialize memory client and tools
client_tools = ClientTools()
mem0_client = AsyncMemoryClient()
# Initialize memory client and tools
client_tools = ClientTools()
mem0_client = AsyncMemoryClient()
```
Here we:
@@ -118,36 +118,36 @@ Here we:
Define the two key memory functions that will be registered as tools:
```python
# Define memory-related functions for the agent
async def add_memories(parameters):
"""Add a message to the memory store"""
message = parameters.get("message")
await mem0_client.add(
messages=message,
user_id=USER_ID
)
return "Memory added successfully"
# Define memory-related functions for the agent
async def add_memories(parameters):
"""Add a message to the memory store"""
message = parameters.get("message")
await mem0_client.add(
messages=message,
user_id=USER_ID
)
return "Memory added successfully"
async def retrieve_memories(parameters):
"""Retrieve relevant memories based on the input message"""
message = parameters.get("message")
async def retrieve_memories(parameters):
"""Retrieve relevant memories based on the input message"""
message = parameters.get("message")
# For Platform API, user_id goes in filters
filters = {"user_id": USER_ID}
# For Platform API, user_id goes in filters
filters = {"user_id": USER_ID}
# Search for relevant memories using the message as a query
results = await mem0_client.search(
query=message,
filters=filters
)
# Search for relevant memories using the message as a query
results = await mem0_client.search(
query=message,
filters=filters
)
# Extract and join the memory texts
memories = ' '.join([result["memory"] for result in results.get('results', [])])
print("[ Memories ]", memories)
# Extract and join the memory texts
memories = ' '.join([result["memory"] for result in results.get('results', [])])
print("[ Memories ]", memories)
if memories:
return memories
return "No memories found"
if memories:
return memories
return "No memories found"
```
These functions:
@@ -171,9 +171,9 @@ These functions:
Register the memory functions with the ElevenLabs ClientTools system:
```python
# Register the memory functions as tools for the agent
client_tools.register("addMemories", add_memories, is_async=True)
client_tools.register("retrieveMemories", retrieve_memories, is_async=True)
# Register the memory functions as tools for the agent
client_tools.register("addMemories", add_memories, is_async=True)
client_tools.register("retrieveMemories", retrieve_memories, is_async=True)
```
This allows the ElevenLabs agent to:
@@ -186,19 +186,19 @@ This allows the ElevenLabs agent to:
Configure the conversation with ElevenLabs:
```python
# Initialize the conversation
conversation = Conversation(
client,
AGENT_ID,
# Assume auth is required when API_KEY is set
requires_auth=bool(API_KEY),
audio_interface=DefaultAudioInterface(),
client_tools=client_tools,
callback_agent_response=lambda response: print(f"Agent: {response}"),
callback_agent_response_correction=lambda original, corrected: print(f"Agent: {original} -> {corrected}"),
callback_user_transcript=lambda transcript: print(f"User: {transcript}"),
# callback_latency_measurement=lambda latency: print(f"Latency: {latency}ms"),
)
# Initialize the conversation
conversation = Conversation(
client,
AGENT_ID,
# Assume auth is required when API_KEY is set
requires_auth=bool(API_KEY),
audio_interface=DefaultAudioInterface(),
client_tools=client_tools,
callback_agent_response=lambda response: print(f"Agent: {response}"),
callback_agent_response_correction=lambda original, corrected: print(f"Agent: {original} -> {corrected}"),
callback_user_transcript=lambda transcript: print(f"User: {transcript}"),
# callback_latency_measurement=lambda latency: print(f"Latency: {latency}ms"),
)
```
This sets up the conversation with:
@@ -217,16 +217,16 @@ This sets up the conversation with:
Start and manage the conversation:
```python
# Start the conversation
print(f"Starting conversation with user_id: {USER_ID}")
conversation.start_session()
# Start the conversation
print(f"Starting conversation with user_id: {USER_ID}")
conversation.start_session()
# Handle Ctrl+C to gracefully end the session
signal.signal(signal.SIGINT, lambda sig, frame: conversation.end_session())
# Handle Ctrl+C to gracefully end the session
signal.signal(signal.SIGINT, lambda sig, frame: conversation.end_session())
# Wait for the conversation to end and get the conversation ID
conversation_id = conversation.wait_for_session_end()
print(f"Conversation ID: {conversation_id}")
# Wait for the conversation to end and get the conversation ID
conversation_id = conversation.wait_for_session_end()
print(f"Conversation ID: {conversation_id}")
if __name__ == '__main__':
@@ -445,4 +445,3 @@ By integrating ElevenLabs Conversational AI with Mem0, you can create voice agen
Create voice-first AI applications
</Card>
</CardGroup>
+164 -37
View File
@@ -1,35 +1,42 @@
---
title: Hermes Agent
description: "Add long-term memory to Hermes agents using Mem0 as a pluggable memory provider with automatic background sync and zero-latency prefetch."
description: "Add long-term memory to Hermes agents with Mem0, on managed Mem0 Cloud or fully self-hosted (OSS), with automatic background sync and zero-latency prefetch."
---
Add long-term memory to [Hermes Agent](https://github.com/NousResearch/hermes-agent) — a self-improving AI agent CLI by Nous Research. Hermes has a pluggable memory system, and Mem0 is one of the supported providers. Once enabled, Mem0 automatically learns facts from your conversations and surfaces relevant ones before each turn — all without slowing down the chat.
Add long-term memory to [Hermes Agent](https://github.com/NousResearch/hermes-agent), a self-improving AI agent CLI by Nous Research. Hermes has a pluggable memory system, and Mem0 is one of the supported providers. Once enabled, Mem0 learns facts from your conversations and surfaces relevant ones before each turn, without slowing down the chat.
## Overview
You can run Mem0 in two ways:
Hermes runs a built-in memory system (file-based `MEMORY.md` and `USER.md`) alongside one external provider. When Mem0 is active, it works additively with the built-in system at three key moments in every conversation turn:
- **Platform mode** (default): managed Mem0 Cloud. Add your API key and you are ready.
- **OSS mode**: fully self-hosted with your own LLM, embedder, and vector store. No data leaves your machine.
### 1. Before the Agent Responds (Prefetch)
## How It Works
When you send a message, Hermes checks if it already has cached Mem0 search results from the previous turn. If so, those memories are injected into the system prompt so the LLM can see them. This is **zero-latency** — no waiting for an API call.
Hermes runs a built-in memory system (file-based `MEMORY.md` and `USER.md`) alongside one external provider. When Mem0 is active, it works additively with the built-in system at three points in every conversation turn.
### 2. After the Agent Responds (Sync)
### 1. Before the agent responds (prefetch)
Once the LLM finishes responding, Hermes sends the `(user message, assistant response)` pair to Mem0's API in a **background thread**. Mem0's server-side LLM automatically extracts facts (e.g., "user prefers Python", "user works at Acme Corp") — you don't have to tell it what to remember.
When you send a message, Hermes checks for cached Mem0 search results from the previous turn. If they exist, those memories are injected into the system prompt so the model can see them. This is zero-latency, with no waiting on an API call.
### 3. Background Prefetch for Next Turn
### 2. After the agent responds (sync)
At the same time as sync, Hermes kicks off a background search on Mem0 to pre-load relevant memories for the next turn. By the time you type your next message, the memories are already cached.
Once the model finishes, Hermes sends the `(user message, assistant response)` pair to Mem0 in a background thread. Mem0 extracts facts automatically (for example, "user prefers Python" or "user works at Acme Corp"), so you never have to tell it what to remember. Each write is tagged with the gateway channel it came from.
### 3. Background prefetch for the next turn
At the same time, Hermes runs a background search to pre-load relevant memories for your next message. By the time you type, the results are already cached.
## Agent Tools
When Mem0 is active, the LLM gets three extra tools it can call during conversations:
When Mem0 is active, the model gets five tools it can call during a conversation:
| Tool | Description |
|------|-------------|
| `mem0_profile` | Fetch all stored memories about the user |
| `mem0_search` | Semantic search through memories (supports optional reranking via `rerank` and `top_k` parameters) |
| `mem0_conclude` | Store a specific fact verbatim — uses `infer=False` so no server-side LLM extraction happens |
| Tool | Description | Parameters |
|------|-------------|------------|
| `mem0_list` | List all stored memories, for a full overview | `page`, `page_size` (default 100, max 200) |
| `mem0_search` | Semantic search by meaning, ranked by relevance | `query` (required), `top_k` (default 10, max 50), `rerank` (default `true`, Platform mode only) |
| `mem0_add` | Store a fact verbatim, with no LLM extraction | `content` (required) |
| `mem0_update` | Update a memory's text by ID | `memory_id`, `text` (both required) |
| `mem0_delete` | Delete a memory by ID | `memory_id` (required) |
## Installation
@@ -40,17 +47,19 @@ curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scri
source ~/.bashrc
```
The `mem0ai` Python package is automatically installed when you enable the Mem0 provider — no manual pip install needed.
The `mem0ai` package is installed automatically when you enable the Mem0 provider, so there is no manual pip step. OSS providers may need extra packages (for example `qdrant-client`, `psycopg2-binary`, or `ollama`), which the setup flow installs for you when you pick them.
## Setup
## Platform Setup
### Option 1: Interactive Setup Wizard (Recommended)
Platform mode uses managed Mem0 Cloud and is the fastest way to start.
### Option 1: Interactive wizard (recommended)
```bash
hermes memory setup
```
Select **mem0** as the provider and enter your Mem0 API key when prompted. The wizard writes your config to `~/.hermes/mem0.json`.
Select **mem0**, choose **Platform**, and paste your API key when prompted. The wizard writes the non-secret settings to `~/.hermes/mem0.json` and keeps the key in `~/.hermes/.env`.
<Note>Get your API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-hermes" rel="nofollow">app.mem0.ai</a>.</Note>
@@ -68,33 +77,151 @@ memory:
provider: mem0
```
That's it — Mem0 runs automatically from this point.
That's it. Mem0 runs automatically from here.
## Configuration Options
## OSS (Self-Hosted) Setup
Configuration is stored in `~/.hermes/mem0.json`. Values can also be set via environment variables.
OSS mode runs Mem0 entirely on your own infrastructure: your LLM, your embedder, and your vector store. No data is sent to Mem0 Cloud, and no Mem0 API key is required.
| Key | Env Variable | Default | Description |
|-----|-------------|---------|-------------|
| `api_key` | `MEM0_API_KEY` | — | **Required.** Mem0 Platform API key |
| `user_id` | `MEM0_USER_ID` | `hermes-user` | User identifier for scoping memories |
| `agent_id` | `MEM0_AGENT_ID` | `hermes` | Agent identifier |
| `rerank` | — | `true` | Enable reranking for memory recall |
### Interactive
```bash
hermes memory setup
# Select "mem0", then "Open Source (self-hosted)"
# Follow the prompts for LLM, embedder, and vector store
```
### With flags
```bash
hermes memory setup mem0 --mode oss \
--oss-llm openai --oss-llm-key sk-... \
--oss-vector qdrant
```
### Supported providers
| Component | Providers |
|-----------|-----------|
| LLM | `openai` (default model `gpt-5-mini`), `ollama` (local, default `llama3.1:8b`) |
| Embedder | `openai` (default `text-embedding-3-small`), `ollama` (local, default `nomic-embed-text`) |
| Vector store | `qdrant` (local path or server), `pgvector` |
### Flag reference
| Flag | Description |
|------|-------------|
| `--mode` | `platform` or `oss` |
| `--oss-llm` | LLM provider (`openai` or `ollama`, default `openai`) |
| `--oss-llm-key` | LLM API key (for `openai`) |
| `--oss-llm-model` | Override the LLM model |
| `--oss-llm-url` | LLM base URL (for `ollama` or a custom endpoint) |
| `--oss-embedder` | Embedder provider (default `openai`) |
| `--oss-embedder-key` | Embedder API key |
| `--oss-vector` | Vector store (`qdrant` or `pgvector`, default `qdrant`) |
| `--oss-vector-path` | Local Qdrant storage path |
| `--oss-vector-host`, `--oss-vector-port` | PGVector or remote Qdrant host and port |
| `--oss-vector-user`, `--oss-vector-password`, `--oss-vector-dbname` | PGVector connection details |
| `--user-id` | Canonical user identifier |
| `--dry-run` | Preview the resolved config without writing it |
## Switching Modes
You can move between Platform and OSS at any time. Run the setup command again, or edit `~/.hermes/mem0.json` directly.
```bash
# Platform to OSS
hermes memory setup mem0 --mode oss --oss-llm-key sk-...
# OSS to Platform
hermes memory setup mem0 --mode platform --api-key sk-...
# Preview without writing anything
hermes memory setup mem0 --mode oss --oss-llm-key sk-... --dry-run
```
A self-hosted `~/.hermes/mem0.json` looks like this:
```json
{
"mode": "oss",
"oss": {
"llm": {"provider": "openai", "config": {"model": "gpt-5-mini"}},
"embedder": {"provider": "openai", "config": {"model": "text-embedding-3-small"}},
"vector_store": {"provider": "qdrant", "config": {"path": "~/.hermes/mem0_qdrant"}}
}
}
```
## Configuration
Behavioral settings live in `~/.hermes/mem0.json` and are written for you by `hermes memory setup`. Only the secret `MEM0_API_KEY` belongs in `~/.hermes/.env`.
| Key | Default | Description |
|-----|---------|-------------|
| `mode` | `platform` | `platform` (Mem0 Cloud) or `oss` (self-hosted) |
| `api_key` | none | Mem0 Platform API key, required in Platform mode. Stored in `.env` as `MEM0_API_KEY` |
| `user_id` | `hermes-user` | Identifier that scopes memories. See cross-channel behavior below |
| `agent_id` | `hermes` | Agent identifier attached to writes |
| `rerank` | `true` | Rerank search results for relevance (Platform mode only) |
### Cross-channel memories
Hermes can run from the CLI and from gateways like Telegram, Slack, and Discord. The `user_id` setting controls how memories are scoped across them:
- **Set a `user_id`** and it applies to every gateway, so one person gets a single merged memory store no matter where they talk to the agent.
- **Leave it unset** (or at the default `hermes-user`) and each gateway uses its own native id, keeping per-platform memories separate.
Either way, every write is tagged with `metadata.channel` (for example `telegram` or `cli`), so per-channel views are still possible at query time.
## Reliability
- **Circuit Breaker** — If Mem0's API fails 5 times in a row, Hermes stops calling it for 2 minutes, then retries. The agent keeps working fine without memory during that time.
- **Non-blocking** — All Mem0 API calls happen in background daemon threads. A slow or failed API call never blocks your conversation.
- **Thread-safe** — The Mem0 client uses lazy initialization with locking, safe for concurrent access.
- **Circuit breaker**: if Mem0 fails five times in a row, Hermes pauses calls for two minutes, then retries. The agent keeps working without memory during that window. Expected client errors, like a 404 on a missing memory id, do not count toward tripping the breaker.
- **Non-blocking**: every Mem0 call runs in a background daemon thread, so a slow or failed call never blocks your conversation.
- **Thread-safe**: the client uses lazy initialization with locking, and the background sync and prefetch threads are guarded so concurrent gateway messages cannot produce duplicate memories.
## Troubleshooting
### "Mem0 temporarily unavailable"
The circuit breaker tripped after five consecutive failures and resets after two minutes.
- **Platform mode**: check your API key and internet connection.
- **OSS mode**: make sure your vector store (Qdrant or PGVector) is running and reachable.
### OSS: vector store connection refused
```bash
# Local Qdrant: confirm the storage path is writable
ls -la ~/.hermes/mem0_qdrant
# Qdrant server: confirm it is reachable
curl http://localhost:6333/healthz
# PGVector: confirm PostgreSQL is accepting connections
pg_isready -h localhost -p 5432
```
### OSS: Ollama not reachable
```bash
curl http://localhost:11434/api/tags
```
### Memories not appearing
- `mem0_add` stores text verbatim with no extraction. Ordinary conversation turns are extracted automatically by the background sync.
- Search is semantic, so try a broader query.
- Confirm `user_id` is the same across sessions (check `~/.hermes/mem0.json`).
## Key Features
1. **Zero-Latency Recall** — Memories are prefetched in the background and cached, ready before you type
2. **Server-side Extraction** — Mem0's API automatically extracts and deduplicates facts from each exchange
3. **Non-blocking** — All API calls run in background daemon threads
4. **Fault Tolerant** — Circuit breaker ensures the agent works even if Mem0 is temporarily unreachable
5. **Additive Memory** — Works alongside Hermes' built-in file-based memory system (MEMORY.md, USER.md)
1. **Two ways to run**: managed Platform or fully self-hosted OSS, switchable at any time.
2. **Zero-latency recall**: memories are prefetched in the background and cached before you type.
3. **Automatic extraction**: Mem0 extracts and deduplicates facts from each exchange for you.
4. **Non-blocking and fault tolerant**: background threads plus a circuit breaker keep the agent responsive even when Mem0 is unreachable.
5. **Additive memory**: works alongside Hermes' built-in file memory (`MEMORY.md`, `USER.md`).
<CardGroup cols={2}>
<Card title="OpenClaw Integration" icon={<svg width="24" height="24" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="m153.5 173.5q24.62 1.46 46 13.5 12.11 8.1 17.5 21.5 0.74 2.45 0.5 5 0.09 0.81 1 1 1.48-4.9 1-10 5.04 10.48 1.5 22-9.81 27.86-35.5 42.5-26.17 14.97-56 19.5-2.77-0.4-2 1 2.86 1.27 6 1 25.64 1.53 48.5-10 0.34 10.08 2 20 1.08 5.76 5 10 1 1.5 0 3-31.11 20.84-68.5 17.5-23.7-5.7-32.5-28.5-4.39-9.18-3.5-19 15.41 6.23 32 4.5-20.68-6.39-39-18-34.81-27.22-12.5-65.5 11.84-14.83 29-23 4.21 7.66 11.5 12.5 3 1 6 0-26.04-34.62-29-78-0.13-8.46 2-16.5 1 6.5 2 13 3.43 39.53 24.5 73 2.03 2.28 4.5 4 0.5-1.25 1-2.5-1.27-6.54-5-12 0.5-0.75 1-1.5 9.72-3.43 20-4 0.55 10.34 8 17.5 1.94 0.74 4 0.5-17.8-64.6 16.5-122 0.98-1.79 1.5 0-28.21 56.64-13.5 118 1.08 1.43 2.5 0.5 2.21-4.98 2-10.5z" fill="currentColor"/><path fill-rule="evenodd" d="m454.5 97.5q-1.33 11.18-8.5 20-21.81 26.28-55.5 32-1.11-0.2-2 0.5 2.31 2.82 5.5 4.5 1 2 0 4-9.56 11.3-19.5 20 19.71-8.72 31-27 2.68-0.43 5 1-14.24 30.97-48 36.5-9.93 1.71-20 1.5-6.8-0.48-13 1 5.81 6.92 14 11-10.78 16.03-27 26.5 27.16-7.4 38-33.5 4.34 1.35 9 1-9.08 23.84-33 33.5-18.45 6.41-38 7 22.59 8.92 45-1 12.05-5.52 24-11 9.01-1.79 17 2.5 5.28-4.38 11-8 12.8-6.07 27-5 0 0.5 0 1-19.34 2.69-34 15.5 0.5 0.25 1 0.5 17.79-8.09 36-15 2.71-0.79 5-2 2.5-1 5-2 5.53-4.04 11-8 11.7-4.18 24-6.5 7.78-1.36 15 1.5-2.97 18.45-13.5 34-34.92 49.37-94.5 62.5-59.27 12.45-108-23-15.53-12.52-21.5-31.5-2.47-14.26 4-27-3.15 24.41 14 42-4.92-10.28-7-22-1.97-17.63 7-33 47.28-69.5 125.5-100 15.86-3.42 32-5.5 18.63-1.47 37 1.5z" fill="currentColor"/><path fill-rule="evenodd" d="m231.5 238.5q1.31-0.2 2 1-3.13 28.62 15 51-16.25 6.75-27-7.5-1-1-2 0 14.73 29.34 46 18.5 1.79 0.52 0 1.5-37.63 16.82-50.5-22.5-5.1-26.48 16.5-42z" fill="currentColor"/><path fill-rule="evenodd" d="m203.5 266.5q1.31-0.2 2 1-2.48 22.08 12 39-6.99 1.35-14 0.5 4.59 4.08 10 7-8.71 0.28-14.5-6.5-16.98-22.76 4.5-41z" fill="currentColor"/><path fill-rule="evenodd" d="m58.5 284.5q9.6-2.17 14.5 6 5.15 14.18-1 28-11.05-13.14-27.5-17.5 5.15-9.9 14-16.5z" fill="currentColor"/><path fill-rule="evenodd" d="m56.5 313.5q3.43 5.43 8 10-4.88 0.44-8 4-1.11-0.2-2 0.5 28.91 1.65 38 28.5 0.45 3.16-1 6-11.02-7.01-23-12.5-4.75-3.75-9.5-7.5 1.47 7.42 7 13 8.34 27.18 32 43 0.99 2.41-1.5 3.5-40.25 5.58-66.5-25.5-15.67-22.01-8-48 10.46-23.87 34.5-15z" fill="currentColor"/><path fill-rule="evenodd" d="m198.5 319.5q1.44 0.68 2.5 2 2.41 8.23 6 16 1.2 2.64-0.5 5-30.65 21.41-68 18.5-25.16-6.17-32.5-30.5 6.96 4.99 15.5 6.5 8.99 0.75 18 0.5 16.25 2.38 32-2.5 15.9-3.94 27-15.5z" fill="currentColor"/><path fill-rule="evenodd" d="m239.5 342.5q7.02-0.25 14 0.5 4.46 1.06 8 3.5-5.2 2.35-10 5.5-3.88 4.65-9 7.5-9.89-3.09-9.5-13 2.36-3.63 6.5-4z" fill="currentColor"/><path fill-rule="evenodd" d="m214.5 349.5q5.96 7.2 13.5 13 1 1 0 2-28.58 23.34-65.5 20.5-18.15-4.24-27.5-19.5 1.13 0.94 2.5 1.5 14.7 1.42 29-1.5 26.57-0.52 48-16z" fill="currentColor"/><path fill-rule="evenodd" d="m302.5 373.5q0.21 2.44-2 3.5-28.69 7.6-50.5-12.5-0.06-6.71 6.5-9 4.45-0.75 9-1 22.26 2.27 37 19z" fill="currentColor"/><path fill-rule="evenodd" d="m232.5 365.5q17.6 6.19 10.5 23-10.6 10.42-25.5 11.5-25.94 3.21-49-9 36.75-1.65 64-25.5z" fill="currentColor"/><path fill-rule="evenodd" d="m113.5 367.5q7.7-0.01 9.5 7-9.69 7.19-18.5 15.5-7.23 5.76-5.5-3.5 3.12-12.84 14.5-19z" fill="currentColor"/><path fill-rule="evenodd" d="m126.5 380.5q7.88-0.4 12 6.5-8.5 7.25-17 14.5-5.62-12.55 5-21z" fill="currentColor"/><path fill-rule="evenodd" d="m283.5 385.5q3.22 2.95 7 5.5 2.8 4.03 6 7.5 0.42 2.77-2 4-15.5-9.75-31-19.5-1.79-0.98 0-1.5 9.96 2.49 20 4z" fill="currentColor"/></svg>} href="/integrations/openclaw">
+22 -31
View File
@@ -98,20 +98,9 @@ add_result = add_tool.invoke(add_input)
```json Output
{
"results": [
{
"memory": "Name is Alex",
"event": "ADD"
},
{
"memory": "Is a vegetarian",
"event": "ADD"
},
{
"memory": "Is allergic to nuts",
"event": "ADD"
}
]
"message": "Memory processing has been queued for background execution",
"status": "PENDING",
"event_id": "3a1b2c3d-4e5f-6789-abcd-ef0123456789"
}
```
</CodeGroup>
@@ -173,23 +162,25 @@ result = search_tool.invoke(search_input)
```
```json Output
[
{
"id": "1a75e827-7eca-45ea-8c5c-cfd43299f061",
"memory": "Name is Alex",
"user_id": "alex",
"hash": "d0fccc8fa47f7a149ee95750c37bb0ca",
"metadata": {
"food": "vegan"
},
"categories": [
"personal_details"
],
"created_at": "2024-11-27T16:53:43.276872-08:00",
"updated_at": "2024-11-27T16:53:43.276885-08:00",
"score": 0.3810526501504994
}
]
{
"results": [
{
"id": "1a75e827-7eca-45ea-8c5c-cfd43299f061",
"memory": "Name is Alex",
"user_id": "alex",
"hash": "d0fccc8fa47f7a149ee95750c37bb0ca",
"metadata": {
"food": "vegan"
},
"categories": [
"personal_details"
],
"created_at": "2024-11-27T16:53:43.276872-08:00",
"updated_at": "2024-11-27T16:53:43.276885-08:00",
"score": 0.3810526501504994
}
]
}
```
</CodeGroup>
+1 -1
View File
@@ -41,7 +41,7 @@ load_dotenv()
# MEM0_API_KEY = 'your-mem0-key' # Replace with your actual Mem0 API key
# Initialize LangChain and Mem0
llm = ChatOpenAI(model="gpt-4")
llm = ChatOpenAI(model="gpt-5-mini")
mem0 = MemoryClient()
```
+58 -23
View File
@@ -1,6 +1,6 @@
---
title: OpenCode
description: "Add persistent memory to OpenCode with the Mem0 plugin — MCP server, lifecycle hooks, and slash commands."
description: "Add persistent memory to OpenCode with the Mem0 plugin — native SDK-backed memory tools, lifecycle hooks, and skills."
---
Add persistent memory to [**OpenCode**](https://opencode.ai) with the Mem0 plugin. Your agent forgets everything between sessions — Mem0 fixes that by storing decisions, preferences, and learnings so they carry over automatically.
@@ -30,27 +30,17 @@ echo 'export MEM0_API_KEY="m0-your-api-key"' >> ~/.bashrc && source ~/.bashrc
opencode plugin @mem0/opencode-plugin
```
Or using this command which does the same thing:
```bash
bunx @mem0/opencode-plugin@latest install
```
**Or let your agent do it** — paste this into OpenCode:
```
Install @mem0/opencode-plugin by following https://raw.githubusercontent.com/mem0ai/mem0/main/mem0-plugin/.opencode-plugin/README.md
Install @mem0/opencode-plugin by following https://raw.githubusercontent.com/mem0ai/mem0/main/integrations/mem0-plugin/.opencode-plugin/README.md
```
All commands auto-add the plugin and MCP server to your `~/.config/opencode/opencode.json`. Restart OpenCode — you get the MCP server, lifecycle hooks, and all `/mem0:` slash commands.
This adds the plugin to your `~/.config/opencode/opencode.json`. Restart OpenCode — you get the native memory tools, lifecycle hooks, and all `/mem0-*` slash commands. The memory tools are registered by the plugin itself via the `mem0ai` SDK — no MCP server to configure.
### Option B — MCP Only
### Option B — Standalone MCP Server
If you only need the memory tools without hooks or skills, add this to your `opencode.json` (project-level or global at `~/.config/opencode/opencode.json`):
If you only need the memory tools without the plugin's hooks or skills, point OpenCode at Mem0's hosted MCP server directly. Add this to your `opencode.json` (project-level or global at `~/.config/opencode/opencode.json`):
```json
{
@@ -69,13 +59,13 @@ If you only need the memory tools without hooks or skills, add this to your `ope
## What's Included
| Component | Plugin (A) | MCP Only (B) |
|-----------|:----------:|:------------:|
| MCP Server (9 memory tools) | Yes | Yes |
| Component | Plugin (A) | Standalone MCP (B) |
|-----------|:----------:|:------------------:|
| 9 memory tools | Native (SDK) | Remote MCP server |
| Lifecycle Hooks | Yes | No |
| 16 Slash Commands | Yes | No |
| 9 Skills | Yes | No |
## Available MCP Tools
## Available Memory Tools
| Tool | Description |
|------|-------------|
@@ -89,25 +79,70 @@ If you only need the memory tools without hooks or skills, add this to your `ope
| `delete_entities` | Delete a user/agent/app/run entity and its memories |
| `list_entities` | List users/agents/apps/runs stored in Mem0 |
## Memory scope
`search_memories`, `get_memories`, `add_memory`, and `delete_all_memories` accept an optional **`scope`** that controls how widely they read or write:
| Scope | Reads | Writes |
|-------|-------|--------|
| `project` *(default)* | this repo (`user_id` + `app_id`) | this repo |
| `session` | this run only (`+ run_id`) | this run |
| `global` | **all your projects in the workspace** (`app_id: "*"`) | user-wide |
Just ask naturally — e.g. *"search my memories across all my projects"* — and the agent passes `scope: "global"`. For normal questions it stays scoped to the current project automatically.
To change the **default** scope (used when no scope is passed), run the `/mem0-scope` skill:
```
/mem0-scope # show the current default scope + identity
/mem0-scope global # save & search across all your projects by default
/mem0-scope project # back to repo-only (the default)
```
The default persists in `~/.mem0/settings.json` (`default_scope`) and is read fresh on each memory operation, so a change applies immediately — no restart. `delete_all_memories` always requires an explicit `scope: "global"` to delete user-wide, so changing the default can't trigger a cross-project wipe.
The project id (`app_id`) is derived from your git remote (`owner-repo`), falling back to the git repo's root directory name, then the current directory. Launch OpenCode from inside your repo so memories scope to the project rather than your home directory.
## Lifecycle Hooks
The plugin uses the [mem0ai](https://www.npmjs.com/package/mem0ai) TypeScript SDK directly — pure TypeScript, no Python, no shell scripts.
| OpenCode Event | Hook | What happens |
|----------------|------|-------------|
| `config` | **Config** | Registers the `/mem0-*` slash commands (`config.command`) and adds the plugin's own `opencode-skills/` dir to OpenCode's `skills.paths` for in-place skill discovery (no copying) |
| `chat.message` | **Chat message** | Searches prior memories on session start, searches relevant memories before each prompt, auto-captures learnings periodically |
| `tool.execute.before` | **Pre-tool** | Blocks MEMORY.md writes, injects `user_id`/`app_id` on mem0 tool calls |
| `tool.execute.after` | **Post-tool** | Tracks stats, scans Bash errors and pre-fetches related error memories |
| `experimental.chat.system.transform` | **System transform** | Injects memory context (session memories, search results, error lookups) into the system prompt |
| `tool.execute.before` | **Pre-tool** | Blocks MEMORY.md writes, steering them to the `add_memory` tool |
| `tool.execute.after` | **Post-tool** | Scans Bash errors and pre-fetches related error memories |
| `experimental.chat.messages.transform` | **Messages transform** | Injects memory context (session memories, search results, error lookups) into the prompt |
| `experimental.session.compacting` | **Compaction** | Stores session state memory, then injects prior memories into compaction context so nothing is lost |
| `shell.env` | **Shell env** | Exports `MEM0_USER_ID`, `MEM0_APP_ID`, `MEM0_SESSION_ID`, and `MEM0_BRANCH` to all shell executions |
## Auto-dream (memory consolidation)
The plugin can automatically consolidate stored memories — merging duplicates, dropping stale/sensitive entries, and rewriting vague ones — so your memory set stays clean over time. It runs at most once per session, and only when **all** gates pass:
- **Time** — at least `minHours` (default 24) since the last consolidation
- **Sessions** — at least `minSessions` (default 5) sessions since then
- **Memories** — at least `minMemories` (default 20) stored for the project
A filesystem lock (`~/.mem0/mem0-dream.lock`) keeps two sessions from consolidating at once. Tune the thresholds with a `dream` block in `~/.mem0/settings.json`, or disable entirely with `MEM0_DREAM=false`:
```json
{
"dream": { "enabled": true, "auto": true, "minHours": 24, "minSessions": 5, "minMemories": 20 }
}
```
If auto-dream hasn't run yet, it's almost always because a gate hasn't been met (most often too few memories). Run `/mem0-status` to see the exact gate progress (e.g. `sessions 2/5, memories 3/20`), `/mem0-dream` to consolidate **now** regardless of the gates, or lower the thresholds above.
## Troubleshooting
- **No tools appearing** — Restart OpenCode after installing
- **"Connection failed"** — Verify your key is set: `echo $MEM0_API_KEY`
- **Plugin not loading** — Run `opencode plugin @mem0/opencode-plugin` again, then restart
- **Hooks not firing** — Hooks require the plugin install (Option A). MCP-only installs don't include hooks.
- **Auto-dream never runs** — It's gated (time + sessions + memories). Run `/mem0-status` to see which gate is blocking, or `/mem0-dream` to consolidate now.
- **Wrong project name / memories not found** — The project id comes from your git remote; launch OpenCode from inside the repo (not your home directory). Check the resolved id with `/mem0-status`.
<CardGroup cols={2}>
<Card title="Mem0 MCP Setup" icon="puzzle-piece" href="/platform/mem0-mcp">
+3
View File
@@ -59,6 +59,7 @@ For advanced settings, create `~/.pi/agent/mem0-config.json`:
"userId": "your-username",
"autoCapture": true,
"defaultScope": "project",
"searchThreshold": 0.3,
"dream": {
"enabled": true,
"auto": true,
@@ -75,12 +76,14 @@ For advanced settings, create `~/.pi/agent/mem0-config.json`:
| `userId` | `string` | `$MEM0_USER_ID` or `"default"` | User identity for memory scoping |
| `autoCapture` | `boolean` | `true` | Store facts from conversations automatically |
| `defaultScope` | `string` | `"project"` | Default memory scope: `project`, `session`, or `global` |
| `searchThreshold` | `number` | `0.3` | Minimum similarity score (0–1) a memory must reach to count as a match for `/mem0-search`, `/mem0-forget`, and `/mem0-pin`, enforced on each result's relevance score. Raise it to be stricter; lower it if relevant results are missed. |
| `dream.enabled` | `boolean` | `true` | Enable dream consolidation |
| `dream.auto` | `boolean` | `true` | Auto-trigger dreams when thresholds are met |
| `dream.minHours` | `number` | `24` | Minimum hours between auto-dreams |
| `dream.minSessions` | `number` | `5` | Minimum sessions before first auto-dream |
| `dream.minMemories` | `number` | `20` | Minimum memories before auto-dream triggers |
## What's Included
| Component | Description |
+1 -1
View File
@@ -121,7 +121,7 @@ async def websocket_endpoint(websocket: WebSocket):
# LLM for response generation
llm = OpenAILLMService(
api_key=os.getenv("OPENAI_API_KEY"),
model="gpt-3.5-turbo",
model="gpt-5-mini",
system_prompt="You are a helpful assistant that remembers past conversations."
)
@@ -1,22 +1,22 @@
---
title: Keywords AI
description: "Combine Mem0 persistent memory with Keywords AI observability for tracked, cost-optimized AI applications."
title: Respan
description: "Combine Mem0 persistent memory with Respan observability for tracked, cost-optimized AI applications."
---
Build AI applications with persistent memory and comprehensive LLM observability by integrating Mem0 with Keywords AI.
Build AI applications with persistent memory and comprehensive LLM observability by integrating Mem0 with Respan.
## Overview
Mem0 is a self-improving memory layer for LLM applications, enabling personalized AI experiences that save costs and delight users. Keywords AI provides complete LLM observability.
Mem0 is a self-improving memory layer for LLM applications, enabling personalized AI experiences that save costs and delight users. Respan (formerly Keywords AI) provides complete LLM observability.
Combining Mem0 with Keywords AI allows you to:
Combining Mem0 with Respan allows you to:
1. Add persistent memory to your AI applications
2. Track interactions across sessions
3. Monitor memory usage and retrieval with Keywords AI observability
3. Monitor memory usage and retrieval with Respan observability
4. Optimize token usage and reduce costs
<Note>
You can get your Mem0 API key from the <a href="https://app.mem0.ai/?utm_source=oss&utm_medium=integration-keywords" rel="nofollow">Mem0 dashboard</a>.
You can get your Mem0 API key from the <a href="https://app.mem0.ai/?utm_source=oss&utm_medium=integration-respan" rel="nofollow">Mem0 dashboard</a>.
</Note>
## Setup and Configuration
@@ -24,7 +24,7 @@ You can get your Mem0 API key from the <a href="https://app.mem0.ai/?utm_source=
Install the necessary libraries:
```bash
pip install mem0ai keywordsai-sdk
pip install mem0ai openai
```
Set up your environment variables:
@@ -34,13 +34,13 @@ import os
# Set your API keys
os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
os.environ["KEYWORDSAI_API_KEY"] = "your-keywords-api-key"
os.environ["KEYWORDSAI_BASE_URL"] = "https://api.keywordsai.co/api/"
os.environ["RESPAN_API_KEY"] = "your-respan-api-key"
os.environ["RESPAN_BASE_URL"] = "https://api.respan.ai/api/"
```
## Basic Integration Example
Here's a simple example of using Mem0 with Keywords AI:
Here's a simple example of using Mem0 with Respan:
```python
from mem0 import Memory
@@ -48,17 +48,17 @@ import os
# Configuration
api_key = os.getenv("MEM0_API_KEY")
keywordsai_api_key = os.getenv("KEYWORDSAI_API_KEY")
base_url = os.getenv("KEYWORDSAI_BASE_URL") # "https://api.keywordsai.co/api/"
respan_api_key = os.getenv("RESPAN_API_KEY")
base_url = os.getenv("RESPAN_BASE_URL") # "https://api.respan.ai/api/"
# Set up Mem0 with Keywords AI as the LLM provider
# Set up Mem0 with Respan as the LLM provider
config = {
"llm": {
"provider": "openai",
"config": {
"model": "gpt-5-mini",
"temperature": 0.0,
"api_key": keywordsai_api_key,
"api_key": respan_api_key,
"openai_base_url": base_url,
},
}
@@ -79,7 +79,7 @@ print(result)
## Advanced Integration with OpenAI SDK
For more advanced use cases, you can integrate Keywords AI with Mem0 through the OpenAI SDK:
For more advanced use cases, you can integrate Respan with Mem0 through the OpenAI SDK:
```python
from openai import OpenAI
@@ -88,8 +88,8 @@ import json
# Initialize client
client = OpenAI(
api_key=os.environ.get("KEYWORDSAI_API_KEY"),
base_url=os.environ.get("KEYWORDSAI_BASE_URL"),
api_key=os.environ.get("RESPAN_API_KEY"),
base_url=os.environ.get("RESPAN_BASE_URL"),
)
# Sample conversation messages
@@ -118,18 +118,18 @@ response = client.chat.completions.create(
print(json.dumps(response.model_dump(), indent=4))
```
For detailed information on this integration, refer to the official [Keywords AI Mem0 integration documentation](https://docs.keywordsai.co/integration/development-frameworks/mem0).
For detailed information on this integration, refer to the official [Respan Mem0 integration documentation](https://www.respan.ai/docs/integrations/mem0).
## Key Features
1. **Memory Integration**: Store and retrieve relevant information from past interactions
2. **LLM Observability**: Track memory usage and retrieval patterns with Keywords AI
2. **LLM Observability**: Track memory usage and retrieval patterns with Respan
3. **Session Persistence**: Maintain context across multiple user sessions
4. **Cost Optimization**: Reduce token usage through efficient memory retrieval
## Conclusion
Integrating Mem0 with Keywords AI provides a powerful combination for building AI applications with persistent memory and comprehensive observability. This integration enables more personalized user experiences while providing insights into your application's memory usage.
Integrating Mem0 with Respan provides a powerful combination for building AI applications with persistent memory and comprehensive observability. This integration enables more personalized user experiences while providing insights into your application's memory usage.
<CardGroup cols={2}>
<Card title="OpenAI Agents SDK" icon="cube" href="/integrations/openai-agents-sdk">
@@ -139,4 +139,3 @@ Integrating Mem0 with Keywords AI provides a powerful combination for building A
Monitor agent performance with AgentOps
</Card>
</CardGroup>
+8 -5
View File
@@ -26,12 +26,12 @@ Install the SDK provider and AI SDK:
npm install @mem0/vercel-ai-provider ai@^6
```
### Peer Dependencies
### Dependencies
`@mem0/vercel-ai-provider` v3.0.0 requires:
- `ai` v6+ (`^6.0.199`)
- `@ai-sdk/provider` v3+ (`^3.0.10`)
- Provider packages at v3+: `@ai-sdk/openai@^3`, `@ai-sdk/anthropic@^3`, `@ai-sdk/google@^3`, `@ai-sdk/groq@^3`, `@ai-sdk/cohere@^3`
`@mem0/vercel-ai-provider` bundles `ai`, all `@ai-sdk/*` provider packages, and `@ai-sdk/provider` as regular dependencies — you do **not** need to install them separately. The install command above (`npm install @mem0/vercel-ai-provider ai@^6`) is sufficient.
The only true peer dependency is `zod` (optional):
- `zod` v3+ (`^3.0.0`) — required only if you use Zod schemas in tool definitions
## Getting Started
@@ -305,6 +305,8 @@ These options can be passed per-request when creating a model instance:
| `rerank` | `boolean` | Enable reranking of results |
| `page` | `number` | Page number for pagination |
| `page_size` | `number` | Results per page |
| `mem0ApiKey` | `string` | Mem0 API key; overrides the `MEM0_API_KEY` env var |
| `host` | `string` | Custom Mem0 API base URL for self-hosted deployments |
## Key Features
@@ -312,6 +314,7 @@ These options can be passed per-request when creating a model instance:
- `retrieveMemories()`: Retrieves memory context for prompts as a formatted system prompt string.
- `getMemories()`: Get memories from your profile in array format.
- `addMemories()`: Adds user memories to enhance contextual responses.
- `searchMemories()`: Searches memories and returns the raw results array (semantic search rather than the full retrieval pipeline).
## Migrating from v2.x
+11 -6
View File
@@ -197,6 +197,7 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
- [Platform Features Overview](https://docs.mem0.ai/platform/features/platform-overview) [Platform]: Use when surveying what managed offers beyond CRUD.
- [V2 Memory Filters](https://docs.mem0.ai/platform/features/v2-memory-filters) [Platform]: Use when compound filters (AND/OR on metadata, entity, time) are needed at search.
- [Entity-Scoped Memory](https://docs.mem0.ai/platform/features/entity-scoped-memory) [Platform]: Use when partitioning memories by user, agent, app, or run.
- [Graph Memory](https://docs.mem0.ai/platform/features/graph-memory) [Platform]: Use when connecting facts across memories through shared entities for entity-centric or multi-hop questions.
- [Async Client](https://docs.mem0.ai/platform/features/async-client) [Platform]: Use when the app issues many concurrent Mem0 calls and needs non-blocking I/O.
- [Multimodal Support](https://docs.mem0.ai/platform/features/multimodal-support) [Platform]: Use when storing images or PDFs as memory input.
- [Custom Categories](https://docs.mem0.ai/platform/features/custom-categories) [Platform]: Use when the default categories do not match the domain.
@@ -285,7 +286,7 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
- [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.
- [AgentOps](https://docs.mem0.ai/integrations/agentops) [Both]: Use when tracking agent observability with memory metadata.
- [Keywords AI](https://docs.mem0.ai/integrations/keywords) [Both]: Use when monitoring with Keywords AI.
- [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.
## Cookbooks
@@ -366,6 +367,8 @@ All API Reference docs describe Mem0 Platform REST endpoints (requires API key).
- [Get Organization](https://docs.mem0.ai/api-reference/organization/get-org) [Platform]: Use when fetching one org.
- [Get Organization Members](https://docs.mem0.ai/api-reference/organization/get-org-members) [Platform]: Use when listing org members.
- [Add Organization Member](https://docs.mem0.ai/api-reference/organization/add-org-member) [Platform]: Use when inviting a member to an org.
- [Update Organization Member](https://docs.mem0.ai/api-reference/organization/update-org-member) [Platform]: Use when updating an org member's role.
- [Remove Organization Member](https://docs.mem0.ai/api-reference/organization/remove-org-member) [Platform]: Use when removing a member from an organization.
- [Delete Organization](https://docs.mem0.ai/api-reference/organization/delete-org) [Platform]: Use when removing an org.
### Projects
@@ -374,6 +377,9 @@ All API Reference docs describe Mem0 Platform REST endpoints (requires API key).
- [Get Project](https://docs.mem0.ai/api-reference/project/get-project) [Platform]: Use when fetching one project.
- [Get Project Members](https://docs.mem0.ai/api-reference/project/get-project-members) [Platform]: Use when listing project members.
- [Add Project Member](https://docs.mem0.ai/api-reference/project/add-project-member) [Platform]: Use when inviting a member to a project.
- [Update Project](https://docs.mem0.ai/api-reference/project/update-project) [Platform]: Use when updating project settings.
- [Update Project Member](https://docs.mem0.ai/api-reference/project/update-project-member) [Platform]: Use when updating a project member's role.
- [Remove Project Member](https://docs.mem0.ai/api-reference/project/remove-project-member) [Platform]: Use when removing a member from a project.
- [Delete Project](https://docs.mem0.ai/api-reference/project/delete-project) [Platform]: Use when removing a project.
### Webhooks
@@ -398,9 +404,9 @@ Each subdirectory is a Claude Code Skill (`SKILL.md` + supporting assets). Load
### Editor Plugin (shared glue)
Source: https://github.com/mem0ai/mem0/tree/main/mem0-plugin
Source: https://github.com/mem0ai/mem0/tree/main/integrations/mem0-plugin
The `mem0-plugin/` directory provides MCP server connection, lifecycle hooks, and skill bundling for Claude Code, Cursor, Codex, OpenCode, and Antigravity. It exposes 9 MCP tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`.
The `integrations/mem0-plugin/` directory provides MCP server connection, lifecycle hooks, and skill bundling for Claude Code, Cursor, Codex, OpenCode, and Antigravity. It exposes 9 MCP tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`.
Editor-specific setup docs (already listed above under `## Integrations > AI Coding Tools`):
@@ -459,6 +465,7 @@ Everything below is OSS-only provider configuration. Skip this entire section wh
- [LM Studio Embeddings](https://docs.mem0.ai/components/embedders/models/lmstudio) [OSS]: Use when embeddings run through LM Studio.
- [Together Embeddings](https://docs.mem0.ai/components/embedders/models/together) [OSS]: Use when embeddings run on Together.
- [LangChain Embeddings](https://docs.mem0.ai/components/embedders/models/langchain) [OSS]: Use when embeddings are wrapped behind a LangChain adapter.
- [FastEmbed](https://docs.mem0.ai/components/embedders/models/fastembed) [OSS]: Use when embeddings run locally via FastEmbed (ONNX).
### Vector Databases [OSS]
- [Vector Database Overview](https://docs.mem0.ai/components/vectordbs/overview) [OSS]: Use when choosing a vector store.
@@ -497,7 +504,5 @@ Everything below is OSS-only provider configuration. Skip this entire section wh
- [Custom Reranker Prompts](https://docs.mem0.ai/components/rerankers/custom-prompts) [OSS]: Use when rewriting reranker prompts.
- [Cohere Reranker](https://docs.mem0.ai/components/rerankers/models/cohere) [OSS]: Use for Cohere Rerank.
- [Sentence Transformer Reranker](https://docs.mem0.ai/components/rerankers/models/sentence_transformer) [OSS]: Use for local cross-encoder rerankers.
- [Hugging Face Reranker](https://docs.mem0.ai/components/rerankers/models/huggingface) [OSS]: Use for HF-hosted reranker models.
- [LLM Reranker (prompt)](https://docs.mem0.ai/components/rerankers/models/llm) [OSS]: Use when the reranker is a prompted LLM (config guide).
- [LLM Reranker](https://docs.mem0.ai/components/rerankers/models/llm_reranker) [OSS]: Use when the reranker is a prompted LLM (implementation reference).
- [Hugging Face Reranker](https://docs.mem0.ai/components/rerankers/models/huggingface) [OSS]: Use for HF-hosted reranker models.- [LLM Reranker](https://docs.mem0.ai/components/rerankers/models/llm_reranker) [OSS]: Use when the reranker is a prompted LLM (implementation reference).
- [Zero Entropy Reranker](https://docs.mem0.ai/components/rerankers/models/zero_entropy) [OSS]: Use for the Zero Entropy reranker.
+18 -10
View File
@@ -62,7 +62,8 @@ def add(
filters: dict = None,
output_format: str = None, # ❌ REMOVED
version: str = None # ❌ REMOVED
) -> Union[List[dict], dict]
) -> Union[List[dict], dict]:
...
```
#### v1.0.0 Signature
@@ -76,7 +77,8 @@ def add(
metadata: dict = None,
filters: dict = None,
infer: bool = True # ✅ NEW: Control memory inference
) -> dict # Always returns dict with "results" key
) -> dict: # Always returns dict with "results" key
...
```
#### Changes Summary
@@ -147,7 +149,8 @@ def search(
filters: dict = None, # Basic key-value only
output_format: str = None, # ❌ REMOVED
version: str = None # ❌ REMOVED
) -> Union[List[dict], dict]
) -> Union[List[dict], dict]:
...
```
#### v1.0.0 Signature
@@ -161,7 +164,8 @@ def search(
limit: int = 100,
filters: dict = None, # ✅ ENHANCED: Advanced operators
rerank: bool = True # ✅ NEW: Reranking support
) -> dict # Always returns dict with "results" key
) -> dict: # Always returns dict with "results" key
...
```
#### Enhanced Filtering
@@ -216,7 +220,8 @@ def get_all(
filters: dict = None,
output_format: str = None, # ❌ REMOVED
version: str = None # ❌ REMOVED
) -> Union[List[dict], dict]
) -> Union[List[dict], dict]:
...
```
#### v1.0.0 Signature
@@ -227,7 +232,8 @@ def get_all(
agent_id: str = None,
run_id: str = None,
filters: dict = None # ✅ ENHANCED: Advanced operators
) -> dict # Always returns dict with "results" key
) -> dict: # Always returns dict with "results" key
...
```
### update() Method
@@ -239,7 +245,8 @@ def update(
self,
memory_id: str,
data: str
) -> dict
) -> dict:
...
```
### delete() Method
@@ -250,7 +257,8 @@ def update(
def delete(
self,
memory_id: str
) -> dict
) -> dict:
...
```
### delete_all() Method
@@ -344,7 +352,7 @@ config = {
### New Configuration Options
#### Reranker Configuration
```python
```text
# Cohere reranker
"reranker": {
"provider": "cohere",
@@ -563,4 +571,4 @@ results = m.search(
<Info>
Use this reference to systematically update your codebase. Test each change thoroughly before deploying to production.
</Info>
</Info>
+19 -4
View File
@@ -6,9 +6,7 @@ versionFrom: "Open Source"
versionTo: "Platform"
---
# Migrate from Open Source to Platform
Move your Mem0 implementation to managed infrastructure with enterprise features.
## Overview
| Scope | Effort | Downtime |
| --------------------- | -------------- | ---------------------------- |
@@ -30,12 +28,29 @@ Move your Mem0 implementation to managed infrastructure with enterprise features
- **Production Grade**: Auto-scaling, high availability, dedicated support
</Info>
## Plan
### Plan
1. **Sign up**: Create an account on <a href="https://app.mem0.ai?utm_source=oss&utm_medium=migration-oss-to-platform" rel="nofollow">Mem0 Platform</a>.
2. **Get API Key**: Navigate to **Settings > API Keys** and generate a new key.
3. **Review Usage**: Identify where you instantiate `Memory` and where you call `search` or `get_all`.
## Migrate with Agent Skill
Paste this prompt into your coding agent. It uses a migration skill to produce a plan; once you review and approve it, the agent implements the changes.
```text
Migrate my project from Mem0 OSS to the Mem0 Platform SDK using the
mem0-oss-to-platform skill in the mem0ai/mem0 repo, at
skills/mem0-oss-to-platform/
Get the skill whichever way is easiest:
- install it: npx skills add https://github.com/mem0ai/mem0 --skill mem0-oss-to-platform
- if the mem0 repo is cloned locally, read it from skills/mem0-oss-to-platform/
- otherwise fetch that folder from github.com/mem0ai/mem0 (SKILL.md + references/)
Then read SKILL.md and begin the migration.
```
## Migrate
### 1. Import Memories Into Platform
+11 -11
View File
@@ -62,7 +62,7 @@ These changes produce a **+20 point improvement on LoCoMo** (71.4 → 91.6) and
|---|---|---|---|
| Constructor | `MemoryClient(api_key, org_id, project_id)` | `MemoryClient(api_key)` | Remove `org_id`, `project_id` from constructor |
| Method options | `client.add(messages, **kwargs)` | `client.add(messages, options=AddMemoryOptions(...))` | Use typed option classes (or `**kwargs` still works) |
| Removed params | `api_version`, `output_format`, `async_mode`, `filter_memories`, `expiration_date`, `keyword_search`, `force_add_only`, `batch_size`, `immutable`, `includes`, `excludes`, `enable_graph`, `org_name`, `project_name` | — | Remove from all calls |
| Removed params | `api_version`, `output_format`, `async_mode`, `filter_memories`, `keyword_search`, `force_add_only`, `batch_size`, `immutable`, `includes`, `excludes`, `enable_graph`, `org_name`, `project_name` | — | Remove from all calls |
### TypeScript Client SDK
@@ -70,7 +70,7 @@ These changes produce a **+20 point improvement on LoCoMo** (71.4 → 91.6) and
|---|---|---|---|
| Constructor | `new MemoryClient({ apiKey, organizationId, projectId })` | `new MemoryClient({ apiKey })` | Remove `organizationId`, `projectId`, `organizationName`, `projectName` |
| All params | snake_case: `user_id`, `agent_id`, `top_k` | camelCase: `userId`, `agentId`, `topK` | Rename all params to camelCase |
| Removed params | `api_version`, `output_format`, `async_mode`, `enable_graph`, `org_id`, `project_id`, `org_name`, `project_name`, `filter_memories`, `batch_size`, `force_add_only`, `immutable`, `expiration_date`, `includes`, `excludes`, `keyword_search` | — | Remove from all calls |
| Removed params | `api_version`, `output_format`, `async_mode`, `enable_graph`, `org_id`, `project_id`, `org_name`, `project_name`, `filter_memories`, `batch_size`, `force_add_only`, `immutable`, `includes`, `excludes`, `keyword_search` | — | Remove from all calls |
| Output format enum | `OutputFormat.V1`, `OutputFormat.V1_1` | Removed | v1.1 is now always used |
| API version enum | `API_VERSION.V1`, `API_VERSION.V2` | Removed | Handled internally |
@@ -328,27 +328,27 @@ The new algorithm automatically creates a parallel entity store collection named
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 → Entity Linking
## Graph Memory: Now Built-In
Graph store support has been removed from the open-source SDK. It is replaced by **built-in entity linking**, which runs natively with no external dependencies.
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.
**What was removed:**
- `enable_graph` / `enableGraph` config flag
- `graph_store` / `graphStore` configuration block (Neo4j, Memgraph, Kuzu, Apache AGE, Neptune)
- All graph memory code paths (~4000 lines)
- All external graph store code paths (~4000 lines)
**What replaces it:**
Entity linking 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. At search time, entities from the query are matched against this collection and used to boost relevant memories. The boost is folded into the combined `score` on each result.
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.
**Migration:**
- Remove `enable_graph` / `enableGraph` from your config
- Remove the `graph_store` / `graphStore` block — it is no longer read
- Uninstall graph drivers (neo4j, memgraph, etc.) if you were using them only for Mem0
- No data migration is required. Entity linking activates automatically on the next `add()` call.
- 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.
<Warning>
Graph relationships exposed via the old `relations` field on search results are no longer populated. Entity relationships are consumed indirectly through retrieval ranking, not exposed as a queryable graph structure. If your application depended on traversing graph relationships directly, 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. 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.
</Warning>
## How the New Algorithm Works
@@ -423,7 +423,7 @@ These parameters have been removed across all SDKs. Remove them from your code:
**All methods:** `api_version`, `output_format`, `async_mode`, `org_name`, `project_name`, `org_id`, `project_id`
**add():** `enable_graph`, `immutable`, `expiration_date`, `filter_memories`, `batch_size`, `force_add_only`, `includes`, `excludes`, `keyword_search`
**add():** `enable_graph`, `immutable`, `filter_memories`, `batch_size`, `force_add_only`, `includes`, `excludes`, `keyword_search`
**search():** `enable_graph`
@@ -437,7 +437,7 @@ These parameters have been removed across all SDKs. Remove them from your code:
**All methods:** `OutputFormat` enum, `API_VERSION` enum
**add():** `enable_graph` / `enableGraph`, `async_mode` / `asyncMode`, `output_format` / `outputFormat`, `immutable`, `expiration_date` / `expirationDate`, `filter_memories` / `filterMemories`, `batch_size` / `batchSize`, `force_add_only` / `forceAddOnly`, `includes`, `excludes`, `keyword_search` / `keywordSearch`
**add():** `enable_graph` / `enableGraph`, `async_mode` / `asyncMode`, `output_format` / `outputFormat`, `immutable`, `filter_memories` / `filterMemories`, `batch_size` / `batchSize`, `force_add_only` / `forceAddOnly`, `includes`, `excludes`, `keyword_search` / `keywordSearch`
**search():** `enable_graph` / `enableGraph`
+11 -13
View File
@@ -1,6 +1,6 @@
---
title: "Platform: Migrating to the New Memory Algorithm"
description: "Guide for Mem0 Platform users to adopt the new memory algorithm with single-pass extraction, entity linking, and multi-signal retrieval."
description: "Guide for Mem0 Platform users to adopt the new memory algorithm with single-pass extraction, built-in graph memory, and multi-signal retrieval."
icon: "arrow-right"
iconType: "solid"
---
@@ -18,8 +18,7 @@ The new Mem0 memory algorithm is a ground-up redesign of how memories are extrac
| **Extraction** | Two LLM passes (extract + merge) | Single-pass ADD-only (one LLM call) |
| **Memory mutations** | ADD, UPDATE, DELETE | ADD only — nothing is overwritten or deleted |
| **Agent-generated facts** | Often ignored | First-class, stored with equal weight |
| **Entity linking** | Not available | Entities extracted and linked across memories |
| **Graph memory** | Separate graph store + dashboard visualization | Replaced by built-in entity linking, no graph visuals on platform dashboard |
| **Graph memory** | External graph store (Neo4j, etc.) + manual setup | Built-in and automatic; entities extracted and linked across memories natively, no external store |
| **Retrieval** | Semantic (vector) only | Hybrid retrieval combining multiple signals |
## What This Means for Your Application
@@ -216,7 +215,7 @@ client.add(messages, user_id="alice")
# async_mode and output_format removed (async by default, v1.1 always)
```
**Removed parameters:** `org_id`, `project_id`, `api_version`, `output_format`, `async_mode`, `enable_graph`, `immutable`, `expiration_date`, `filter_memories`, `batch_size`, `force_add_only`, `includes`, `excludes`, `keyword_search`, `org_name`, `project_name`
**Removed parameters:** `org_id`, `project_id`, `api_version`, `output_format`, `async_mode`, `enable_graph`, `immutable`, `filter_memories`, `batch_size`, `force_add_only`, `includes`, `excludes`, `keyword_search`, `org_name`, `project_name`
### TypeScript Client SDK
@@ -243,25 +242,24 @@ await client.search("query", {
});
```
**Removed:** `OutputFormat` enum, `API_VERSION` enum, `organizationId`, `projectId`, `organizationName`, `projectName`, `enableGraph`, `asyncMode`, `outputFormat`, `immutable`, `expirationDate`, `filterMemories`, `batchSize`, `forceAddOnly`, `includes`, `excludes`, `keywordSearch`
**Removed:** `OutputFormat` enum, `API_VERSION` enum, `organizationId`, `projectId`, `organizationName`, `projectName`, `enableGraph`, `asyncMode`, `outputFormat`, `immutable`, `filterMemories`, `batchSize`, `forceAddOnly`, `includes`, `excludes`, `keywordSearch`
<Info>
For the full list of parameter changes across all SDKs, see the [OSS migration guide](/migration/oss-v2-to-v3#removed-parameters-reference).
</Info>
## Graph Memory → Entity Linking
## Graph Memory Is Now Built-In
Graph memory has been replaced by **built-in entity linking**. The changes:
Graph memory no longer requires an external graph database. It is now **native to the platform** and automatic. The changes:
- **Graph visualizations removed from the platform dashboard.** The graph view in your project dashboard is no longer available.
- **`enable_graph` project setting removed.** The toggle is gone from the dashboard; the API parameter is ignored.
- **No external graph store to configure.** Previously graph memory required a separate Neo4j (or similar) deployment. Entity linking runs natively inside the platform — nothing to provision, no connection strings to manage.
- **Entity linking is the native replacement.** Entities (proper nouns, quoted text, compound noun phrases) are automatically extracted from every memory and linked across memories belonging to the same user. At search time, entities from the query are matched against this index and used to boost ranking. The boost is folded into the combined `score` returned on each result.
- **No external graph store to configure.** Previously, graph memory required a separate Neo4j (or similar) deployment. Mem0 now builds the graph itself from your memories, so there is nothing to provision and no connection strings to manage.
- **Always on, no flag.** The `enable_graph` project setting is no longer needed; graph memory activates automatically. (The API parameter is now ignored if sent.)
- **Connections power retrieval directly.** Entities (proper nouns, quoted text, compound noun phrases) are automatically extracted from every memory and linked across memories belonging to the same user. At search time, entities from the query are matched against the graph and used to boost ranking. The boost is folded into the combined `score` returned on each result.
**No migration work is required.** Entity linking activates automatically for all projects on the new algorithm. Existing memories are not re-processed, but any new memories you add will be indexed for entity-based retrieval going forward.
**No migration work is required.** Graph memory activates automatically for all projects on the new algorithm. Existing memories are not re-processed, but any new memories you add are added to the graph going forward. See [Graph Memory](/platform/features/graph-memory) for how the built-in graph works.
<Note>
If your application previously read graph relations from the API response (`relations` field on search results), note that this field is no longer populated. Entity relationships are now consumed indirectly through retrieval ranking, not exposed as a separate graph structure.
If your application previously read graph relations from the API response (`relations` field on search results), note that this field is no longer populated. Entity connections are now applied through retrieval ranking rather than returned as a separate `relations` array.
</Note>
## Migration Checklist
+1 -1
View File
@@ -130,7 +130,7 @@ memory = Memory.from_config_file("config.yaml")
</Tabs>
<Info icon="check">
Run `memory.add(["Remember my favorite cafe in Tokyo."], user_id="alex")` and then `memory.search("favorite cafe", filters={"user_id": "alex"})`. You should see the Qdrant collection populate and the reranker mark the memory as a top hit.
Run `memory.add("Remember my favorite cafe in Tokyo.", user_id="alex")` and then `memory.search("favorite cafe", filters={"user_id": "alex"})`. You should see the Qdrant collection populate and the reranker mark the memory as a top hit.
</Info>
## Tune component settings
+1 -1
View File
@@ -18,7 +18,7 @@ icon: "bolt"
</Warning>
<Note>
Working in TypeScript? The Node SDK still uses synchronous calls—use `Memory` there and rely on Python’s `AsyncMemory` when you need awaited operations.
Working in TypeScript? The OSS `Memory` class in the Node SDK (`mem0ai/oss`) is also fully async — every method returns a `Promise` and must be `await`ed. Python’s `AsyncMemory` serves the same purpose within Python async frameworks like FastAPI. Both runtimes support awaited memory operations; choose the SDK that matches your language.
</Note>
## Feature anatomy
@@ -165,8 +165,7 @@ await memory.add("Yesterday, I ordered a laptop, the order id is 12345", { userI
{"memory": "Ordered a laptop", "event": "ADD"},
{"memory": "Order ID: 12345", "event": "ADD"},
{"memory": "Order placed yesterday", "event": "ADD"}
],
"relations": []
]
}
```
</CodeGroup>
@@ -188,8 +187,7 @@ await memory.add("I like going to hikes", { userId: "user123" });
```json Output
{
"results": [],
"relations": []
"results": []
}
```
</CodeGroup>
@@ -41,6 +41,14 @@ Multimodal support lets Mem0 extract facts from images alongside regular text. A
## Configure it
<Warning>
You must set `enable_vision: True` in your LLM config for image content to be processed. Without it, image turns are silently dropped and no vision memories are created. Example:
```python
config = {"llm": {"provider": "openai", "config": {"enable_vision": True, "vision_details": "auto"}}}
client = Memory.from_config(config)
```
</Warning>
### Add image messages from URLs
<CodeGroup>
@@ -66,7 +74,7 @@ client.add(messages, user_id="alice")
```
```ts TypeScript
import { Memory } from "mem0ai";
import { Memory } from "mem0ai/oss";
const client = new Memory();
@@ -123,7 +131,7 @@ client.add(messages, user_id="alice")
```ts TypeScript
import fs from "fs";
import { Memory } from "mem0ai";
import { Memory } from "mem0ai/oss";
function encodeImage(imagePath: string) {
const buffer = fs.readFileSync(imagePath);
@@ -226,7 +234,7 @@ client.add(messages, user_id="user123")
<CodeGroup>
```python Python
from mem0 import Memory
from mem0.exceptions import InvalidImageError, FileSizeError
from mem0.exceptions import ValidationError
client = Memory()
@@ -242,16 +250,14 @@ try:
client.add(messages, user_id="user123")
print("Image processed successfully")
except InvalidImageError:
print("Invalid image format or corrupted file")
except FileSizeError:
print("Image file too large")
except ValidationError as exc:
print(f"Image validation error: {exc}")
except Exception as exc:
print(f"Unexpected error: {exc}")
```
```ts TypeScript
import { Memory } from "mem0ai";
import { Memory } from "mem0ai/oss";
const client = new Memory();
@@ -124,7 +124,7 @@ config = {
"provider": "llm_reranker",
"config": {
"provider": "openai",
"model": "gpt-4o-mini",
"model": "gpt-5-mini",
"api_key": "your-openai-api-key",
"top_k": 5
}
@@ -150,7 +150,7 @@ config = {
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4",
"model": "gpt-5-mini",
"api_key": "your-openai-api-key"
}
},
+23 -1
View File
@@ -1779,6 +1779,11 @@
"type": "object",
"description": "Entity and metadata filters. Must include at least one entity ID (`user_id`, `agent_id`, `app_id`, or `run_id`).",
"additionalProperties": true
},
"show_expired": {
"type": "boolean",
"default": false,
"description": "When true, include memories whose `expiration_date` has passed. Expired memories are hidden by default."
}
}
},
@@ -1977,6 +1982,12 @@
"additionalProperties": true,
"description": "User-supplied metadata to attach to each extracted memory."
},
"expiration_date": {
"type": "string",
"format": "date",
"nullable": true,
"description": "Optional expiration date in YYYY-MM-DD format. After this date, memories are hidden from search and get-all unless `show_expired` is true."
},
"custom_instructions": {
"type": "string",
"description": "Project-level instructions that guide extraction for this call."
@@ -2094,6 +2105,11 @@
"description": "Entity and metadata filters. Must include at least one entity ID (`user_id`, `agent_id`, `app_id`, or `run_id`). Supports `AND`, `OR`, `NOT`, and comparison operators (`in`, `gte`, `lte`, `gt`, `lt`, `contains`, `icontains`, `ne`).",
"additionalProperties": true
},
"show_expired": {
"type": "boolean",
"default": false,
"description": "When true, include memories whose `expiration_date` has passed. Expired memories are hidden by default."
},
"top_k": {
"type": "integer",
"minimum": 1,
@@ -2432,6 +2448,12 @@
"metadata": {
"type": "object",
"description": "Additional metadata associated with the memory"
},
"expiration_date": {
"type": "string",
"format": "date",
"nullable": true,
"description": "Expiration date in YYYY-MM-DD format, or null to clear the expiration date."
}
}
}
@@ -6256,4 +6278,4 @@
}
},
"x-original-swagger-version": "2.0"
}
}
@@ -117,7 +117,7 @@ results_without_criteria = client.search(
### Compare Results
### Search Results (with Criteria)
```python
```text
[
{"memory": "User feels refreshed and ready to take on anything on a beautiful sunny day", "score": 0.666, ...},
{"memory": "User finally has time to draw something after a long time", "score": 0.616, ...},
@@ -128,7 +128,7 @@ results_without_criteria = client.search(
```
### Search Results (without Criteria)
```python
```text
[
{"memory": "User is happy today", "score": 0.607, ...},
{"memory": "User feels refreshed and ready to take on anything on a beautiful sunny day", "score": 0.512, ...},
+1 -1
View File
@@ -190,7 +190,7 @@ messages = [
client.add(messages, user_id='alice')
```
```python Memories with categories
```text Memories with categories
# Following categories will be created for the memories added
Sometimes draws and sketches in free time (hobbies)
Is quite athletic (sports)
@@ -5,6 +5,10 @@ description: Scope conversations by user, agent, app, and session so memories la
Mem0's Platform API lets you separate memories for different users, agents, and apps. By tagging each write and query with the right identifiers, you can prevent data from mixing between them, maintain clear audit trails, and control data retention.
<Note>
**Entity IDs vs. graph entities.** This page covers the `user_id` / `agent_id` / `app_id` / `run_id` identifiers used to *scope* memories. These are different from the **graph entities** (the people, places, and concepts surfaced in [Graph Memory](/platform/features/graph-memory)).
</Note>
<Tip icon="layers">
Want the long-form tutorial? The <Link href="/cookbooks/essentials/entity-partitioning-playbook">Partition Memories by Entity</Link> cookbook walks through multi-agent storage, debugging, and cleanup step by step.
</Tip>
+93
View File
@@ -0,0 +1,93 @@
---
title: "Graph Memory"
description: "Mem0 Platform builds a native graph linking people, places, and concepts across your memories, with no external graph database to provision."
icon: "circle-nodes"
iconType: "solid"
---
Mem0 Platform automatically organizes your memories into a **graph**: the **graph entities** mentioned across your memories (the people, places, organizations, and concepts they refer to) become nodes, and memories that share an entity are connected. This is how Mem0 reasons across separate facts, for example linking everything it knows about a person, a company, or a project, without you defining any schema.
Graph Memory is **built in**. There is no Neo4j, Memgraph, or other graph store to deploy, no connection strings to manage, and nothing to enable. It runs natively inside the platform and is always on.
<Info>
**Graph Memory matters when…**
- You ask entity-centric questions like "what do we know about Alice?" and expect facts pulled from many different conversations
- Your app needs multi-hop recall, connecting a fact in one memory to a related fact in another
- You previously used an external graph store and want the same cross-memory connections with zero infrastructure
</Info>
<Note>
**Graph entities vs. entity IDs.** The entities in your graph (people, places, and concepts extracted from memory text) are different from the *entity IDs* (`user_id`, `agent_id`, `app_id`, `run_id`) used to scope memories. Those are covered in [Entity-Scoped Memory](/platform/features/entity-scoped-memory).
</Note>
<Note>
Graph Memory is the native successor to Mem0's earlier graph store integration. Earlier versions connected an external graph database (Neo4j and others) and exposed a `relations` field. Mem0 now builds the graph itself from your memories. See [What changed from the external graph store](#what-changed-from-the-external-graph-store) below.
</Note>
## How it works
Graph Memory is built and used across the two phases of the memory pipeline: **extraction** (when you add memories) and **retrieval** (when you search).
### 1. Entities become nodes
Every time you add a memory, Mem0 extracts the **entities** it contains: the proper nouns, names, and key phrases that identify a specific person, place, organization, product, or concept (for example *Alice*, *San Francisco*, *Acme Corp*, *the Q1 roadmap*). Each distinct entity is stored once and embedded, so entities that refer to the same thing can be matched even when they are phrased differently.
### 2. Shared entities become connections
When the same entity appears in more than one memory, those memories are **linked** through that entity. Over time this forms a graph: a web of entities, each connecting all the memories that mention it. The connections are derived directly from your data. There is no relationship schema to define and nothing to label by hand.
### 3. The graph powers retrieval
At search time, Mem0 extracts the entities from your query and matches them against the graph. Memories connected to those entities receive a ranking boost, which is combined with semantic (vector) and keyword (BM25) scores into the single `score` returned on each result.
This is what lets Mem0 answer entity-centric and multi-hop questions: a query about *Alice* surfaces facts about Alice that live in completely different memories, because the graph connects them. The connecting-facts-across-memories behavior contributes to Mem0's gains on multi-hop and temporal benchmarks. See [Memory Evaluation](/core-concepts/memory-evaluation).
<Info>
Graph Memory affects **ranking**, not the response shape. Search results come back in the normal format with a combined `score`; there is no separate graph payload to parse.
</Info>
## What's in the graph
| Element | What it is |
| --- | --- |
| **Graph entity** (node) | A distinct person, place, organization, product, or concept extracted from your memories (e.g. *Alice*, *Acme Corp*). Distinct from the user/agent/app/run *entity IDs* used to scope memories. |
| **Memory node** | An individual memory (fact) stored for a user, agent, or session. |
| **Connection** | A link between an entity and every memory that mentions it. Two entities are related when they co-occur in one or more memories. |
Graph Memory captures **which entities your memories are about and how they connect through shared context**. It does not assign typed, labeled relationships between entities (it won't, for example, record a "manages" edge from one person to another); connections are inferred from co-occurrence rather than declared. This is what makes it schema-free and zero-configuration.
## Availability
Graph Memory is **automatic and included on all plans**. It activates on the new memory algorithm with no flag, no configuration, and no external dependencies. You don't need to do anything to benefit from it.
```python
from mem0 import MemoryClient
client = MemoryClient(api_key="your-api-key")
# Entities are extracted and linked into the graph automatically on add
client.add(
messages=[
{"role": "user", "content": "I work at Acme Corp with Alice on the Q1 roadmap"}
],
user_id="jordan",
)
# Entity matches from the query are used to connect and boost related memories
results = client.search(
query="who does jordan work with?",
filters={"user_id": "jordan"},
)
```
## What changed from the external graph store
Earlier versions of Mem0 offered graph memory by connecting an **external graph database** (Neo4j, Memgraph, Kuzu, Apache AGE, or Neptune) through an `enable_graph` flag and a `graph_store` configuration block. That integration has been replaced by **native, built-in Graph Memory**:
- **No external graph store.** The graph is built inside Mem0 from your memories. There is nothing to provision or connect.
- **Always on, all plans.** The `enable_graph` flag is no longer needed; Graph Memory is automatic. (If you still send the parameter, it is ignored.)
- **Connections power retrieval directly.** Entity connections are folded into the combined `score` on each result. The standalone `relations` field that the external graph store returned is no longer populated. If your application read that field, see the migration guide below.
<Card title="Platform Migration Guide" icon="arrow-right" href="/migration/platform-v2-to-v3">
Full details on the move to the new algorithm, including the `relations` field change.
</Card>
+5 -5
View File
@@ -108,10 +108,10 @@ print(response)
```javascript JavaScript
// Basic Export request
const filters = {"user_id": "alice"};
const basicFilters = {"user_id": "alice"};
const response = await client.createMemoryExport({
schema: json_schema,
filters: filters
filters: basicFilters
});
// Export with custom instructions and additional filters
@@ -124,16 +124,16 @@ const export_instructions = `
`;
// For create operation, using only user_id filter as requested
const filters = {
const exportFilters = {
"AND": [
{"user_id": "alex"},
{"created_at": {"gte": "2024-01-01"}}
]
}
};
const responseWithInstructions = await client.createMemoryExport({
schema: json_schema,
filters: filters,
filters: exportFilters,
exportInstructions: export_instructions
});
+2
View File
@@ -45,10 +45,12 @@ Let your assistant execute an end-to-end workflow in an existing repo. Invoked a
```bash
npx skills add https://github.com/mem0ai/mem0 --skill mem0-integrate
npx skills add https://github.com/mem0ai/mem0 --skill mem0-test-integration
npx skills add https://github.com/mem0ai/mem0 --skill mem0-oss-to-platform
```
- `/mem0-integrate` — wire Mem0 into an existing repository using a goal-driven, test-first pipeline. Detects the stack, asks whether to use Platform or OSS, writes failing tests first, and keeps the integration additive and feature-flagged.
- `/mem0-test-integration` — verify what `/mem0-integrate` produced. Runs the repo's native test suite and a real end-to-end smoke flow against your API key, then produces a scorecard.
- `/mem0-oss-to-platform` — migrate an existing project from Mem0 OSS to the hosted Platform SDK. Audits where Mem0 is used, writes a reviewable migration plan, then executes it on approval.
See the [skills index](https://github.com/mem0ai/mem0/tree/main/skills) for the full catalog.
Submodule
+1
Submodule evaluation added at 4b61c5d31b
-31
View File
@@ -1,31 +0,0 @@
# Run the experiments
run-mem0-add:
python run_experiments.py --technique_type mem0 --method add
run-mem0-search:
python run_experiments.py --technique_type mem0 --method search --output_folder results/ --top_k 30
run-mem0-plus-add:
python run_experiments.py --technique_type mem0 --method add --is_graph
run-mem0-plus-search:
python run_experiments.py --technique_type mem0 --method search --is_graph --output_folder results/ --top_k 30
run-rag:
python run_experiments.py --technique_type rag --chunk_size 500 --num_chunks 1 --output_folder results/
run-full-context:
python run_experiments.py --technique_type rag --chunk_size -1 --num_chunks 1 --output_folder results/
run-langmem:
python run_experiments.py --technique_type langmem --output_folder results/
run-zep-add:
python run_experiments.py --technique_type zep --method add --output_folder results/
run-zep-search:
python run_experiments.py --technique_type zep --method search --output_folder results/
run-openai:
python run_experiments.py --technique_type openai --output_folder results/

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