# NousResearch/hermes-agent · Hindsight memory provider missing-dependency handling

## Open now

- Nothing open on GitHub.

These issues and fixes center on the hindsight-client package being absent, optional, or lost, causing gateway crashes or silent failures. Work covers import guards, early failure, optional dependency declarations, and baking the client into Docker images.

## TL;DR

- 10 member(s): 0 open issue(s), 4 closed issue(s), 0 open PR(s), 2 merged PR(s), 4 PR(s) closed without merging.
- A fix was merged to main in PR #21818. Verify it addresses your case.
- **Recommended:** read PR #21818 (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: `partially_resolved` · deciding PR(s): `pr-21818,pr-38530`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
- Members outside that structural core may belong to a different underlying problem.
- Pairwise link density `0.19`: 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

- #8873: \[Setup\]: Hindsight-client required to use hindsight as memory provider, but can't be installed with non-container nixos config
- #18875: Hindsight memory provider crashes gateway with no error when hindsight-client not installed
- #18876: Hindsight memory provider crashes gateway when hindsight-client not installed
- #38128: \[Bug\]: Docker Hindsight memory provider loses hindsight-client after container recreate/update

## Prior & competing PRs

- **#21818: feat(deps): add hindsight-client as optional dependency**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `pyproject.toml`
  - fix hunks:
  - `pyproject.toml`

    ```diff
    @@ -55,6 +55,7 @@ dependencies = [
     modal = ["modal>=1.0.0,<2"]
     daytona = ["daytona>=0.148.0,<1"]
     vercel = ["vercel>=0.5.7,<0.6.0"]
    +hindsight = ["hindsight-client>=0.4.22"]
     dev = ["debugpy>=1.8.0,<2", "pytest>=9.0.2,<10", "pytest-asyncio>=1.3.0,<2", "pytest-xdist>=3.0,<4", "pytest-split>=0.9,<1", "mcp>=1.2.0,<2", "ty>=0.0.1a29,<0.0.22", "ruff"]
     messaging = ["python-telegram-bot[webhooks]>=22.6,<23", "discord.py[voice]>=2.7.1,<3", "aiohttp>=3.13.3,<4", "slack-bolt>=1.18.0,<2", "slack-sdk>=3.27.0,<4", "qrcode>=7.0,<8"]
     cron = []  # croniter is now a core dependency; this extra kept for back-compat
    ```
  - `uv.lock`

    ```diff
    @@ -8,10 +8,6 @@ resolution-markers = [
         "python_full_version < '3.12'",
     ]
     
    -[options]
    -exclude-newer = "2026-05-01T22:46:56.926194148Z"
    -exclude-newer-span = "P7D"
    -
     [[package]]
     name = "agent-client-protocol"
     version = "0.9.0"
    ```

    ```diff
    @@ -1273,6 +1269,15 @@ wheels = [
         { url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7", size = 5337658, upload-time = "2026-01-29T23:04:17.404Z" },
     ]
     
    +[[package]]
    +name = "defusedxml"
    +version = "0.7.1"
    +source = { registry = "https://pypi.org/simple" }
    +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" }
    +wheels = [
    +    { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" },
    +]
    +
     [[package]]
     name = "deprecated"
     version = "1.3.1"
    ```

    ```diff
    @@ -2014,6 +2019,7 @@ all = [
         { name = "ptyprocess", marker = "sys_platform != 'win32'" },
         { name = "pytest" },
         { name = "pytest-asyncio" },
    +    { name = "pytest-split" },
         { name = "pytest-xdist" },
         { name = "python-telegram-bot", extra = ["webhooks"] },
         { name = "pywinpty", marker = "sys_platform == 'win32'" },
    ```

    ```diff
    @@ -2026,6 +2032,7 @@ all = [
         { name = "ty" },
         { name = "uvicorn", extra = ["standard"] },
         { name = "vercel" },
    +    { name = "youtube-transcript-api" },
     ]
     bedrock = [
         { name = "boto3" },
    ```

    ```diff
    @@ -2044,6 +2051,7 @@ dev = [
         { name = "mcp" },
         { name = "pytest" },
         { name = "pytest-asyncio" },
    +    { name = "pytest-split" },
         { name = "pytest-xdist" },
         { name = "ruff" },
         { name = "ty" },
    ```

    ```diff
    @@ -2062,6 +2070,9 @@ google = [
         { name = "google-auth-httplib2" },
         { name = "google-auth-oauthlib" },
     ]
    +hindsight = [
    +    { name = "hindsight-client" },
    +]
     homeassistant = [
         { name = "aiohttp" },
     ]
    ```

    ```diff
    @@ -2162,6 +2173,9 @@ web = [
     yc-bench = [
         { name = "yc-bench", marker = "python_full_version >= '3.12'" },
     ]
    +youtube = [
    +    { name = "youtube-transcript-api" },
    +]
     
     [package.metadata]
     requires-dist = [
    ```

    ```diff
    @@ -2234,6 +2248,8 @@ requires-dist = [
         { name = "hermes-agent", extras = ["voice"], marker = "extra == 'all'" },
         { name = "hermes-agent", extras = ["web"], marker = "extra == 'all'" },
         { name = "hermes-agent", extras = ["web"], marker = "extra == 'termux-all'" },
    +    { name = "hermes-agent", extras = ["youtube"], marker = "extra == 'all'" },
    +    { name = "hindsight-client", marker = "extra == 'hindsight'", specifier = ">=0.4.22" },
         { name = "honcho-ai", marker = "extra == 'honcho'", specifier = ">=2.0.1,<3" },
         { name = "httpx", extras = ["socks"], specifier = ">=0.28.1,<1" },
         { name = "jinja2", specifier = ">=3.1.5,<4" },
    ```

    ```diff
    @@ -2255,6 +2271,7 @@ requires-dist = [
         { name = "pyjwt", extras = ["crypto"], specifier = ">=2.12.0,<3" },
         { name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.2,<10" },
         { name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=1.3.0,<2" },
    +    { name = "pytest-split", marker = "extra == 'dev'", specifier = ">=0.9,<1" },
         { name = "pytest-xdist", marker = "extra == 'dev'", specifier = ">=3.0,<4" },
         { name = "python-dotenv", specifier = ">=1.2.1,<2" },
         { name = "python-telegram-bot", extras = ["webhooks"], marker = "extra == 'messaging'", specifier = ">=22.6,<23" },
    ```

    ```diff
    @@ -2283,8 +2300,9 @@ requires-dist = [
         { name = "vercel", marker = "extra == 'vercel'", specifier = ">=0.5.7,<0.6.0" },
         { name = "wandb", marker = "extra == 'rl'", specifier = ">=0.15.0,<1" },
         { name = "yc-bench", marker = "python_full_version >= '3.12' and extra == 'yc-bench'", git = "https://github.com/collinear-ai/yc-bench.git?rev=bfb0c88062450f46341bd9a5298903fc2e952a5c" },
    +    { name = "youtube-transcript-api", marker = "extra == 'youtube'", specifier = ">=1.2.0" },
     ]
    -provides-extras = ["modal", "daytona", "vercel", "dev", "messaging", "cron", "slack", "matrix", "cli", "tts-premium", "voice", "pty", "honcho", "mcp", "homeassistant", "sms", "computer-use", "acp", "mistral", "bedrock", "termux", "termux-all", "dingtalk", "feishu", "google", "web", "rl", "yc-bench", "all"]
    +provides-extras = ["modal", "daytona", "vercel", "hindsight", "dev", "messaging", "cron", "slack", "matrix", "cli", "tts-premium", "voice", "pty", "honcho", "mcp", "homeassistant", "sms", "computer-use", "acp", "mistral", "bedrock", "termux", "termux-all", "dingtalk", "feishu", "google", "youtube", "web", "rl", "yc-bench", "all"]
     
     [[package]]
     name = "hf-transfer"
    ```

    ```diff
    @@ -2350,6 +2368,23 @@ wheels = [
         { url = "https://files.pythonhosted.org/packages/4e/46/1ba8d36f8290a4b98f78898bdce2b0e8fe6d9a59df34a1399eb61a8d877f/hf_xet-1.3.1-cp37-abi3-win_arm64.whl", hash = "sha256:851b1be6597a87036fe7258ce7578d5df3c08176283b989c3b165f94125c5097", size = 3500490, upload-time = "2026-02-25T00:58:00.667Z" },
     ]
     
    +[[package]]
    +name = "hindsight-client"
    +version = "0.6.1"
    +source = { registry = "https://pypi.org/simple" }
    +dependencies = [
    +    { name = "aiohttp" },
    +    { name = "aiohttp-retry" },
    +    { name = "pydantic" },
    +    { name = "python-dateutil" },
    +    { name = "typing-extensions" },
    +    { name = "urllib3" },
    +]
    +sdist = { url = "https://files.pythonhosted.org/packages/33/26/8b8efa4be21fc3ba12ade3b1353d87f9837ec0d3ec2607e8adbf85bc9c63/hindsight_client-0.6.1.tar.gz", hash = "sha256:314d0bb9e13622e15586ba1586a799726d405b27bc20d78872474b5d6d96cd51", size = 99833, upload-time = "2026-05-08T13:01:23.537Z" }
    +wheels = [
    +    { url = "https://files.pythonhosted.org/packages/24/4f/a1d0bc33ef933ecc52e76dc1514163594d25836a5d303c256a61bb61445d/hindsight_client-0.6.1-py3-none-any.whl", hash = "sha256:9fdda176ab50f7cec8d7339c6608c148f0cd9ad7e65d9d76192f2db730bc330a", size = 249379, upload-time = "2026-05-08T13:01:22.035Z" },
    +]
    +
     [[package]]
     name = "honcho-ai"
     version = "2.0.1"
    ```

    ```diff
    @@ -4439,6 +4474,18 @@ wheels = [
         { url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" },
     ]
     
    +[[package]]
    +name = "pytest-split"
    +version = "0.11.0"
    +source = { registry = "https://pypi.org/simple" }
    +dependencies = [
    +    { name = "pytest" },
    +]
    +sdist = { url = "https://files.pythonhosted.org/packages/2f/16/8af4c5f2ceb3640bb1f78dfdf5c184556b10dfe9369feaaad7ff1c13f329/pytest_split-0.11.0.tar.gz", hash = "sha256:8ebdb29cc72cc962e8eb1ec07db1eeb98ab25e215ed8e3216f6b9fc7ce0ec2b5", size = 13421, upload-time = "2026-02-03T09:14:31.469Z" }
    +wheels = [
    +    { url = "https://files.pythonhosted.org/packages/ae/a1/d4423657caaa8be9b31e491592b49cebdcfd434d3e74512ce71f6ec39905/pytest_split-0.11.0-py3-none-any.whl", hash = "sha256:899d7c0f5730da91e2daf283860eb73b503259cb416851a65599368849c7f382", size = 11911, upload-time = "2026-02-03T09:14:33.708Z" },
    +]
    +
     [[package]]
     name = "pytest-xdist"
     version = "3.8.0"
    ```

    ```diff
    @@ -6165,6 +6212,19 @@ dependencies = [
         { name = "typer", marker = "python_full_version >= '3.12'" },
     ]
     
    +[[package]]
    +name = "youtube-transcript-api"
    +version = "1.2.4"
    +source = { registry = "https://pypi.org/simple" }
    +dependencies = [
    +    { name = "defusedxml" },
    +    { name = "requests" },
    +]
    +sdist = { url = "https://files.pythonhosted.org/packages/60/43/4104185a2eaa839daa693b30e15c37e7e58795e8e09ec414f22b3db54bec/youtube_transcript_api-1.2.4.tar.gz", hash = "sha256:b72d0e96a335df599d67cee51d49e143cff4f45b84bcafc202ff51291603ddcd", size = 469839, upload-time = "2026-01-29T09:09:17.088Z" }
    +wheels = [
    +    { url = "https://files.pythonhosted.org/packages/be/95/129ea37efd6cd6ed00f62baae6543345c677810b8a3bf0026756e1d3cf3c/youtube_transcript_api-1.2.4-py3-none-any.whl", hash = "sha256:03878759356da5caf5edac77431780b91448fb3d8c21d4496015bdc8a7bc43ff", size = 485227, upload-time = "2026-01-29T09:09:15.427Z" },
    +]
    +
     [[package]]
     name = "zipp"
     version = "3.23.0"
    ```
