Skip to content

Commit ea3815a

Browse files
prrao87claude
andcommitted
docs: add Hermes Agent memory integration
Add an integration page for the LanceDB memory plugin for Hermes Agent, covering install and activation, the four memory tools, a remember -> recall -> read -> forget walkthrough, vector/hybrid retrieval modes, store inspection, and configuration. Wires the page into the AI Platforms & Frameworks nav group. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 55e040f commit ea3815a

2 files changed

Lines changed: 322 additions & 0 deletions

File tree

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@
277277
"group": "AI Platforms & Frameworks",
278278
"pages": [
279279
"integrations/ai/agno",
280+
"integrations/ai/hermes-agent",
280281
"integrations/ai/huggingface",
281282
"integrations/ai/langchain",
282283
"integrations/ai/llamaIndex",
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
---
2+
title: "Hermes Agent"
3+
sidebarTitle: "Hermes Agent"
4+
description: "Use LanceDB as a persistent, semantic memory backend for Hermes Agent — durable recall across sessions with vector and hybrid search."
5+
---
6+
7+
[Hermes Agent](https://github.com/NousResearch/hermes-agent) is a self-hosted, open-source
8+
personal agent from [Nous Research](https://nousresearch.com). You can talk to it from a
9+
terminal UI or reach the same agent from Telegram, Discord, and Slack, and it exposes a
10+
dedicated slot for external *memory providers* that run alongside its built-in notes.
11+
12+
The [LanceDB memory plugin](https://github.com/lancedb/hermes-agent-memory) fills that slot.
13+
It gives Hermes durable, semantic recall across sessions: state a preference or a project
14+
convention once, and the agent can retrieve it weeks later in a brand-new session — even when
15+
you ask for it in completely different words. Everything runs inside Hermes' own Python
16+
process, storing a single LanceDB table on local disk. There's no memory server to operate.
17+
18+
The mental model is clean: **Hermes owns the agent loop; LanceDB manages the durable
19+
long-term memory and offers semantic recall.**
20+
21+
## Why LanceDB fits agent memory
22+
23+
Out of the box, Hermes remembers with a small curated notes file frozen into the system
24+
prompt, plus lexical (keyword) search over past sessions. Both are useful, but keyword search
25+
misses paraphrases of what you originally typed — the exact thing you need when recalling a
26+
fact you phrased differently months ago.
27+
28+
LanceDB is an embedded retrieval library, which makes it a natural fit here:
29+
30+
- **No server to stand up** — it reads and writes a table on local disk, so the plugin ships
31+
as a dependency rather than a service to operate.
32+
- **One table holds everything** — content, metadata, and embeddings live together. A memory
33+
becomes a structured row with a category, tags, timestamps, and provenance, not just a text
34+
blob.
35+
- **Query it any way you need** — vector similarity for meaning, BM25 full-text for exact
36+
names and jargon, a hybrid of the two, or plain metadata filters to keep recall scoped to
37+
the right workspace.
38+
- **It scales up** — the same table abstraction carries over to larger LanceDB deployments
39+
later, so the local setup is never a dead end.
40+
41+
## Install and activate
42+
43+
<Tip>
44+
Want to try this without touching your existing Hermes setup? Run everything in an isolated
45+
profile: `hermes profile create demo`, then add `-p demo` to the commands below. When you're
46+
done, `rm -rf ~/.hermes/profiles/demo` removes all trace.
47+
</Tip>
48+
49+
<Steps>
50+
<Step title="Install Hermes Agent">
51+
Skip this if you already have Hermes installed.
52+
53+
```bash
54+
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
55+
```
56+
</Step>
57+
58+
<Step title="Install the plugin">
59+
This shallow-clones the plugin into `~/.hermes/plugins/lancedb/`.
60+
61+
```bash
62+
hermes plugins install lancedb/hermes-agent-memory
63+
```
64+
</Step>
65+
66+
<Step title="Install runtime dependencies into Hermes' environment">
67+
Hermes loads plugins inside its own Python interpreter, so the dependencies go *there* — not
68+
into a separate virtualenv. (This interpreter is shared across profiles, so you only install
69+
once.)
70+
71+
```bash
72+
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 lancedb openai pyyaml
73+
```
74+
</Step>
75+
76+
<Step title="Set your embeddings API key">
77+
The plugin turns conversations into embeddings, so it needs an embeddings key. By default that
78+
is OpenAI, so set `OPENAI_API_KEY` in your environment or in `~/.hermes/.env`.
79+
80+
<Info>
81+
Prefer a local or non-OpenAI model? The plugin uses an OpenAI-compatible client, so you can
82+
point it at any compatible endpoint (OpenRouter, Ollama, vLLM, …) in your config — no code
83+
change needed. See [Configuration](#configuration) below.
84+
</Info>
85+
</Step>
86+
87+
<Step title="Activate and verify">
88+
Switch memory on and pick this plugin:
89+
90+
```bash
91+
hermes memory setup # choose "lancedb"
92+
```
93+
94+
Then confirm it's actually active before you start chatting — this is the one step worth not
95+
skipping, because Hermes quietly falls back to its built-in notes if the provider isn't set:
96+
97+
```bash
98+
hermes memory status
99+
```
100+
101+
```text
102+
Memory status
103+
────────────────────────────────────────
104+
Built-in: always active
105+
Provider: lancedb
106+
107+
Plugin: installed ✓
108+
Status: available ✓
109+
```
110+
111+
You want to see `Provider: lancedb` with both `installed ✓` and `available ✓`.
112+
</Step>
113+
</Steps>
114+
115+
## The memory tools
116+
117+
Once activated, the agent has four tools for working with long-term memory:
118+
119+
| Tool | What it does |
120+
|:--|:--|
121+
| `lancedb_recall` | Semantic (vector, the default) or hybrid search over your workspace memory. Returns matching facts with scores and provenance. |
122+
| `lancedb_remember` | Stores a durable fact when you explicitly ask. Deduplicated by content hash, so remembering the same thing twice doesn't pile up rows. |
123+
| `lancedb_read` | Fetches a single memory by ID, optionally with the original conversation messages it was distilled from. |
124+
| `lancedb_forget` | Deletes safely: previews candidates first, then deletes by exact ID, so nothing disappears by accident. |
125+
126+
Beyond these tools, the plugin also captures durable facts from your conversations
127+
automatically — an auxiliary model distills them before context is compressed and again when a
128+
session ends, so insights survive even when the raw messages are summarized away.
129+
130+
## Walkthrough: teach it a project convention
131+
132+
Let's make this concrete with the pain we opened on: re-explaining your setup every session.
133+
We'll save a convention once, then prove a brand-new session can recall it — touching all four
134+
tools along the way.
135+
136+
### Remember
137+
138+
Ask Hermes to commit a convention to long-term memory. Saying "remember in long-term memory"
139+
makes sure it lands in the LanceDB store, which shows up as the `⚡ lancedb_r` (`lancedb_remember`)
140+
line below:
141+
142+
```text
143+
● Remember in long-term memory: for this project I only use uv, never pip, and I always add type hints to Python functions.
144+
145+
┊ 🧠 memory +memory: "For this project, the user only uses uv for Python package management, never pip, and always adds type hints to Python functions."
146+
┊ ⚡ lancedb_r 0.0s
147+
─ ⚕ Hermes ────────────────────────────────────────────────────────────────
148+
149+
Remembered. I've stored that project convention: use uv only, never pip, and always add type hints to Python functions.
150+
```
151+
152+
### Recall
153+
154+
First, take Hermes' built-in notes out of the picture so recall can *only* come from LanceDB —
155+
the two layers run side by side otherwise, and either could answer:
156+
157+
```bash
158+
hermes config set memory.memory_enabled false
159+
```
160+
161+
Now start a fresh session (`/new`) and ask for the convention back, worded completely
162+
differently from how you saved it:
163+
164+
```text
165+
● /new
166+
● Look through your long-term memory for my Python project preferences.
167+
168+
─ ⚕ Hermes ────────────────────────────────────────────────────────────────
169+
170+
I found one durable memory about Python project preferences:
171+
172+
- Project Python tooling preference is uv; pip is not used; type hints are required.
173+
```
174+
175+
This is the whole point in one exchange. You asked about your *preferences* using none of the
176+
words you stored the fact with — no *uv*, no *pip*, no *type hints* — yet a fresh session, with
177+
none of the earlier conversation in context, pulls it straight back. Semantic search matches on
178+
meaning rather than exact wording, which is precisely where keyword search falls short.
179+
180+
<Tip>
181+
Turn the built-in layer back on for everyday use with `hermes config set memory.memory_enabled true`
182+
— the two memory layers happily coexist. We only disabled it here to prove the recall came from
183+
LanceDB.
184+
</Tip>
185+
186+
### Read
187+
188+
You can also ask where a fact came from. Hermes attributes the answer to its stored memory
189+
rather than guessing from a file in the repo (under the hood, `lancedb_read` can also return
190+
the exact source messages a fact was distilled from):
191+
192+
```text
193+
● Where did that uv preference come from?
194+
195+
─ ⚕ Hermes ────────────────────────────────────────────────────────────────
196+
197+
It came from the project's persistent memory, not from a codebase file I inspected.
198+
199+
Specifically, the recalled memory says:
200+
- "For this project, the user only uses uv for Python package management, never pip, and always adds type hints to Python functions."
201+
```
202+
203+
### Forget
204+
205+
When a preference changes, ask Hermes to drop the old fact. The tool calls tell the whole
206+
story: the two `⚡ lancedb_f` (`lancedb_forget`) lines are it previewing matches and then
207+
deleting, and the trailing `⚡ lancedb_r` is it saving the replacement in the same breath:
208+
209+
```text
210+
● I've switched from uv to pixi. Forget the uv preference.
211+
212+
┊ ⚡ lancedb_f uv preference python package management never pip type hints 0.3s
213+
┊ ⚡ lancedb_f 0.0s
214+
┊ ⚡ lancedb_r 0.2s
215+
─ ⚕ Hermes ────────────────────────────────────────────────────────────────
216+
217+
Done — I removed the uv preference from memory and replaced it with:
218+
219+
- This project uses pixi for Python package management
220+
- Type hints on Python functions are still preferred
221+
```
222+
223+
Remember, recall, read, forget: four small operations that between them cover the entire
224+
lifecycle of a durable memory.
225+
226+
## Retrieval modes
227+
228+
Recall ships in `vector` mode by default — pure semantic search, which is what survives the
229+
paraphrasing you saw above. If you also need exact name or jargon matching, switch to `hybrid`
230+
(vector + BM25) and choose how the two legs are fused: RRF, a vector-biased linear blend, or a
231+
cross-encoder reranker. Mode is set per call; fusion is a config setting.
232+
233+
```yaml
234+
# ~/.hermes/config.yaml
235+
plugins:
236+
lancedb:
237+
retrieval:
238+
mode: hybrid # vector (default) | hybrid
239+
reranker:
240+
type: rrf # how the vector + BM25 legs are fused
241+
# Swap RRF for a reranking pass (pulls in sentence-transformers + torch):
242+
# type: cross-encoder
243+
# model: cross-encoder/ettin-reranker-17m-v1
244+
# rerank_top_n: 50
245+
```
246+
247+
The cross-encoder is the one path that pulls in a local ML stack, so it stays opt-in. It
248+
defaults to the compact 17M-parameter [ettin reranker](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1).
249+
250+
## Inspect the store
251+
252+
Everything lives in one table named `memories` at `~/.hermes/lancedb/memories.lance`. Because
253+
it's a plain LanceDB table, you can open it directly and see exactly what the agent has stored
254+
— a `kind` column separates extracted `fact` rows from the raw `turn` rows they were drawn
255+
from:
256+
257+
```python
258+
import lancedb
259+
260+
db = lancedb.connect("~/.hermes/lancedb")
261+
tbl = db.open_table("memories")
262+
print(tbl.to_pandas()[["kind", "category", "content"]].head())
263+
```
264+
265+
## Configuration
266+
267+
The plugin runs on sensible defaults once activated — you don't have to configure anything.
268+
`~/.hermes/config.yaml` is purely for overrides. Two common ones:
269+
270+
Use a cheaper model for the auxiliary fact-extraction calls:
271+
272+
```yaml
273+
# ~/.hermes/config.yaml
274+
auxiliary:
275+
lancedb_extraction:
276+
provider: openrouter
277+
model: google/gemini-3-flash
278+
```
279+
280+
Point embeddings at a fully local endpoint (for example, Ollama) so nothing leaves your
281+
machine:
282+
283+
```yaml
284+
# ~/.hermes/config.yaml
285+
plugins:
286+
lancedb:
287+
embedding:
288+
model: nomic-embed-text
289+
base_url: http://localhost:11434/v1
290+
api_key_env: OLLAMA_API_KEY # any value works for local Ollama
291+
```
292+
293+
<Info>
294+
Changing the embedding model (or its dimension) against an existing store requires recreating
295+
the table — the plugin fails loudly on a dimension mismatch rather than silently returning
296+
nothing. Every option is documented in the plugin's [`default_config.yaml`](https://github.com/lancedb/hermes-agent-memory/blob/main/src/default_config.yaml).
297+
</Info>
298+
299+
## Benchmark
300+
301+
On [LongMemEval-S](https://huggingface.co/datasets/xiaowu0162/longmemeval-cleaned), a
302+
long-conversation QA benchmark, LanceDB's semantic recall clearly beat Hermes' built-in lexical
303+
search (0.66 vs. 0.53 answer accuracy) by finding the right messages even when the question was
304+
worded differently from the original conversation. For the full methodology, the
305+
per-question-type breakdown, and a reproducible harness, see the
306+
[blog post](https://www.lancedb.com/blog/semantic-memory-for-hermes-agent-with-lancedb) and the
307+
[benchmark harness](https://github.com/lancedb/hermes-agent-memory/tree/main/benchmarks).
308+
309+
## Why this works well
310+
311+
- **It's local-first and embedded.** The memory table lives on your disk with no server to run;
312+
the plugin installs as a dependency of Hermes' own environment.
313+
- **Recall survives paraphrasing.** Semantic search matches meaning, not spelling, which is the
314+
failure mode that sinks keyword-only session search.
315+
- **Memories are structured and traceable.** Each fact is a row with metadata and a link back
316+
to the messages it came from, and `forget` always previews before it deletes.
317+
- **Nothing about it is a dead end.** As your needs grow, the same table abstraction carries
318+
over to LanceDB [Enterprise](/enterprise) for automatic compaction, reindexing, and scale.
319+
320+
To try it, install the plugin, enable it with `hermes memory setup`, and run the kind of
321+
workflow we walked through above.

0 commit comments

Comments
 (0)