Skip to content

feat(copaw-plugin): MemOS Cloud memory backend for CoPaw (demo)#1447

Open
fancyboi999 wants to merge 5 commits intoMemTensor:mainfrom
fancyboi999:feat/copaw-plugin
Open

feat(copaw-plugin): MemOS Cloud memory backend for CoPaw (demo)#1447
fancyboi999 wants to merge 5 commits intoMemTensor:mainfrom
fancyboi999:feat/copaw-plugin

Conversation

@fancyboi999
Copy link
Copy Markdown
Contributor

背景

Issue #1440 提到希望 MemOS 支持 CoPaw 平台。CoPaw 官方已有基于 ReMeLight 的本地记忆系统,架构上也预留了可插拔的 memory backend 接口(BaseMemoryManager + memory_manager_backend 配置)。

这个 PR 是一次集成尝试(demo 级别),验证了 MemOS Cloud 作为 CoPaw memory backend 的可行性。

做了什么

apps/memos-copaw-plugin/ 下新建了一个 CoPaw 插件,包含 4 个文件:

  • plugin.json — CoPaw 插件清单
  • plugin.py — 插件入口,通过 api.register_memory_manager("memos", MemOSMemoryManager) 注册 backend
  • memos_memory_manager.py — 继承 ReMeLightMemoryManager,只覆写 memory_search 走 MemOS Cloud API,其他本地能力(compaction、token 计数、context 管理)全部复用 ReMeLight
  • memos_client.py — MemOS Cloud HTTP 客户端(/search/memory + /add/message

用户安装后,在 CoPaw agent 配置里设 memory_manager_backend: "memos" + MEMOS_API_KEY 环境变量即可启用。

当前集成范围

老实说,目前只接了 MemOS 最基础的一层:

能力 状态
/search/memory 云端记忆召回 ✅ 通过覆写 memory_search 实现
偏好召回(preference_detail_list) ✅ 搜索结果已包含
云端不可达时 fallback 到本地 ReMeLight
/add/message 对话自动上传 ❌ CoPaw 没有 per-turn hook,未实现
工具记忆、技能记忆 ❌ 未接入
知识库检索、多 agent 隔离 ⚠️ 配置字段预留了,但没实际使用
Recall Filter(LLM 二次过滤) ❌ 未实现

核心缺口是 add 流程 — CoPaw 的 BaseMemoryManager 没有 per-turn 回调,对话内容不会自动上传到 MemOS Cloud。目前只能通过外部手段(MemOS 控制台、API)写入记忆。

本地验证

  • 语法检查 + 单元级导入验证通过
  • 实际启动 CoPaw,插件正常加载,memory_search 走 MemOS Cloud 成功召回记忆
  • 不相关对话不受记忆影响,上下文无污染

配套 PR

CoPaw 侧需要一个小改动来支持插件注册 memory backend:agentscope-ai/CoPaw — feat/memos-memory-backend 分支(PluginApi.register_memory_manager + _resolve_memory_class 扩展)。

想讨论的方向

  1. add 流程怎么做? CoPaw 需要 post-turn hook 还是有其他方式?
  2. MemOS 的高级功能(工具记忆、技能记忆、Recall Filter)值不值得在 CoPaw 侧接入? 如果值得,接口怎么设计比较好?
  3. 这个插件应该放在 MemOS 仓库还是独立仓库?

cc @tangg555 @CaralHsi @xyxy 想听听你们的想法。

Closes #1440

Implements CoPaw's BaseMemoryManager interface, delegating long-term
memory search/add to MemOS Cloud API while handling context compaction
locally. Follows the same pattern as existing OpenClaw plugins.

Closes MemTensor#1440
…re parity

Replace the standalone BaseMemoryManager implementation with
inheritance from ReMeLightMemoryManager. This ensures all local
operations (token-aware compaction, check_context, compact_tool_result,
get_in_memory_memory) use CoPaw's battle-tested ReMeLight code.

Only memory_search and summary_memory are overridden for MemOS Cloud.
summary_memory only fires during context compaction, not every turn.
Putting MemOS Cloud add logic there was both unreliable (too infrequent)
and architecturally wrong (mixing local summary with cloud upload).

v1 scope: MemOS Cloud provides recall (memory_search) only.
All local operations (compaction, summary, persistence) stay with
ReMeLight unchanged.  Cloud-side add requires CoPaw to expose a
post-turn hook first.
Copilot AI review requested due to automatic review settings April 9, 2026 09:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a demo CoPaw plugin that registers a MemOS Cloud–backed MemoryManager so CoPaw agents can recall long-term memory via the MemOS Cloud /search/memory API while reusing ReMeLight’s local memory features and providing a local fallback path.

Changes:

  • Introduce a CoPaw plugin manifest + entrypoint that registers the "memos" memory backend.
  • Add MemOSMemoryManager (extends ReMeLightMemoryManager) overriding memory_search to call MemOS Cloud with fallback to local search.
  • Add an aiohttp-based async MemOS Cloud client (search + add endpoints, plus a lightweight ping).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
apps/memos-copaw-plugin/plugin.json Defines CoPaw plugin metadata and dependency on aiohttp.
apps/memos-copaw-plugin/plugin.py Plugin entrypoint; registers the MemOS memory backend and a startup hook.
apps/memos-copaw-plugin/memos_memory_manager.py MemoryManager implementation integrating MemOS Cloud recall with local ReMeLight fallback.
apps/memos-copaw-plugin/memos_client.py Async HTTP client for MemOS Cloud API endpoints used by the memory manager.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2 to +12
"""MemOS Cloud memory manager for CoPaw agents.

Extends ReMeLightMemoryManager — all local operations (context compaction,
token counting, tool result truncation, in-memory memory) are delegated
to the parent class unchanged. Only two methods are overridden:

- memory_search → queries MemOS Cloud instead of local vector index
- summary_memory → uploads conversation to MemOS Cloud after local summary

This ensures full compatibility with CoPaw's MemoryCompactionHook and
force_memory_search auto-recall mechanism.
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module docstring says this class overrides summary_memory to upload conversations to MemOS Cloud, but the implementation does not override summary_memory and the later comment explicitly states cloud "add" is intentionally not implemented. Please update the docstring to match the actual behavior (cloud recall only) to avoid misleading users.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +20
from agentscope.message import Msg, TextBlock
from agentscope.tool import ToolResponse
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Msg is imported but never used. This will fail Ruff (F401) in CI; please remove the unused import or use it if intended.

Copilot uses AI. Check for mistakes.
Comment on lines +132 to +140
"memory_limit_number": cfg.get("memory_limit_number", 9),
"include_preference": cfg.get("include_preference", True),
"preference_limit_number": cfg.get("preference_limit_number", 6),
"relativity": cfg.get("relativity", 0.45),
"timeout": cfg.get("timeout", 8.0),
"conversation_id": cfg.get("conversation_id", ""),
"knowledgebase_ids": cfg.get("knowledgebase_ids", []),
"async_mode": cfg.get("async_mode", True),
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memory_limit_number (and async_mode) are resolved from config/env but never used; memory_search always passes max_results to MemOS instead. Either wire these config values into the request defaults (e.g., use mc["memory_limit_number"] when max_results isn't explicitly provided) or remove the unused config fields to avoid a misleading configuration surface.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +6
import asyncio
import logging
import time
from typing import Any, Dict, List, Optional
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time is imported but never used. This will fail Ruff (F401) in CI; please remove the unused import.

Copilot uses AI. Check for mistakes.
Comment on lines +174 to +183
async def ping(self) -> bool:
"""Lightweight connectivity check via a minimal search call."""
try:
session = await self._ensure_session()
async with session.post(
f"{self.base_url}/search/memory",
json={"user_id": "_ping", "query": "ping"},
timeout=aiohttp.ClientTimeout(total=5),
) as resp:
return resp.status < 500
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping() treats any HTTP status < 500 as "healthy". If the API key is missing/invalid, MemOS will likely return 401/403, which currently reports as healthy and leads start() to log "connected" even though requests will fail. Consider returning True only for 2xx (or at least treating 401/403 as unhealthy) so connectivity/auth problems are surfaced correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +6
"name": "MemOS Cloud Memory",
"version": "0.1.0",
"description": "MemOS Cloud memory backend for CoPaw — provides cloud-based long-term memory via MemOS API (search + add).",
"author": "MemTensor",
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plugin description claims "search + add", but this demo implementation does not implement automatic /add/message uploading (per the PR description and memos_memory_manager comment). Please adjust the description to avoid implying that add/sync is supported.

Copilot uses AI. Check for mistakes.
- SIM105: use contextlib.suppress instead of try-except-pass
- F401: remove unused imports (Msg, time)
- ping(): return True only for 2xx, not all < 500
- plugin.json: remove "add" claim from description
- docstring: remove stale summary_memory override reference
- wire memory_limit_number config into search request
- ruff format fixes
@fancyboi999
Copy link
Copy Markdown
Contributor Author

All review feedback addressed in 32a89db:

  • Stale docstring — removed summary_memory override reference, now accurately describes search-only override
  • Unused imports — removed Msg and time (F401)
  • memory_limit_number unused — now wired into search request as max(max_results, config_limit)
  • ping() too permissive — changed to return True only for 2xx responses
  • plugin.json claims "search + add" — updated to "cloud-based long-term memory recall via MemOS search API"
  • ruff format — ran ruff check --fix, 29 auto-fixes applied, 0 remaining

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.

feat: 咱们的MemOS插件挺好用的,能不能支持一下copaw的安装

2 participants