NousResearch/hermes-agent

Supermemory self-hosted server URL configuration

Cluster 57061 · agent. Data as of

Nothing open on GitHub. Fix merged in #67907 on 20 Jul 2026. Check it covers your case.

The short answer

0open issues
0open PRs
3items grouped
Known?
Yes. 3 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #67907. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PR #67907. That is separate from the fix event.
Still open
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.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #67907 fix(supermemory): route all requests through self-hosted base URL (salvage #67614, #43388)

    merged to main

    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

    Show the diff
    • contributors/emails/[redacted:email]
      @@ -0,0 +1 @@
      +Dhravya
    • plugins/memory/supermemory/README.md
      @@ -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
       
      @@ -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 |
      @@ -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.
      @@ -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
      @@ -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)\.?$",
      @@ -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": "",
      @@ -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
      @@ -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)
      @@ -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
      @@ -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"},
      @@ -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}",
      @@ -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": "",
      @@ -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 = [
      @@ -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
      @@ -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"]
      @@ -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
      @@ -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": []}
      @@ -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 ----------------------------------------------------
       
       
      @@ -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"],
      @@ -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
      @@ -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)
       
      @@ -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 |
      @@ -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.
      @@ -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
      @@ -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 + 近期上下文)
       
      @@ -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` | 每次响应后存储清理过的用户-助手轮次 |
      @@ -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 跨命名容器读写。自动操作(同步、预取)保持在主容器上。
      @@ -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 隔离
       
      @@ -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)了解如何创建自己的提供者。

1 PR closed without merging

From the close comments: other 1

  • #57074 feat(memory/supermemory): support self-hosted server via SUPERMEMORY_BASE_URL · other → #43388
Closed issues · 1
  • Closed#57061feat(memory/supermemory): support self-hosted Supermemory via SUPERMEMORY_BASE_URL
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.67: the share of item 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.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
agent
Merged PRs
#67907
Closed issues
1
Attempts
1 PR closed without merging
Fix link checked
20 Jul 2026

For your agent

The same facts, typed.