Memory LanceDB Plugin: Local Vector Memory with Ollama Embeddings

Learn how to configure the official external LanceDB memory plugin for persistent long-term memory with vector search. This guide covers local Ollama-compatible embeddings and OpenAI endpoints.

Read this when

  • You are configuring the memory-lancedb plugin
  • You want LanceDB-backed long-term memory with auto-recall or auto-capture
  • You are using local OpenAI-compatible embeddings such as Ollama

memory-lancedb is an official external plugin that persists long-term memory within LanceDB using vector search. Before each model interaction, it can automatically retrieve relevant memories, and after a response, it can capture important information on its own.

You can employ it for a local vector database, an embedding endpoint compatible with OpenAI, or as a memory store separate from the default built-in memory backend.

Installation

openclaw plugins install @openclaw/memory-lancedb

This plugin is published on npm and is not included in the standard OpenClaw runtime image. Installing it writes the plugin entry, activates it, and changes plugins.slots.memory to memory-lancedb. If another plugin already controls the memory slot, that plugin gets deactivated with a warning.

Note

Companion plugins like memory-wiki can operate together with memory-lancedb, but only a single plugin holds the active memory slot at any given moment.

Note

The memory_recall component of LanceDB does not receive the protected private transcript authorization that memory.search.rememberAcrossConversations uses. Instead, employ LanceDB's autoRecall or its memory_recall tool through advanced Active Memory. openclaw doctor indicates when Remember across conversations is not available with the current memory provider.

Quick start

{
  plugins: {
    slots: {
      memory: "memory-lancedb",
    },
    entries: {
      "memory-lancedb": {
        enabled: true,
        config: {
          embedding: {
            provider: "openai",
            model: "text-embedding-3-small",
          },
          autoRecall: true,
          autoCapture: false,
        },
      },
    },
  },
}

After modifying plugin configuration, restart the Gateway and then confirm it loaded correctly:

openclaw gateway restart
openclaw plugins list

Embedding config

embedding is mandatory and must contain at least one field. provider has a default of openai; model defaults to text-embedding-3-small.

FieldTypeNotes
embedding.providerstringAdapter identifier, for example openai, github-copilot, or ollama. Default is openai.
embedding.modelstringDefault is text-embedding-3-small.
embedding.apiKeystringNot required; supports ${ENV_VAR} expansion.
embedding.baseUrlstringNot required; supports ${ENV_VAR} expansion.
embedding.dimensionsinteger (>=1)Needed for models not listed in the built-in table (see below).

There are two request pathways:

  • Provider adapter path (default): configure embedding.provider and leave out embedding.apiKey/embedding.baseUrl. The plugin resolves the provider's configured auth profile, environment variable, or models.providers.<provider>.apiKey through the same memory embedding adapters that memory-core uses. This pathway is intended for github-copilot, ollama, and any other bundled provider that supports embeddings.
  • Direct OpenAI-compatible client path: leave embedding.provider unset (or set it to "openai") and configure embedding.apiKey along with embedding.baseUrl. Use this for a raw OpenAI-compatible embeddings endpoint that lacks a bundled provider adapter.

OpenAI Codex / ChatGPT OAuth is not a valid credential for the OpenAI Platform embeddings. For OpenAI embeddings, use an OpenAI API key auth profile, OPENAI_API_KEY, or models.providers.openai.apiKey. Users with OAuth-only access should choose another embedding-capable provider such as github-copilot or ollama.

{
  plugins: {
    entries: {
      "memory-lancedb": {
        enabled: true,
        config: {
          embedding: {
            provider: "github-copilot",
            model: "text-embedding-3-small",
          },
        },
      },
    },
  },
}

Some OpenAI-compatible embedding endpoints reject the encoding_format parameter; others disregard it and always return number[]. memory-lancedb omits encoding_format from requests and accepts either float-array or base64-encoded float32 responses, so both response formats work without any configuration.

Dimensions

