Hindsight memory provider missing-dependency handling

NousResearch/hermes-agent · cluster 8873 · agent

Data as of

Nothing open on GitHub. Fix merged in #21818. Check it covers your case.

The short answer

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

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.

  • #21818 feat(deps): add hindsight-client as optional dependency

    merged to main

    files: pyproject.toml

    Show the diff
    • pyproject.toml
      @@ -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
      @@ -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"
      @@ -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"
      @@ -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'" },
      @@ -2026,6 +2032,7 @@ all = [
           { name = "ty" },
           { name = "uvicorn", extra = ["standard"] },
           { name = "vercel" },
      +    { name = "youtube-transcript-api" },
       ]
       bedrock = [
           { name = "boto3" },
      @@ -2044,6 +2051,7 @@ dev = [
           { name = "mcp" },
           { name = "pytest" },
           { name = "pytest-asyncio" },
      +    { name = "pytest-split" },
           { name = "pytest-xdist" },
           { name = "ruff" },
           { name = "ty" },
      @@ -2062,6 +2070,9 @@ google = [
           { name = "google-auth-httplib2" },
           { name = "google-auth-oauthlib" },
       ]
      +hindsight = [
      +    { name = "hindsight-client" },
      +]
       homeassistant = [
           { name = "aiohttp" },
       ]
      @@ -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 = [
      @@ -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" },
      @@ -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" },
      @@ -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"
      @@ -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"
      @@ -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"
      @@ -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

    files: Dockerfile, tests/tools/test_dockerfile_pid1_reaping.py

    Show the diff
    • Dockerfile
      @@ -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
      @@ -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

4 PRs closed without merging

From the close comments: done elsewhere 2 · duplicate 1 · superseded by another PR 1

  • #18882 fix(hindsight): guard against missing hindsight-client in cloud/external modes · done elsewhere → 6c44471
  • #18924 fix(memory): guard hindsight_client import to prevent gateway crash when package missing · superseded by another PR → 55ac056, #18876
  • #22586 fix(memory): probe hindsight_client import in is_available (#18875) · duplicate → #18882, #18924, #18875
  • #32976 fix(hindsight): guard missing cloud client dependency · done elsewhere → 6c44471
Closed issues · 4
  • Closed#8873[Setup]: Hindsight-client required to use hindsight as memory provider, but can't be installed with non-container nixos config
  • Closed#18875Hindsight memory provider crashes gateway with no error when hindsight-client not installed
  • Closed#18876Hindsight memory provider crashes gateway when hindsight-client not installed
  • Closed#38128[Bug]: Docker Hindsight memory provider loses hindsight-client after container recreate/update
How this cluster was grouped
  • Link evidence (partly structural links): 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 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
#21818, #38530
Closed issues
4
Attempts
4 PRs closed without merging
Fix link checked
3 Jun 2026

For your agent

The same facts, typed.