@marcelferry

Zvec Memory

OpenClaw long-term memory plugin backed by Alibaba Zvec (dense vector ANN)

当前版本
v1.2.4
code-plugin社区source-linked

@kaiporalabs/openclaw-memory-zvec

Long-term memory plugin for OpenClaw using Zvec via the official Node binding @zvec/zvec. Vectors are indexed with an HNSW index and cosine distance; recall and capture follow the usual OpenClaw memory-plugin patterns (tools + optional auto-recall / auto-capture).

npm package: @kaiporalabs/openclaw-memory-zvec
OpenClaw plugin id: memory-zvec (see openclaw.plugin.json)

Features

  • Tools: memory_recall, memory_store, memory_forget (memory slot contract).
  • OpenClaw slot parity: provides memory_search + memory_get, and registers a full memory runtime capability so openclaw status --all and openclaw memory ... work when plugins.slots.memory = "memory-zvec".
  • Embeddings: any OpenClaw memory embedding providerOllama, OpenAI, Copilot, etc. Defaults are tuned for Ollama (nomic-embed-text, 768-d).
  • Storage: local directory under ~/.openclaw/memory/zvec by default (Zvec collection + memory-ids.json id list for listing).
  • CLI: openclaw memory-zvec list|search|stats|status|index|verify|export|import|reembed (always under memory-zvec; see README for memory vs memory-zvec).
  • Retrieval: configurable hybrid fusion (vector + SQLite FTS/BM25), optional cross-encoder rerank (Jina-compatible /rerank), MMR diversity, adaptive recall (skip trivial prompts), optional time decay, scope isolation (global + agent:<id> by default).
  • Status self-test: when OpenClaw opens the memory runtime with purpose: "status" (e.g. Control UI / doctor.memory.status), the plugin runs path checks, SQLite/FTS stats, Zvec count(), and a real embedding provider ping; results are exposed on the manager’s status() payload (see below).

Requirements

  • Node.js ≥ 22 (matches OpenClaw).
  • OpenClaw2026.5.0 (peer dependency; install globally or use the project CLI you already run).
  • Zvec native builds (from @zvec/zvec): Linux x64/ARM64, macOS ARM64, Windows x64. macOS Intel (x64) is not supported by upstream Zvec binaries — use ARM Mac, Linux, or Windows x64.

OpenClaw status (overview vs full)

The default openclaw status command uses a fast scan: it does not open the memory subsystem or run plugin compatibility checks. That is expected OpenClaw behavior, not a bug in this plugin.

You will typically see:

Overview lineMeaning
Memory · enabled (plugin memory-zvec) · not checkedMemory plugins are on and the slot is memory-zvec, but this run did not probe the store (fast mode).
Plugin compatibility · noneNo compatibility notices were collected in this fast scan (empty list).

To inspect memory stats (files/chunks/vector hints when the host resolves them) and populate plugin compatibility notices, run:

openclaw status --all

Use openclaw memory-zvec stats (or list / search) for plugin-local Zvec metrics regardless of status mode.

Status probe (purpose: "status")

When the host resolves the active memory plugin for status (not for a normal tool turn), this plugin runs runStatusSelfTest() once per manager instance. It verifies, among other things:

CheckWhat it means
Workspace directoryAgent workspace exists and is readable (needed to index MEMORY.md, memory/, etc.).
sqlitePathFile path exists on disk when using a local path (non-local URIs are skipped with a note).
dbPath (Zvec root)Directory reachable; after opening the collection, the path is re-checked (directories may be created on first use).
Memory corpus rootsWhich of MEMORY.md, USER.md, IDENTITY.md, memory/ are present (absence is OK if you only use tool-stored memories).
Zvec collectioncount() succeeds (engine + on-disk schema load).
SQLite / FTSChunk/file stats from the open store.
EmbeddingsOne real request via probeEmbeddingAvailability() (validates provider/network/model).

Where to read the report: the synchronous status() return value includes custom.memoryZvecStatusSelfTest, a JSON-serializable object with overallOk, checkedAtMs, per-path probes, embedding, sqlite, zvecCollection, notes[], and embeddingEndpointSummary (provider/model/host only — no secrets).

Top-level hints: after a self-test, vector.available / fts.available and vector.loadError on MemoryProviderStatus reflect combined health (embeddings + Zvec; FTS from SQLite).

Reliability: getMemorySearchManager does not throw on failure; it returns { manager: null, error: "…" } so the gateway status RPC does not crash if paths or native code misbehave.

Retrieval, rerank, scopes (v1.2+)

Workspace chunks (MEMORY.md, memory/, …) are indexed with a scope column (default global). Search filters results to global plus agent:<agentId> unless you override scopes.agentAccess.

