Files
AgapHost/adolf/HINDSIGHT-MIGRATION.md
alvis 4ac595a3a9 Adolf memory: migrate Cognee -> Hindsight + Kimi quota tooling
Memory migration (H1-H5, kb#73-77,84):
- hindsight service in openai/docker-compose.yml: LLM via Kimi (cognee-llm
  wrapper), multilingual GPU embeddings (bge-m3 via ollama), jina multilingual
  reranker; pg0 + model cache persisted
- openclaw.json/shared-mcp.json: mcp.servers cognee -> hindsight (bank "adolf")
- hindsight-openclaw-plugin: forced-hook memory (before_prompt_build recall +
  agent_end retain), replacing cognee's hook layer; cognify-sweep dropped
- verified live: Russian retain->recall, cross-session recall, bank isolation

Kimi quota (kb#62):
- adolf-llm/server.js: LLM-free GET /usage route (Kimi managed-usage API)
- quota-command-openclaw-plugin: /quota readout command

Cognee stack left running (decommission is H4/kb#76). Kimi-quota-footer
auto-append abandoned (streamed Matrix replies bypass outbound hooks).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014t8Qg9gi7H7HtT8MncoXAB
2026-07-15 19:53:21 +00:00

220 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Adolf memory migration — Cognee → Hindsight
**Status:** Planned · **Date:** 2026-07-13 · **Owner:** alvis
This is the authoritative design + plan for replacing Adolf's long-term memory
subsystem (**Cognee**) with **Hindsight** (Vectorize, MIT, self-hosted). It
supersedes the Cognee-specific parts of `docs/ARCHITECTURE.md` and gates 45 of
`docs/SPIKE-FINDINGS.md` in the OpenClaw fork (`/home/alvis/adolf`).
Memory stays integrated into Adolf **exactly the two ways Cognee was** — as a
**tool** (MCP) and as **forced hooks** (an OpenClaw memory plugin) — so no
behaviour the user sees is lost; only the backend changes.
> Scope note: this document + the kanboard **Ready** tasks (H1H5) are the
> migration. No live service, compose file, `openclaw.json`, or plugin code has
> been changed yet — those edits are the H-tasks.
---
## 1. Why migrate
Cognee works, but its Agap deployment carries three structural costs, all
documented in the (now-retired) kanboard cognee tasks:
- **Three bespoke services** to keep the memory stack alive: `cognee` (FastAPI +
embedded Kuzu graph + Qdrant vectors), `cognee-mcp` (a patched MCP→HTTP proxy,
local build overlay from kb#70), and `cognee-llm` (a stateless Kimi-CLI wrapper
that exists *only* to give Cognee an LLM on the flat subscription).
- **The cognify pipeline is fragile and expensive.** "Cognify" (turning raw
turns into a graph) is an LLM step. On the Kimi CLI it runs ~524 s per call
and drains the single-seat subscription quota (SPIKE gate 5 recommended
LiteLLM instead). The plugin's async "cognify sweep" also silently stalled
twice (kb#69) because of OpenClaw plugin-lifecycle edge cases, so freshly told
facts weren't retrievable cross-session until the sweep was re-armed.
- **Scoping is best-effort.** Under `ENABLE_BACKEND_ACCESS_CONTROL=False` all
datasets share one graph/vector backend, so per-chat isolation leaks (kb#59).
## 2. What Hindsight gives us
- **One container.** `ghcr.io/vectorize-io/hindsight:latest` — REST API on
**:8888**, web UI on **:9999**, built-in PostgreSQL (`pg0`, persisted under
`/home/hindsight/.pg0`). It owns its own vector + graph + temporal
representation internally (the "four-network" model), so **no external Qdrant
or Kuzu** is needed for memory.
- **Built-in MCP server** mounted at `/mcp` on the same port — ~30 tools
including `retain` / `recall` / `reflect`. This **removes the need for a
separate `cognee-mcp` proxy container entirely**.
- **Retain learns on its own.** `retain` runs Hindsight's extraction/reflection
pipeline internally (optionally `async`), so there is **no separate "cognify
sweep" to arm, throttle, or watch** — the whole class of kb#69 bugs disappears.
- **Memory banks** are first-class isolation units, scoped by URL path
(`/v1/{tenant}/banks/{bank_id}/…`), so per-chat / per-user scoping is real, not
best-effort.
- **Bring-your-own LLM/embeddings** — OpenAI-compatible, Anthropic, Ollama,
LMStudio, etc. We point it at the infra we already run (LiteLLM `:4000` and/or
Ollama), so we can **delete `cognee-llm`** rather than port it.
Net: **3 services → 1**, plus we drop the cognify-sweep machinery.
## 3. Target architecture
```
Matrix ⇄ OpenClaw ("Adolf" gateway)
│ provider adolf-llm (Kimi wrapper, :8010) — unchanged
adolf-llm ── kimi CLI (agent)
┌─────────┴───────────────── memory is a boundary concern ─────────────┐
│ │
│ (a) FORCED HOOKS — hindsight-memory OpenClaw plugin │
│ before_prompt_build → recall → inject as prependContext │
│ agent_end → retain (async:true) the turn │
│ │
│ (b) TOOL — Hindsight built-in MCP in openclaw.json mcp.servers │
│ http://hindsight:8888/mcp/adolf/ → retain/recall/reflect/… │
└───────────────────────────────┬───────────────────────────────────────┘
hindsight (ONE container)
:8888 REST + /mcp · :9999 UI
built-in Postgres (pg0)
LLM → LiteLLM :4000 (or Ollama) [decision, §6]
embeddings → Ollama / built-in [decision, §6]
```
Reused infra: **LiteLLM `:4000`** and/or **Ollama** for Hindsight's model calls.
**Retired:** `cognee`, `cognee-mcp`, `cognee-llm`, Qdrant-for-cognee, Kuzu, the
`cognee-openclaw-plugin`, and all `openclaw.json` cognee references.
### 3.1 Surface (a) — forced hooks (the `hindsight-memory` plugin)
A new OpenClaw memory plugin replacing `cognee-openclaw-plugin`, modelled on the
same Honcho touchpoints Cognee used, so the plugin shape is familiar:
| Cognee plugin (`cognee-memory`) | Hindsight plugin (`hindsight-memory`) |
|-----------------------------------------------------|---------------------------------------------------------------|
| `before_prompt_build` → LLM-free graph recall inject | `before_prompt_build``recall` → inject `prependContext` |
| `agent_end` → raw `/add` (no inline cognify) | `agent_end``retain` (`async:true`) the user+assistant turn |
| throttled **cognify sweep** (dirty-tracker, timers) | **removed** — retain does extraction/learning internally |
| `cognee_recall` registered tool | `hindsight_recall` (+ optional `hindsight_reflect`) tool |
- Activated via `plugins.entries.hindsight-memory` in `openclaw.json` with the
same hook grants Cognee needed: `hooks.allowConversationAccess: true` and
`allowPromptInjection: true` (external plugins must opt in).
- **Recall stays off the hot LLM path.** Hindsight `recall` is retrieval
(semantic + BM25 + graph + temporal) with evidence scoring — no generative
synthesis — so it's the direct analogue of Cognee's LLM-free `onlyContext`
recall. The LLM-backed synthesis path is `reflect`, exposed as a deliberate
tool, not run per-turn.
- **No freshness dial / sweep.** Retain with `async:true` returns fast and lets
Hindsight extract/consolidate in the background; there is no plugin-owned timer
to stall.
- Same "untrusted metadata" framing on the injected block; same cleaning of
OpenClaw's `Conversation info (untrusted metadata):` and the memory block out
of stored/queried text.
### 3.2 Surface (b) — tool (built-in MCP)
Replace the `cognee` entry in `openclaw.json` `mcp.servers` with:
```jsonc
mcp: {
servers: {
hindsight: {
type: "http",
url: "http://hindsight:8888/mcp/adolf/", // bank-scoped by URL path
},
// openclaw-tools, kanboard, marketplace — unchanged
},
}
```
The single bank in the path (`adolf`, or a per-chat bank) selects isolation; the
built-in MCP then exposes `retain`, `recall`, `reflect`, plus mental-model /
directive / memory-browse tools. This replaces cognee-mcp's `remember` / `recall`
/ `forget` — and gives deliberate delete via the memory-management tools instead
of the hand-patched `forget(data_id)` from kb#70.
## 4. REST / MCP API mapping
Base path: `http://hindsight:8888/v1/default` (tenant `default`). Bank id is a
**path** parameter.
| Operation | Cognee (old) | Hindsight (new) |
|------------------|------------------------------------------------|-----------------------------------------------------------------------|
| store a turn | `POST /api/v1/add` (+ later `/cognify`) | `POST /banks/{bank}/memories` body `{items:[{content,context,tags,timestamp}], async:true}` |
| recall (no LLM) | `POST /api/v1/search` `GRAPH_COMPLETION` `onlyContext:true` | `POST /banks/{bank}/memories/recall` body `{query, budget, max_tokens, tags}` |
| deep answer (LLM)| cognee-mcp `recall` (GRAPH_COMPLETION) | `POST /banks/{bank}/reflect` body `{query, budget, max_tokens, response_schema?}` |
| delete an entry | patched `forget(dataset, data_id)` (kb#70) | memory-management endpoints / MCP (`delete`, `clear_memories`) |
| list / inspect | dataset status polling | `GET /banks/{bank}/memories/list`, `GET /banks` |
| create bank | dataset created implicitly on add | `PUT /banks/{bank}` |
Built-in MCP tools live at `http://hindsight:8888/mcp/{bank}/` (HTTP transport;
bank via URL path, `X-Bank-Id` header, or `HINDSIGHT_MCP_BANK_ID` default).
> Exact request-body field names and any auth headers must be confirmed against
> the running instance's OpenAPI (`http://localhost:8888/docs`) and the Hindsight
> configuration docs during H1 — treat the bodies above as the shape, not gospel.
## 5. Bank scoping
Mirror Cognee's per-conversation `chat_<chatId>` dataset with a per-conversation
**bank**: derive `bank_id` from OpenClaw's `chat_id` (the
`Conversation info (untrusted metadata):` block; see SPIKE gate 2), sanitized to
`chat_<slug>`. A single shared `adolf` bank is the simpler alternative if
cross-chat recall is actually wanted — decide in H3. Banks are hard isolation in
Hindsight, so per-chat is now safe (unlike Cognee's leaky datasets).
## 6. Open decisions (resolve in H1)
1. **LLM backend for retain/reflect.** SPIKE gate 5 already concluded the
extraction workload should *not* sit on the Kimi CLI (latency + single-seat
quota). Recommendation: point Hindsight's LLM at **LiteLLM `:4000`** (or a
local **Ollama** model for zero marginal cost). This is why `cognee-llm` is
deleted, not ported. Confirm Hindsight's provider env-var names on the image.
2. **Embeddings.** Prefer the local **Ollama** embedder already available
(`nomic-embed` / `bge-m3` at `host.docker.internal:11436`) or Hindsight's
built-in, to keep embeddings off any paid path.
3. **Storage path.** Persist `pg0` under `/mnt/ssd/dbs/hindsight/` to match the
Agap storage layout (replaces `/mnt/ssd/dbs/cognee/`).
4. **UI exposure.** Whether to reverse-proxy the `:9999` UI (Caddy) or keep it
internal-only.
5. **Auth.** Open by default; enable the tenant API-key extension
(`HINDSIGHT_API_TENANT_API_KEY`, `Authorization: Bearer`) if the service is
reachable beyond the compose network.
## 7. Data migration
Cognee's Kuzu graph is **not** portable into Hindsight's store. The memory corpus
is low-value conversational history, so **start Hindsight empty** rather than
building an exporter. Optionally replay a handful of durable facts by calling
`retain` once at cutover. The two throwaway datasets left in Cognee
(`chat_verify`, `chat_webchat`) are discarded with the stack.
## 8. Migration phases (kanboard **Ready**, project *Adolf*)
- **H1 · Deploy Hindsight service** — add the `hindsight` container to
`openai/docker-compose.yml` (image, ports 8888/9999, `pg0` volume, LLM +
embedding provider env → LiteLLM/Ollama), bring it up, confirm `/docs` + a
round-trip `retain``recall`. Resolves §6 decisions.
- **H2 · Wire built-in MCP as an Adolf tool** — swap `mcp.servers.cognee`
`mcp.servers.hindsight` (`/mcp/{bank}/`) in `openclaw.json`; verify Adolf can
call `retain`/`recall`/`reflect` as tools.
- **H3 · `hindsight-memory` OpenClaw plugin (forced hooks)** — build the plugin
replacing `cognee-openclaw-plugin`: `before_prompt_build`→recall inject,
`agent_end``retain(async)`, `hindsight_recall`/`hindsight_reflect` tools, bank
scoping; activate in `openclaw.json`. Delete the cognify-sweep machinery.
- **H4 · Decommission Cognee** — remove `cognee`, `cognee-mcp`, `cognee-llm`
services + volumes, the `cognee-openclaw-plugin`, and all `openclaw.json`/
`shared-mcp.json` cognee references. Free `/mnt/ssd/dbs/cognee`.
- **H5 · End-to-end verification** — state a fact → fresh session → recalled via
injected memory (no LLM on the recall path); measure recall latency; confirm
per-bank isolation; confirm no sweep/timer exists to stall.
## 9. What is unchanged
The Kimi/OpenClaw/Matrix substrate is untouched: `adolf` gateway, `adolf-llm`
(:8010) provider, the SSE-heartbeat/idle-watchdog fix (kb#71), the
`openclaw-tools` bridge, `kanboard`/`marketplace` MCP servers, Matrix allow-list
and E2EE. Only the memory backend and its two integration surfaces change.