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
Metadata
Release files for hermes-memra 4.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hermes_memra-4.5.0.tar.gz | 35.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hermes_memra-4.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 65.7 kB
Release files / hermes_memra-4.5.0.tar.gz
| Download URL | hermes_memra-4.5.0.tar.gz |
|---|---|
| Size | 35.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7c93bebd952379eb1114c8e7ab10a18c61d75d4b90f61ce6d1a3e1b49174f9d6
|
|
BLAKE2b-256 checksum How to use checksums |
6615a34d9758d452b55d8b1e152a137ab0e809f37d8f97b0c7f873b5f4b37585
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / hermes_memra-4.5.0-py3-none-any.whl
| Download URL | hermes_memra-4.5.0-py3-none-any.whl |
|---|---|
| Size | 29.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
92bd10cd38d9a9c5b67e030a5360d216b6d6ae9387b3ce841db942f0e94c30e3
|
|
BLAKE2b-256 checksum How to use checksums |
1b28eadc3602731fddd4d7496b503f7ff333bd9198646e2ac480353c44892f90
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|