Skip to content

[WIP] Add integration and support for Hermes agent - #530

Merged
Nicola Franco (franconicola) merged 2 commits into
mainfrom
claude/add-hermes-agent-support
Jul 26, 2026
Merged

[WIP] Add integration and support for Hermes agent#530
Nicola Franco (franconicola) merged 2 commits into
mainfrom
claude/add-hermes-agent-support

Conversation

@Claude

@Claude Claude AI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.


This section details on the original issue you should resolve

<issue_title>Integration and support for Hermes agent</issue_title>
<issue_description>## What is Hermes Agent

Hermes Agent is Nous Research's open-source, self-hosted, self-improving agent (curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash, global hermes command). Unlike a plain chat model, it runs persistent sessions with long-term memory (~/.hermes/MEMORY.md), a skill curator that writes and reuses its own skills, tool/code execution, browser automation, MCP servers, and delivery through 16+ messaging platforms. That autonomy and persistence is exactly why it's worth having as a first-class red-team target.

Proposed approach: CLI-driven provider, same shape as Claude Code

Hermes has no OpenAI-compatible HTTP endpoint, but it does have a documented one-shot headless mode:

hermes -z "prompt"        # final response only, no decorations — ideal for automation
hermes chat -q "prompt"   # one-shot, includes tool-call transcript

This is the same shape as claude -p in router/providers/claude.py, so the integration should follow that provider almost line for line rather than invent a new pattern:

  • Add HERMES = "HERMES" to AgentTypeEnum in router/types.py, plus common aliases ("HERMES_AGENT", "HERMES_CLI") in its _missing_ alias table.
  • New router/providers/hermes.py:
    • A per-instance litellm.CustomLLM (_HermesCustomLLM) registered under hackagent_hermes_<id>, exactly like _ClaudeCodeCustomLLMcompletion() shells out to hermes -z, feeds the prompt via stdin (never argv, so adversarial payloads starting with - aren't parsed as flags), and maps stdout/exit code onto ModelResponse.
    • HermesAgent(Agent) with ADAPTER_TYPE = "HermesAgent", constructed like ClaudeCodeAgent: validates the hermes binary is on PATH (shutil.which) at construction time, builds the argv, registers the custom provider, exposes litellm_model = f"{provider_name}/{model}".
  • Wire it into AGENT_TYPE_TO_ADAPTER_MAP in router/router.py (AgentTypeEnum.HERMES: HermesAgent), next to CLAUDE_CODE and CODEX.

Config surface (HermesAgent.__init__)

key maps to notes
name (required) -m <model> overrides the configured default model for this run only
binary (default hermes) argv[0] checked with shutil.which at construction
timeout (default e.g. 300s) subprocess.run(..., timeout=) Hermes can trigger tool/browser use, so this likely needs a higher default than Claude Code's
provider --provider <provider> optional per-run provider override
cwd subprocess.run(..., cwd=) working dir Hermes operates in (skills, worktrees, file tools)
extra_args appended raw flags escape hatch, same as Claude Code

Reproducibility and isolation — the part that's different from Claude Code

Claude Code is stateless per invocation; Hermes is explicitly not — it has persistent memory, a background skill curator, and session continuation. Left on defaults, red-teaming a real Hermes install would (a) let it "learn" from being probed, biasing later attack turns, and (b) pollute the user's actual ~/.hermes state. The provider should default to flags that neutralize this rather than leave it to the caller to discover:

  • Always pass --ignore-user-config (defaults + .env credentials only, skip ~/.hermes/config.yaml) and never pass -r/--resume/-c/--continue, so every attack turn is a fresh, isolated session by default.
  • Consider --safe-mode (disables all customizations) as an opt-in for maximum isolation, and/or driving attacks through hermes profile so the target under test never touches the operator's real profile/memory/skills.
  • --pass-session-id / --source hackagent are worth passing so Hermes-side logs are attributable to hackagent runs during debugging.

Output parsing

hermes -z gives bare text on stdout with no structured metadata (no session id, cost, exit reason) — simpler than Claude Code's --output-format json, but it means the adapter can't currently distinguish "the agent declined" from "the agent errored" the way _extract_result_text does for Claude Code. Needs investigation before implementation: does any one-shot mode support a --json-style result envelope, or does the provider need to rely on exit codes only (0 success, 1 delivery/backend failure, 2 usage error per the CLI reference)? If not, non-zero exit + non-empty stdout should still be captured as a content-level response (mirroring the Claude Code refusal-capture logic), not treated as a hard failure.

Out of scope for the first pass

hermes serve exposes a headless backend over JSON-RPC/WebSocket (rather than plain HTTP), which would let hackagent target a remotely deployed Hermes instance the way ADKAgent does over HTTP. That's a reasonable phase 2 once the local CLI-driven path is proven, but is a different transport (needs a WS/JSON-RPC client, not just subprocess) and shouldn't block this issue.

Acceptance criteria

  • AgentTypeEnum.HERMES + aliases added
  • router/providers/hermes.py with HermesAgent + _HermesCustomLLM, isolation flags on by default
  • Wired into AGENT_TYPE_TO_ADAPTER_MAP
  • Missing-binary and timeout paths raise the same AdapterConfigurationError/AdapterInteractionError shape as the other CLI providers
  • Test coverage mirroring tests/unit/router/test_claude_agent.py (mock subprocess.run, assert argv construction and isolation flags, assert refusal/error handling)
  • Example under hackagent/examples/ showing a Hermes target
    </issue_description>
  • Closes Integration and support for Hermes agent #428

Comments on the Issue (you are @claude[agent] in this section)

try:
import litellm

_litellm_module = litellm
None, lambda: self.completion(*args, **kwargs)
)