Hybrid scoring merges vector ANN with SQLite FTS BM25 (retrieval.mode, weights, minScore / hardMinScore). Optional rerank calls a Jina-style POST endpoint ({ model, query, documents:[{text}] }). adaptive skips auto-recall / hybrid search on very short “hello/thanks” prompts unless force-keywords match. decay optionally down-weights older chunks.

Example fragment:

{
  "retrieval": {
    "mode": "hybrid",
    "vectorWeight": 0.65,
    "ftsWeight": 0.35,
    "minScore": 0.2,
    "hardMinScore": 0.08,
    "mmrEnabled": true,
    "mmrLambda": 0.65,
    "mmrPoolSize": 36
  },
  "rerank": {
    "enabled": false,
    "endpoint": "https://api.jina.ai/v1/rerank",
    "model": "jina-reranker-v2-base-multilingual",
    "candidatePoolSize": 16,
    "timeoutMs": 8000,
    "rerankBlendWeight": 0.45
  },
  "autoRecallTimeoutMs": 15000
}

smartExtraction is parsed for forward compatibility; LLM-based extraction is not enabled in this release.

Diagnostics & logging

Messages go through OpenClaw’s api.logger (info, warn, error, optional debug). Whether debug lines appear depends on the gateway/host log level.

This plugin also formats Error.cause chains (for example fetch failed from embeddings) into warn lines so failures are visible without raw String(err).

Environment variables

VariableWhen setEffect
OPENCLAW_MEMORY_ZVEC_DEBUG1Enables extra logger.debug calls (for example right before auto-recall).
DEBUGcontains substring memory-zvecSame behavior as OPENCLAW_MEMORY_ZVEC_DEBUG=1 (common DEBUG convention).

Examples

# Enable debug lines for this plugin (session only)
export OPENCLAW_MEMORY_ZVEC_DEBUG=1
openclaw gateway restart
# One-shot: run the CLI with diagnostics enabled (adjust to how you start OpenClaw)
OPENCLAW_MEMORY_ZVEC_DEBUG=1 openclaw gateway run
# Alternative using DEBUG (can combine with other DEBUG tokens)
DEBUG="memory-zvec" OPENCLAW_MEMORY_ZVEC_DEBUG=1 openclaw gateway run

Typical warn sources: auto-recall / auto-capture failures, initial workspace sync failures, vector search leg failures (plugin falls back to SQLite FTS), embedding probe failures.

Install

From npm (recommended)

openclaw plugins install @kaiporalabs/openclaw-memory-zvec

Equivalent:

npm install -g @kaiporalabs/openclaw-memory-zvec
# then register the plugin in OpenClaw config per your setup

From this GitHub repository

openclaw plugins install github:kaiporalabs/openclaw-memory-zvec

If your installer checks out source without a prebuilt dist/, run npm install && npm run build in the clone first, or install from a release tarball that includes dist/.

Publishing (maintainers)

The package is scoped under @kaiporalabs. package.json includes "publishConfig": { "access": "public" } so the first publish works as a public package:

npm login
npm publish --access public

More detail: docs/PUBLISHING.md.

Configuration

OpenClaw reads the main config from ~/.openclaw/openclaw.json (unless you override state dir). The plugin system uses:

  • plugins.slots.memory — string plugin id that owns the exclusive memory slot ("none" disables memory plugins).
  • plugins.entries.<pluginId> — per-plugin record: enabled, optional hooks, and config (plugin-specific payload).

This matches the shipped schema (plugins.slots + strict plugins.entries records). See Gateway configuration reference — Plugins.

Non-bundled plugins: OpenClaw blocks conversation hooks (agent_end, etc.) unless you set plugins.entries.<id>.hooks.allowConversationAccess: true. This plugin uses before_prompt_build (auto-recall) and agent_end (auto-capture). Set both hook flags below so recall/capture work; if you only use tools and disable auto-capture, allowConversationAccess is still safe to enable.

If your config uses plugins.allow (allowlist), add "memory-zvec" to the list or the plugin will not load.

After edits, restart the gateway:

openclaw gateway restart

Full example (Ollama, aligned with OpenClaw PluginEntryConfig)

Ensure Ollama is running and the embedding model is pulled (e.g. ollama pull nomic-embed-text).

{
  plugins: {
    slots: {
      memory: "memory-zvec",
    },
    entries: {
      "memory-zvec": {
        enabled: true,
        hooks: {
          allowPromptInjection: true,
          allowConversationAccess: true,
        },
        config: {
          embedding: {
            provider: "ollama",
            model: "nomic-embed-text",
            baseUrl: "http://127.0.0.1:11434/v1",
          },
          autoRecall: true,
          autoCapture: false,
        },
      },
    },
  },
}