OpenClaw includes a built-in dimension for text-embedding-3-small (1536) and text-embedding-3-large (3072) only. Any other model requires an explicit embedding.dimensions so that LanceDB can create the vector column, for instance ZhiPu embedding-3 at 2048 dimensions:

{
  plugins: {
    entries: {
      "memory-lancedb": {
        enabled: true,
        config: {
          embedding: {
            apiKey: "${ZHIPU_API_KEY}",
            baseUrl: "https://open.bigmodel.cn/api/paas/v4",
            model: "embedding-3",
            dimensions: 2048,
          },
        },
      },
    },
  },
}

Ollama embeddings

Use the built-in Ollama provider adapter path (embedding.provider: "ollama"). This adapter invokes Ollama's native /api/embed endpoint and follows the same authentication and base URL conventions as the Ollama provider.

{
  plugins: {
    slots: {
      memory: "memory-lancedb",
    },
    entries: {
      "memory-lancedb": {
        enabled: true,
        config: {
          embedding: {
            provider: "ollama",
            baseUrl: "http://127.0.0.1:11434",
            model: "mxbai-embed-large",
            dimensions: 1024,
          },
          recallMaxChars: 400,
          autoRecall: true,
          autoCapture: false,
        },
      },
    },
  },
}

Since mxbai-embed-large is absent from the default dimension table, you must supply dimensions. For small local embedding models, reduce recallMaxChars when the local server returns context-length errors.

Recall and capture limits

SettingDefaultRangeApplies to
recallMaxChars1000100-10000Text forwarded to the embedding API for recall operations.
captureMaxChars500100-10000Message length that qualifies for automatic capture.
customTriggers[]0-50 items, each <=100 charsExact phrases that cause auto-capture to evaluate a message.

recallMaxChars limits the before_prompt_build auto-recall query, the memory_recall tool, the memory_forget query path, and openclaw ltm search. Auto-recall embeds the most recent user message from the current turn and only falls back to the full prompt when no user message exists, keeping channel metadata and large prompt blocks out of the embedding request.

captureMaxChars determines whether a user message from the turn's agent_end event is short enough to qualify for auto-capture; it does not affect recall queries.

customTriggers adds literal auto-capture phrases without regex. Default triggers cover common memory phrases in English, Czech, Chinese, Japanese, and Korean (remember, prefer, 记住, 覚えて, 기억해, and similar).

Auto-capture also rejects text resembling envelope or transport metadata, prompt-injection payloads, or already-injected <relevant-memories> context, and limits captures to 3 memories per agent turn.

Every memory belongs to a single agent. Recall, duplicate detection, capture, listing, raw queries, and deletion all enforce this owner check before returning or modifying rows. An agent with memory.search.enabled: false in its agents.entries.* entry, or one that inherits a disabled top-level search, also receives none of the memory_recall, memory_store, or memory_forget tools and does not participate in automatic recall or capture, even when the plugin-level autoRecall/autoCapture flags are enabled.

Commands

memory-lancedb registers the ltm CLI namespace whenever it is installed, not only when it owns the active memory slot:

openclaw ltm list [--agent <id>] [--limit <n>] [--order-by-created-at]
openclaw ltm search <query> [--agent <id>] [--limit <n>]
openclaw ltm stats [--agent <id>]

ltm query executes a non-vector query directly against the LanceDB table:

openclaw ltm query --agent research --cols id,text,createdAt --limit 20
openclaw ltm query --filter "category = 'preference'" --order-by createdAt:desc
FlagDefaultNotes
--agent <id>configured default agentSelects the private agent namespace. Available on list, search, query, and stats.
--cols <columns>id,text,importance,category,createdAtComma-separated column allowlist.
--filter <condition>noneA single comparison over an output column, such as category = 'preference' or importance >= 0.8. String values must be quoted.
--limit <n>10Positive integer.
--order-by <column>:<asc|desc>noneSorted in memory after the filter runs; the sort column is automatically added to the projection and removed from output if not requested.