- **#38530: fix(docker): bake hindsight-client into the image (#38128)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `Dockerfile`, `tests/tools/test_dockerfile_pid1_reaping.py`
  - fix hunks:
  - `Dockerfile`

    ```diff
    @@ -157,10 +157,17 @@ RUN npm install --prefer-offline --no-audit && \
     # so Docker users can use these providers without requiring runtime
     # lazy-install access to PyPI (often blocked in containerized envs).
     #
    +# The hindsight memory provider's client (hindsight-client) is baked in
    +# for the same reason: it lazy-installs into /opt/hermes/.venv at first
    +# use, which lives inside the (immutable) image layer rather than the
    +# mounted /opt/data volume, so it is lost on every container recreate /
    +# image update and recall/retain then fails with
    +# `ModuleNotFoundError: No module named 'hindsight_client'` (#38128).
    +#
     # The editable link is created after the source copy below.
     COPY pyproject.toml uv.lock ./
     RUN touch ./README.md
    -RUN uv sync --frozen --no-install-project --extra all --extra messaging --extra anthropic --extra bedrock --extra azure-identity
    +RUN uv sync --frozen --no-install-project --extra all --extra messaging --extra anthropic --extra bedrock --extra azure-identity --extra hindsight
     
     # ---------- Source code ----------
     # .dockerignore excludes node_modules, so the installs above survive.
    ```
  - `tests/tools/test_dockerfile_pid1_reaping.py`

    ```diff
    @@ -172,6 +172,23 @@ def test_dockerfile_preinstalls_gateway_messaging_dependencies(dockerfile_text):
         )
     
     
    +def test_dockerfile_preinstalls_hindsight_memory_dependency(dockerfile_text):
    +    sync_steps = [
    +        step for step in _run_steps(dockerfile_text)
    +        if "uv sync" in step and "--no-install-project" in step
    +    ]
    +
    +    assert sync_steps, "Dockerfile must install Python dependencies with uv sync"
    +    assert any("--extra hindsight" in step for step in sync_steps), (
    +        "Published Docker images must preload the [hindsight] extra so the "
    +        "native Hindsight memory provider's client (hindsight-client) is baked "
    +        "into /opt/hermes/.venv. It lazy-installs into the image layer (not the "
    +        "mounted /opt/data volume), so without baking it in recall/retain fails "
    +        "with `ModuleNotFoundError: No module named 'hindsight_client'` after "
    +        "every container recreate / image update (#38128)."
    +    )
    +
    +
     def test_dockerfile_builds_tui_assets(dockerfile_text):
         assert any(
             "ui-tui" in step and "npm" in step and "run build" in step
    ```
- **#18882: fix(hindsight): guard against missing hindsight-client in cloud/external modes**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `6c44471bfdb8a243200abe7aac44371727fda5ca`
- **#18924: fix(memory): guard hindsight_client import to prevent gateway crash when package missing**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `55ac05692`, `#18876`
- **#22586: fix(memory): probe hindsight_client import in is_available (#18875)**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#18882`, `#18924`, `#18875`
- **#32976: fix(hindsight): guard missing cloud client dependency**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `6c44471bfdb8a243200abe7aac44371727fda5ca`

## Fix status

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