nomic-embed-text is built into the plugin’s dimension map (768). For other models, set config.embedding.dimensions explicitly.

OpenAI-compatible HTTP API (explicit API key)

{
  plugins: {
    slots: {
      memory: "memory-zvec",
    },
    entries: {
      "memory-zvec": {
        enabled: true,
        hooks: {
          allowPromptInjection: true,
          allowConversationAccess: true,
        },
        config: {
          embedding: {
            provider: "openai",
            model: "text-embedding-3-small",
            apiKey: "sk-...",
          },
        },
      },
    },
  },
}

When provider is openai and apiKey is set under config.embedding, the plugin uses the OpenAI SDK against the default or config.embedding.baseUrl. For gateway-managed auth without a plugin-local key, use another provider id (e.g. github-copilot) and omit apiKey, per OpenClaw’s provider docs.

Entry fields (plugins.entries.memory-zvec.*)

FieldDescription
enabledSet true so the entry is active (recommended).
hooks.allowPromptInjectionMust be true for before_prompt_build / auto-recall (OpenClaw blocks prompt mutation hooks when false).
hooks.allowConversationAccessRequired true for this npm plugin so agent_end (auto-capture) is registered.
configPlugin-specific settings (embedding, paths, autoRecall, …).

Plugin config keys (plugins.entries.memory-zvec.config.*)

KeyDescription
embeddingProvider/model/baseUrl/apiKey/dimensions (see openclaw.plugin.json / manifest).
dbPathData root (default ~/.openclaw/memory/zvec). Holds the Zvec collection directory and memory-ids.json. Do not set dbPath to "" or whitespace — that used to yield “dbPath resolved to empty path”; empty values are now treated as “use default”. Prefer omitting the key entirely.
sqlitePathOptional explicit SQLite path for chunk metadata + FTS. Defaults to ~/.openclaw/memory/<agentId>.sqlite. Empty or whitespace-only values are ignored (defaults apply); do not set "sqlitePath": "" unless you intend the default.
autoRecallInject top memories before the model runs (default true).
autoCaptureHeuristic capture from user lines after each successful turn (default false).
captureMaxChars / recallMaxCharsLength limits for capture and recall query text.
dreamingReserved for OpenClaw dreaming integration when this plugin owns the memory slot.

Troubleshooting

SymptomWhat to check
memory-zvec: dbPath resolved to empty path (older builds)Remove dbPath: "" from config, or set a real path / ~/.openclaw/memory/zvec. Current versions treat empty dbPath / sqlitePath as “use default” and fall back if resolvePath returns empty.
memory-zvec: dbPath missing after config resolveCorrupt or missing merged config; ensure plugins.entries["memory-zvec"].config parses and includes valid embedding.

CLI

Plugin-local commands (always registered under memory-zvec, no clash with bundled extensions):

openclaw memory-zvec list --limit 20 --order-by-created-at
openclaw memory-zvec search "your query" --limit 5
openclaw memory-zvec stats
openclaw memory-zvec status
openclaw memory-zvec status --agent main

memory-zvec status prints JSON from MemorySearchManager.status() after the status self-test (see Status probe), including custom.memoryZvecStatusSelfTest when present.

Why not openclaw memory status?

OpenClaw only attaches one plugin CLI group per top-level command name. If memory-core (or another plugin) registers memory first, this plugin’s memory status / memory search handlers are not installed — you will still see memory in help, but it may be the other plugin’s implementation. Use openclaw memory-zvec status (and other memory-zvec … commands) for behaviour that is guaranteed to come from memory-zvec.

Architecture notes

  • Zvec stores dense float32 embeddings under dbPath/collection/.
  • memory-ids.json tracks document ids so list can call fetchSync (Zvec does not expose a cheap full scan in the Node API used here). If you delete this file, list may be empty until you re-sync manually; vector search still works for stored docs.
  • Changing embedding dimension without a fresh store will fail with a clear error; move or delete dbPath to re-index.

References

License

MIT — see LICENSE.

Zvec itself is licensed under Apache-2.0 (see upstream notices).

源码与版本

源码仓库

kaiporalabs/openclaw-memory-zvec

打开仓库

源码提交

95c5e2c

查看提交

安装命令

openclaw plugins install clawhub:@kaiporalabs/openclaw-memory-zvec

元数据

  • 包名: @kaiporalabs/openclaw-memory-zvec
  • 创建时间: 2026/05/08
  • 更新时间: 2026/05/08
  • 执行代码:
  • 源码标签: main

兼容性

  • 构建于 OpenClaw: 2026.5.3-1
  • 插件 API 范围: >=2026.5.2
  • 标签: latest
  • 文件数: 72