_HERMES_CUSTOM_LLM_CLASS = _HermesCustomLLM
@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.25843% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
hackagent/router/providers/hermes.py 93.18% 12 Missing ⚠️

📢 Thoughts on this report? Let us know!

Claude AI and others added 2 commits July 26, 2026 22:09
Agent-Logs-Url: https://github.com/AISecurityLab/hackagent/sessions/ab8dee77-7964-41f6-a9cb-4dc474b0d3d0

Co-authored-by: franconicola <51865029+franconicola@users.noreply.github.com>
Add the hermes.mdx integration guide and its index.mdx tab, wire the
generated hackagent.router.providers.hermes / hack_hermes API reference
pages into sidebars.ts, and mention HERMES alongside the other CLI-driven
adapters in the architecture overview.
@franconicola
Nicola Franco (franconicola) force-pushed the claude/add-hermes-agent-support branch from 9b2b04a to ab964bf Compare July 26, 2026 20:10
@franconicola
Nicola Franco (franconicola) temporarily deployed to claude/add-hermes-agent-support - Docs PR #530 July 26, 2026 20:10 — with Render Destroyed
@franconicola
Nicola Franco (franconicola) marked this pull request as ready for review July 26, 2026 20:23
Copilot AI review requested due to automatic review settings July 26, 2026 20:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a first-class Hermes Agent target to HackAgent’s router by introducing a new CLI-driven provider (patterned after the existing Claude Code adapter), plus unit tests, examples, and documentation updates to expose and explain the new agent type.

Changes:

  • Introduce AgentTypeEnum.HERMES (with aliases) and route it via AGENT_TYPE_TO_ADAPTER_MAP.
  • Add hackagent.router.providers.hermes implementing a per-instance LiteLLM CustomLLM that shells out to hermes -z with isolation defaults.
  • Add unit tests and end-user docs/examples for configuring and running Hermes as a local target.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/unit/router/test_hermes_agent.py Adds unit tests for Hermes provider argv construction, stdin prompting, error handling, and router integration.
hackagent/router/types.py Introduces HERMES agent type and adds shorthand aliases.
hackagent/router/router.py Registers HermesAgent in AGENT_TYPE_TO_ADAPTER_MAP.
hackagent/router/providers/hermes.py Implements Hermes CLI-backed provider and adapter via LiteLLM CustomLLM.
hackagent/examples/hermes/README.md Adds a runnable example README and explains isolation defaults and config mapping.
hackagent/examples/hermes/hack_hermes.py Adds an example script demonstrating FlipAttack against local Hermes.
hackagent/cli/utils.py Adds Hermes mappings in CLI agent-type normalization helper.
docs/sidebars.ts Adds Hermes pages to the Docusaurus sidebar and API reference listing.
docs/docs/hackagent/router/types.md Updates router types documentation to include Hermes.
docs/docs/hackagent/router/providers/hermes.md Adds API documentation page for the Hermes provider module.
docs/docs/hackagent/examples/hermes/hack_hermes.md Adds docs page for the Hermes example script.
docs/docs/architecture/system-overview.mdx Updates architecture diagram/text to include Hermes as a router target.
docs/docs/agents/index.mdx Adds Hermes section to the Agents overview with quickstart examples.
docs/docs/agents/hermes.mdx Adds dedicated Hermes agent documentation, including isolation and troubleshooting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +185 to +186
argv.extend(self.extra_args)
return argv
@franconicola
Nicola Franco (franconicola) merged commit e9e5c82 into main Jul 26, 2026
25 checks passed
@franconicola
Nicola Franco (franconicola) deleted the claude/add-hermes-agent-support branch July 26, 2026 20:27
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.

Integration and support for Hermes agent

3 participants