The active memory plugin provides agents with three tools:

  • memory_recall: vector search across stored memories.
  • memory_store: store a fact, preference, decision, or entity (rejects text that resembles a prompt-injection payload; skips near-duplicate stores).
  • memory_forget: delete by memoryId, or by query (automatically deletes a single match above 90% score, otherwise lists candidate IDs for disambiguation).

Storage

By default, LanceDB stores data at ~/.openclaw/memory/lancedb. To change this location, provide dbPath:

{
  plugins: {
    entries: {
      "memory-lancedb": {
        enabled: true,
        config: {
          dbPath: "~/.openclaw/memory/lancedb",
          embedding: {
            apiKey: "${OPENAI_API_KEY}",
            model: "text-embedding-3-small",
          },
        },
      },
    },
  },
}

A single LanceDB table is maintained by the plugin, with each row carrying a normalized agent owner identifier. This acts as a partitioning mechanism rather than a filtering step applied after search results are returned. Agent ownership is enforced before vector ranking takes place and is incorporated into list, query, count, and delete operations. ltm query --filter allows one validated comparison against the public output columns. The store constructs this comparison independently from the required owner predicate, so a filter cannot extend the query scope to a different agent.

For databases created prior to the introduction of per-agent ownership, row provenance cannot be reliably determined. During an upgrade, openclaw doctor --fix assigns those legacy rows to the configured default agent once. Runtime access is blocked until that migration finishes; other agents never gain access to the old shared rows.

storageOptions accepts string key/value pairs for LanceDB storage backends, such as S3-compatible object storage, and supports ${ENV_VAR} variable expansion:

{
  plugins: {
    entries: {
      "memory-lancedb": {
        enabled: true,
        config: {
          dbPath: "s3://memory-bucket/openclaw",
          storageOptions: {
            access_key: "${AWS_ACCESS_KEY_ID}",
            secret_key: "${AWS_SECRET_ACCESS_KEY}",
            endpoint: "${AWS_ENDPOINT_URL}",
          },
          embedding: {
            apiKey: "${OPENAI_API_KEY}",
            model: "text-embedding-3-small",
          },
        },
      },
    },
  },
}

Runtime dependencies and platform support

memory-lancedb relies on the native @lancedb/lancedb package, which belongs to the plugin package rather than the OpenClaw core distribution. Plugin dependencies are not repaired during Gateway startup. If the native dependency is missing or fails to load, reinstall or update the plugin package and restart the Gateway.

@lancedb/lancedb does not provide a native build for darwin-x64 (Intel Mac). On that platform, the plugin logs that LanceDB is unavailable at load time. Use the default memory backend instead, run the Gateway on a supported platform or architecture, or disable memory-lancedb.

Troubleshooting

Input length exceeds the context length

The embedding model rejected the recall query:

memory-lancedb: recall failed: Error: 400 the input length exceeds the context length

Reduce recallMaxChars, then restart the Gateway:

{
  plugins: {
    entries: {
      "memory-lancedb": {
        config: {
          recallMaxChars: 400,
        },
      },
    },
  },
}

For Ollama, also confirm that the embedding server is reachable from the Gateway host using its native embed endpoint:

curl http://127.0.0.1:11434/api/embed \
  -H "Content-Type: application/json" \
  -d '{"model":"mxbai-embed-large","input":"hello"}'

Unsupported embedding model

Without embedding.dimensions, only the built-in OpenAI embedding dimensions are recognized (text-embedding-3-small, text-embedding-3-large). For any other model, set embedding.dimensions to the vector size reported by that model.

Plugin loads but no memories appear

Verify that plugins.slots.memory points to memory-lancedb, then execute:

openclaw ltm stats
openclaw ltm search "recent preference"

If autoCapture is disabled, the plugin can still retrieve existing memories but will not automatically store new ones. Use the memory_store tool, or enable autoCapture.