Skip to content

feat: add OSS/self-hosted mem0 support in dashboard plugin#13

Draft
terencez127 wants to merge 7 commits into
xraysight:mainfrom
terencez127:feat/mem0-oss-support
Draft

feat: add OSS/self-hosted mem0 support in dashboard plugin#13
terencez127 wants to merge 7 commits into
xraysight:mainfrom
terencez127:feat/mem0-oss-support

Conversation

@terencez127

Copy link
Copy Markdown

Problem

The plugin only supported mem0 Cloud (MemoryClient + API key). Users running self-hosted mem0 with "mode": "oss" in mem0.json (Qdrant + Ollama or other local stack) hit a hard error in the dashboard:

Mem0 API key not configured. Set MEM0_API_KEY in $HERMES_HOME/.env or the process environment.

Changes

_load_mem0_config

  • Detects OSS mode: mem0.json has "mode": "oss" or an "oss" config block
  • Surfaces oss_mode (bool) and oss_config (dict) for downstream use

_mem0_payload

  • Branches on oss_mode
  • OSS path: instantiates mem0.Memory(config=oss_cfg) and calls get_all/search with user_id/agent_id kwargs
  • Cloud path: unchanged (MemoryClient + API key guard)
  • Base response now includes mem0_mode field ("oss" or "cloud") for UI display

Tested

Local stack: Qdrant on localhost:6333, Ollama with nomic-embed-text embedder and llama3.2:3b LLM, mem0.json mode=oss.

The plugin previously only supported mem0 Cloud (MemoryClient + API key).
Users running self-hosted mem0 (mode=oss in mem0.json with Qdrant/Ollama)
would get a hard 'Mem0 API key not configured' error from the dashboard.

Changes:
- _load_mem0_config: detect oss_mode (mode=="oss" or oss block present)
  and surface oss_config for downstream use
- _mem0_payload: branch on oss_mode; OSS path uses mem0.Memory(config=oss_cfg)
  with user_id/agent_id kwargs; cloud path unchanged
- base response now includes mem0_mode field ("oss" or "cloud") for UI display

Tested against a local Qdrant+Ollama stack (nomic-embed-text, llama3.2:3b).
@terencez127 terencez127 marked this pull request as draft June 29, 2026 00:27
terencez127 and others added 5 commits June 28, 2026 17:28
Two bugs in the initial OSS support:

1. Memory() requires a MemoryConfig Pydantic object, not a raw dict.
   Passing oss_cfg directly raised 'dict object has no attribute embedder'.
   Fix: coerce via MemoryConfig.model_validate(oss_cfg) with **-fallback.

2. OSS Memory.get_all() / .search() take filters={} not top-level
   user_id/agent_id kwargs (same API shape as the cloud client).
   Fix: use filters={'user_id': ..., 'agent_id': ...} and top_k= for search.
Fixes from code review of the initial OSS patch:

#1 & xraysight#2 - Silent swallow + duplicate import bug:
  Hoist MemoryConfig import above both try blocks, catch ImportError
  explicitly with a user-facing error. Replace 'pass' fallthrough
  (which silently called Memory(config=raw_dict) and always crashed)
  with an explicit error message returned to the dashboard.

xraysight#3 - mode:oss with flat config layout ignored:
  When mem0.json uses {"mode":"oss", "llm":{...}} (flat, no "oss"
  sub-block), oss_config was None and Memory() was called with no
  config at all, ignoring user settings. Now: flat layout is detected
  and the whole file_cfg (minus "mode" key) is used as oss_config.

xraysight#4 - agent_id asymmetry between OSS and cloud scope:
  OSS was always injecting agent_id="hermes" (the default) into
  filters, causing OSS to return a narrower result set than cloud for
  the same user. Now: agent_id filter only applied when explicitly set
  to a non-default value, matching cloud path behaviour.

xraysight#5 - rerank not forwarded to OSS search:
  Memory.search() supports rerank=bool. Now forwarded consistently
  with the cloud path.

xraysight#6 - double file_cfg.get('oss') call:
  Replaced with a single _oss_block local variable.

xraysight#7 - get_all() fetches unbounded, client-side limit only:
  Memory.get_all() and Memory.search() both support top_k. Now passed
  server-side so large local vector stores are not over-fetched.
@xraysight

Copy link
Copy Markdown
Owner

Hi @terencez127, thanks for your contribution!

The backend direction looks good, and the local test suite passes (36 passed). I also checked the current mem0ai API shape, and the OSS path using MemoryConfig + Memory(config=...) + filters/top_k is broadly aligned.

Before I can accept/merge this PR, could you please address a few remaining items?

  1. Mark the PR ready for review

    • The PR is still in Draft state, so I’ll treat it as not final yet.
  2. Update the README for Mem0 OSS support
    The docs still describe Mem0 as Platform/API-only and still say local mem0.Memory stores are unsupported.
    Please update the Mem0 section to cover:

    • mode: "oss"
    • flat vs nested oss config layouts
    • that OSS mode does not require MEM0_API_KEY
    • the current limitations section, which currently says local mem0.Memory is not supported
  3. Update the dashboard UI copy/badges
    The backend now returns mem0_mode, but the frontend still shows:

    • “Mem0 Platform memories”
    • “api mode”
    • “no api key”

    For OSS mode, this is misleading. Please use data.mem0_mode in the UI, e.g. show “OSS mode” vs “API mode”, and avoid implying that a missing API key is an error when mem0_mode === "oss".

  4. Add regression tests for the actual OSS payload path
    The new tests cover _load_mem0_config, but not the runtime _mem0_payload behavior.
    Please add tests covering:

    • OSS get_all calls mem0.Memory.get_all(filters=..., top_k=...)
    • OSS search calls mem0.Memory.search(query=..., filters=..., top_k=..., rerank=...)
    • invalid OSS config returns a safe user-facing error
    • missing/unsupported MemoryConfig import returns a clean error

Once those are addressed, I’ll be comfortable reviewing again for approval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants