# NousResearch/hermes-agent · Supermemory self-hosted server URL configuration

## Open now

- Nothing open on GitHub.

These items add support for configuring a custom base URL for self-hosted Supermemory instances via the SUPERMEMORY_BASE_URL environment variable, including routing all requests through that URL.

## TL;DR

- 3 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 1 PR(s) closed without merging.
- A fix was merged to main in PR #67907. Verify it addresses your case.
- **Recommended:** read PR #67907 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-67907`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.67`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #57061: feat(memory/supermemory): support self-hosted Supermemory via SUPERMEMORY_BASE_URL

## Prior & competing PRs

- **#57074: feat(memory/supermemory): support self-hosted server via SUPERMEMORY_BASE_URL**. closed without merge · fix tier `suggested`
  - maintainer direction: category `uncategorized`; implication `needs_llm`; refs `#43388`
  - _suggested-tier fix detail withheld; re-request with `?tier=all` to include it._
- **#67907: fix(supermemory): route all requests through self-hosted base URL (salvage #67614, #43388)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `contributors/emails/[redacted:email]`, `plugins/memory/supermemory/README.md`, `plugins/memory/supermemory/__init__.py`, `tests/plugins/memory/test_supermemory_provider.py`, `website/docs/user-guide/features/memory-providers.md`, `website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/memory-providers.md`
  - fix hunks:
  - `contributors/emails/[redacted:email]`

    ```diff
    @@ -0,0 +1 @@
    +Dhravya
    ```
  - `plugins/memory/supermemory/README.md`

    ```diff
    @@ -5,7 +5,8 @@ Semantic long-term memory with profile recall, semantic search, explicit memory
     ## Requirements
     
     - `pip install supermemory`
    -- Supermemory API key from [app.supermemory.ai/integrations?connect=hermes](http://app.supermemory.ai/integrations?connect=hermes)
    +- Hosted: API key from [app.supermemory.ai/integrations?connect=hermes](http://app.supermemory.ai/integrations?connect=hermes)
    +- Self-hosted: a running [Supermemory local](https://supermemory.ai/docs/self-hosting/overview) server and the API key it prints on first boot
     
     ## Setup
     
    ```

    ```diff
    @@ -20,12 +21,32 @@ hermes config set memory.provider supermemory
     echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
     ```
     
    +For a fully self-hosted setup, start Supermemory local and note the API key it
    +prints on first boot:
    +
    +```bash
    +npx supermemory local
    +```
    +
    +Before running `hermes memory setup`, add the local endpoint to
    +`$HERMES_HOME/supermemory.json`:
    +
    +```json
    +{
    +  "base_url": "http://localhost:6767"
    +}
    +```
    +
    +Then run `hermes memory setup` and enter the local server's API key. Configuring
    +the endpoint first ensures the setup connection probe also stays local.
    +
     ## Config
     
     Config file: `$HERMES_HOME/supermemory.json`
     
     | Key | Default | Description |
     |-----|---------|-------------|
    +| `base_url` | `https://api.supermemory.ai` | API endpoint for hosted or self-hosted Supermemory. Takes priority over `SUPERMEMORY_BASE_URL`. |
     | `container_tag` | `hermes` | Container tag used for search and writes. Supports `{identity}` template for profile-scoped tags (e.g. `hermes-{identity}` → `hermes-coder`). |
     | `auto_recall` | `true` | Inject relevant memory context before turns |
     | `auto_capture` | `true` | Store cleaned user-assistant turns after each response |
    ```

    ```diff
    @@ -41,8 +62,13 @@ Config file: `$HERMES_HOME/supermemory.json`
     | Variable | Description |
     |----------|-------------|
     | `SUPERMEMORY_API_KEY` | API key (required) |
    +| `SUPERMEMORY_BASE_URL` | Compatibility fallback for the API endpoint when `base_url` is not configured |
     | `SUPERMEMORY_CONTAINER_TAG` | Override container tag (takes priority over config file) |
     
    +Base URL precedence is `supermemory.json` → `SUPERMEMORY_BASE_URL` →
    +`https://api.supermemory.ai`. Hermes resolves it once and uses the same endpoint
    +for SDK operations, setup/status probes, and full-session conversation ingest.
    +
     ## Tools
     
     Kebab-case names are registered for the agent; snake_case aliases remain supported.
    ```

    ```diff
    @@ -69,6 +95,7 @@ When enabled, Hermes can:
     - prefetch relevant memory context before each turn
     - buffer the full conversation and ingest it as **one session** at session end (or on `/reset`, branch, compression, or shutdown)
     - ingest the full session to the conversations endpoint for richer profile/graph updates
    +- route every SDK, probe, and conversation-ingest request through the configured hosted or self-hosted endpoint
     - expose explicit tools for search, store, forget, and profile access
     
     The session is written once via the conversations endpoint, which drives Supermemory's entity extraction and profile building while keeping a clean, retrievable full transcript.
    ```
  - `plugins/memory/supermemory/__init__.py`

    ```diff
    @@ -31,7 +31,7 @@
     _DEFAULT_API_TIMEOUT = 5.0
     _MIN_CAPTURE_LENGTH = 10
     _MAX_ENTITY_CONTEXT_LENGTH = 1500
    -_CONVERSATIONS_URL = "https://api.supermemory.ai/v4/conversations"
    +_DEFAULT_BASE_URL = "https://api.supermemory.ai"
     _API_KEY_URL = "[redacted:secret-assignment]"
     _TRIVIAL_RE = re.compile(
         r"^(ok|okay|thanks|thank you|got it|sure|yes|no|yep|nope|k|ty|thx|np)\.?$",
    ```

    ```diff
    @@ -65,6 +65,7 @@ def _default_config() -> dict:
             "search_mode": _DEFAULT_SEARCH_MODE,
             "entity_context": _DEFAULT_ENTITY_CONTEXT,
             "api_timeout": _DEFAULT_API_TIMEOUT,
    +        "base_url": "",
             "enable_custom_container_tags": False,
             "custom_containers": [],
             "custom_container_instructions": "",
    ```

    ```diff
    @@ -77,6 +78,18 @@ def _sanitize_tag(raw: str) -> str:
         return tag.strip("_") or _DEFAULT_CONTAINER_TAG
     
     
    +def _resolve_base_url(config_value: Any = "") -> str:
    +    """Resolve the API base URL: config > SUPERMEMORY_BASE_URL env var > default.
    +
    +    Supports self-hosted Supermemory servers (e.g. http://localhost:6767).
    +    """
    +    raw = (
    +        str(config_value or "").strip()
    +        or os.environ.get("SUPERMEMORY_BASE_URL", "").strip()
    +    )
    +    return (raw or _DEFAULT_BASE_URL).rstrip("/") or _DEFAULT_BASE_URL
    +
    +
     def _clamp_entity_context(text: str) -> str:
         if not text:
             return _DEFAULT_ENTITY_CONTEXT
    ```

    ```diff
    @@ -129,6 +142,7 @@ def _load_supermemory_config(hermes_home: str) -> dict:
             config["api_timeout"] = max(0.5, min(15.0, float(config.get("api_timeout", _DEFAULT_API_TIMEOUT))))
         except Exception:
             config["api_timeout"] = _DEFAULT_API_TIMEOUT
    +    config["base_url"] = str(config.get("base_url", "") or "").strip()
     
         # Multi-container support
         config["enable_custom_container_tags"] = _as_bool(config.get("enable_custom_container_tags"), False)
    ```

    ```diff
    @@ -263,7 +277,8 @@ def _is_trivial_message(text: str) -> bool:
     
     
     class _SupermemoryClient:
    -    def __init__(self, api_key: str, timeout: float, container_tag: str, search_mode: str = "hybrid"):
    +    def __init__(self, api_key: str, timeout: float, container_tag: str,
    +                 search_mode: str = "hybrid", base_url: str = ""):
             # Lazy-install the supermemory SDK on demand. ensure() honors
             # security.allow_lazy_installs (default true) and, on a sealed Docker
             # venv, redirects the install to the durable target. On failure we
    ```

    ```diff
    @@ -276,15 +291,16 @@ def __init__(self, api_key: str, timeout: float, container_tag: str, search_mode
                 pass
             except Exception:
                 pass
    -
             from supermemory import Supermemory
     
             self._api_key = [redacted:secret-assignment]
             self._container_tag = container_tag
             self._search_mode = search_mode if search_mode in _VALID_SEARCH_MODES else _DEFAULT_SEARCH_MODE
             self._timeout = timeout
    +        self._base_url = _resolve_base_url(base_url)
             self._client = Supermemory(
                 api_key=[redacted:secret-assignment]
    +            base_url=self._base_url,
                 timeout=timeout,
                 max_retries=0,
                 default_headers={"x-sm-source": "hermes"},
    ```

    ```diff
    @@ -388,7 +404,7 @@ def ingest_conversation(self, session_id: str, messages: list[dict], metadata: d
                 payload["metadata"] = self._merge_metadata(metadata)
     
             req = urllib.request.Request(
    -            _CONVERSATIONS_URL,
    +            f"{self._base_url}/v4/conversations",
                 data=json.dumps(payload).encode("utf-8"),
                 headers={
                     "Authorization": f"Bearer {self._api_key}",
    ```

    ```diff
    @@ -410,6 +426,7 @@ def _resolve_container_tag_for_setup(hermes_home: str, *, identity: str = "defau
     
     def _probe_supermemory_connection(api_key: str, hermes_home: str, *, identity: str = "default") -> dict:
         config = _load_supermemory_config(hermes_home)
    +    base_url = _resolve_base_url(config["base_url"])
         status = {
             "ok": False,
             "error": "",
    ```

    ```diff
    @@ -432,6 +449,7 @@ def _probe_supermemory_connection(api_key: str, hermes_home: str, *, identity: s
                 timeout=config["api_timeout"],
                 container_tag=status["container_tag"],
                 search_mode=config["search_mode"],
    +            base_url=base_url,
             )
             profile = client.get_profile()
             facts = [
    ```

    ```diff
    @@ -531,6 +549,7 @@ def __init__(self):
             self._search_mode = _DEFAULT_SEARCH_MODE
             self._entity_context = _DEFAULT_ENTITY_CONTEXT
             self._api_timeout = _DEFAULT_API_TIMEOUT
    +        self._base_url = _DEFAULT_BASE_URL
             self._hermes_home = ""
             self._write_enabled = True
             self._active = False
    ```

    ```diff
    @@ -645,6 +664,9 @@ def initialize(self, session_id: str, **kwargs) -> None:
             self._search_mode = self._config["search_mode"]
             self._entity_context = self._config["entity_context"]
             self._api_timeout = self._config["api_timeout"]
    +        # Base URL: config > SUPERMEMORY_BASE_URL env var > api.supermemory.ai.
    +        # Supports self-hosted Supermemory servers.
    +        self._base_url = _resolve_base_url(self._config["base_url"])
             self._enable_custom_containers = self._config["enable_custom_container_tags"]
             self._custom_containers = self._config["custom_containers"]
             self._custom_container_instructions = self._config["custom_container_instructions"]
    ```

    ```diff
    @@ -663,6 +685,7 @@ def initialize(self, session_id: str, **kwargs) -> None:
                         timeout=self._api_timeout,
                         container_tag=self._container_tag,
                         search_mode=self._search_mode,
    +                    base_url=self._base_url,
                     )
                 except Exception:
                     logger.warning("Supermemory initialization failed", exc_info=True)
    ```
  - `tests/plugins/memory/test_supermemory_provider.py`

    ```diff
    @@ -17,11 +17,13 @@
     
     
     class FakeClient:
    -    def __init__(self, api_key: str, timeout: float, container_tag: str, search_mode: str = "hybrid"):
    +    def __init__(self, api_key: str, timeout: float, container_tag: str, search_mode: str = "hybrid",
    +                 base_url: str = ""):
             self.api_key = [redacted:secret-assignment]
             self.timeout = timeout
             self.container_tag = container_tag
             self.search_mode = search_mode
    +        self.base_url = base_url
             self.add_calls = []
             self.search_results = []
             self.profile_response = {"static": [], "dynamic": [], "search_results": []}
    ```

    ```diff
    @@ -373,6 +375,107 @@ def test_invalid_search_mode_falls_back_to_default(monkeypatch, tmp_path):
         assert p._search_mode == "hybrid"
     
     
    +# -- Base URL tests -------------------------------------------------------------
    +
    +
    +def test_base_url_defaults_to_cloud(monkeypatch, tmp_path):
    +    """Without config or env override, the client targets api.supermemory.ai."""
    +    monkeypatch.setenv("SUPERMEMORY_API_KEY", "test-key")
    +    monkeypatch.delenv("SUPERMEMORY_BASE_URL", raising=False)
    +    monkeypatch.setattr("plugins.memory.supermemory._SupermemoryClient", FakeClient)
    +    p = SupermemoryMemoryProvider()
    +    p.initialize("s1", hermes_home=str(tmp_path), platform="cli")
    +    assert p._base_url == "https://api.supermemory.ai"
    +    assert p._client.base_url == "https://api.supermemory.ai"
    +
    +
    +def test_base_url_env_var_override(monkeypatch, tmp_path):
    +    """SUPERMEMORY_BASE_URL points the provider at a self-hosted server (trailing slash stripped)."""
    +    monkeypatch.setenv("SUPERMEMORY_API_KEY", "test-key")
    +    monkeypatch.setenv("SUPERMEMORY_BASE_URL", "http://localhost:6767/")
    +    monkeypatch.setattr("plugins.memory.supermemory._SupermemoryClient", FakeClient)
    +    p = SupermemoryMemoryProvider()
    +    p.initialize("s1", hermes_home=str(tmp_path), platform="cli")
    +    assert p._base_url == "http://localhost:6767"
    +    assert p._client.base_url == "http://localhost:6767"
    +
    +
    +def test_base_url_config_overrides_env(monkeypatch, tmp_path):
    +    """base_url in supermemory.json takes precedence over the env var."""
    +    monkeypatch.setenv("SUPERMEMORY_API_KEY", "test-key")
    +    monkeypatch.setenv("SUPERMEMORY_BASE_URL", "http://env-host:6767")
    +    monkeypatch.setattr("plugins.memory.supermemory._SupermemoryClient", FakeClient)
    +    _save_supermemory_config({"base_url": "http://config-host:6767/"}, str(tmp_path))
    +    p = SupermemoryMemoryProvider()
    +    p.initialize("s1", hermes_home=str(tmp_path), platform="cli")
    +    assert p._base_url == "http://config-host:6767"
    +    assert p._client.base_url == "http://config-host:6767"
    +
    +
    +def test_client_passes_custom_base_url_to_sdk(monkeypatch):
    +    """SDK operations and raw conversation ingest share one normalized base URL."""
    +    import sys
    +    import types
    +
    +    from plugins.memory.supermemory import _SupermemoryClient
    +
    +    captured = {}
    +
    +    class StubSupermemory:
    +        def __init__(self, **kwargs):
    +            captured.update(kwargs)
    +
    +    module = types.ModuleType("supermemory")
    +    module.Supermemory = StubSupermemory
    +    monkeypatch.setitem(sys.modules, "supermemory", module)
    +    monkeypatch.setattr("tools.lazy_deps.ensure", lambda *args, **kwargs: None)
    +
    +    client = _SupermemoryClient(
    +        api_key="[redacted:secret-assignment]",
    +        timeout=1.0,
    +        container_tag="hermes",
    +        base_url="http://localhost:6767/",
    +    )
    +
    +    assert client._base_url == "http://localhost:6767"
    +    assert captured["base_url"] == "http://localhost:6767"
    +
    +
    [redacted:email](
    +    ("base_url", "expected_url"),
    +    [
    +        ("https://api.supermemory.ai", "https://api.supermemory.ai/v4/conversations"),
    +        ("http://localhost:6767", "http://localhost:6767/v4/conversations"),
    +    ],
    +)
    +def test_ingest_conversation_uses_client_base_url(monkeypatch, base_url, expected_url):
    +    """Raw conversation ingest follows the same endpoint as SDK operations."""
    +    from plugins.memory.supermemory import _SupermemoryClient
    +
    +    client = _SupermemoryClient.__new__(_SupermemoryClient)
    +    client._api_key = "[redacted:secret-assignment]"
    +    client._container_tag = "hermes"
    +    client._timeout = 1.0
    +    client._base_url = base_url
    +
    +    captured = {}
    +
    +    class _FakeResponse:
    +        def __enter__(self):
    +            return self
    +
    +        def __exit__(self, *args):
    +            return False
    +
    +    def fake_urlopen(req, timeout=None):
    +        captured["url"] = req.full_url
    +        return _FakeResponse()
    +
    +    monkeypatch.setattr("urllib.request.urlopen", fake_urlopen)
    +    client.ingest_conversation("s1", [{"role": "user", "content": "hello there"}])
    +    assert captured["url"] == expected_url
    +
    +
     # -- Multi-container tests ----------------------------------------------------
     
     
    ```

    ```diff
    @@ -533,9 +636,13 @@ def fake_import(name, *args, **kwargs):
     
     def test_probe_supermemory_connection_success(monkeypatch, tmp_path):
         _stub_supermemory_importable(monkeypatch)
    -    monkeypatch.setattr("plugins.memory.supermemory._SupermemoryClient", FakeClient)
    +    seen_base_urls = []
     
         class CountingClient(FakeClient):
    +        def __init__(self, *args, **kwargs):
    +            super().__init__(*args, **kwargs)
    +            seen_base_urls.append(self.base_url)
    +
             def get_profile(self, query=None, *, container_tag=None):
                 return {
                     "static": ["Prefers TypeScript"],
    ```

    ```diff
    @@ -544,10 +651,13 @@ def get_profile(self, query=None, *, container_tag=None):
                 }
     
         monkeypatch.setattr("plugins.memory.supermemory._SupermemoryClient", CountingClient)
    +    monkeypatch.setenv("SUPERMEMORY_BASE_URL", "http://env-host:6767")
    +    _save_supermemory_config({"base_url": "http://localhost:6767/"}, str(tmp_path))
         status = _probe_supermemory_connection("test-key", str(tmp_path))
         assert status["ok"] is True
         assert status["profile_facts"] == 2
         assert status["auto_recall"] is True
    +    assert seen_base_urls == ["http://localhost:6767"]
     
     
     def test_probe_supermemory_connection_client_error(monkeypatch, tmp_path):
    ```
  - `website/docs/user-guide/features/memory-providers.md`

    ```diff
    @@ -537,9 +537,9 @@ Semantic long-term memory with profile recall, semantic search, explicit memory
     | | |
     |---|---|
     | **Best for** | Semantic recall with user profiling and session-level graph building |
    -| **Requires** | `pip install supermemory` + [API key](http://app.supermemory.ai/integrations?connect=hermes) |
    -| **Data storage** | Supermemory Cloud |
    -| **Cost** | Supermemory pricing |
    +| **Requires** | `pip install supermemory` + [cloud API key](http://app.supermemory.ai/integrations?connect=hermes), or a [self-hosted server](https://supermemory.ai/docs/self-hosting/overview) |
    +| **Data storage** | Supermemory Cloud or self-hosted |
    +| **Cost** | Supermemory pricing (cloud) / free (self-hosted) |
     
     **Tools:** `supermemory_store` (save explicit memories), `supermemory_search` (semantic similarity search), `supermemory_forget` (forget by ID or best-match query), `supermemory_profile` (persistent profile + recent context)
     
    ```

    ```diff
    @@ -551,10 +551,30 @@ hermes config set memory.provider supermemory
     echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
     ```
     
    +Self-hosted setup:
    +
    +```bash
    +npx supermemory local
    +```
    +
    +Before running `hermes memory setup`, set `base_url` in
    +`$HERMES_HOME/supermemory.json`:
    +
    +```json
    +{
    +  "base_url": "http://localhost:6767"
    +}
    +```
    +
    +Then run `hermes memory setup` and enter the API key printed by the local
    +server. Configuring the endpoint first ensures the setup connection probe also
    +stays local.
    +
     **Config:** `$HERMES_HOME/supermemory.json`
     
     | Key | Default | Description |
     |-----|---------|-------------|
    +| `base_url` | `https://api.supermemory.ai` | API endpoint for hosted or self-hosted Supermemory. Takes priority over `SUPERMEMORY_BASE_URL`. |
     | `container_tag` | `hermes` | Container tag used for search and writes. Supports `{identity}` template for profile-scoped tags. |
     | `auto_recall` | `true` | Inject relevant memory context before turns |
     | `auto_capture` | `true` | Store cleaned user-assistant turns after each response |
    ```

    ```diff
    @@ -564,12 +584,15 @@ echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
     | `search_mode` | `hybrid` | Search mode: `hybrid`, `memories`, or `documents` |
     | `api_timeout` | `5.0` | Timeout for SDK and ingest requests |
     
    -**Environment variables:** `SUPERMEMORY_API_KEY` (required), `SUPERMEMORY_CONTAINER_TAG` (overrides config).
    +**Environment variables:** `SUPERMEMORY_API_KEY` (required), `SUPERMEMORY_BASE_URL` (compatibility fallback when `base_url` is not configured), `SUPERMEMORY_CONTAINER_TAG` (overrides config).
    +
    +Base URL precedence is `supermemory.json` → `SUPERMEMORY_BASE_URL` → `https://api.supermemory.ai`. SDK operations, setup/status probes, and conversation ingest all use the resolved endpoint.
     
     **Key features:**
     - Automatic context fencing — strips recalled memories from captured turns to prevent recursive memory pollution
     - Full-session ingest — the entire conversation is sent once at session boundaries
     - Session-end conversation ingest (to `/v4/conversations`) for richer profile + graph building in Supermemory
    +- End-to-end self-hosted routing — SDK, probe, and conversation-ingest requests use the same configured endpoint
     - Profile facts injected on first turn and at configurable intervals
     - **Profile-scoped containers** — use `{identity}` in `container_tag` (e.g. `hermes-{identity}` → `hermes-coder`) to isolate memories per Hermes profile
     - **Multi-container mode** — enable `enable_custom_container_tags` with a `custom_containers` list to let the agent read/write across named containers. Automatic operations stay on the primary container.
    ```

    ```diff
    @@ -624,7 +647,7 @@ hermes memory setup
     | **Holographic** | Local | Free | 2 | None | HRR algebra + trust scoring |
     | **RetainDB** | Cloud | $20/mo | 5 | `requests` | Delta compression |
     | **ByteRover** | Local/Cloud | Free/Paid | 3 | `brv` CLI | Pre-compression extraction |
    -| **Supermemory** | Cloud | Paid | 4 | `supermemory` | Context fencing + session graph ingest + multi-container |
    +| **Supermemory** | Cloud/Self-hosted | Free/Paid | 4 | `supermemory` | Context fencing + session graph ingest + multi-container |
     | **Memori** | Cloud | Free/Paid | 5 | `hermes-memori` | Tool-aware memory + structured recall |
     
     ## Profile Isolation
    ```
  - `website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/memory-providers.md`

    ```diff
    @@ -467,9 +467,9 @@ hermes config set memory.provider byterover
     | | |
     |---|---|
     | **适合场景** | 带用户 profile 和会话级图谱构建的语义召回 |
    -| **依赖** | `pip install supermemory` + [API key](http://app.supermemory.ai/integrations?connect=hermes) |
    -| **数据存储** | Supermemory Cloud |
    -| **费用** | Supermemory 定价 |
    +| **依赖** | `pip install supermemory` + [云端 API key](http://app.supermemory.ai/integrations?connect=hermes)，或[自托管服务器](https://supermemory.ai/docs/self-hosting/overview) |
    +| **数据存储** | Supermemory 云端或自托管 |
    +| **费用** | 云端按 Supermemory 定价 / 自托管免费 |
     
     **工具：** `supermemory_store`（保存显式记忆）、`supermemory_search`（语义相似度搜索）、`supermemory_forget`（按 ID 或最佳匹配查询遗忘）、`supermemory_profile`（持久化 profile + 近期上下文）
     
    ```

    ```diff
    @@ -481,10 +481,28 @@ hermes config set memory.provider supermemory
     echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
     ```
     
    +自托管安装：
    +
    +```bash
    +npx supermemory local
    +```
    +
    +在运行 `hermes memory setup` **之前**，先在
    +`$HERMES_HOME/supermemory.json` 中设置 `base_url`：
    +
    +```json
    +{
    +  "base_url": "http://localhost:6767"
    +}
    +```
    +
    +然后运行 `hermes memory setup` 并输入本地服务器打印的 API key。先配置端点可确保安装连接探测也只访问本地服务器。
    +
     **配置：** `$HERMES_HOME/supermemory.json`
     
     | 键 | 默认值 | 描述 |
     |-----|---------|-------------|
    +| `base_url` | `https://api.supermemory.ai` | 托管或自托管 Supermemory 的 API 端点。优先级高于 `SUPERMEMORY_BASE_URL`。 |
     | `container_tag` | `hermes` | 用于搜索和写入的容器标签。支持 `{identity}` 模板用于 profile 范围隔离。 |
     | `auto_recall` | `true` | 在每轮对话前注入相关记忆上下文 |
     | `auto_capture` | `true` | 每次响应后存储清理过的用户-助手轮次 |
    ```

    ```diff
    @@ -494,12 +512,15 @@ echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
     | `search_mode` | `hybrid` | 搜索模式：`hybrid`、`memories` 或 `documents` |
     | `api_timeout` | `5.0` | SDK 和导入请求的超时时间 |
     
    -**环境变量：** `SUPERMEMORY_API_KEY`（必填）、`SUPERMEMORY_CONTAINER_TAG`（覆盖配置）。
    +**环境变量：** `SUPERMEMORY_API_KEY`（必填）、`SUPERMEMORY_BASE_URL`（未配置 `base_url` 时的兼容回退）、`SUPERMEMORY_CONTAINER_TAG`（覆盖配置）。
    +
    +Base URL 优先级为 `supermemory.json` → `SUPERMEMORY_BASE_URL` → `https://api.supermemory.ai`。SDK 操作、安装/状态探测和会话导入都会使用解析后的同一端点。
     
     **主要特性：**
     - 自动上下文隔离——从捕获的轮次中剥离已召回的记忆，防止递归记忆污染
     - 在会话边界时将整个会话**一次性导入**
     - 会话结束时同时导入到对话端点（`/v4/conversations`），用于 Supermemory 的 profile 和图谱构建
    +- 端到端自托管路由——SDK、探测和会话导入请求使用同一配置端点
     - 在第一轮及可配置间隔注入 profile 事实
     - **Profile 范围容器**——在 `container_tag` 中使用 `{identity}`（例如 `hermes-{identity}` → `hermes-coder`），按 Hermes profile 隔离记忆
     - **多容器模式**——启用 `enable_custom_container_tags` 并配置 `custom_containers` 列表，让 Agent 跨命名容器读写。自动操作（同步、预取）保持在主容器上。
    ```

    ```diff
    @@ -533,7 +554,7 @@ echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
     | **Holographic** | 本地 | 免费 | 2 | 无 | HRR 代数 + 信任评分 |
     | **RetainDB** | 云端 | $20/月 | 5 | `requests` | 增量压缩 |
     | **ByteRover** | 本地/云端 | 免费/付费 | 3 | `brv` CLI | 预压缩提取 |
    -| **Supermemory** | 云端 | 付费 | 4 | `supermemory` | 上下文隔离 + 会话图谱导入 + 多容器 |
    +| **Supermemory** | 云端/自托管 | 免费/付费 | 4 | `supermemory` | 上下文隔离 + 会话图谱导入 + 多容器 |
     
     ## Profile 隔离
     
    ```

    ```diff
    @@ -546,4 +567,4 @@ echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
     
     ## 构建记忆提供者
     
    -参见[开发者指南：Memory Provider 插件](/developer-guide/memory-provider-plugin)了解如何创建自己的提供者。
    \ No newline at end of file
    +参见[开发者指南：Memory Provider 插件](/developer-guide/memory-provider-plugin)了解如何创建自己的提供者。
    ```

## Fix status

- Merged to main in PR #67907 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-07-20`.
- Subsystem: `agent`
