Skip to content

Add Hermes as a third agent with a permission-free gateway setup#69

Open
robobryce wants to merge 3 commits into
brycelelbach:mainfrom
robobryce:add/hermes-agent
Open

Add Hermes as a third agent with a permission-free gateway setup#69
robobryce wants to merge 3 commits into
brycelelbach:mainfrom
robobryce:add/hermes-agent

Conversation

@robobryce

@robobryce robobryce commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Hermes (NousResearch) as a third agent alongside Claude Code and Codex, configured for unattended use in a safe sandbox with the same philosophy as the existing agents.

  • One arbitrary OpenAI-compatible gateway. Hermes has no first-party/third-party split here — it points at a single configurable gateway via AAB_HERMES_BASE_URL / AAB_HERMES_API_KEY / AAB_HERMES_MODEL. There is no built-in default gateway or model (exposing an internal endpoint in a public repo would be wrong): both are unset by default, write_hermes_config warns (does not fail) when either is missing, and the base URL is normalized to end in /v1 (trailing slash trimmed, /v1 appended only when absent). The gateway is declared as a custom_providers entry whose key_env references AAB_HERMES_API_KEY, so no secret is written into the world-readable ~/.hermes/config.yaml.
  • Permission-free. approvals.mode: off, cron_mode: approve, destructive_slash_confirm: false, hooks_auto_accept: true, delegation.subagent_auto_approve: true. The launcher also exports HERMES_YOLO_MODE=1 + HERMES_ACCEPT_HOOKS=1. (Hermes has no --dangerously-skip-permissions; its --yolo is chat-scoped and would break config/doctor, so the bypass lives in env vars + persisted config, not an injected flag. Hermes keeps an unconditional catastrophic-command floor in code that no config can disable.)
  • Built to run for days unattended. Turn/iteration budgets (agent.max_turns, goals.max_turns, delegation.max_iterations) set to 999999 — Hermes uses a used >= max check, so 0 would stop instantly and a large number is the correct "unlimited". Inactivity gateway timeouts set to 0 (Hermes treats 0 as unlimited), the auto-continue freshness gate disabled, and tool_loop_guardrails turned off. Per-operation timeouts are raised, not removed: shell-command timeout 10 min, subagent stuck-detector 24 h.
  • xhigh effort, reasoning always shown (agent.reasoning_effort: xhigh, display.show_reasoning: true).
  • Concurrency matches Codex. delegation.max_concurrent_children defaults to AAB_CODEX_AGENT_MAX_THREADS (16).
  • Plugins installed into Hermes too. AAB's repos are Claude/Codex marketplaces (.claude-plugin/marketplace.json + nested plugins/<name>/), not Hermes-native single-plugin repos. install_hermes_plugins bridges the formats: clone each marketplace once, materialize each plugin's subtree into ~/.hermes/plugins/<name>/, synthesize the plugin.yaml Hermes requires from the plugin's plugin.json, and enable it.
  • Self-improvement disabled. Hermes's background curator (the skill review/prune/consolidate loop — NousResearch's "the agent that grows with you") is set to curator.enabled: false; AAB_HERMES_CURATOR=true re-enables it.
  • xz-utils added to install_base_deps — the Hermes installer unpacks a bundled Node runtime .tar.xz, and bare ubuntu:22.04 ships without xz.

New env vars (all in ~/.aab/.env, documented in the README): AAB_HERMES_BASE_URL, AAB_HERMES_API_KEY, AAB_HERMES_MODEL, AAB_HERMES_API_MODE, AAB_HERMES_EFFORT, AAB_HERMES_SHELL_TIMEOUT, AAB_HERMES_CHILD_TIMEOUT, AAB_HERMES_MAX_CONCURRENCY, AAB_HERMES_CURATOR.

Rebased onto upstream/main, which had rearchitected the Claude launcher (native binary stays at ~/.local/bin/claude, AAB entrypoint moved to ~/.local/aab-bin) and added a third-party-nemotron Claude provider. The Hermes launcher follows the unchanged codex symlink pattern (~/.local/bin/hermes -> hermes-gateway, with hermes-aab-real tracking the installed binary), and the _is_aab_launcher_symlink_target allowlist now carries both claude-third-party-nemotron and hermes-gateway.

