Tools
Noesis
Memory plugin for OpenClaw agents
Install
npm install @blaspat/openclaw-noesis
Configuration Example
{
"plugins": {
"entries": {
"noesis": {
"enabled": true,
"config": {
"ollamaEndpoint": "http://localhost:11434",
"embeddingModel": "nomic-embed-text",
"topK": 6,
"indexQmdSessions": true
}
}
},
"slots": {
"memory": "noesis"
}
}
}
README
# Noesis — Local-First Semantic Memory for OpenClaw
Local-first semantic memory for OpenClaw. No API keys. No cloud. Just your data, on your machine.
Noesis gives your OpenClaw agents a persistent, searchable memory layer backed by [LanceDB](https://lancedb.com) and [Ollama](https://ollama.ai). It slots directly into OpenClaw's memory system so the auto-recall loop just works — your agents remember things across sessions, across restarts, and across each other.
---
## Table of Contents
- [Why Noesis?](#why-noesis)
- [Stack](#stack)
- [Installation](#installation)
- [1. Install the plugin](#1-install-the-plugin)
- [2. Set the memory slot](#2-set-the-memory-slot)
- [3. Start Ollama](#3-start-ollama)
- [4. Restart the gateway](#4-restart-the-gateway)
- [How It Works](#how-it-works)
- [Hybrid Search Pipeline](#hybrid-search-pipeline)
- [Memory Types](#memory-types)
- [When Agents Write to Noesis](#when-agents-write-to-noesis)
- [Multi-Agent Isolation](#multi-agent-isolation)
- [ANN Index](#ann-index)
- [Tools](#tools)
- [Agent tools](#agent-tools-use-these-in-your-prompts)
- [Memory slot tools](#memory-slot-tools-used-by-openclaw-auto-recall)
- [Data Model](#data-model)
- [Migrating Existing Memory Files](#migrating-existing-memory-files)
- [Configuration](#configuration)
- [Embedding Model Choice](#embedding-model-choice)
- [Performance](#performance)
- [Git LFS Persistence](#git-lfs-persistence)
- [Requirements](#requirements)
- [Python CLI Dependencies](#python-cli-dependencies)
- [Architecture Notes](#architecture-notes)
- [License](#license)
---
## Why Noesis?
The pain points it solves:
- **"My agent forgets everything between sessions"** — Noesis persists memory to disk in LanceDB. It survives restarts.
- **"I want semantic search, not just keyword matching"** — Hybrid pipeline: vector ANN + BM25 keyword + MMR reranking.
- **"I don't want to pay API costs for memory"** — Ollama embeddings, fully local. Zero external calls.
- **"I have multiple agents and want shared memory"** — Multi-agent support with `agentId` isolation and opt-in cross-agent search.
- **"Built-in memory search is too slow for large datasets"** — LanceDB IVF-PQ ANN index: sub-30ms queries at scale.
---
## Stack
| Layer | Technology |
|-------|-----------|
| Vector store | LanceDB (disk-based, ARM64 native) |
| Embeddings | Ollama (local, no API key) |
| Default model | `nomic-embed-text` (768d, fast, ~274MB) |
| Alt model | `mxbai-embed-large` (1024d, higher accuracy) |
| Search | Vector ANN + BM25 FTS + MMR rerank |
| Session indexing | QMD session watcher |
| Plugin type | Memory slot (`plugins.slots.memory: "noesis"`) |
---
## Installation
### 1. Install the plugin
```bash
# Via npm (if published as `@blaspat/openclaw-noesis`)
npm install @blaspat/openclaw-noesis
# Or via ClawHub
openclaw plugins install clawhub:@blaspat/openclaw-noesis
```
### 2. Set the memory slot
```bash
openclaw config set plugins.slots.memory noesis
```
Or edit your OpenClaw config:
```json
{
"plugins": {
"entries": {
"noesis": {
"enabled": true,
"config": {
"ollamaEndpoint": "http://localhost:11434",
"embeddingModel": "nomic-embed-text",
"topK": 6,
"indexQmdSessions": true
}
}
},
"slots": {
"memory": "noesis"
}
}
}
```
### 3. Start Ollama
```bash
ollama serve
```
Noesis auto-detects Ollama on startup and pulls the embedding model if it's not already downloaded. No manual steps needed.
### 4. Restart the gateway
```bash
openclaw gateway restart
```
That's it. Your agents now have persistent semantic memory.
---
## How It Works
### Hybrid Search Pipeline
Every `memory_search` call runs through this pipeline:
```
Query text
↓
Ollama embeddings (~20ms, local)
↓
LanceDB IVF-PQ vector search (topK × 2 candidates)
↓
BM25 full-text search (keyword fallback/supplement)
↓
Hybrid merge (vector 60% + BM25 40%)
↓
MMR rerank (λ=0.7, balances relevance + diversity)
↓
Top-K results with full content (lossless)
```
### Memory Types
| Type | Used for |
|------|---------|
| `fact` | Objective info (names, settings, world knowledge) |
| `decision` | Things that were decided, logged for recall |
| `preference` | How things should be done |
| `context` | Project or session context |
| `session` | Auto-indexed from QMD session transcripts |
### When Agents Write to Noesis
Noesis auto-indexes without needing explicit agent calls. Memory flows in through these paths:
**1. Session transcripts (automatic)**
When `indexQmdSessions: true`, a background watcher picks up new QMD session files in `~/.openclaw/sessions/`. Session content is chunked and stored as `memoryType: session` entries under the agent's session ID.
**2. Agent memory dirs (automatic)**
When `watchMemoryDirs: true`, Noesis watches `~/.openclaw/agents/*/workspace/memory/*.md`. Any `.md` file in an agent's memory directory is checksummed, chunked, and indexed — deduplicated by content hash. This includes `MEMORY.md`, daily notes, and anything else an agent writes to disk.
**3. Manual via `noesis_index`**
Agents can call `noesis_index` directly with text, tags, `memoryType`, `priority`, and `ttlDays`. Used for explicitly important entries — a decision the agent wants to guarantee will be remembered.
### Multi-Agent Isolation
Each entry stores an `agentId`. By default, search only returns entries from the querying agent. Pass `crossAgent: true` to search across all agents (read-only — agents can't write each other's memories).
### ANN Index
After enough data is loaded, Noesis creates an IVF-PQ index on the embedding column:
- **nprobe = 16** — 16 partition probes per query. >90% recall at ~20ms on HDD.
- **num_sub_vectors = 96** — PQ compression for 768-dim vectors.
- Index is persistent on disk and survives restarts.
---
## Tools
### Agent tools (use these in your prompts)
| Tool | Description |
|------|-------------|
| `noesis_index` | Store a memory entry (text + metadata + priority + TTL) |
| `noesis_search` | Semantic search with filters |
| `noesis_recall` | List recent entries by agent or session |
| `noesis_import` | Trigger MD → LanceDB migration |
| `noesis_stats` | Entry counts, breakdown by agent/type/priority, expired count |
| `noesis_delete` | Delete entry by ID |
| `noesis_cleanup` | Apply 20% score penalty to all currently expired entries (stay in DB) |
| `noesis_export` | Bulk export all entries as JSON (with optional filters) |
| `noesis_set_priority` | Update priority and/or TTL on an existing entry |
### Memory slot tools (used by OpenClaw auto-recall)
| Tool | Description |
|------|-------------|
| `memory_search` | Auto-recall entry point |
| `memory_get` | Retrieve by ID |
| `memory_index` | Auto-index new content |
| `memory_recall` | Cross-session recall |
---
## Data Model
```
memories table:
id string UUID v4
agentId string "assistantAgent", "tradeAgent", etc.
sessionId string OpenClaw session ID
content string Full original text (lossless)
chunk string Embedded chunk (for reference)
embedding float32[] 768-dim or 1024-dim vector
memoryType string fact/decision/preference/context/session
priority int64 Priority 0–100 (high ≥75 always surfaces)
expiresAt int64 Unix ms. 0 = never. Penalized at 20% score after expiry.
createdAt int64 Unix timestamp (ms)
sourcePath string Origin .md or QMD file path
checksum string SHA-256(content+agentId) for dedup
tags string[] Custom tags
```
---
## Migrating Existing Memory Files
If you have existing markdown memory files (`MEMORY.md`, `memory/*.md`), import them:
```bash
# Import one agent
noesis_import agentId=<agentId>
# Import all agents
noesis_import
```
Or use the standalone Python CLI:
**Standalone Python CLI:**
```bash
pip install lancedb requests
python3 scripts/import_memory.py --agent <agentId>
python3 scripts/import_memory.py --all
python3 scripts/import_memory.py --agent <agentId> --chunk-size 256 --model mxbai-embed-large
```
---
## Configuration
| Key | Default | Description |
|-----|---------|-------------|
| `lanceDbPath` | `~/.openclaw/noesis/db` | LanceDB storage directory |
| `ollamaEndpoint` | `http://localhost:11434` | Ollama API endpoint |
| `embeddingModel` | `nomic-embed-text` | Embedding model (see below) |
| `chunkSize` | `512` | Chunk size in words |
| `chunkOverlap` | `64` | Overlap between chunks |
| `topK` | `6` | Default search result count |
| `autoMigrate` | `false` | Auto-import markdown files on startup |
| `indexQmdSessions` | `true` | Watch + auto-index QMD sessions |
| `watchMemoryDirs` | `false` | Watch agent memory dirs for changes and auto-index .md files |
| `defaultTtlDays` | `90` | Default TTL in days for new entries. `0` = never expire. |
| `autoCleanup` | `true` | On startup, penalize expired entries (20% score). Entries stay in DB. |
| `gitLfsEnabled` | `false` | Enable Git LFS persistence for LanceDB backups |
| `gitLfsRepo` | `blaspat/openclaw-noesis-data` | GitHub repo for Git LFS snapshots |
| `annNprobe` | `16` | IVF-PQ search probes (higher = more accurate, slower) |
| `annNumSubvectors` | `96` | IVF-PQ compression granularity |
### Embedding Model Choice
**`nomic-embed-text` (default, 768d, ~274MB)**
- Faster inference (~20ms on CPU)
- Excellent for short queries and agent memory recall
- Recommended for most setups
**`mxbai-embed-large` (alternative, 1024d, ~834MB)**
- Higher accuracy on longer contexts
- Better MTEB scores overall
- Use when retrieval accuracy matters more than speed
Switch model:
```json
{ "plugins": { "entries": { "noesis": { "config": { "embeddingModel": "mxbai-embed-large" } } } } }
```
---
## Performance
| Setup | Query latency | Notes |
|-------|--------------|-------|
| No index, small dataset | ~50–200ms | Fine for <1K entries |
| IVF-PQ index, HDD | ~2
... (truncated)
tools
Comments
Sign in to leave a comment