Skip to content
Closed
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
7 changes: 5 additions & 2 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ Mechanical only; behaviour is identical.
- The setup wizard imports private helpers from `hermes_cli.memory_setup` (`_curses_select`,
`_prompt`, ...). Those are Hermes internals, not API; expect to own a copy or drop the wizard
hook if they move.
- Tests were not copied: the in-tree tests import `plugins.memory.supermemory` and depend on the
hermes-agent test harness. See `tests/plugins/memory/` in hermes-agent for the originals.
- The in-tree tests were not copied (they depend on the hermes-agent test harness; see
`tests/plugins/memory/` in hermes-agent). `tests/` here stubs the few host modules the provider
imports and runs against the real SDK over a mock HTTP transport; see README → Development.
- 2.0 moved to the v5 API (`supermemory>=5,<6`). `_SupermemoryClient` refuses other SDK majors at
construction; widen `_SDK_MAJOR` together with `pyproject.toml` and `plugin.yaml`.
- While the in-tree copy still exists, a same-named user plugin is shadowed by it
(bundled providers win on name). It takes effect the moment core drops `plugins/memory/supermemory`.

Expand Down
39 changes: 34 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Semantic long-term memory with profile recall, semantic search, explicit memory

## Requirements

- `pip install supermemory`
- `supermemory>=5,<6` (the Python SDK for the v5 API; `hermes plugins install` installs it from `pyproject.toml`)
- Hosted: API key from [console.supermemory.ai/keys](https://console.supermemory.ai/keys?create=true)
- Self-hosted: a running [Supermemory local](https://supermemory.ai/docs/self-hosting/overview) server and the API key it prints on first boot
- Self-hosted: a running [Supermemory local](https://supermemory.ai/docs/self-hosting/overview) server that serves the v5 API (`/ns/{namespace}/...`) and the API key it prints on first boot

## Setup

Expand Down Expand Up @@ -57,7 +57,7 @@ Config file: `$HERMES_HOME/supermemory.json`
| `max_recall_results` | `10` | Max recalled items to format into context |
| `profile_frequency` | `50` | Include profile facts on first turn and every N turns |
| `capture_mode` | `all` | Skip tiny or trivial turns by default |
| `search_mode` | `hybrid` | Search mode: `hybrid` (profile + memories), `memories` (memories only), `documents` (documents only) |
| `search_mode` | `hybrid` | Search mode: `hybrid` (memories + source chunks), `memories` (memories only), `chunks` (source chunks only; `documents` is accepted as the pre-v5 name) |
| `entity_context` | built-in default | Extraction guidance passed to Supermemory |
| `api_timeout` | `5.0` | Timeout for SDK requests |

Expand Down Expand Up @@ -97,12 +97,32 @@ Supermemory app, so you can filter, browse, and bulk-manage them per source agen
When enabled, Hermes can:

- prefetch relevant memory context before each turn
- write each completed user/assistant turn to **one document per session per 4-hour window** (`customId` = `<session>_<date>_b<0-5>`, so the API appends deltas), matching the capture shape of the other Supermemory agent integrations
- retry failed turn writes on the next turn, session end, `/reset`, or shutdown (at-least-once: if the API accepted a write but the response was lost, the same turn is appended again)
- write each completed user/assistant turn to **one document per session per 4-hour window** (document `id` = `<session>_<date>_b<0-5>`; a v5 `POST` with an existing `id` appends the delta rather than replacing the document), matching the capture shape of the other Supermemory agent integrations
- retry failed turn writes on the next turn, session end, `/reset`, or shutdown. Delivery is **at-least-once**, not exactly-once: SDK-level retries are disabled so one hook sends each batch once, but if the API accepted a write and the response was lost (timeout, dropped connection), the provider's retry appends the same turns again. The retry buffer is in memory only (lost when the process exits) and capped at 50 turns / 256 KiB, dropping the oldest turns first
- route every SDK and probe request through the configured hosted or self-hosted endpoint
- expose explicit tools for search, store, forget, and profile access


## Upgrading from 1.x (SDK 3)

2.0 talks to the namespace-first v5 API through `supermemory>=5,<6`. Tools, config keys and environment
variables are unchanged. What to know:

- **No data migration.** The configured container tag (after the same sanitization as before) is used as the
v5 namespace, so existing memories stay addressable.
- **Self-hosted servers** must serve the v5 API. An older local server will reject the requests; the
configured `base_url` is still used for everything, never silently replaced by the hosted API.
- **Search keeps its pre-v5 behaviour.** v5 lowered the default similarity threshold to 0.3; the provider
sends `threshold: 0.6`, `rerank: "none"` and `rewriteQuery: false` explicitly. Hybrid hits that carry
their text in `chunk` (source passages) are now rendered instead of showing up empty.
- **Profile + query.** The v5 profile endpoint has no query parameter, so a query (automatic recall or
`supermemory-profile` with `query`) fetches the profile and runs a separate search concurrently, bounded by
`api_timeout`. If one of the two fails, the other is still used and the tool reports the failure under `errors`.
- **Forget is confirmed.** Forgetting by id succeeds only when the API reports that exact id as forgotten;
forgetting by query searches memories only (chunk ids are not memory ids).
- If another component pins an older SDK into the Hermes venv, the provider stays inactive and
`hermes memory status` reports the installed version instead of failing on every request.

## Profile-Scoped Containers

Use `{identity}` in the `container_tag` to scope memories per Hermes profile:
Expand Down Expand Up @@ -134,6 +154,15 @@ When enabled:
- Automatic operations (turn capture, prefetch, memory write mirroring) always use the **primary** container only
- Custom container instructions are injected into the system prompt

## Development

The tests run the provider against the real installed SDK with an in-process mock HTTP transport
(no network, no Hermes checkout needed):

```bash
uv run --isolated --no-project --python 3.11 --with 'supermemory>=5.0.0,<6' --with pytest python -m pytest tests -q
```

## Support

- [Supermemory Discord](https://supermemory.link/discord)
Expand Down
Loading