Test plan

  • ./test.bash (lint + unit) — shellcheck clean; bats 1..123, all ok, 0 failures (incl. the new Hermes cases):

    ok 15 write_aab_env_file writes Hermes gateway config and defaults
    ok 16 write_hermes_config writes a permission-free gateway config by default
    ok 17 write_hermes_config can re-enable the curator via AAB_HERMES_CURATOR
    ok 18 write_hermes_config defaults an invalid curator toggle back to false
    ok 19 write_hermes_config honors concurrency and timeout overrides
    ok 20 write_hermes_config defaults Hermes concurrency to the Codex thread cap
    ok 21 write_hermes_config honors base URL, model, api-mode, and effort overrides
    ok 22 write_hermes_config appends /v1 to a base URL that lacks it
    ok 23 write_hermes_config does not double /v1 (trailing slash tolerated)
    ok 24 write_hermes_config warns when base URL and model are unset (no built-in default)
    ok 25 write_hermes_config defaults an invalid api mode back to chat_completions
    ok 26 write_hermes_config defaults an invalid effort back to xhigh
    ok 27 write_hermes_config backs up pre-existing config.yaml
    ok 28 install_hermes_launcher wraps hermes with permission-free env and no injected flag
    ok 69 install_base_deps installs xz-utils when xz is missing (Hermes Node runtime)
    
  • ./test.bash --docker — full bootstrap on a fresh ubuntu:22.04, both idempotency passes green (All e2e assertions passed. ×2, === docker e2e passed ===), including the new Hermes config/wrapper/plugin assertions alongside the rebased Claude launcher assertions:

    PASS: claude wrapper family installed and selected (launcher dir wins on PATH).
    PASS: Hermes config.yaml written with gateway routing + permission-free, no-limit defaults.
    PASS: hermes wrapper installed and selected.
    PASS: Hermes agent plugins installed.
    
  • ./test.bash --secrets (gitleaks v8.18.4)no leaks found.

  • git diff --check upstream/main..HEAD — no whitespace/conflict errors; branch is 3 commits ahead, 0 behind upstream/main.

  • ./test.bash --e2e — covered by --docker (same code path on a clean image); not re-run destructively on the host.

🤖 Generated with Claude Code

brycelelbach and others added 3 commits June 9, 2026 02:33
Install NousResearch's Hermes alongside Claude Code and Codex and wire it
up with the same unattended philosophy: a single arbitrary OpenAI-compatible
inference gateway, approvals off, hooks auto-accepted, subagents
auto-approved, xhigh effort with reasoning always shown, and the
run-duration limits removed so it can run unattended for days.

- install_hermes runs NousResearch's installer; install_base_deps gains
  xz-utils, which the installer needs to unpack its bundled Node runtime on
  bare images.
- write_hermes_config emits ~/.hermes/config.yaml: the gateway as a
  custom_providers entry whose key_env points at AAB_HERMES_API_KEY (no
  secret in the world-readable file), the permission-free block, and
  no-limit settings (turn/iteration budgets at 999999 since 0 stops
  instantly, inactivity gateway timeouts at 0 = unlimited, auto-continue
  freshness disabled, tool-loop guardrails off). Per-operation timeouts are
  raised, not removed (shell 10 min, subagent stuck-detector 24 h), and
  delegated concurrency tracks AAB_CODEX_AGENT_MAX_THREADS.
- _write_hermes_launcher / install_hermes_launcher add the hermes-gateway
  wrapper and hermes -> hermes-gateway symlink, handling both the ~/.local
  and the root FHS install layouts. The wrapper sets HERMES_YOLO_MODE and
  HERMES_ACCEPT_HOOKS rather than injecting a flag (Hermes has no
  --dangerously-skip-permissions, and its --yolo is chat-scoped).
- install_hermes_plugins materializes AAB's marketplace plugins into
  ~/.hermes/plugins/<name>/ (synthesizing the plugin.yaml Hermes expects
  from each plugin's plugin.json) and enables them.
- AAB_HERMES_* env vars are written to ~/.aab/.env; README and the unit /
  e2e / smoke suites cover the new agent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The curator is Hermes's "self-improvement" feature — a background
auxiliary-model task that periodically reviews, prunes, and consolidates
agent-created skills (curator.enabled, default true in Hermes). For
predictable unattended runs, write_hermes_config now sets
`curator.enabled: false`. Add AAB_HERMES_CURATOR (default false) to override.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The gateway base URL and model no longer default to an internal NVIDIA
endpoint / model — exposing those in a public repo was wrong. Both are now
unset by default: write_hermes_config warns (doesn't fail) when either is
missing, leaving Hermes unconfigured until the operator fills them into
~/.aab/.env, exactly like the API key.

As a convenience matching the documented gateway convention, the base URL is
normalized to end in /v1: a trailing slash is trimmed and /v1 is appended
only when absent, so both "https://host" and "https://host/v1" work.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants