Compare commits

..
43 changed files with 127 additions and 127 deletions
+4 -4
View File
@@ -21,10 +21,10 @@ Package workflows keep their own push-to-main and manual triggers. Their `pull_r
| Mem0 Plugin | `mem0-plugin-checks.yml` | Push to main (`integrations/mem0-plugin/`, excluding `.opencode-plugin/`), manual | pytest + hook exec bits + JSON manifest validation on Python 3.10, 3.11, 3.12 | | Mem0 Plugin | `mem0-plugin-checks.yml` | Push to main (`integrations/mem0-plugin/`, excluding `.opencode-plugin/`), manual | pytest + hook exec bits + JSON manifest validation on Python 3.10, 3.11, 3.12 |
| OpenCode Plugin | `opencode-plugin-checks.yml` | Push to main (`.opencode-plugin/`), manual | Bun: tsc + build + dist artifact check | | OpenCode Plugin | `opencode-plugin-checks.yml` | Push to main (`.opencode-plugin/`), manual | Bun: tsc + build + dist artifact check |
| Pi Agent Plugin | `pi-agent-plugin-checks.yml` | Push to main (`integrations/pi-agent-plugin/`), manual | tsc + vitest + tsup on Node 20, 22 | | Pi Agent Plugin | `pi-agent-plugin-checks.yml` | Push to main (`integrations/pi-agent-plugin/`), manual | tsc + vitest + tsup on Node 20, 22 |
| DeepSeek Harness Plugin | `dsh-mem0-checks.yml` | Push to main (`integrations/dsh-mem0/`), manual | tsc + vitest + tsup on Node 20, 22 | | DeepSeek Harness Plugin | `deepseek-plugin-checks.yml` | Push to main (`integrations/deepseek-plugin/`), manual | tsc + vitest + tsup on Node 20, 22 |
| n8n Node | `n8n-nodes-mem0-checks.yml` | Push to main (`integrations/n8n-nodes-mem0/`), manual | ESLint + tsc build on Node 20 | | n8n Node | `n8n-nodes-mem0-checks.yml` | Push to main (`integrations/n8n-nodes-mem0/`), manual | ESLint + tsc build on Node 20 |
| Zapier App | `zapier-mem0-checks.yml` | Push to main (`integrations/zapier-mem0/`), manual | tsc + `zapier validate` + offline unit tests on Node 22 | | Zapier App | `zapier-mem0-checks.yml` | Push to main (`integrations/zapier-mem0/`), manual | tsc + `zapier validate` + offline unit tests on Node 22 |
| strands-mem0 | `strands-mem0-checks.yml` | Push to main (`integrations/strands-mem0/`), manual | Ruff + mypy + pytest + hatch build on Python 3.10, 3.11, 3.12 | | mem0-strands | `mem0-strands-checks.yml` | Push to main (`integrations/mem0-strands/`), manual | Ruff + mypy + pytest + hatch build on Python 3.10, 3.11, 3.12 |
| docs llms.txt | `docs-llms-txt-check.yml` | Manual | `docs/llms.txt` coverage | | docs llms.txt | `docs-llms-txt-check.yml` | Manual | `docs/llms.txt` coverage |
| GitHub Scripts | inline in `ci-gate.yml` | none | `node` over every `.github/scripts/*.test.js` | | GitHub Scripts | inline in `ci-gate.yml` | none | `node` over every `.github/scripts/*.test.js` |
@@ -60,9 +60,9 @@ Requiring `CI Gate` also means fork PRs from first-time contributors cannot merg
| OpenClaw | `openclaw-cd.yml` | `openclaw-v*` | npm (`@mem0/openclaw-mem0`) | | OpenClaw | `openclaw-cd.yml` | `openclaw-v*` | npm (`@mem0/openclaw-mem0`) |
| OpenCode Plugin | `opencode-plugin-cd.yml` | `opencode-v*` | npm (`@mem0/opencode-plugin`) | | OpenCode Plugin | `opencode-plugin-cd.yml` | `opencode-v*` | npm (`@mem0/opencode-plugin`) |
| Pi Agent Plugin | `pi-agent-plugin-cd.yml` | `pi-agent-v*` | npm (`@mem0/pi-agent-plugin`) | | Pi Agent Plugin | `pi-agent-plugin-cd.yml` | `pi-agent-v*` | npm (`@mem0/pi-agent-plugin`) |
| DeepSeek Harness Plugin | `dsh-mem0-cd.yml` | `dsh-mem0-v*` | npm (`@mem0/dsh-mem0`) | | DeepSeek Harness Plugin | `deepseek-plugin-cd.yml` | `deepseek-plugin-v*` | npm (`@mem0/deepseek-plugin`) |
| n8n Node | `n8n-nodes-mem0-cd.yml` | `n8n-nodes-mem0-v*` | npm (`@mem0/n8n-nodes-mem0`) | | n8n Node | `n8n-nodes-mem0-cd.yml` | `n8n-nodes-mem0-v*` | npm (`@mem0/n8n-nodes-mem0`) |
| strands-mem0 | `strands-mem0-cd.yml` | `strands-mem0-v*` | PyPI (`strands-mem0`) | | mem0-strands | `mem0-strands-cd.yml` | `mem0-strands-v*` | PyPI (`mem0-strands`) |
- Package CD workflows are `workflow_dispatch`-only, with `tag` and `prerelease` inputs. They check out and build the given tag. - Package CD workflows are `workflow_dispatch`-only, with `tag` and `prerelease` inputs. They check out and build the given tag.
- All publishing uses **OIDC trusted publishing**. No tokens, no secrets. - All publishing uses **OIDC trusted publishing**. No tokens, no secrets.
+17 -17
View File
@@ -41,10 +41,10 @@ jobs:
mem0_plugin: ${{ steps.filter.outputs.mem0_plugin }} mem0_plugin: ${{ steps.filter.outputs.mem0_plugin }}
opencode_plugin: ${{ steps.filter.outputs.opencode_plugin }} opencode_plugin: ${{ steps.filter.outputs.opencode_plugin }}
pi_agent_plugin: ${{ steps.filter.outputs.pi_agent_plugin }} pi_agent_plugin: ${{ steps.filter.outputs.pi_agent_plugin }}
dsh_mem0: ${{ steps.filter.outputs.dsh_mem0 }} deepseek_plugin: ${{ steps.filter.outputs.deepseek_plugin }}
n8n_nodes_mem0: ${{ steps.filter.outputs.n8n_nodes_mem0 }} n8n_nodes_mem0: ${{ steps.filter.outputs.n8n_nodes_mem0 }}
zapier_mem0: ${{ steps.filter.outputs.zapier_mem0 }} zapier_mem0: ${{ steps.filter.outputs.zapier_mem0 }}
strands_mem0: ${{ steps.filter.outputs.strands_mem0 }} mem0_strands: ${{ steps.filter.outputs.mem0_strands }}
docs_llms_txt: ${{ steps.filter.outputs.docs_llms_txt }} docs_llms_txt: ${{ steps.filter.outputs.docs_llms_txt }}
github_scripts: ${{ steps.filter.outputs.github_scripts }} github_scripts: ${{ steps.filter.outputs.github_scripts }}
steps: steps:
@@ -90,9 +90,9 @@ jobs:
- 'integrations/pi-agent-plugin/**' - 'integrations/pi-agent-plugin/**'
- '.github/workflows/pi-agent-plugin-checks.yml' - '.github/workflows/pi-agent-plugin-checks.yml'
- '.github/workflows/ci-gate.yml' - '.github/workflows/ci-gate.yml'
dsh_mem0: deepseek_plugin:
- 'integrations/dsh-mem0/**' - 'integrations/deepseek-plugin/**'
- '.github/workflows/dsh-mem0-checks.yml' - '.github/workflows/deepseek-plugin-checks.yml'
- '.github/workflows/ci-gate.yml' - '.github/workflows/ci-gate.yml'
n8n_nodes_mem0: n8n_nodes_mem0:
- 'integrations/n8n-nodes-mem0/**' - 'integrations/n8n-nodes-mem0/**'
@@ -101,9 +101,9 @@ jobs:
- 'integrations/zapier-mem0/**' - 'integrations/zapier-mem0/**'
- '.github/workflows/zapier-mem0-checks.yml' - '.github/workflows/zapier-mem0-checks.yml'
- '.github/workflows/ci-gate.yml' - '.github/workflows/ci-gate.yml'
strands_mem0: mem0_strands:
- 'integrations/strands-mem0/**' - 'integrations/mem0-strands/**'
- '.github/workflows/strands-mem0-checks.yml' - '.github/workflows/mem0-strands-checks.yml'
- '.github/workflows/ci-gate.yml' - '.github/workflows/ci-gate.yml'
docs_llms_txt: docs_llms_txt:
- 'docs/**/*.mdx' - 'docs/**/*.mdx'
@@ -176,11 +176,11 @@ jobs:
uses: ./.github/workflows/pi-agent-plugin-checks.yml uses: ./.github/workflows/pi-agent-plugin-checks.yml
secrets: inherit secrets: inherit
dsh-mem0: deepseek-plugin:
name: DeepSeek Harness Plugin name: DeepSeek Harness Plugin
needs: changes needs: changes
if: needs.changes.outputs.dsh_mem0 == 'true' if: needs.changes.outputs.deepseek_plugin == 'true'
uses: ./.github/workflows/dsh-mem0-checks.yml uses: ./.github/workflows/deepseek-plugin-checks.yml
secrets: inherit secrets: inherit
n8n-nodes-mem0: n8n-nodes-mem0:
@@ -195,11 +195,11 @@ jobs:
uses: ./.github/workflows/zapier-mem0-checks.yml uses: ./.github/workflows/zapier-mem0-checks.yml
secrets: inherit secrets: inherit
strands-mem0: mem0-strands:
name: strands-mem0 name: mem0-strands
needs: changes needs: changes
if: needs.changes.outputs.strands_mem0 == 'true' if: needs.changes.outputs.mem0_strands == 'true'
uses: ./.github/workflows/strands-mem0-checks.yml uses: ./.github/workflows/mem0-strands-checks.yml
secrets: inherit secrets: inherit
docs-llms-txt: docs-llms-txt:
@@ -239,10 +239,10 @@ jobs:
- mem0-plugin - mem0-plugin
- opencode-plugin - opencode-plugin
- pi-agent-plugin - pi-agent-plugin
- dsh-mem0 - deepseek-plugin
- n8n-nodes-mem0 - n8n-nodes-mem0
- zapier-mem0 - zapier-mem0
- strands-mem0 - mem0-strands
- docs-llms-txt - docs-llms-txt
- github-scripts - github-scripts
if: always() if: always()
@@ -1,13 +1,13 @@
name: Publish @mem0/dsh-mem0 📦 to npm name: Publish @mem0/deepseek-plugin 📦 to npm
# Dispatched by release.yml (Release Router) when a release tagged # Dispatched by release.yml (Release Router) when a release tagged
# dsh-mem0-v* is published. Can also be dispatched manually to re-publish # deepseek-plugin-v* is published. Can also be dispatched manually to re-publish
# a tag. # a tag.
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
tag: tag:
description: 'Release tag to build and publish (e.g. dsh-mem0-v0.1.1)' description: 'Release tag to build and publish (e.g. deepseek-plugin-v0.1.1)'
required: true required: true
type: string type: string
prerelease: prerelease:
@@ -18,14 +18,14 @@ on:
jobs: jobs:
build-n-publish: build-n-publish:
name: Build and publish @mem0/dsh-mem0 📦 to npm name: Build and publish @mem0/deepseek-plugin 📦 to npm
if: startsWith(inputs.tag, 'dsh-mem0-v') if: startsWith(inputs.tag, 'deepseek-plugin-v')
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
id-token: write id-token: write
defaults: defaults:
run: run:
working-directory: integrations/dsh-mem0 working-directory: integrations/deepseek-plugin
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@@ -42,7 +42,7 @@ jobs:
node-version: '22' node-version: '22'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
cache: 'pnpm' cache: 'pnpm'
cache-dependency-path: integrations/dsh-mem0/pnpm-lock.yaml cache-dependency-path: integrations/deepseek-plugin/pnpm-lock.yaml
- name: Install dependencies - name: Install dependencies
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
@@ -1,4 +1,4 @@
name: dsh-mem0 checks name: deepseek-plugin checks
# On PRs this is invoked by ci-gate.yml (the single required check); # On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main and manual runs remain standalone. # push-to-main and manual runs remain standalone.
@@ -7,8 +7,8 @@ on:
push: push:
branches: [main] branches: [main]
paths: paths:
- 'integrations/dsh-mem0/**' - 'integrations/deepseek-plugin/**'
- '.github/workflows/dsh-mem0-checks.yml' - '.github/workflows/deepseek-plugin-checks.yml'
workflow_call: workflow_call:
jobs: jobs:
@@ -27,13 +27,13 @@ jobs:
with: with:
node-version: 20 node-version: 20
cache: 'pnpm' cache: 'pnpm'
cache-dependency-path: integrations/dsh-mem0/pnpm-lock.yaml cache-dependency-path: integrations/deepseek-plugin/pnpm-lock.yaml
- name: Install dependencies - name: Install dependencies
run: cd integrations/dsh-mem0 && pnpm install --frozen-lockfile run: cd integrations/deepseek-plugin && pnpm install --frozen-lockfile
- name: Type check - name: Type check
run: cd integrations/dsh-mem0 && pnpm exec tsc --noEmit run: cd integrations/deepseek-plugin && pnpm exec tsc --noEmit
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -53,13 +53,13 @@ jobs:
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'pnpm' cache: 'pnpm'
cache-dependency-path: integrations/dsh-mem0/pnpm-lock.yaml cache-dependency-path: integrations/deepseek-plugin/pnpm-lock.yaml
- name: Install dependencies - name: Install dependencies
run: cd integrations/dsh-mem0 && pnpm install --frozen-lockfile run: cd integrations/deepseek-plugin && pnpm install --frozen-lockfile
- name: Run tests - name: Run tests
run: cd integrations/dsh-mem0 && pnpm exec vitest run run: cd integrations/deepseek-plugin && pnpm exec vitest run
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -76,15 +76,15 @@ jobs:
with: with:
node-version: 20 node-version: 20
cache: 'pnpm' cache: 'pnpm'
cache-dependency-path: integrations/dsh-mem0/pnpm-lock.yaml cache-dependency-path: integrations/deepseek-plugin/pnpm-lock.yaml
- name: Install dependencies - name: Install dependencies
run: cd integrations/dsh-mem0 && pnpm install --frozen-lockfile run: cd integrations/deepseek-plugin && pnpm install --frozen-lockfile
- name: Build - name: Build
run: cd integrations/dsh-mem0 && pnpm build run: cd integrations/deepseek-plugin && pnpm build
- name: Verify dist output exists - name: Verify dist output exists
run: | run: |
test -f integrations/dsh-mem0/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1) test -f integrations/deepseek-plugin/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
test -f integrations/dsh-mem0/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1) test -f integrations/deepseek-plugin/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
@@ -1,15 +1,15 @@
name: Publish strands-mem0 🐍 distribution 📦 to PyPI name: Publish mem0-strands 🐍 distribution 📦 to PyPI
# Dispatched by release.yml (Release Router) when a release tagged # Dispatched by release.yml (Release Router) when a release tagged
# strands-mem0-v* is published. Can also be dispatched manually to re-publish # mem0-strands-v* is published. Can also be dispatched manually to re-publish
# a tag. Publishing uses PyPI Trusted Publishing (OIDC), so no API token is # a tag. Publishing uses PyPI Trusted Publishing (OIDC), so no API token is
# stored; the `strands-mem0` PyPI project must have a trusted publisher # stored; the `mem0-strands` PyPI project must have a trusted publisher
# configured for mem0ai/mem0 + this workflow. # configured for mem0ai/mem0 + this workflow.
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
tag: tag:
description: 'Release tag to build and publish (e.g. strands-mem0-v0.1.0)' description: 'Release tag to build and publish (e.g. mem0-strands-v0.1.0)'
required: true required: true
type: string type: string
prerelease: prerelease:
@@ -20,14 +20,14 @@ on:
jobs: jobs:
build-n-publish: build-n-publish:
name: Build and publish strands-mem0 📦 to PyPI name: Build and publish mem0-strands 📦 to PyPI
if: startsWith(inputs.tag, 'strands-mem0-v') if: startsWith(inputs.tag, 'mem0-strands-v')
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
id-token: write id-token: write
defaults: defaults:
run: run:
working-directory: integrations/strands-mem0/python working-directory: integrations/mem0-strands/python
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@@ -47,4 +47,4 @@ jobs:
- name: Publish distribution 📦 to PyPI - name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1 uses: pypa/gh-action-pypi-publish@release/v1
with: with:
packages-dir: integrations/strands-mem0/python/dist/ packages-dir: integrations/mem0-strands/python/dist/
@@ -1,4 +1,4 @@
name: strands-mem0 CI name: mem0-strands CI
# On PRs this is invoked by ci-gate.yml (the single required check); # On PRs this is invoked by ci-gate.yml (the single required check);
# push-to-main and manual runs remain standalone. # push-to-main and manual runs remain standalone.
@@ -7,8 +7,8 @@ on:
push: push:
branches: [main] branches: [main]
paths: paths:
- 'integrations/strands-mem0/**' - 'integrations/mem0-strands/**'
- '.github/workflows/strands-mem0-checks.yml' - '.github/workflows/mem0-strands-checks.yml'
workflow_call: workflow_call:
jobs: jobs:
@@ -23,19 +23,19 @@ jobs:
python-version: '3.12' python-version: '3.12'
- name: Install dev dependencies - name: Install dev dependencies
working-directory: integrations/strands-mem0/python working-directory: integrations/mem0-strands/python
run: pip install -e ".[dev]" run: pip install -e ".[dev]"
- name: Lint with ruff - name: Lint with ruff
working-directory: integrations/strands-mem0/python working-directory: integrations/mem0-strands/python
run: ruff check . run: ruff check .
- name: Check formatting - name: Check formatting
working-directory: integrations/strands-mem0/python working-directory: integrations/mem0-strands/python
run: ruff format --check . run: ruff format --check .
- name: Type-check with mypy - name: Type-check with mypy
working-directory: integrations/strands-mem0/python working-directory: integrations/mem0-strands/python
run: mypy src run: mypy src
test: test:
@@ -52,11 +52,11 @@ jobs:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install dev dependencies - name: Install dev dependencies
working-directory: integrations/strands-mem0/python working-directory: integrations/mem0-strands/python
run: pip install -e ".[dev]" run: pip install -e ".[dev]"
- name: Run tests - name: Run tests
working-directory: integrations/strands-mem0/python working-directory: integrations/mem0-strands/python
run: pytest run: pytest
build: build:
@@ -73,10 +73,10 @@ jobs:
run: pip install hatch run: pip install hatch
- name: Build - name: Build
working-directory: integrations/strands-mem0/python working-directory: integrations/mem0-strands/python
run: hatch build --clean run: hatch build --clean
- name: Verify dist output - name: Verify dist output
run: | run: |
ls integrations/strands-mem0/python/dist/*.whl || (echo "Wheel file missing" && exit 1) ls integrations/mem0-strands/python/dist/*.whl || (echo "Wheel file missing" && exit 1)
ls integrations/strands-mem0/python/dist/*.tar.gz || (echo "Source dist missing" && exit 1) ls integrations/mem0-strands/python/dist/*.tar.gz || (echo "Source dist missing" && exit 1)
+2 -2
View File
@@ -45,9 +45,9 @@ jobs:
openclaw-v*) workflow="openclaw-cd.yml" ;; openclaw-v*) workflow="openclaw-cd.yml" ;;
opencode-v*) workflow="opencode-plugin-cd.yml" ;; opencode-v*) workflow="opencode-plugin-cd.yml" ;;
pi-agent-v*) workflow="pi-agent-plugin-cd.yml" ;; pi-agent-v*) workflow="pi-agent-plugin-cd.yml" ;;
dsh-mem0-v*) workflow="dsh-mem0-cd.yml" ;; deepseek-plugin-v*) workflow="deepseek-plugin-cd.yml" ;;
n8n-nodes-mem0-v*) workflow="n8n-nodes-mem0-cd.yml" ;; n8n-nodes-mem0-v*) workflow="n8n-nodes-mem0-cd.yml" ;;
strands-mem0-v*) workflow="strands-mem0-cd.yml" ;; mem0-strands-v*) workflow="mem0-strands-cd.yml" ;;
v*) workflow="cd.yml" ;; v*) workflow="cd.yml" ;;
*) *)
echo "::error::Release tag '$TAG' does not match any known package prefix — nothing will be published. See the tag prefix table in AGENTS.md." echo "::error::Release tag '$TAG' does not match any known package prefix — nothing will be published. See the tag prefix table in AGENTS.md."
+1 -1
View File
@@ -192,6 +192,6 @@ testing.ipynb
.weave/ .weave/
# TypeScript incremental build info and local, uncommitted e2e scripts (used by the integrations, e.g. integrations/dsh-mem0) # TypeScript incremental build info and local, uncommitted e2e scripts (used by the integrations, e.g. integrations/deepseek-plugin)
*.tsbuildinfo *.tsbuildinfo
*.local.mjs *.local.mjs
+3 -3
View File
@@ -8,14 +8,14 @@ mode: "wide"
**DeepSeek Harness: Mem0 as a Native Cordis Plugin** **DeepSeek Harness: Mem0 as a Native Cordis Plugin**
The DeepSeek Harness agent forgets everything between sessions. [`@mem0/dsh-mem0`](https://www.npmjs.com/package/@mem0/dsh-mem0) gives it two Mem0-backed tools, so recall and writes persist across runs against the same memory bank you already use from Claude Code, Codex, and every other connected agent. The DeepSeek Harness agent forgets everything between sessions. [`@mem0/deepseek-plugin`](https://www.npmjs.com/package/@mem0/deepseek-plugin) gives it two Mem0-backed tools, so recall and writes persist across runs against the same memory bank you already use from Claude Code, Codex, and every other connected agent.
- **Two agent-callable tools:** `search_memory` recalls facts relevant to a query, `add_memory` stores a fact for future sessions. Both accept per-call `userId` / `agentId` / `runId` scope overrides. - **Two agent-callable tools:** `search_memory` recalls facts relevant to a query, `add_memory` stores a fact for future sessions. Both accept per-call `userId` / `agentId` / `runId` scope overrides.
- **Native Cordis lifecycle:** The plugin declares `inject = ['tools']` so it waits for the harness tool registry, then registers through `ctx.tools.register()`. Unmounting the plugin removes the tools automatically. - **Native Cordis lifecycle:** The plugin declares `inject = ['tools']` so it waits for the harness tool registry, then registers through `ctx.tools.register()`. Unmounting the plugin removes the tools automatically.
- **Managed backend, not a memory file:** Server-side extraction, semantic dedup, and conflict resolution, rather than a Markdown file the agent has to maintain itself. - **Managed backend, not a memory file:** Server-side extraction, semantic dedup, and conflict resolution, rather than a Markdown file the agent has to maintain itself.
- **Config:** `userId` is required, `apiKey` defaults to `$MEM0_API_KEY`, and `host` optionally targets a dedicated Mem0 Platform base URL. - **Config:** `userId` is required, `apiKey` defaults to `$MEM0_API_KEY`, and `host` optionally targets a dedicated Mem0 Platform base URL.
See [DeepSeek Harness](/integrations/dsh-mem0) for setup and [SDK & Tools](/changelog/sdk) for PR links. See [DeepSeek Harness](/integrations/deepseek-plugin) for setup and [SDK & Tools](/changelog/sdk) for PR links.
<Note> <Note>
Developer preview. Auto-capture and auto-recall, where memory reaches the context with no explicit tool call, are planned but not yet built. Developer preview. Auto-capture and auto-recall, where memory reaches the context with no explicit tool call, are planned but not yet built.
@@ -27,7 +27,7 @@ See [DeepSeek Harness](/integrations/dsh-mem0) for setup and [SDK & Tools](/chan
**Strands Agents: Mem0 as a Native MemoryStore** **Strands Agents: Mem0 as a Native MemoryStore**
[`strands-mem0`](https://pypi.org/project/strands-mem0/) plugs Mem0 into AWS's [Strands Agents](https://strandsagents.com/) SDK as a native `MemoryStore`, so recall and writes happen inside the agent loop rather than as tool calls the model has to remember to make. [`mem0-strands`](https://pypi.org/project/mem0-strands/) plugs Mem0 into AWS's [Strands Agents](https://strandsagents.com/) SDK as a native `MemoryStore`, so recall and writes happen inside the agent loop rather than as tool calls the model has to remember to make.
- **Automatic recall:** The `MemoryManager` drives the store on every turn, searching Mem0 and injecting the results into the prompt with no tool call required. - **Automatic recall:** The `MemoryManager` drives the store on every turn, searching Mem0 and injecting the results into the prompt with no tool call required.
- **Server-side extraction:** Because the store implements `add_messages`, enabling extraction routes raw conversation turns straight to Mem0's extraction pipeline, skipping the extra client-side model call needed to distill facts first. - **Server-side extraction:** Because the store implements `add_messages`, enabling extraction routes raw conversation turns straight to Mem0's extraction pipeline, skipping the extra client-side model call needed to distill facts first.
+5 -5
View File
@@ -2841,9 +2841,9 @@ Existing memories written by the previous versions are not rewritten. If your me
<Tab title="Strands"> <Tab title="Strands">
<Update label="2026-08-24" description="strands-mem0 v0.1.0"> <Update label="2026-08-24" description="mem0-strands v0.1.0">
**Initial release** of [`strands-mem0`](https://pypi.org/project/strands-mem0/), a native `MemoryStore` that plugs Mem0 into the [Strands Agents](https://strandsagents.com/) `MemoryManager` ([#7021](https://github.com/mem0ai/mem0/pull/7021)) **Initial release** of [`mem0-strands`](https://pypi.org/project/mem0-strands/), a native `MemoryStore` that plugs Mem0 into the [Strands Agents](https://strandsagents.com/) `MemoryManager` ([#7021](https://github.com/mem0ai/mem0/pull/7021))
**New Features:** **New Features:**
- **Automatic recall and injection:** `Mem0MemoryStore.search()` runs every turn through the `MemoryManager`, so relevant memories are searched and prepended to the prompt with no explicit tool call required. - **Automatic recall and injection:** `Mem0MemoryStore.search()` runs every turn through the `MemoryManager`, so relevant memories are searched and prepended to the prompt with no explicit tool call required.
@@ -2863,9 +2863,9 @@ Existing memories written by the previous versions are not rewritten. If your me
<Tab title="DeepSeek Harness"> <Tab title="DeepSeek Harness">
<Update label="2026-08-24" description="dsh-mem0 v0.1.0"> <Update label="2026-08-24" description="deepseek-plugin v0.1.0">
**Initial release** of [`dsh-mem0`](https://www.npmjs.com/package/@mem0/dsh-mem0), a native DeepSeek Harness (Cordis) plugin that registers Mem0 as two agent-callable tools ([#7027](https://github.com/mem0ai/mem0/pull/7027)) **Initial release** of [`deepseek-plugin`](https://www.npmjs.com/package/@mem0/deepseek-plugin), a native DeepSeek Harness (Cordis) plugin that registers Mem0 as two agent-callable tools ([#7027](https://github.com/mem0ai/mem0/pull/7027))
**New Features:** **New Features:**
- **`search_memory`:** Recalls facts relevant to a query, with an optional `limit` (default 10) and per-call `userId` / `agentId` / `runId` scope overrides. - **`search_memory`:** Recalls facts relevant to a query, with an optional `limit` (default 10) and per-call `userId` / `agentId` / `runId` scope overrides.
@@ -2874,7 +2874,7 @@ Existing memories written by the previous versions are not rewritten. If your me
- **Config:** `userId` is required; `apiKey` defaults to `$MEM0_API_KEY`; `host` optionally points at a dedicated Mem0 Platform base URL (not a switch to self-hosted Mem0 OSS). - **Config:** `userId` is required; `apiKey` defaults to `$MEM0_API_KEY`; `host` optionally points at a dedicated Mem0 Platform base URL (not a switch to self-hosted Mem0 OSS).
<Note> <Note>
Developer preview: auto-capture and auto-recall (memory injected into context automatically, without an explicit tool call) are planned but not yet built. The backend's `KNOWN_EVENT_SOURCES` allowlist also needs `"DEEPSEEK_HARNESS"` added before usage surfaces by name in telemetry rather than bucketing into "OTHERS". See [DeepSeek Harness](/integrations/dsh-mem0) for setup. Developer preview: auto-capture and auto-recall (memory injected into context automatically, without an explicit tool call) are planned but not yet built. The backend's `KNOWN_EVENT_SOURCES` allowlist also needs `"DEEPSEEK_HARNESS"` added before usage surfaces by name in telemetry rather than bucketing into "OTHERS". See [DeepSeek Harness](/integrations/deepseek-plugin) for setup.
</Note> </Note>
</Update> </Update>
+1 -1
View File
@@ -383,7 +383,7 @@
"integrations/openclaw", "integrations/openclaw",
"integrations/hermes", "integrations/hermes",
"integrations/pi-agent", "integrations/pi-agent",
"integrations/dsh-mem0" "integrations/deepseek-plugin"
] ]
} }
] ]
@@ -3,7 +3,7 @@ title: DeepSeek Harness
description: "Add persistent Mem0 memory to the DeepSeek Harness (Cordis) agent with two native tools: search and add." description: "Add persistent Mem0 memory to the DeepSeek Harness (Cordis) agent with two native tools: search and add."
--- ---
Add persistent memory to the [**DeepSeek Harness**](https://github.com/deepseek-ai/deepseek-harness) with `@mem0/dsh-mem0`. The Harness agent forgets everything between sessions. This plugin gives it two Mem0-backed tools so recall and writes persist across runs, sharing the same memory bank you already use from Claude Code, Codex, and other agents. Add persistent memory to the [**DeepSeek Harness**](https://github.com/deepseek-ai/deepseek-harness) with `@mem0/deepseek-plugin`. The Harness agent forgets everything between sessions. This plugin gives it two Mem0-backed tools so recall and writes persist across runs, sharing the same memory bank you already use from Claude Code, Codex, and other agents.
## Overview ## Overview
@@ -23,8 +23,8 @@ A Cordis plugin is a module exporting `apply(ctx, config)`. This one declares `i
## Prerequisites ## Prerequisites
1. A Mem0 Platform account and API key: 1. A Mem0 Platform account and API key:
- <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-dsh-mem0" rel="nofollow">Sign up at app.mem0.ai</a> - <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-deepseek-plugin" rel="nofollow">Sign up at app.mem0.ai</a>
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-dsh-mem0" rel="nofollow">Get your API key</a> (starts with `m0-`) - <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-deepseek-plugin" rel="nofollow">Get your API key</a> (starts with `m0-`)
2. The DeepSeek Harness installed. 2. The DeepSeek Harness installed.
@@ -46,14 +46,14 @@ source ~/.bashrc
1. Build the plugin: 1. Build the plugin:
```sh ```sh
cd integrations/dsh-mem0 cd integrations/deepseek-plugin
pnpm install pnpm install
pnpm build pnpm build
``` ```
2. Point the Harness at it. Copy `cordis.example.yml`, set the absolute path to `dist/index.js` and your `userId`, then load it: 2. Point the Harness at it. Copy `cordis.example.yml`, set the absolute path to `dist/index.js` and your `userId`, then load it:
```sh ```sh
pnpm dsh web --patch ./integrations/dsh-mem0/cordis.example.yml pnpm dsh web --patch ./integrations/deepseek-plugin/cordis.example.yml
``` ```
3. Open the web UI and ask the agent to remember something, then recall it in a later turn. 3. Open the web UI and ask the agent to remember something, then recall it in a later turn.
@@ -65,7 +65,7 @@ The `cordis.yml` entry looks like this:
- name: "@deepseek-ai/dsh-tools" - name: "@deepseek-ai/dsh-tools"
- insert: - insert:
- id: mem0 - id: mem0
name: "/absolute/path/to/integrations/dsh-mem0/dist/index.js" name: "/absolute/path/to/integrations/deepseek-plugin/dist/index.js"
config: config:
# apiKey is read from MEM0_API_KEY when omitted here. # apiKey is read from MEM0_API_KEY when omitted here.
userId: "your-user-id" userId: "your-user-id"
+4 -4
View File
@@ -3,7 +3,7 @@ title: Strands Agents
description: "Add persistent long-term memory to AWS Strands agents with Mem0, as a native MemoryStore that plugs into the agent loop." description: "Add persistent long-term memory to AWS Strands agents with Mem0, as a native MemoryStore that plugs into the agent loop."
--- ---
Integrate [**Mem0**](https://github.com/mem0ai/mem0) with [Strands Agents](https://github.com/strands-agents/sdk-python), AWS's open-source SDK for building AI agents. The [`strands-mem0`](https://github.com/mem0ai/mem0/tree/main/integrations/strands-mem0) package ships a native `MemoryStore`, so recall and writes happen automatically inside the agent loop, not as tool calls the model has to remember. Integrate [**Mem0**](https://github.com/mem0ai/mem0) with [Strands Agents](https://github.com/strands-agents/sdk-python), AWS's open-source SDK for building AI agents. The [`mem0-strands`](https://github.com/mem0ai/mem0/tree/main/integrations/mem0-strands) package ships a native `MemoryStore`, so recall and writes happen automatically inside the agent loop, not as tool calls the model has to remember.
## Overview ## Overview
@@ -17,7 +17,7 @@ Before setting up Mem0 with Strands, ensure you have:
1. Installed the required packages: 1. Installed the required packages:
```bash ```bash
pip install strands-mem0 pip install mem0-strands
``` ```
2. A valid API key: 2. A valid API key:
@@ -31,7 +31,7 @@ Hand a `Mem0MemoryStore` to a `MemoryManager`, and the agent gets automatic reca
import os import os
from strands import Agent from strands import Agent
from strands.memory import MemoryManager from strands.memory import MemoryManager
from strands_mem0 import Mem0MemoryStore from mem0_strands import Mem0MemoryStore
os.environ["MEM0_API_KEY"] = "your-mem0-api-key" os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
@@ -65,5 +65,5 @@ If you want the model to call memory explicitly instead of (or alongside) the au
## Learn more ## Learn more
- [strands-mem0 on GitHub](https://github.com/mem0ai/mem0/tree/main/integrations/strands-mem0) - [mem0-strands on GitHub](https://github.com/mem0ai/mem0/tree/main/integrations/mem0-strands)
- [Strands Agents documentation](https://strandsagents.com) - [Strands Agents documentation](https://strandsagents.com)
+1 -1
View File
@@ -257,7 +257,7 @@ If the user is on a pre-current major (Python < 2, TS < 3, or a Platform call st
- [ChatDev](https://docs.mem0.ai/integrations/chatdev) [Platform]: Use when the user is on ChatDev. - [ChatDev](https://docs.mem0.ai/integrations/chatdev) [Platform]: Use when the user is on ChatDev.
- [Hermes](https://docs.mem0.ai/integrations/hermes) [Both]: Use when the user is on Hermes. - [Hermes](https://docs.mem0.ai/integrations/hermes) [Both]: Use when the user is on Hermes.
- [Pi Agent](https://docs.mem0.ai/integrations/pi-agent) [Platform]: Use when adding persistent memory to Pi Agent with the Mem0 plugin. - [Pi Agent](https://docs.mem0.ai/integrations/pi-agent) [Platform]: Use when adding persistent memory to Pi Agent with the Mem0 plugin.
- [DeepSeek Harness](https://docs.mem0.ai/integrations/dsh-mem0) [Platform]: Use when adding persistent memory to the DeepSeek Harness (Cordis) agent via the Mem0 plugin. - [DeepSeek Harness](https://docs.mem0.ai/integrations/deepseek-plugin) [Platform]: Use when adding persistent memory to the DeepSeek Harness (Cordis) agent via the Mem0 plugin.
- [OpenAI Agents SDK](https://docs.mem0.ai/integrations/openai-agents-sdk) [Platform]: Use when the user is on the OpenAI Agents SDK. - [OpenAI Agents SDK](https://docs.mem0.ai/integrations/openai-agents-sdk) [Platform]: Use when the user is on the OpenAI Agents SDK.
- [Google AI ADK](https://docs.mem0.ai/integrations/google-ai-adk) [Platform]: Use when the user is on Google's Agent Development Kit. - [Google AI ADK](https://docs.mem0.ai/integrations/google-ai-adk) [Platform]: Use when the user is on Google's Agent Development Kit.
- [Mastra](https://docs.mem0.ai/integrations/mastra) [Platform]: Use when the user is on Mastra (TypeScript). - [Mastra](https://docs.mem0.ai/integrations/mastra) [Platform]: Use when the user is on Mastra (TypeScript).
+5 -5
View File
@@ -9,12 +9,12 @@ Agent and editor integrations. Each subdirectory is self-contained: its own `pac
| `mem0-plugin/` | Claude Code / Cursor / Codex plugin | none | none | pytest | | `mem0-plugin/` | Claude Code / Cursor / Codex plugin | none | none | pytest |
| `mem0-plugin/.opencode-plugin/` | `@mem0/opencode-plugin` | Bun | none | tsc type-check | | `mem0-plugin/.opencode-plugin/` | `@mem0/opencode-plugin` | Bun | none | tsc type-check |
| `pi-agent-plugin/` | `@mem0/pi-agent-plugin` | tsup | none | vitest | | `pi-agent-plugin/` | `@mem0/pi-agent-plugin` | tsup | none | vitest |
| `dsh-mem0/` | `@mem0/dsh-mem0` | tsup (ESM) | none | vitest | | `deepseek-plugin/` | `@mem0/deepseek-plugin` | tsup (ESM) | none | vitest |
| `n8n-nodes-mem0/` | `@mem0/n8n-nodes-mem0` | tsc | ESLint (n8n-nodes-base) | none | | `n8n-nodes-mem0/` | `@mem0/n8n-nodes-mem0` | tsc | ESLint (n8n-nodes-base) | none |
| `zapier-mem0/` | `@mem0/zapier` | tsc | none | offline unit tests + `zapier validate` | | `zapier-mem0/` | `@mem0/zapier` | tsc | none | offline unit tests + `zapier validate` |
| `strands-mem0/` | `strands-mem0` (PyPI) | hatch | Ruff + mypy | pytest | | `mem0-strands/` | `mem0-strands` (PyPI) | hatch | Ruff + mypy | pytest |
pnpm everywhere except `.opencode-plugin/` (Bun) and `strands-mem0/` (Python: pip / hatch). Never npm, never yarn. pnpm everywhere except `.opencode-plugin/` (Bun) and `mem0-strands/` (Python: pip / hatch). Never npm, never yarn.
## Commands ## Commands
@@ -41,10 +41,10 @@ Run the type check after every TypeScript change: `pnpm run typecheck` or `tsc -
- **`vercel-ai-sdk/`** wraps the Vercel AI SDK through a `createMem0` provider. Integrations for AI-SDK repos go through this wrapper, not raw `MemoryClient`. - **`vercel-ai-sdk/`** wraps the Vercel AI SDK through a `createMem0` provider. Integrations for AI-SDK repos go through this wrapper, not raw `MemoryClient`.
- **`mem0-plugin/`** connects Claude Code, Cursor, and Codex to the MCP server at `mcp.mem0.ai` and installs lifecycle hooks for automatic memory capture. Exposes 9 MCP tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`. - **`mem0-plugin/`** connects Claude Code, Cursor, and Codex to the MCP server at `mcp.mem0.ai` and installs lifecycle hooks for automatic memory capture. Exposes 9 MCP tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`.
- **`openclaw/`**, **`pi-agent-plugin/`**, **`dsh-mem0/`** are editor and agent plugins with the same shape. `dsh-mem0/` registers Mem0 search/add tools as a native DeepSeek Harness (Cordis) plugin. - **`openclaw/`**, **`pi-agent-plugin/`**, **`deepseek-plugin/`** are editor and agent plugins with the same shape. `deepseek-plugin/` registers Mem0 search/add tools as a native DeepSeek Harness (Cordis) plugin.
- **`n8n-nodes-mem0/`** is an n8n community node: add, search, get, update, delete. - **`n8n-nodes-mem0/`** is an n8n community node: add, search, get, update, delete.
- **`zapier-mem0/`** is a Zapier Platform CLI app: add, search, get, delete. It deploys to Zapier, not npm, so it is **not** in the release router. Deploy it with `gh workflow run zapier-mem0-cd.yml --ref main` (needs the `ZAPIER_DEPLOY_KEY` secret). - **`zapier-mem0/`** is a Zapier Platform CLI app: add, search, get, delete. It deploys to Zapier, not npm, so it is **not** in the release router. Deploy it with `gh workflow run zapier-mem0-cd.yml --ref main` (needs the `ZAPIER_DEPLOY_KEY` secret).
- **`strands-mem0/`** is a native Strands `MemoryStore` (Python, published to PyPI as `strands-mem0`). It plugs into the Strands `MemoryManager` for automatic recall and server-side extraction, over the hosted Mem0 platform or self-hosted Mem0 OSS. The package lives under `strands-mem0/python/`. - **`mem0-strands/`** is a native Strands `MemoryStore` (Python, published to PyPI as `mem0-strands`). It plugs into the Strands `MemoryManager` for automatic recall and server-side extraction, over the hosted Mem0 platform or self-hosted Mem0 OSS. The package lives under `mem0-strands/python/`.
## Adding an integration ## Adding an integration
@@ -1,4 +1,4 @@
# dsh-mem0 # deepseek-plugin
[Mem0](https://mem0.ai) long-term memory as a native [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (Cordis) plugin. [Mem0](https://mem0.ai) long-term memory as a native [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (Cordis) plugin.
@@ -18,7 +18,7 @@ A Cordis plugin is a module exporting `apply(ctx, config)`. This one declares `i
``` ```
[ mem0ai SDK ] <-- managed memory, owned by Mem0 [ mem0ai SDK ] <-- managed memory, owned by Mem0
| |
[ dsh-mem0: apply(ctx) -> ctx.tools.register(...) ] <-- this package [ deepseek-plugin: apply(ctx) -> ctx.tools.register(...) ] <-- this package
| |
[ DeepSeek Harness ] <-- the agent, loaded via cordis.yml [ DeepSeek Harness ] <-- the agent, loaded via cordis.yml
``` ```
@@ -27,7 +27,7 @@ A Cordis plugin is a module exporting `apply(ctx, config)`. This one declares `i
1. Build the plugin: 1. Build the plugin:
```sh ```sh
cd integrations/dsh-mem0 cd integrations/deepseek-plugin
pnpm install pnpm install
pnpm build pnpm build
``` ```
@@ -37,7 +37,7 @@ A Cordis plugin is a module exporting `apply(ctx, config)`. This one declares `i
``` ```
3. Point Harness at it. Copy `cordis.example.yml`, set the absolute path to `dist/index.js` and your `userId`, then: 3. Point Harness at it. Copy `cordis.example.yml`, set the absolute path to `dist/index.js` and your `userId`, then:
```sh ```sh
pnpm dsh web --patch ./integrations/dsh-mem0/cordis.example.yml pnpm dsh web --patch ./integrations/deepseek-plugin/cordis.example.yml
``` ```
4. Open http://127.0.0.1:3080 and ask the agent to remember something, then recall it in a later turn. 4. Open http://127.0.0.1:3080 and ask the agent to remember something, then recall it in a later turn.
@@ -1,7 +1,7 @@
# Example DeepSeek Harness config that loads dsh-mem0 alongside the built-in # Example DeepSeek Harness config that loads deepseek-plugin alongside the built-in
# tools plugin. Load with: # tools plugin. Load with:
# #
# pnpm dsh web --patch ./integrations/dsh-mem0/cordis.example.yml # pnpm dsh web --patch ./integrations/deepseek-plugin/cordis.example.yml
# #
# The tools plugin (and its system-prompt dependency) must be present, because # The tools plugin (and its system-prompt dependency) must be present, because
# the memory tools contribute schemas the system prompt renders. # the memory tools contribute schemas the system prompt renders.
@@ -12,7 +12,7 @@
- id: mem0 - id: mem0
# Absolute path to the built plugin (run `pnpm build` first), or point # Absolute path to the built plugin (run `pnpm build` first), or point
# at src/index.ts when running through tsx during development. # at src/index.ts when running through tsx during development.
name: "/absolute/path/to/mem0/integrations/dsh-mem0/dist/index.js" name: "/absolute/path/to/mem0/integrations/deepseek-plugin/dist/index.js"
config: config:
# apiKey is read from the MEM0_API_KEY env var when omitted here. # apiKey is read from the MEM0_API_KEY env var when omitted here.
userId: "your-user-id" userId: "your-user-id"
@@ -1,5 +1,5 @@
{ {
"name": "@mem0/dsh-mem0", "name": "@mem0/deepseek-plugin",
"version": "0.1.0", "version": "0.1.0",
"description": "Mem0 long-term memory as a native DeepSeek Harness (Cordis) plugin.", "description": "Mem0 long-term memory as a native DeepSeek Harness (Cordis) plugin.",
"type": "module", "type": "module",
@@ -7,7 +7,7 @@
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/mem0ai/mem0", "url": "https://github.com/mem0ai/mem0",
"directory": "integrations/dsh-mem0" "directory": "integrations/deepseek-plugin"
}, },
"keywords": [ "keywords": [
"deepseek-harness", "deepseek-harness",
@@ -1,5 +1,5 @@
/** /**
* dsh-mem0: Mem0 long-term memory as a native DeepSeek Harness (Cordis) plugin. * deepseek-plugin: Mem0 long-term memory as a native DeepSeek Harness (Cordis) plugin.
* *
* Registers two agent-callable tools backed by the Mem0 SDK: * Registers two agent-callable tools backed by the Mem0 SDK:
* - `search_memory` recalls facts relevant to a query * - `search_memory` recalls facts relevant to a query
@@ -69,11 +69,11 @@ const scopeParams = {
export function apply(ctx: Context, config: Config): void { export function apply(ctx: Context, config: Config): void {
const apiKey = config.apiKey ?? process.env.MEM0_API_KEY; const apiKey = config.apiKey ?? process.env.MEM0_API_KEY;
if (!apiKey) { if (!apiKey) {
throw new Error("dsh-mem0: set config.apiKey or the MEM0_API_KEY env var"); throw new Error("deepseek-plugin: set config.apiKey or the MEM0_API_KEY env var");
} }
const userId = config.userId; const userId = config.userId;
if (!userId) { if (!userId) {
throw new Error("dsh-mem0: config.userId is required"); throw new Error("deepseek-plugin: config.userId is required");
} }
const client = new MemoryClient({ const client = new MemoryClient({
@@ -1,4 +1,4 @@
strands-mem0 mem0-strands
Copyright 2026 Mem0 Copyright 2026 Mem0
This product includes software developed at Mem0 (https://mem0.ai). This product includes software developed at Mem0 (https://mem0.ai).
@@ -1,5 +1,5 @@
<div align="center"> <div align="center">
<h1>strands-mem0</h1> <h1>mem0-strands</h1>
<h3>Persistent long-term memory for Strands Agents, backed by Mem0</h3> <h3>Persistent long-term memory for Strands Agents, backed by Mem0</h3>
<p> <p>
A community <a href="https://strandsagents.com/">Strands Agents</a> integration that plugs A community <a href="https://strandsagents.com/">Strands Agents</a> integration that plugs
@@ -9,7 +9,7 @@
--- ---
`strands-mem0` gives [Strands](https://github.com/strands-agents/sdk-python) agents durable memory `mem0-strands` gives [Strands](https://github.com/strands-agents/sdk-python) agents durable memory
that survives across sessions, backed by [Mem0](https://mem0.ai). Where the that survives across sessions, backed by [Mem0](https://mem0.ai). Where the
`mem0_memory` tool is called explicitly by the model, `Mem0MemoryStore` plugs into the **agent loop** `mem0_memory` tool is called explicitly by the model, `Mem0MemoryStore` plugs into the **agent loop**
directly: the manager recalls context and injects it automatically, and writes new memories, either directly: the manager recalls context and injects it automatically, and writes new memories, either
@@ -22,7 +22,7 @@ verbatim or by extracting facts from the conversation.
## Install ## Install
```bash ```bash
pip install strands-mem0 pip install mem0-strands
``` ```
## Usage ## Usage
@@ -30,7 +30,7 @@ pip install strands-mem0
```python ```python
from strands import Agent from strands import Agent
from strands.memory import MemoryManager from strands.memory import MemoryManager
from strands_mem0 import Mem0MemoryStore from mem0_strands import Mem0MemoryStore
# Recall + write, distilling facts from the conversation via Mem0's server-side extraction. # Recall + write, distilling facts from the conversation via Mem0's server-side extraction.
store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True) store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True)
@@ -1,4 +1,4 @@
# strands-mem0 (Python) # mem0-strands (Python)
Persistent long-term memory for [Strands Agents](https://github.com/strands-agents/sdk-python), Persistent long-term memory for [Strands Agents](https://github.com/strands-agents/sdk-python),
backed by [Mem0](https://mem0.ai). backed by [Mem0](https://mem0.ai).
@@ -6,7 +6,7 @@ backed by [Mem0](https://mem0.ai).
See the [repository README](../README.md) for full usage. Quick start: See the [repository README](../README.md) for full usage. Quick start:
```bash ```bash
pip install strands-mem0 pip install mem0-strands
``` ```
As a `MemoryStore` that plugs into the agent loop (Strands >= 1.45): As a `MemoryStore` that plugs into the agent loop (Strands >= 1.45):
@@ -14,7 +14,7 @@ As a `MemoryStore` that plugs into the agent loop (Strands >= 1.45):
```python ```python
from strands import Agent from strands import Agent
from strands.memory import MemoryManager from strands.memory import MemoryManager
from strands_mem0 import Mem0MemoryStore from mem0_strands import Mem0MemoryStore
store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True) store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True)
agent = Agent(memory_manager=MemoryManager(stores=[store])) agent = Agent(memory_manager=MemoryManager(stores=[store]))
@@ -32,6 +32,6 @@ hatch run prepare # format + lint + typecheck + test
## Release ## Release
Publish a GitHub release tagged `strands-mem0-v*` (e.g. `strands-mem0-v0.1.0`). The Publish a GitHub release tagged `mem0-strands-v*` (e.g. `mem0-strands-v0.1.0`). The
release router (`.github/workflows/release.yml`) dispatches `strands-mem0-cd.yml`, release router (`.github/workflows/release.yml`) dispatches `mem0-strands-cd.yml`,
which builds the wheel and publishes it to PyPI via trusted publishing (OIDC). which builds the wheel and publishes it to PyPI via trusted publishing (OIDC).
@@ -3,7 +3,7 @@ requires = ["hatchling"]
build-backend = "hatchling.build" build-backend = "hatchling.build"
[project] [project]
name = "strands-mem0" name = "mem0-strands"
version = "0.1.0" version = "0.1.0"
description = "Persistent long-term memory for Strands agents, backed by Mem0." description = "Persistent long-term memory for Strands agents, backed by Mem0."
readme = "README.md" readme = "README.md"
@@ -33,7 +33,7 @@ dependencies = [
[project.urls] [project.urls]
Homepage = "https://mem0.ai" Homepage = "https://mem0.ai"
Documentation = "https://github.com/mem0ai/mem0/tree/main/integrations/strands-mem0#readme" Documentation = "https://github.com/mem0ai/mem0/tree/main/integrations/mem0-strands#readme"
Repository = "https://github.com/mem0ai/mem0" Repository = "https://github.com/mem0ai/mem0"
Issues = "https://github.com/mem0ai/mem0/issues" Issues = "https://github.com/mem0ai/mem0/issues"
@@ -47,7 +47,7 @@ dev = [
] ]
[tool.hatch.build.targets.wheel] [tool.hatch.build.targets.wheel]
packages = ["src/strands_mem0"] packages = ["src/mem0_strands"]
[tool.hatch.envs.default] [tool.hatch.envs.default]
dependencies = [ dependencies = [
@@ -12,8 +12,8 @@ share one Mem0 backend and namespace.
from importlib.metadata import PackageNotFoundError, version from importlib.metadata import PackageNotFoundError, version
from strands_mem0.client import Mem0ServiceClient from mem0_strands.client import Mem0ServiceClient
from strands_mem0.store import Mem0MemoryStore from mem0_strands.store import Mem0MemoryStore
__all__ = [ __all__ = [
"Mem0MemoryStore", "Mem0MemoryStore",
@@ -21,6 +21,6 @@ __all__ = [
] ]
try: try:
__version__ = version("strands-mem0") __version__ = version("mem0-strands")
except PackageNotFoundError: # pragma: no cover - only when running from a source tree except PackageNotFoundError: # pragma: no cover - only when running from a source tree
__version__ = "0.0.0+unknown" __version__ = "0.0.0+unknown"
@@ -1,4 +1,4 @@
"""A thin wrapper around the Mem0 SDK used by :class:`~strands_mem0.store.Mem0MemoryStore`. """A thin wrapper around the Mem0 SDK used by :class:`~mem0_strands.store.Mem0MemoryStore`.
Both Mem0 backends -- the hosted platform (:class:`mem0.MemoryClient`) and Both Mem0 backends -- the hosted platform (:class:`mem0.MemoryClient`) and
self-hosted OSS (:class:`mem0.Memory`) -- expose the same call shape to the store: self-hosted OSS (:class:`mem0.Memory`) -- expose the same call shape to the store:
@@ -95,7 +95,7 @@ class Mem0ServiceClient:
from mem0 import Memory from mem0 import Memory
except ImportError as err: # pragma: no cover - exercised via install docs except ImportError as err: # pragma: no cover - exercised via install docs
raise ImportError( raise ImportError(
"The mem0ai package is required. Install it with: pip install 'strands-mem0'" "The mem0ai package is required. Install it with: pip install 'mem0-strands'"
) from err ) from err
self.mem0 = Memory.from_config(config) self.mem0 = Memory.from_config(config)
self.is_platform = False self.is_platform = False
@@ -104,7 +104,7 @@ class Mem0ServiceClient:
try: try:
from mem0 import MemoryClient from mem0 import MemoryClient
except ImportError as err: # pragma: no cover - exercised via install docs except ImportError as err: # pragma: no cover - exercised via install docs
raise ImportError("The mem0ai package is required. Install it with: pip install 'strands-mem0'") from err raise ImportError("The mem0ai package is required. Install it with: pip install 'mem0-strands'") from err
api_key = api_key or os.environ.get("MEM0_API_KEY") api_key = api_key or os.environ.get("MEM0_API_KEY")
# MemoryClient(host=None) would override the SDK default with None, so only # MemoryClient(host=None) would override the SDK default with None, so only
# pass host when the caller actually set one. # pass host when the caller actually set one.
@@ -21,7 +21,7 @@ Example:
```python ```python
from strands import Agent from strands import Agent
from strands.memory import MemoryManager from strands.memory import MemoryManager
from strands_mem0 import Mem0MemoryStore from mem0_strands import Mem0MemoryStore
# Recall + write, with Mem0 extracting facts from the conversation server-side. # Recall + write, with Mem0 extracting facts from the conversation server-side.
store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True) store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True)
@@ -41,7 +41,7 @@ from typing import Any
from strands.memory import AddMessagesContext, MemoryEntry, MemoryStore, SearchOptions from strands.memory import AddMessagesContext, MemoryEntry, MemoryStore, SearchOptions
from strands.types.content import Message from strands.types.content import Message
from strands_mem0.client import Mem0ServiceClient from mem0_strands.client import Mem0ServiceClient
DEFAULT_MAX_SEARCH_RESULTS = 5 DEFAULT_MAX_SEARCH_RESULTS = 5
# Entity fields that scope a memory in Mem0. At least one must be set. # Entity fields that scope a memory in Mem0. At least one must be set.
@@ -92,7 +92,7 @@ class Mem0MemoryStore(MemoryStore):
api_key: Mem0 platform API key (defaults to ``$MEM0_API_KEY``). api_key: Mem0 platform API key (defaults to ``$MEM0_API_KEY``).
host: Mem0 platform base URL. host: Mem0 platform base URL.
config: Mem0 OSS config dict for a self-hosted backend. config: Mem0 OSS config dict for a self-hosted backend.
client: A pre-built :class:`~strands_mem0.client.Mem0ServiceClient` client: A pre-built :class:`~mem0_strands.client.Mem0ServiceClient`
(for testing, or to wrap your own raw Mem0 client via (for testing, or to wrap your own raw Mem0 client via
``Mem0ServiceClient(client=...)``); when omitted, one is ``Mem0ServiceClient(client=...)``); when omitted, one is
constructed lazily on first use from ``api_key`` / ``config``. constructed lazily on first use from ``api_key`` / ``config``.
@@ -8,7 +8,7 @@ what the earlier permissive fakes did not do.
import pytest import pytest
from strands_mem0.client import Mem0ServiceClient, _extract_results, _is_platform_client from mem0_strands.client import Mem0ServiceClient, _extract_results, _is_platform_client
class FakeMemoryClient: class FakeMemoryClient:
@@ -10,7 +10,7 @@ import pytest
from strands.memory import MemoryEntry, MemoryStore from strands.memory import MemoryEntry, MemoryStore
from strands.memory.types import _has_method, _has_write_sink from strands.memory.types import _has_method, _has_write_sink
from strands_mem0 import Mem0MemoryStore from mem0_strands import Mem0MemoryStore
@pytest.fixture @pytest.fixture
@@ -241,7 +241,7 @@ def test_client_constructed_lazily(monkeypatch):
calls["n"] += 1 calls["n"] += 1
self.api_key = api_key self.api_key = api_key
monkeypatch.setattr("strands_mem0.store.Mem0ServiceClient", FakeClient) monkeypatch.setattr("mem0_strands.store.Mem0ServiceClient", FakeClient)
store = Mem0MemoryStore(user_id="alex", api_key="m0-x") store = Mem0MemoryStore(user_id="alex", api_key="m0-x")
assert calls["n"] == 0 # not built yet assert calls["n"] == 0 # not built yet