Memra memory provider for Hermes Agent — EU-native, privacy-first persistent memory with hybrid recall, supersede chains, and staleness signals. Cloud or fully-local.
Project description
Memra ↔ Hermes Agent
A Memra memory-provider plugin for Hermes Agent (Nous Research).
Hermes Agent supports pluggable, single-select external memory providers (Honcho, Mem0, Hindsight, OpenViking, Holographic, RetainDB, ByteRover, Supermemory). This makes Memra an option alongside them: hybrid semantic + structured recall, typed memories, importance ranking, EU-native self-hosting, and server-side compression of long-lived memories.
memra/ is the drop-in plugin directory. In the Hermes source tree it
lives at plugins/memory/memra/ (the bundled-provider layout, imported as the
package plugins.memory.memra). A user install instead goes one level deep
at $HERMES_HOME/plugins/memra/ — see below.
Install (pip — recommended)
pip install hermes-memra
Hermes Agent discovers the provider automatically via the hermes_agent.plugins
entry point — no files to copy. Then set your key and select the provider:
export MEMRA_API_KEY=memra_live_... # free key at https://usememra.com
hermes memory provider memra
Fully-local mode (no cloud): pip install memra-local, run memra serve, and
set mode: local in the plugin config — same tools, zero external calls.
The install.sh script remains for source-tree / $HERMES_HOME drop-in installs.
What it does
| Hermes lifecycle | Memra behavior |
|---|---|
prefetch / queue_prefetch |
Background hybrid recall before each turn |
sync_turn |
Persists each turn as an event memory |
on_pre_compress |
Ships about-to-be-discarded context to Memra so it survives window compression (Memra then compresses it server-side) |
on_memory_write |
Mirrors Hermes MEMORY.md / USER.md writes into Memra |
| Tools | memra_search, memra_remember (store or supersede a fact), memra_profile |
All network calls are wrapped in a circuit breaker so a Memra outage never
blocks the agent loop. The plugin is self-contained (only httpx) — it calls
the Memra REST API directly, no Memra client package required.
Install today (Hermes ≥ 0.11)
Hermes discovers user-installed providers one level deep under
$HERMES_HOME/plugins/<name>/. The easiest path is the installer:
curl -fsSL https://raw.githubusercontent.com/usememra/hermes-memra/main/install.sh | bash
hermes memory setup # select "memra", paste API key + project id
Or do it by hand — note the destination is plugins/memra/, not
plugins/memory/memra/ (that's the in-tree bundled path):
cp -r memra ~/.hermes/plugins/memra
hermes memory setup # select "memra", paste API key + project id
Or wire it manually:
hermes config set memory.provider memra
echo "MEMRA_API_KEY=memra_live_xxx" >> ~/.hermes/.env
echo '{"project_id": "proj_xxx"}' > ~/.hermes/memra.json
Get an API key and project id at usememra.com, or point
base_url at your own self-hosted Memra to keep all data on your infra.
Want zero cloud? Skip the account entirely and run fully on-device — see Run fully local below. It's a single
"mode": "local"switch.
Run fully local (memra-local)
Run everything on your own machine — no account, no API key, no network. The
plugin points at memra-local, a
single-process on-device memory server (SQLite + on-device embeddings). This is
distinct from self-hosting the cloud API above: memra-local runs entirely
locally.
Cloud vs local is one switch. The plugin has a mode setting:
mode |
Backend | Needs an API key / account? |
|---|---|---|
cloud (default) |
Hosted / self-hosted Memra API | Yes |
local |
memra-local on this machine | No |
Set mode to local and the plugin auto-fills the local URL
(http://127.0.0.1:8765/v1), a throwaway API key, and a default namespace —
nothing else to configure.
What you'll need
- Python 3.11+ with
pip(to install and run memra-local). - Hermes Agent ≥ 0.11 (this plugin).
- ~300 MB disk for memra-local (no PyTorch — it uses an ONNX runtime ~55 MB plus a one-time ~90 MB model download). Your memories live in a local SQLite file.
- A terminal you can leave open (or a background process) for the server — it must be running whenever you use Hermes.
Quick start
Option A — one command (installs the server, configures the plugin, starts it):
curl -fsSL https://raw.githubusercontent.com/usememra/hermes-memra/main/install-local.sh | bash
hermes config set memory.provider memra
That installs memra-local, writes ~/.hermes/memra.json with "mode": "local",
and starts the server on port 8765 in the background.
Option B — step by step (you stay in control of each piece):
# 1. Install the on-device server
pip install memra-local
# 2. Start it — LEAVE THIS RUNNING (its own terminal/tab). Port 8765.
memra serve --port 8765
# 3. Install the plugin in local mode (in a second terminal)
MEMRA_MODE=local \
curl -fsSL https://raw.githubusercontent.com/usememra/hermes-memra/main/install.sh | bash
# 4. Select Memra as the provider
hermes config set memory.provider memra
Either way you end up with a one-line ~/.hermes/memra.json:
{ "mode": "local", "project_id": "hermes", "tenant_id": "hermes-user" }
To switch an existing cloud install to local, just add "mode": "local" to that
file (and start the server). To go back, set it to "cloud".
⚠️ The server must be running
This is the one thing that trips people up: memra-local is a separate process
that has to be up (listening on http://127.0.0.1:8765). If it isn't, every
memory call fails and the plugin's circuit breaker quietly pauses retries for a
couple of minutes — looking like "memory just doesn't work."
- Check it's up:
curl http://127.0.0.1:8765/health→{"status":"healthy",...} - It does not auto-start on reboot. After a reboot, run
memra serveagain. - Background it:
nohup memra serve --port 8765 >~/.memra-local.log 2>&1 & - Always-on: run
memra serveas asystemd --userservice.
Good to know
/v1, not/api/v1— memra-local mounts the API at/v1.mode: localhandles this for you; only matters if you setbase_urlby hand.- The API key is ignored — memra-local doesn't authenticate. The plugin
still needs some non-empty key, so
mode: localsets a placeholder. Don't paste a realmemra_live_…key into a local config. project_id/tenant_idare local namespaces — any names you like; they scope memories within the on-device store.- Stale env wins: a
MEMRA_BASE_URL/MEMRA_API_KEYleft in~/.hermes/.envoverridesmode: local. If local mode seems to hit the cloud, clear those. The init line in~/.hermes/logs/agent.logprints the resolvedmode=andbase_url=so you can confirm.
What runs local: the plugin's full REST contract — memra_remember (add and
supersede), memra_search, memra_profile, plus the supersession audit chain —
is verified end-to-end against memra-local. Recall is semantic (on-device
all-MiniLM-L6-v2 embeddings via ONNX, with FTS5 keyword as fallback), so
"recall by meaning" works fully offline — no OpenAI key and no PyTorch.
Ship to all Hermes users (PR)
To appear in Hermes's official provider list, the memra/ directory is
submitted to NousResearch/hermes-agent under plugins/memory/memra/:
- Fork
NousResearch/hermes-agent. - Copy
memra/→plugins/memory/memra/. - Add an entry to
website/docs/user-guide/features/memory-providers.md. - Open a PR. (See
docs/developer-guide/memory-provider-plugin.mdfor their contribution requirements — this plugin already follows that contract.)
PR note for maintainers: unlike the other providers this one ships
self-contained (httpx only) rather than depending on a memra-sdk PyPI package,
because the import name collides with an unrelated existing memra package.
Happy to switch to the SDK once it's published under a non-colliding name.
Test
The unit tests stub out the host imports, so they run standalone — no Hermes checkout and no live Memra account required:
pip install pytest
pytest tests/
They cover tenant-id resolution, the memra_remember supersede paths, and the
migrate_tenant cascade handling.
Troubleshooting
Local mode: memory does nothing / every call fails. The memra-local server
isn't running. It's a separate process — start it with memra serve --port 8765
and confirm curl http://127.0.0.1:8765/health returns healthy. After a
reboot you must start it again. See Run fully local.
Local mode seems to hit the cloud anyway. A leftover MEMRA_BASE_URL or
MEMRA_API_KEY in ~/.hermes/.env overrides mode: local. Clear them. The init
line in ~/.hermes/logs/agent.log shows the resolved mode= and base_url=.
Very long memories occasionally fail to store with some local models. This is a host-side (Hermes) limitation, not a Memra one. Some local models (e.g. certain OpenRouter local models) emit slightly-malformed JSON when a tool call carries a large argument; Hermes' tool-call sanitizer may drop the argument before it reaches Memra. Memra itself accepts content up to 10,000 characters of any shape. Workarounds: use a well-behaved model (Claude, GPT, most hosted models), or split very large memories into smaller writes. Tracked in #4.
License
MIT © Ali Vonsensey
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hermes_memra-4.5.0.tar.gz.
File metadata
- Download URL: hermes_memra-4.5.0.tar.gz
- Upload date:
- Size: 35.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c93bebd952379eb1114c8e7ab10a18c61d75d4b90f61ce6d1a3e1b49174f9d6
|
|
| MD5 |
cf08101ee533484dcaeeb0a4c34a3b36
|
|
| BLAKE2b-256 |
6615a34d9758d452b55d8b1e152a137ab0e809f37d8f97b0c7f873b5f4b37585
|
File details
Details for the file hermes_memra-4.5.0-py3-none-any.whl.
File metadata
- Download URL: hermes_memra-4.5.0-py3-none-any.whl
- Upload date:
- Size: 29.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92bd10cd38d9a9c5b67e030a5360d216b6d6ae9387b3ce841db942f0e94c30e3
|
|
| MD5 |
cf7b7db9e06d05492ac4e28c00d6dfa8
|
|
| BLAKE2b-256 |
1b28eadc3602731fddd4d7496b503f7ff333bd9198646e2ac480353c44892f90
|