Correctly install Hermes Agent dependencies#2834
Conversation
This change introduces UV to sync the .[all] target for all python dependencies. This was introduced due to missing dependencies such as `discord.py` in the logs. Additionally runs npm install to get the JS dependencies for the TUI and web dashboards.
📝 WalkthroughWalkthroughThe Hermes Agent Docker build process transitions from a direct pip installation with pinned dependencies to a structured multi-step approach: installing the Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Review rate limit: 9/10 reviews remaining, refill in 6 minutes. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
agents/hermes/Dockerfile.base (2)
99-104: Recommend running Hermes E2E workflows for this dependency-bootstrap change.Given this modifies Hermes install/bootstrap behavior, run
hermes-e2eandrebuild-hermes-e2ebefore merge to cover onboarding, health probes, and live inference.As per coding guidelines,
agents/hermes/**recommends:hermes-e2eandrebuild-hermes-e2e.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agents/hermes/Dockerfile.base` around lines 99 - 104, This change alters Hermes bootstrap (see Dockerfile.base RUN uv venv and uv pip install -e ".[all]") so before merging run the Hermes E2E suites: execute hermes-e2e and rebuild-hermes-e2e to validate onboarding, health probes, and live inference; if failures occur, iterate on the Dockerfile.base install steps (uv venv/uv pip install) until both e2e commands pass and then re-run hermes --version verification in the image build.
99-101: Usenpm ciinstead ofnpm installfor deterministic installs.Lines 99-101 use
npm install, which can resolve different transitive versions over time. The upstream Hermes tarball containspackage-lock.jsonfiles, makingnpm cithe appropriate choice for reproducible builds.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agents/hermes/Dockerfile.base` around lines 99 - 101, Replace the failing non-deterministic install step in the Dockerfile RUN line: locate the RUN line that contains "uv venv && uv pip install --no-cache-dir -e \".[all]\" && npm install --prefer-offline --no-audit" and change the npm invocation to "npm ci" (preserving any compatible flags or removing flags that npm ci doesn't accept) so the build uses the lockfile for deterministic installs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@agents/hermes/Dockerfile.base`:
- Line 97: The Dockerfile currently downloads the Hermes tarball with
HERMES_VERSION without verifying integrity; update the RUN that creates
/opt/hermes to also fetch a checksum (or .sha256/.asc) for the same release,
verify it before extraction (e.g., curl -fL
.../hermes-agent-${HERMES_VERSION}.tar.gz -o /tmp/hermes.tar.gz and curl -fL
.../hermes-agent-${HERMES_VERSION}.tar.gz.sha256 -o /tmp/hermes.sha256 && echo
"<expected-format>" | sha256sum -c /tmp/hermes.sha256 or run sha256sum
/tmp/hermes.tar.gz && compare), fail the build on mismatch, and only then tar
-xz -C /opt/hermes --strip-components=1; reference the existing RUN that uses
HERMES_VERSION and the target directory /opt/hermes to locate where to add
checksum download and sha256 verification steps.
- Line 96: Replace the unpinned pip install of "uv" with a pinned version by
introducing an ARG named UV_VERSION (mirroring the existing HERMES_VERSION ARG
pattern) and update the RUN pip3 install invocation to install "uv" using that
UV_VERSION (i.e., pip3 install --no-cache-dir --break-system-packages
uv==${UV_VERSION}) so the base image build becomes deterministic; modify the
existing RUN pip3 install line and add the new ARG UV_VERSION above it.
---
Nitpick comments:
In `@agents/hermes/Dockerfile.base`:
- Around line 99-104: This change alters Hermes bootstrap (see Dockerfile.base
RUN uv venv and uv pip install -e ".[all]") so before merging run the Hermes E2E
suites: execute hermes-e2e and rebuild-hermes-e2e to validate onboarding, health
probes, and live inference; if failures occur, iterate on the Dockerfile.base
install steps (uv venv/uv pip install) until both e2e commands pass and then
re-run hermes --version verification in the image build.
- Around line 99-101: Replace the failing non-deterministic install step in the
Dockerfile RUN line: locate the RUN line that contains "uv venv && uv pip
install --no-cache-dir -e \".[all]\" && npm install --prefer-offline --no-audit"
and change the npm invocation to "npm ci" (preserving any compatible flags or
removing flags that npm ci doesn't accept) so the build uses the lockfile for
deterministic installs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 853200f4-7f32-4b67-b466-f66e01139a52
📒 Files selected for processing (1)
agents/hermes/Dockerfile.base
| "pyyaml==6.0.3" \ | ||
| "python-telegram-bot>=21.0" \ | ||
| && hermes --version | ||
| RUN pip3 install --no-cache-dir --break-system-packages uv |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify whether uv is pinned in this Dockerfile
rg -n 'pip3 install.*\buv\b' agents/hermes/Dockerfile.base
rg -n 'ARG UV_VERSION|uv==|uv~=' agents/hermes/Dockerfile.baseRepository: NVIDIA/NemoClaw
Length of output: 121
🏁 Script executed:
#!/bin/bash
# Check overall versioning pattern in Dockerfile.base
head -n 120 agents/hermes/Dockerfile.base | grep -E 'pip3 install|apt-get install|RUN|FROM'Repository: NVIDIA/NemoClaw
Length of output: 729
🏁 Script executed:
#!/bin/bash
# Check for ARG declarations and understand versioning strategy
head -n 30 agents/hermes/Dockerfile.base | grep -E 'ARG|FROM'
rg -n 'ARG HERMES_VERSION|ARG UV_VERSION' agents/hermes/Dockerfile.baseRepository: NVIDIA/NemoClaw
Length of output: 212
Pin uv to a fixed version to match the file's versioning strategy.
Line 96 installs uv unpinned, creating non-deterministic base-image rebuilds. The file already pins HERMES_VERSION via ARG and the base image by digest; uv should follow the same pattern.
Suggested fix:
ARG UV_VERSION=0.x.y
RUN pip3 install --no-cache-dir --break-system-packages uv==${UV_VERSION}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@agents/hermes/Dockerfile.base` at line 96, Replace the unpinned pip install
of "uv" with a pinned version by introducing an ARG named UV_VERSION (mirroring
the existing HERMES_VERSION ARG pattern) and update the RUN pip3 install
invocation to install "uv" using that UV_VERSION (i.e., pip3 install
--no-cache-dir --break-system-packages uv==${UV_VERSION}) so the base image
build becomes deterministic; modify the existing RUN pip3 install line and add
the new ARG UV_VERSION above it.
| "python-telegram-bot>=21.0" \ | ||
| && hermes --version | ||
| RUN pip3 install --no-cache-dir --break-system-packages uv | ||
| RUN mkdir /opt/hermes && curl -L https://github.com/NousResearch/hermes-agent/archive/refs/tags/${HERMES_VERSION}.tar.gz | tar -xz -C /opt/hermes --strip-components=1 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify whether checksum validation exists for Hermes tarball download
rg -n 'hermes-agent/archive/refs/tags/\$\{HERMES_VERSION\}\.tar\.gz' agents/hermes/Dockerfile.base
rg -n 'HERMES_TARBALL_SHA256|sha256sum -c|gpg' agents/hermes/Dockerfile.baseRepository: NVIDIA/NemoClaw
Length of output: 301
Add integrity verification for the downloaded Hermes tarball.
Line 97 fetches the Hermes agent source from GitHub without verifying checksums or signatures. This weakens supply-chain security guarantees for a production base image. The same Dockerfile already validates checksums for other downloads (gosu on line 51), establishing a consistent security pattern that should apply here.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@agents/hermes/Dockerfile.base` at line 97, The Dockerfile currently downloads
the Hermes tarball with HERMES_VERSION without verifying integrity; update the
RUN that creates /opt/hermes to also fetch a checksum (or .sha256/.asc) for the
same release, verify it before extraction (e.g., curl -fL
.../hermes-agent-${HERMES_VERSION}.tar.gz -o /tmp/hermes.tar.gz and curl -fL
.../hermes-agent-${HERMES_VERSION}.tar.gz.sha256 -o /tmp/hermes.sha256 && echo
"<expected-format>" | sha256sum -c /tmp/hermes.sha256 or run sha256sum
/tmp/hermes.tar.gz && compare), fail the build on mismatch, and only then tar
-xz -C /opt/hermes --strip-components=1; reference the existing RUN that uses
HERMES_VERSION and the target directory /opt/hermes to locate where to add
checksum download and sha256 verification steps.
|
✨ Thanks for submitting this PR that proposes a way to correctly install Hermes Agent dependencies by introducing UV to sync python dependencies and running npm install. |
…2846) This is a maintainer experiment that builds on Ben Barclay's PR #2834. Ben identified the right install gap: the Hermes image needs the dependencies required for supported runtime integrations, otherwise users hit missing-package failures after onboarding. This branch keeps that direction while narrowing the dependency surface for NemoClaw: - targets the selected Hermes release `v2026.4.23` / `0.11.0` - verifies the GitHub release tarball by SHA256 before extraction - installs Hermes with `uv sync --frozen --no-dev --extra messaging --extra web` by default instead of `[all]` - preserves the `/usr/local/bin/hermes` final-image contract used by policy and e2e checks - grants the Hermes gateway group write access to runtime state directories while keeping config files non-group-writable - opens `/tmp/gateway.log` from inside the `gateway` user context so capability-dropping does not block startup - updates the Hermes manifest expected version to `2026.4.23` - leaves OpenClaw dependency handling unchanged The intent is to prebake the Hermes dependencies that map to NemoClaw-supported onboarding integrations today: Telegram, Discord, Slack, and the API/health runtime. Larger or unsupported integrations should stay out of the base image and be installed by the agent workflow when enabled. Local validation completed: - `docker build --progress=plain -f agents/hermes/Dockerfile.base -t nemoclaw-hermes-base-experiment .` - `docker build --progress=plain -f agents/hermes/Dockerfile.base --build-arg HERMES_VERSION=v2026.4.13 --build-arg HERMES_TARBALL_SHA256=5e4529b8cb6e4821eb916b81517e48125109b1764d6d1e68a204a9f0ddf2d98c --build-arg HERMES_UV_EXTRAS=messaging -t nemoclaw-hermes-old-base-e2e-rebuild-test .` - `docker build --progress=plain -f agents/hermes/Dockerfile --build-arg BASE_IMAGE=nemoclaw-hermes-base-experiment -t nemoclaw-hermes-final-experiment .` - final image resolves `hermes` to `/usr/local/bin/hermes` and reports `Hermes Agent v0.11.0 (2026.4.23)` - imports present: `telegram`, `discord`, `slack_bolt`, `fastapi`, `uvicorn` - imports absent: `faster_whisper`, `mautrix`, `boto3`, `dingtalk_stream`, `lark_oapi` - entrypoint gateway health check returns `{"status":"ok","platform":"hermes-agent"}` through port `8642` - `npm test -- test/sandbox-provisioning.test.ts src/lib/agent-defs.test.ts src/lib/sandbox-version.test.ts` - `npm run validate:configs` - `npm run typecheck:cli` - `npx prek run --all-files --stage pre-push` Focused e2e passed on this branch: https://github.com/NVIDIA/NemoClaw/actions/runs/25222726016 Earlier focused e2e on this experiment found four useful issues that this branch now addresses: first the image contract expected `/usr/local/bin/hermes`, then the gateway needed writable Hermes runtime state under `/sandbox/.hermes`, then the entrypoint opened `/tmp/gateway.log` before switching to the `gateway` user. The rebuild e2e also needed its old-version fixture pinned to the matching tarball checksum and extras profile. The final OpenShell-specific blocker was that the Hermes executable is a symlink into /opt/hermes, so the Hermes policy now grants read-only access to that venv path. Related context: - Contributor PR: #2834 - Hermes version selection context: #2745 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enhanced startup logging with improved diagnostics for troubleshooting sandbox initialization issues * Added runtime diagnostics to capture system state and logs when errors occur * **Chores** * Updated Hermes agent to v2026.4.23 * Improved build pipeline with better dependency verification and deterministic installation <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ben Barclay <ben@nousresearch.com>
|
Thanks to Ben Barclay and the NousResearch team for identifying the Hermes dependency-bootstrap gap and proposing the original fix here. I opened a maintainer follow-up in #2872 that carries that work into the current NemoClaw base-image flow, with credit in the PR description and commit metadata. |
<!-- markdownlint-disable MD041 --> ## Summary Follows up on NousResearch's dependency-bootstrap proposal in #2834 and the maintainer-side #2846 by carrying the remaining root Node dependency install into the Hermes base image. The existing `uv sync` step covers the supported Python integration extras; this adds deterministic `npm ci` from the Hermes root lockfile so browser tooling such as `agent-browser` is available in the extracted Hermes tree. ## Credit Thanks to Ben Barclay and the NousResearch team for the original PR #2834. They identified the Hermes dependency-bootstrap gap and proposed the direction this follow-up carries into the current NemoClaw base-image flow. ## Related Issue Follow-up to #2834 and #2846. ## Changes - Install Hermes root Node dependencies with `npm ci --prefer-offline --no-audit --no-fund` after the existing `uv sync` step. - Remove transient `/tmp/camoufox-*` installer downloads in the same Docker layer so large temporary archives do not persist into the image. - Document why the root Node install belongs in the Hermes base image. ## Type of Change - [x] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Verification - [ ] `npx prek run --all-files` passes - [ ] `npm test` passes - [ ] Tests added or updated for new or changed behavior - [x] No secrets, API keys, or credentials committed - [ ] Docs updated for user-facing behavior changes - [ ] `make docs` builds without warnings (doc changes only) - [ ] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) Additional validation: - `git diff --check` - `docker build --progress=plain --output=type=cacheonly -f agents/hermes/Dockerfile.base .` - validated the `uv sync` step - validated the new `npm ci` step - validated `/usr/local/bin/hermes --version` reports `Hermes Agent v0.11.0 (2026.4.23)` --- Signed-off-by: Aaron Erickson <aerickson@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Optimized the container image build by removing temporary build artifacts to reduce clutter and image size. * Made tooling dependencies for browser-related features explicit so tooling is reliably present during build. * Ensured Node package installation runs deterministically during image creation to improve build stability and reproducibility. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Aaron Erickson <aerickson@nvidia.com> Co-authored-by: Ben Barclay <ben@nousresearch.com>
|
Closing as superseded by #2872. That follow-up carried the Hermes dependency-bootstrap work into the current base-image flow, credited @benbarclay and the NousResearch team for the original direction, and merged on 2026-05-04. Thanks again for identifying the dependency gap here. |
Summary
This change introduces UV to sync the .[all] target for all python dependencies. This was introduced due to missing dependencies such as
discord.pyin the logs.Additionally runs npm install to get the JS dependencies for the TUI and web dashboards.
Technically the UV part of this change is optional, though it's easier than handling the virtualenv, etc manually in the container. I can remove that part if desired.
Changes
Type of Change
Verification
npx prek run --all-filespassesnpm testpassesmake docsbuilds without warnings (doc changes only)Signed-off-by: Ben Barclay ben@nousresearch.com
Summary by CodeRabbit