Skip to content

Package Hermes Agent as a built-in guest#136

Merged
JAORMX merged 4 commits intomainfrom
package-hermes-agent
Apr 23, 2026
Merged

Package Hermes Agent as a built-in guest#136
JAORMX merged 4 commits intomainfrom
package-hermes-agent

Conversation

@JAORMX
Copy link
Copy Markdown
Contributor

@JAORMX JAORMX commented Apr 22, 2026

Summary

Adds Nous Research's Hermes Agent as a fourth built-in agent alongside claude-code, codex, and opencode. Hermes is a provider-agnostic Python CLI that dispatches to Anthropic/OpenAI/OpenRouter/Gemini/etc. — it ships no weights and needs no GPU, so it slots cleanly into the existing agent contract.

  • Image (images/hermes/Dockerfile) — pins HERMES_VERSION=v2026.4.16, installs the minimal [mcp,acp] extras into an isolated venv on top of the shared base image. Only extra apk dep is ffmpeg. Heavy optional extras (messaging, slack, matrix, voice, rl, bedrock, …) are intentionally deferred — they can be layered on later.
  • MCP config (pkg/domain/agent, internal/infra/vm/mcpconfig.go) — new MCPConfigFormatHermes + injectHermesMCP that writes ~/.hermes/config.yaml and deep-merges a sandbox-tools entry under mcp_servers, preserving any pre-existing YAML. A mergeYAMLMapEntries helper parallels the existing JSON/TOML helpers.
  • Registry (internal/infra/agent/registry.go) — hermes entry with locked egress for api.anthropic.com / api.openai.com / openrouter.ai / generativelanguage.googleapis.com. Env-forwards ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY, GEMINI_API_KEY, GOOGLE_API_KEY, HF_TOKEN, HERMES_*. Credentials persist via ~/.hermes/.
  • Build plumbingimage-hermes Taskfile target wired into image-all/image-push; docker-bake.hcl hermes target added to the default group so CI and release pick it up.

Explicitly out of scope (for follow-up)

  • Messaging gateway hosts (Telegram / Discord / Slack / WhatsApp / Matrix) are deliberately not in the locked-profile host list. Enabling them should be a conscious per-workspace opt-in.
  • The host ~/.hermes/config.yaml is not injected via the settings manifest — the settings injector has no YAML format yet, and that file can contain host-side MCP endpoints that must not leak into the guest. hermes setup runs inside the VM on first launch.

Test plan

  • task fmt && task lint — 0 issues
  • task test — all tests pass, including the new TestInjectHermesMCP* cases and the expanded registry tests
  • task image-base && task image-hermes — verify image builds on a Linux host
  • bbox hermes --help inside a freshly-built VM
  • End-to-end smoke: bbox hermes -q "hello" with a real provider key
  • Inspect ~/.hermes/config.yaml in the guest to confirm the sandbox-tools MCP entry is present and points at the vmcp proxy

🤖 Generated with Claude Code

JAORMX and others added 4 commits April 22, 2026 10:07
Adds Nous Research's Hermes Agent as a fourth built-in agent alongside
claude-code, codex, and opencode. Hermes is a provider-agnostic Python
CLI that dispatches to Anthropic/OpenAI/OpenRouter/Gemini/etc; it ships
no weights and needs no GPU.

Changes:
- images/hermes/Dockerfile pins HERMES_VERSION=v2026.4.16, installs the
  minimal [mcp,acp] extras into an isolated venv on top of the base
  image (ffmpeg is the only extra apk dep).
- pkg/domain/agent adds MCPConfigFormatHermes.
- internal/infra/vm/mcpconfig emits ~/.hermes/config.yaml with a
  sandbox-tools entry under mcp_servers, merging with any pre-existing
  YAML so user MCP servers survive. Introduces a mergeYAMLMapEntries
  helper parallel to the JSON/TOML ones.
- internal/infra/agent/registry registers the hermes agent with an
  anthropic/openai/openrouter/gemini locked egress profile. Messaging
  gateway hosts (Telegram / Discord / Slack / WhatsApp / Matrix) are
  deliberately excluded — enabling those extras is a future opt-in.
- Taskfile and docker-bake wire image-hermes into image-all / image-push
  and the default bake group so CI and release build it.
- Drop ffmpeg: only used by voice/TTS extras that are not installed.
  Saves ~80 MB from every VM boot for a disabled feature.
- Collapse clone + venv + install + link into one RUN, and rm the
  source tree after pip install (installed code lives in site-packages,
  the clone is dead weight). Saves ~15 MB and one layer.
- Drop pip install --upgrade pip; Wolfi's pip is recent enough.
- Drop the hermes-agent symlink so an upstream [project.scripts]
  rename can't break the build. The primary hermes CLI is sufficient;
  the direct agent loop is still reachable via venv/bin/hermes-agent.
- Add OCI image labels (source, description, license) for GHCR
  provenance.
Cross-referenced the Hermes integration against the upstream
NousResearch/hermes-agent repo and fixed four drifts:

- Locked egress now covers Nous Portal (*.nousresearch.com) and the
  HuggingFace router (HF_TOKEN was forwarded without a matching host
  allowance, so locked-profile users would silently fail).
- Settings manifest injects ~/.hermes/SOUL.md instead of AGENTS.md.
  Upstream loads AGENTS.md from the project CWD, not HERMES_HOME;
  SOUL.md is the real HERMES_HOME identity file.
- injectHermesMCP no longer writes a transport: http key. Upstream
  selects transport by presence of url vs command; the extra key is
  unread today and could collide with future upstream schema.
- Test flipped to assert transport is absent, guarding regression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Found during a sanity-check run: `bbox list` showed hermes, but the
root command's long-help "Supported agents" line was stale.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX merged commit a425a24 into main Apr 23, 2026
8 checks passed
@JAORMX JAORMX deleted the package-hermes-agent branch April 23, 2026 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant