Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: test

on:
push:
branches: [main]
pull_request:

jobs:
hermes-provider:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Syntax checks
run: |
bash -n hermes/install.sh
bash -n plugin/hooks/with-venv.sh
python -m compileall -q hermes/engram plugin/core

- name: Install pytest
run: pip install pytest

- name: Run Hermes provider tests
run: python -m pytest hermes/tests -v
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# Weaviate Engram Integrations

Persistent, cross-session memory for **Claude Code**, backed by
[Weaviate Engram](https://docs.weaviate.io/engram). Claude remembers your preferences,
Persistent, cross-session memory for AI assistants, backed by
[Weaviate Engram](https://docs.weaviate.io/engram). Your assistant remembers your preferences,
decisions, and project context across sessions — and recalls what's relevant before it answers.

## Integrations

- **Claude Code** — the `engram` plugin in [`plugin/`](plugin) (install below).
- **Hermes Agent** — the memory provider in [`hermes/`](hermes); see [`hermes/README.md`](hermes/README.md).

## Claude Code

- **Recall** — before each answer, relevant memories are fetched and added to the conversation.
- **Store** — after each turn, the exchange is saved so it can be recalled later.

Expand Down
57 changes: 57 additions & 0 deletions hermes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Engram × Hermes Agent

A [Hermes Agent](https://hermes-agent.nousresearch.com) memory provider backed by
[Weaviate Engram](https://docs.weaviate.io/engram) — persistent, cross-session memory with
server-side extraction and scoped recall.

## Install

```bash
bash hermes/install.sh
```

The installer auto-detects where your Hermes looks for providers:

- **`$HERMES_HOME/plugins/engram/`** (user-installed providers, survives `hermes update`) —
preferred when supported;
- **`<hermes checkout>/plugins/memory/engram/`** (bundled) — fallback for older versions,
or forced with `--bundled`.

Flags: `--link` symlinks instead of copying (development — edits here go live);
pass a checkout path or set `HERMES_REPO` if auto-detection fails.

Then configure:

```bash
hermes memory setup # choose "engram", paste your API key
```

Get a key at https://console.weaviate.cloud/engram. Memory works from the first turn.

**Config reference, identity rules, tools, privacy:** see [`engram/README.md`](engram/README.md).

## Layout

```
hermes/
├── install.sh # installer (copy/symlink into the right plugin location)
├── engram/ # the provider package — self-contained, upstream-PR-ready
│ ├── __init__.py # EngramMemoryProvider + register()
│ ├── plugin.yaml # metadata + pip_dependencies (weaviate-engram)
│ └── README.md # setup + config reference
└── tests/ # pytest suite — no network, no real SDK (stubbed)
```

The provider package is deliberately self-contained (no imports from this repo) so it can be
dropped into a `NousResearch/hermes-agent` PR at `plugins/memory/engram/` unchanged.

## Development

```bash
bash hermes/install.sh --link # live-edit against your Hermes install
python3 -m venv .venv && .venv/bin/pip install pytest
.venv/bin/python -m pytest hermes/tests -v
```

The tests stub the Hermes ABC, `hermes_constants`, and the Engram SDK, and load the provider by
file path — mirroring Hermes' own discovery, so they double as a drop-in compatibility check.
79 changes: 79 additions & 0 deletions hermes/engram/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Engram Memory Provider for Hermes Agent

Persistent, cross-session memory backed by [Weaviate Engram](https://docs.weaviate.io/engram).
Conversation turns are sent to Engram for server-side extraction; relevant memories are recalled
before each turn and searchable on demand.

| | |
| --- | --- |
| **Best for** | Hands-off memory — Engram handles extraction and organization automatically |
| **Requires** | `pip install weaviate-engram` (auto-installed) + API key |
| **Data storage** | Engram Cloud |
| **Cost** | Engram pricing (cloud) |

## Setup

Get an API key at https://console.weaviate.cloud/engram, then:

```bash
hermes memory setup # select "engram", paste the key
```

Or manually:

```bash
hermes config set memory.provider engram
echo "ENGRAM_API_KEY=your-key" >> ~/.hermes/.env
```

**Tools (2):** `engram_search` (semantic search over the user's memories),
`engram_add` (store a durable fact the moment the user states one).

## How it works

- **Recall** — before each turn, a background `memories.search` runs against the current prompt;
results are injected as context. The agent can also search on demand with `engram_search`.
- **Store** — after each turn, the exchange is sent to `memories.add` in a daemon thread (never
blocks a response), tagged with `session_id` as the scope property.
- **Mirroring** — writes to Hermes' built-in `MEMORY.md` / `USER.md` are mirrored to Engram
(`add` and `replace` actions). `remove` is **not** propagated — Engram is append-only from this
provider's side, so a built-in deletion can't be undone remotely.
- **Fail-open** — a missing key, missing identity, or a down API disables memory for the session;
it never breaks a conversation. After 5 consecutive API failures, calls pause for 120s
(circuit breaker).

## Identity

Memories are isolated per `user_id`, resolved in this order:

1. `user_id` in `$HERMES_HOME/engram.json` (or `ENGRAM_USER_ID` env) — operator-configured,
applies uniformly across every gateway (CLI, Telegram, Discord, …).
2. The gateway-native user id (Telegram numeric id, Discord snowflake, …).
3. `git config user.email`.

There is deliberately **no shared default**: a non-unique id would commingle different people's
memories with no way to un-mix them later. If no identity resolves, the provider stays disabled
and logs why.

## Config

Secret — in `$HERMES_HOME/.env` or the environment:

| Variable | Purpose |
| --- | --- |
| `ENGRAM_API_KEY` | Your Engram API key (required). |

Non-secret — `$HERMES_HOME/engram.json` (written by `hermes memory setup`; env vars read as
fallback):

| Key | Env var | Default | Description |
| --- | --- | --- | --- |
| `user_id` | `ENGRAM_USER_ID` | — | Canonical user identifier (see Identity above). |
| `base_url` | `ENGRAM_BASE_URL` | `https://api.engram.weaviate.io` | Endpoint override (dev/self-hosted). |

## Privacy

Off-device data: conversation turns (user + assistant text), facts stored via `engram_add`, and
mirrored built-in memory writes are sent to Engram Cloud for extraction and storage. Tool calls
and tool results are **not** forwarded. Recall queries (the user's current prompt) are sent on
search.
Loading
Loading