TL;DR - Hermes ships with built-in memory, but it forgets the shape of things - how facts connect, not just the facts themselves. Cognee doesn't. For example, it'll still remember that the API rate limit you mentioned last week belongs to the same project whose codename you gave it the day before.
Cognee doesn't. In this walkthrough I install both from scratch on a fresh Windows box, install the official Cognee memory plugin, point Hermes at it, and then stress-test it with real facts - to see whether the agent actually remembers across sessions.
It does. I hit a few sharp edges along the way.I've written down every one of them so you don't have to.
1. Why bother bolting Cognee onto Hermes?
Let me start with the problem, because it's easy to skip past and then wonder why any of this matters.
Out of the box, an agent's memory is basically a scroll back buffer. It remembers what's in the current session and then, as the conversation grows, earlier conversations get summarised or dropped. That's fine for a single sitting. It falls apart the moment you close the terminal and come back tomorrow expecting it to know that the staging rate limit is 47 requests a minute, or that the backend runs on Postgres.
Hermes has a decent built-in memory that handles the short game. What it doesn't do on its own is build a structured long-term picture - the kind where "Alice," "engineering," and "the Falcon project" aren't just three strings floating in a vector store but nodes with edges between them. That's exactly the gap Cognee fills. Cognee ingests whatever you feed it and quietly builds a knowledge graph in the background, so retrieval can follow relationships instead of returning isolated chunks.
So the pitch is simple: Hermes is the agent, Cognee is the hippocampus. Wire them together and the agent stops forgetting the shape of your world.
The good news is Hermes was clearly built with this in mind - it has a first-class memory-provider plugin system, and Cognee slots into it cleanly. The rest of this post is me actually doing it, screenshot by screenshot.
Here's the finish line so you know what you're aiming at - the Hermes home screen, which by the end will be backed by Cognee:
Nothing here requires a GPU, a paid graph database, or any cloud infrastructure. Everything runs on your own machine - though if you'd rather not run anything locally at all, there's a Cognee Cloud path too.
2. Prerequisites & installation
Before you start: prerequisites
You need a handful of tools on your PATH. Hermes checks for these itself during installation
| Tool | Why Hermes wants it |
|---|---|
| uv | Fast Python packaging and environment management. |
| Python 3.11 | Runtime for both Hermes and Cognee. |
| Git | Cloning repositories and plugin discovery. |
| Node.js | Required by parts of the tooling layer. |
| ripgrep | Fast in-repository search for the agent. |
| ffmpeg | Media handling. |
| LLM API Key | Local mode only - Cognee uses an LLM to extract entities and relationships while building the graph |
That last row has a caveat worth knowing up front. The LLM key is only needed if you're running Cognee locally. If you go the Cognee Cloud route instead, you don't need an LLM key at all - you need a tenant URL and an API key from the Cognee Cloud dashboard, and the tenant runs the models for you.
When you run the installer, it verifies each of these and - if you already have Hermes - updates the existing install rather than clobbering it.
If any of these come back red, fix that first. Everything downstream assumes a clean prerequisite check.
Step 1 - Install Hermes
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
Run the installer and let it do the prerequisite sweep above. Once it's green across the board, Hermes is on your machine. We'll come back and point it at a model in Section 3 - first, let's get Cognee down.
Step 2 - Install Cognee
One lines:
pip install cognee-integration-hermes-agent
That's it - Hermes picks up the plugin automatically once it's installed.
Upgrading is the same single command:
pip install -U cognee-integration-hermes-agent
Skip the second and you're still running the old copy. hermes cognee status will tell you when the installed copy and the installed package have drifted apart, which is a nice touch.
Prefer to work from source? The integration lives in Cognee's integrations monorepo:
git clone https://github.com/topoteretes/cognee-integrations.git
mkdir -p ~/.hermes/plugins/cognee
cp -R cognee-integrations/integrations/hermes-agent/. ~/.hermes/plugins/cognee/
Fair warning: it pulls in a long tail of dependencies - vector store, graph engine, the LLM plumbing, the lot. Don't be alarmed by the wall of package names scrolling past.
💡 Rule of thumb: when two tools disagree on a shared library version, separate environments beat forcing a single resolution. Reproducibility over convenience.
3. Give Hermes a model to talk to
Hermes stores its config and secrets in ~/.hermes/.env. On my first attempt PowerShell threw a path error because the directory didn't exist yet - a one-line fix, then it wrote the file and I dropped in my GOOGLE_API_KEY.
If you hit the same path error, just create the folder first:
mkdir -p ~/.hermes
Now pick a provider. hermes model opens a menu with a genuinely long list of supported providers - OpenAI, Anthropic, Google, and plenty more.
I went with Google AI Studio: paste the API key, choose a default Gemini model.
Relaunch, and Hermes comes back up on Gemini (gemini-2.5-flash-lite) with the normal welcome dashboard.
One thing I like here: swapping the model is completely decoupled from the memory layer. You can run Gemini today and Opus tomorrow, and Cognee doesn't care - it sits underneath both.
4. The memory-provider plugin
You don't have to build any of this yourself any more, but it's worth a couple of minutes understanding what you just installed, because it explains the behaviour you'll see later - and one or two things that would otherwise look like bugs.
Hermes discovers memory providers by scanning $HERMES_HOME/plugins/ for a folder containing a plugin.yaml next to a Python implementation. The YAML declares the metadata and - crucially - which lifecycle hooks the provider implements. The Cognee plugin lands at ~/.hermes/plugins/cognee/, and that folder name is the provider's identity: it's what shows up in the setup menu.
[screenshot: plugin.yaml - caption it as the file that ships with the package, not one you write. Those hook names are exactly what Hermes scans to know what the provider can do.]
What happens, and when
| Moment | What Cognee does with it |
|---|---|
| Session start | Ensures a local Cognee server is running - or attaches to one a sibling plugin already started - and connects as a thin client |
| After each completed turn | Writes turn into Cognee session memory. Fast, no graph build. |
| cognee_recall | Searches session memory first, falls back to the knowledge graph. A cognee_remember fact is already in the graph, so that's where recall finds it. |
| cognee_remember | Writes a durable fact straight into the graph |
| cognee_forget | Handles deletion requests |
| Explicit Hermes memory writes | Mirrored through on_memory_write |
| Session end | Runs cognee.improve() to bridge the session's turns into the permanent graph |
That last row is the design decision I'd point at if you only read one thing here. The expensive part of Cognee - chunking text, running an LLM to pull out entities and relationships, embedding, committing edges - does not happen inline on every turn. If it did, every single turn would freeze while the graph churned. Instead turns go into cheap session memory, and the graph build happens once, at the end, when nobody is waiting on it.
And it happens out of process. On session end the plugin hands the close to a detached worker, which runs improve() to completion and only then unregisters from the server.Exiting Hermes returns immediately - you're never sitting in a terminal watching a graph build finish.
That ordering is required, not stylistic. The local server runs in agent mode and retires itself within 60 seconds of the last agent unregistering, so unregistering first would kill the promotion halfway through. The same detached worker also covers the case where Hermes dies uncleanly, which means you don't lose the session and you don't leak an orphaned server either way.
The three modes
The provider connects to Cognee in one of three modes, and it picks automatically from your config:
| Mode | When it is used | How it talks to Cognee |
|---|---|---|
| local-server (default) | no COGNEE_BASE_URL, COGNEE_EMBEDDED unset | ensures a local Cognee server is running and connects as a thin client |
| remote | COGNEE_BASE_URL is set | thin client to Cognee Cloud or your own managed instance |
| embedded | COGNEE_EMBEDDED=true | runs Cognee in-process |
I'd assumed embedded would be the sensible default. It isn't, and the reason is a good one. Cognee's local stores - SQLite, Kuzu/Ladybug, LanceDB - are single-writer. Driving them in-process from the agent's background threads, or from a second Hermes process sharing the same data root, gets you database is locked errors and eventually corruption. A local Cognee server is the single owner that serialises all access, so the agent just makes HTTP calls. It's the same design the Claude Code and Codex plugins use. Embedded is opt-in and safe for single-process or offline use only.
The other thing I came to appreciate: no silent fallbacks. If COGNEE_BASE_URL is set but unreachable, or the local server fails to start, initialization raises rather than quietly switching to a different mode. A silent fallback would either mask a config error - remote and local data drifting apart without you noticing - or reintroduce exactly the DB-lock risk this design removes. And if initialization does fail, memory stays off: Hermes logs the error and starts anyway, and the provider refuses every call rather than operating a half-connected backend. You get a loud failure instead of three weeks of mysteriously missing memories.
One brain across agents
This is my favourite part, and it wasn't obvious from the outside.
By default the Hermes plugin joins the same memory as the Claude Code, Codex and OpenClaw Cognee plugins: the same dataset (agent_sessions), the same local storage (~/.cognee/{data,system}), the same server port (8011) and the same minted API key (~/.cognee-plugin/api_key.json). Whichever plugin boots the server first, the rest attach to it. A fact you remember in Claude Code is recallable in Hermes, and the other way round.
If you'd rather keep Hermes - or one Hermes profile - apart, give it its own COGNEE_PLUGIN_DATASET. For full isolation, give it its own COGNEE_DATA_ROOT / COGNEE_SYSTEM_ROOT and its own COGNEE_LOCAL_PORT. A server belongs to whoever reaches its port first, so a private store needs a private port.
5. Set Cognee as the memory provider
Now the payoff. Run:
hermes memory setup
Hermes lists the available memory providers - its own built-in memory plus Cognee.
Select Cognee and it asks you how you want to connect, which is the mode decision from Section 4 showing up as a prompt. Local keeps everything on your machine — that's the local-server default, and it's the one that wants an LLM API key, because Cognee needs a model to pull entities and relationships out of your text while it builds the graph. Cloud points at a hosted tenant instead: a base URL and a Cognee Cloud API key, no LLM key of your own, because the tenant runs the models.
I went local. Pasted the key, and Hermes wrote the activation into both its config and the .env.
Worth knowing before you pick: this choice lands in ~/.hermes/cognee.json, and that file wins over your environment. A local setup writes an empty service_url there, which is why exporting COGNEE_BASE_URL later doesn't move you to the cloud - see rough edge #4. Changing your mind means re-running hermes memory setup, not editing a variable.
Confirm it stuck:
hermes memory status
Installed. Available. Active. That's the whole handshake - Hermes now routes its remembering and learning through Cognee.
6. Prove it actually remembers
A config that says it works means nothing. Let me actually test recall, because this is where most "memory" demos quietly cheat.
So I gave it something to hold onto: "Use cognee_remember that my favorite editor is Helix."
It called cognee_remember. Nineteen seconds, then confirmation. What I didn't ask for is what happened next - it turned around and called cognee_recall on itself to check the write had landed. Came back with "Your favorite editor is Helix," and, more usefully, a source tag: graph, dataset agent_sessions. Then it wrote the same fact into Hermes' own memory store. That one took 0.0s, because the fact was already sitting there.
Sit with that source tag for a second, because it's doing more work than it looks like. cognee_recall checks session memory first and only falls back to the graph. So when it tells you the answer came from the graph, it isn't handing you back a warm copy of the sentence you typed thirty seconds ago. The fact is genuinely in there.
It's worth being precise about what's happening underneath, because I got this wrong at first and it changes how you test.
There are two write paths and they behave differently. cognee_remember is the durable one - it goes straight into the knowledge graph, immediately. Ordinary conversation turns don't do that; they land in session memory, and only get promoted into the graph by improve() when the session ends.
Which means the thing you say in passing and the thing you explicitly ask it to remember don't live in the same place, at least not straight away. Mention your Postgres version mid-conversation and ask about it ten minutes later, and session memory is almost certainly what answers you. Ask tomorrow and it's the graph.
That matters mostly for how you test. Two ways to prove the graph path rather than accidentally testing the scroll-back buffer: use cognee_remember outright and read the source tag, like above. Or do it the slow way - close Hermes completely, give the detached worker a moment to finish promoting the session, reopen, and ask cold. The second one is more convincing. The first one takes twenty seconds.
7. How the whole thing fits together
Here's the mental model I wish I'd had at the start. When you talk to Hermes, your message flows through the agent to the LLM, Hermes' plugin discovery routes memory operations to the Cognee SDK, and Cognee reads from and writes to its knowledge graph.
In plain words:
Your Prompt ──► Hermes Agent ──► LLM (Gemini / Opus / whatever)
│
├─ every turn ───────────► session memory (cognee server, :8011)
│
├─ cognee_recall ────────► session memory first, graph as fallback
│
├─ cognee_remember ──────► knowledge graph (durable, immediate)
│
└─ session end ──────────► detached worker runs improve()
└─► session memory promoted into the graph
Every turn does two cheap things: before the model answers, recall pulls relevant memory in; after it answers, the turn is written to session memory. Neither one blocks on a graph build.
The expensive work - chunking, extracting entities and relationships with an LLM, embedding, committing edges - happens once, at session end, in a process that isn't yours. So the next session starts smarter than the last one, and you never paid for it mid-conversation. That's the trick, and it's why the integration feels fast in a way I didn't expect.
Final proof, on a different model. To show the memory layer is model-agnostic, I switched Hermes to gemini-3.5-flash and told it: "our next product launch is September 12th." That kicked off Cognee's memory processing.
Cognee ran its full ingestion pipeline, and when I asked later, Hermes recalled the launch date correctly: September 12th.
Different model, same memory, correct answer. That's the whole point - the intelligence layer and the memory layer are cleanly separated, and you can swap one without disturbing the other.
8. Rough edges, honest feedback, and where to go next
The rough edges I hit
I'd be doing you a disservice if I pretended this was frictionless. It wasn't - and honestly, the friction is the most useful part of a guide like this.
| # | What happened | Fix |
|---|---|---|
| 1 |
packaging 24.2 conflicted with packaging==26.0. |
Isolate Cognee in its own uv virtual environment so the two environments don't share the same dependency. This is less likely now that you're installing the integration package rather than pulling Cognee into the Hermes environment yourself, but if you hit it, separate environments beat forcing a single resolution. |
| 2 | PowerShell couldn't create ~/.hermes/.env because the directory didn't exist. |
Run mkdir -p ~/.hermes (or create the folder manually on Windows) before creating the .env file and adding the API key. |
| 3 | The First hermes session after setup hung for a couple of minutes | That's the one-time database migration on first boot of the local server. curl -s http://127.0.0.1:8011/health tells you when it's actually up. |
| 4 | Exported COGNEE_BASE_URL to move to the cloud and it stubbornly stayed local |
~/.hermes/cognee.json takes precedence over the environment, and a local setup writes an empty service_url there. Re-run hermes memory setup. |
None of these are dealbreakers. But every one of them would've cost me twenty minutes of head-scratching if nobody had written them down, so now they're written down.
Where to go next
If you got this far, you have a Hermes agent with a real, graph-backed memory that survives across sessions and across model swaps. A few directions from here:
- Share the brain. Install the Cognee plugin for Claude Code, Codex or OpenClaw too. They default to the same dataset, storage and port, so a fact you teach one is recallable in all of them.
- Scale the backend. Swap the local defaults for Postgres/pgvector, Neo4j, or Qdrant when your graph outgrows local storage.
- Feed it documents, not just chat. Cognee ingests files, JSON, and more - point it at your project docs and let the graph build itself. Then use it with your agent to get the benefit of Hermes with AI memory.
- Explore Cognee's search modes. It ships more than a dozen retrieval strategies, from classic RAG to graph-traversal completion.
- Tune the session-end behaviour. COGNEE_IMPROVE_BACKGROUND controls where the graph build runs. The default auto hands it to the detached worker, which is what you want on a local server. Persistent memory is the difference between a tool you re-explain your world to every morning and a colleague who already knows it. Wiring Cognee into Hermes gets you the second one - and now you've seen every step, every error, and every fix along the way.
9. FAQ
1. Do I need a GPU or a paid cloud service to run this?
No. Everything in this guide runs locally on your own machine, backed by local cognee server using - SQLite, an embedded vector store, and an embedded graph engine. No GPU, no hosted database, no cloud account. You only reach for Postgres/pgvector, Neo4j, or Qdrant when your graph outgrows local storage, and even then it's optional.
Worth noting that "local" doesn't mean "in-process." The default is a small local server on 127.0.0.1:8011, because Cognee's local stores are single-writer and the server is what keeps a single owner over them. You only reach for Postgres/pgvector, Neo4j or Qdrant when your graph outgrows local storage, and even then it's optional.
2. What happens if Cognee can't start?
Memory stays off, loudly. The provider never quietly downgrades - if your remote URL is unreachable or the local server won't boot, initialization raises. Hermes logs the error, starts anyway, and the provider refuses every call.
That's deliberate. A silent fallback would either mask a config error (your remote and local data quietly diverging) or reintroduce the database-lock risk the local-server design exists to remove. If you genuinely want the in-process trade-off, you opt into it explicitly with COGNEE_EMBEDDED=true.
3. Can I switch models without losing my memory?
Yes - that's the whole point of the plugin design. The memory layer is completely decoupled from the model. I ran the same memory on gemini-2.5-flash-lite and later on gemini-2.5-flash-lite, and it recalled facts correctly on both. Swap Gemini for Opus tomorrow and Cognee doesn't care; it sits underneath.
4. Can I run more than one external memory provider at once?
No. Hermes enforces a single external memory provider at a time and rejects a second registration with a warning. This is intentional - it stops two backends from fighting over the tool schema and corrupting each other. Pick one; switch by re-running hermes memory setup.
5. Where is my memory data actually stored?
Not in your Hermes profile, and that surprised me at first. It lives in ~/.cognee/data and ~/.cognee/system, under the dataset agent_sessions - the same roots every Cognee agent plugin pins, which is exactly what makes the shared-brain thing work across Claude Code, Codex, OpenClaw and Hermes.
Because those roots sit outside HERMES_HOME, the plugin reports them to hermes backup, so a profile backup deliberately includes the machine's shared memory store. Roots you point elsewhere with COGNEE_DATA_ROOT / COGNEE_SYSTEM_ROOT get reported the same way.
Want Hermes isolated instead? Give it its own COGNEE_PLUGIN_DATASET, or for full separation its own COGNEE_DATA_ROOT / COGNEE_SYSTEM_ROOT and COGNEE_LOCAL_PORT.
6. I'm upgrading from an older version of the plugin and my memory is gone. What happened?
It isn't gone, you're just looking in a different place. Three defaults moved in 1.0 to line up with the other Cognee plugins: the local port went from 8000 to 8011, the default dataset went from hermes to the shared agent_sessions, and local storage now defaults to ~/.cognee/{data,system}.
Point COGNEE_PLUGIN_DATASET=hermes at the old data to get it back, or migrate it across. And if an old plugin-started server is still listening on 8000, stop it - two servers sharing one data directory is precisely the single-writer contention this design exists to avoid. COGNEE_LOCAL_PORT=8000 restores the old port if you need it.
Sources & further reading
- The official plugin on PyPI: https://pypi.org/project/cognee-integration-hermes-agent/
- Cognee integrations monorepo: https://github.com/topoteretes/cognee-integrations
- Cognee (open-source AI memory): https://github.com/topoteretes/cognee
- Cognee - Cognify docs: https://docs.cognee.ai/core-concepts/main-operations/cognify
- Cognee blog: https://www.cognee.ai/blog
- My original hand-built plugin, kept for reference only - use the official package instead: https://github.com/Ayush9026/hermes-cognee-plugin














Top comments (0)