agentscope-ai / agentscope-ai/agentscope
feat(dakera): integrate Dakera self-hosted decay-weighted long-term memory as an agent middleware
- Lingua principale
- Python
- Stelle
- 31.5k
- Fork
- 3.5k
- Merge medio
- 1g 23h
- PR unite (30g)
- 95
Descrizione
### Background
The `_longterm_memory` middleware module already ships three long-term memory backends — `AgenticMemoryMiddleware`, `Mem0Middleware`, and `ReMeMiddleware` (added via #1747, on the unified RAG/LTM abstraction from #1663/#1664). Each is a `MiddlewareBase` subclass that injects relevant past memories on `on_reply` and (optionally) exposes `search_memory` / `add_memory` tools via the `static_control` / `agent_control` / `both` modes.
I'd like to propose a fourth peer backend: **`DakeraMiddleware`**, backed by [Dakera](https://dakera.ai) — an **open, self-hosted** memory server that gives *persistent, decay-weighted vector recall* across sessions. Memories are importance-scored and decay over time, so stale context stops competing with fresh, relevant facts. It runs beside the app as a container; the Python SDK ([`dakera-ai/dakera-py`](https://github.com/dakera-ai/dakera-py), PyPI `dakera`) ships a full-parity `AsyncDakeraClient`.
**Why it's complementary to the existing three, not a duplicate:**
- `Mem0Middleware` targets mem0 (OSS `AsyncMemory` or the **hosted** Platform client). Dakera is a **self-hosted-first** backend — no SaaS dependency, no per-call egress to a third-party API — for teams that need memory to stay inside their own infra.
- Where mem0 leans on LLM-based fact extraction and ReMe on its own reflection pipeline, Dakera's differentiator is **server-side importance + time-decay ranking** at recall time, which maps naturally onto the middleware's "inject the most relevant past memories" job.
- It slots into the exact same extension point as the existing backends, so it adds an option without touching the shared abstraction.
### Proposed design
Mirror the existing siblings as closely as possible so there are no surprises for reviewers:
```
src/agentscope/middleware/_longterm_memory/_dakera/
__init__.py # exports DakeraMiddleware
_middleware.py # DakeraMiddleware(MiddlewareBase)
_tools.py # _SearchMemoryTool / _AddMemoryTool (agent_control / both)
_utils.py # query-text / memory-text extraction helpers
```
- `DakeraMiddleware(MiddlewareBase)` implementing `on_reply` (recall relevant memories → inject a `HintBlock` memory section) and `list_tools()` for the tool modes, matching `Mem0Middleware`'s `mode` semantics (`static_control` / `agent_control` / `both`).
- Backed by `dakera.AsyncDakeraClient` — `recall(agent_id, query, top_k=...)` for retrieval and `store_memory(agent_id, content=..., importance=...)` for writes. Namespacing via `user_id` / `agent_id` string params set at construction (same shape as `Mem0Middleware`), no `Agent` reference held at call time.
- Optional dependency, declared exactly like the others:
```toml
# ------------ Long-term memory ------------
dakera = ["dakera>=0.12.8"]
```
with a lazy import inside the middleware so the core install is unaffected.
- Tests: `tests/dakera_middleware_test.py`, mirroring `tests/mem0_middleware_test.py` / `tests/reme_middleware_test.py` (mocked async client — no live server needed in CI).
- Conventional commit `feat(dakera): ...`, Python 3.11+, lazy imports, no changes to the shared abstraction — kept atomic per CONTRIBUTING §2.
Self-hosting is a single `docker-compose` ([`dakera-ai/dakera-deploy`](https://github.com/dakera-ai/dakera-deploy), server + object store, default port `3000`), so the example/test story is fully reproducible.
### Design alternatives (happy to go either way)
1. **Full parity with `Mem0Middleware`** — all three control modes + tools (my default proposal above).
2. **Lean first cut** — `static_control`-only (recall-inject on `on_reply`, no agent tools) as a smaller initial PR, with agent-control tools as a follow-up. Smaller review surface if you'd prefer to land it incrementally.
### Next step
Per CONTRIBUTING §3, I'm opening this to get the core team's read on **(a)** whether a self-hosted decay-weighted backend is a welcome addition alongside mem0/reme, and **(b)** which of the two scopes above you'd prefer, before I start the implementation. Once you give a direction I'll open a single focused, tested PR mirroring the existing middlewares — I'll be the author and will be able to walk through every line in review.
Thanks for considering it! 🙏
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.