feat(copaw-plugin): MemOS Cloud memory backend for CoPaw (demo)#1447
feat(copaw-plugin): MemOS Cloud memory backend for CoPaw (demo)#1447fancyboi999 wants to merge 5 commits intoMemTensor:mainfrom
Conversation
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.
There was a problem hiding this comment.
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(extendsReMeLightMemoryManager) overridingmemory_searchto 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.
| """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. |
There was a problem hiding this comment.
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.
| from agentscope.message import Msg, TextBlock | ||
| from agentscope.tool import ToolResponse |
There was a problem hiding this comment.
Msg is imported but never used. This will fail Ruff (F401) in CI; please remove the unused import or use it if intended.
| "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), | ||
| } |
There was a problem hiding this comment.
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.
| import asyncio | ||
| import logging | ||
| import time | ||
| from typing import Any, Dict, List, Optional |
There was a problem hiding this comment.
time is imported but never used. This will fail Ruff (F401) in CI; please remove the unused import.
| 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 |
There was a problem hiding this comment.
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.
| "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", |
There was a problem hiding this comment.
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.
- 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
|
All review feedback addressed in 32a89db:
|
背景
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)注册 backendmemos_memory_manager.py— 继承ReMeLightMemoryManager,只覆写memory_search走 MemOS Cloud API,其他本地能力(compaction、token 计数、context 管理)全部复用 ReMeLightmemos_client.py— MemOS Cloud HTTP 客户端(/search/memory+/add/message)用户安装后,在 CoPaw agent 配置里设
memory_manager_backend: "memos"+MEMOS_API_KEY环境变量即可启用。当前集成范围
老实说,目前只接了 MemOS 最基础的一层:
/search/memory云端记忆召回memory_search实现/add/message对话自动上传核心缺口是 add 流程 — CoPaw 的
BaseMemoryManager没有 per-turn 回调,对话内容不会自动上传到 MemOS Cloud。目前只能通过外部手段(MemOS 控制台、API)写入记忆。本地验证
memory_search走 MemOS Cloud 成功召回记忆配套 PR
CoPaw 侧需要一个小改动来支持插件注册 memory backend:agentscope-ai/CoPaw —
feat/memos-memory-backend分支(PluginApi.register_memory_manager+_resolve_memory_class扩展)。想讨论的方向
cc @tangg555 @CaralHsi @xyxy 想听听你们的想法。
Closes #1440