# Hermes Agent — Adapter Reconnaissance Reconnaissance of [NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent) (v0.8.0, 68,713 ⭐, MIT) for potential Molecule AI adapter integration. > **Status:** Design-only recon — no implementation. --- ## a) CLI Invocation **Install** (curl-to-bash, targets Linux/macOS/WSL2/Termux): ```bash curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash ``` The `hermes` binary in the repo root is a Python script (`#!/usr/bin/env python3`) that imports and calls `hermes_cli.main.main()`. After install it lands on `$PATH`. **Minimal interactive session:** ```bash hermes # launches TUI, auto-detects provider from env hermes chat # explicit; same as bare `hermes` hermes setup # one-time wizard: sets model, provider, API keys ``` **Key runtime flags:** ```bash hermes chat \ --model anthropic/claude-opus-4.6 \ --provider openrouter \ --toolsets terminal,file,web \ --max-turns 60 \ --query "build me a FastAPI app" \ --resume # continue most recent session --worktree # git-worktree isolation per session --profile myprofile # load alternate HERMES_HOME profile ``` **One-shot (non-interactive):** ```bash hermes chat --query "summarise this repo" --quiet ``` **Gateway (messaging platforms) start:** ```bash hermes gateway start # daemonises; reads gateway config from config.yaml hermes gateway status hermes gateway stop ``` **OpenClaw migration:** ```bash hermes claw migrate --dry-run # preview; drop --dry-run to execute ``` --- ## b) Config Format **Format:** YAML **Primary path:** `~/.hermes/config.yaml` (default), overrideable via `HERMES_HOME` env var. **Reference file in repo:** `cli-config.yaml.example` **Minimal working config** (provider = OpenRouter, Docker terminal backend): ```yaml # ~/.hermes/config.yaml model: default: "anthropic/claude-opus-4.6" provider: "openrouter" # required; "auto" if you want env-var detection base_url: "https://openrouter.ai/api/v1" terminal: backend: "local" # required; options: local | ssh | docker | singularity | modal | daytona cwd: "." timeout: 180 lifetime_seconds: 300 memory: memory_enabled: true user_profile_enabled: true memory_char_limit: 2200 user_char_limit: 1375 nudge_interval: 10 agent: max_turns: 60 reasoning_effort: "medium" # xhigh | high | medium | low | minimal | none ``` **Required fields:** `model.default`, `model.provider`, `terminal.backend`. Everything else has a hardcoded default. **Credentials** go in `~/.hermes/.env` (separate from config.yaml): ```bash OPENROUTER_API_KEY=sk-or-... ANTHROPIC_API_KEY=sk-ant-... HERMES_HOME=~/.hermes # optional override ``` **Skills config** (in `config.yaml`): ```yaml skills: creation_nudge_interval: 15 # remind agent to persist a skill every N tool iterations external_dirs: - ~/.agents/shared-skills # read-only external skill dirs ``` **Compression config** (in `config.yaml`): ```yaml compression: enabled: true threshold: 0.50 summary_model: "google/gemini-3-flash-preview" ``` --- ## c) Runtime Dependencies **Python version:** 3.13 (Dockerfile base: `ghcr.io/astral-sh/uv:0.11.6-python3.13-trixie`) **Package manager:** [uv](https://github.com/astral-sh/uv) (not pip directly; `uv pip install .`) **Package version:** `hermes-agent==0.8.0` **Top core pip dependencies** (from `pyproject.toml`): | Package | Version constraint | Purpose | |---|---|---| | `openai` | `>=2.21.0,<3` | Primary LLM client (all providers via OpenAI-compat API) | | `anthropic` | `>=0.39.0,<1` | Direct Anthropic API adapter | | `python-dotenv` | `>=1.2.1,<2` | `.env` loading | | `fire` | `>=0.7.1,<1` | CLI argument dispatch | | `httpx[socks]` | `>=0.28.1,<1` | Async HTTP (gateway, webhooks) | | `rich` | `>=14.3.3,<15` | TUI rendering | | `pyyaml` | `>=6.0.2,<7` | Config file parsing | | `pydantic` | `>=2.12.5,<3` | Data validation | | `prompt_toolkit` | `>=3.0.52,<4` | Interactive TUI / multiline input | | `tenacity` | `>=9.1.4,<10` | Retry logic | **Key optional extras:** ```bash pip install "hermes-agent[modal]" # modal>=1.0.0 — serverless backend pip install "hermes-agent[daytona]" # daytona>=0.148.0 — cloud sandbox backend pip install "hermes-agent[mcp]" # mcp>=1.2.0 — MCP server/client pip install "hermes-agent[honcho]" # honcho-ai — cross-session user modeling pip install "hermes-agent[messaging]" # telegram, discord.py, aiohttp, slack pip install "hermes-agent[voice]" # faster-whisper, sounddevice, numpy pip install "hermes-agent[rl]" # atroposlib, fastapi, uvicorn, wandb ``` **System binaries** (from Dockerfile `apt-get install`): ``` nodejs npm ripgrep ffmpeg gcc python3-dev libffi-dev procps build-essential ``` `ripgrep` is used by the `file` toolset for fast codebase search. `ffmpeg` is used for voice transcription pre-processing. --- ## d) Session State **All persistent state lives under `HERMES_HOME`** (default: `~/.hermes/`, overrideable via env var). **Primary state store: SQLite** ``` ~/.hermes/state.db ← DEFAULT_DB_PATH = get_hermes_home() / "state.db" ``` - Schema version: **6** (`SCHEMA_VERSION = 6` in `hermes_state.py`) - WAL mode (`PRAGMA journal_mode=WAL`) — supports concurrent gateway + CLI writers - Three core tables: `schema_version`, `sessions`, `messages` - **FTS5 virtual table** `messages_fts` with auto-sync triggers on INSERT/UPDATE/DELETE — backs the `session_search` toolset (full-text search across all past conversation content) - Compression-triggered session splitting tracked via `parent_session_id` chain in `sessions` table - Session source tagged as `'cli'`, `'telegram'`, `'discord'`, etc. for per-platform filtering **Full directory layout:** ``` ~/.hermes/ ├── config.yaml ← get_config_path() ├── .env ← get_env_path() ├── state.db ← SQLite WAL, FTS5 ├── skills/ ← get_skills_dir() — user-created skill SKILL.md files ├── logs/ ← get_logs_dir() — trajectory JSONs │ └── session_YYYYMMDD_HHMMSS_.json ├── MEMORY.md ← agent's curated notes (injected into system prompt) ├── USER.md ← user profile (injected into system prompt) └── skins/ ← optional custom theme YAMLs ``` **State is persistent by default.** Session history, memories (`MEMORY.md`/`USER.md`), and skills survive restarts. The `session_reset` config controls when gateway sessions are cleared (default: `mode: both`, idle after 1440 min or at 4 AM daily). Before any reset, Hermes is given one flush turn to write important context to `MEMORY.md`. Container backend state is controlled separately by `container_persistent: true/false` in the `terminal:` block. --- ## e) Execution Backends **Six backends configured via a single `terminal.backend` key in `config.yaml`:** | Backend | Where commands run | Key extra config | |---|---|---| | `local` | Host machine, current dir | — | | `ssh` | Remote server | `ssh_host`, `ssh_user`, `ssh_key` | | `docker` | Inside a Docker container | `docker_image`, `docker_mount_cwd_to_workspace` | | `singularity` | Singularity/Apptainer container (HPC) | `singularity_image` | | `modal` | Modal cloud sandbox (serverless) | `modal_image`, `pip install hermes-agent[modal]` | | `daytona` | Daytona cloud sandbox | `daytona_image`, `container_disk`, `pip install hermes-agent[daytona]` | **Architecture clarification:** Hermes's Python process **always runs locally** (or wherever you launched it). The `backend` setting controls only where the **`terminal` tool** executes shell commands. For `docker`, Hermes calls the Docker API to spawn/reuse a container and routes `terminal` tool calls into it via exec — Hermes itself is **not** containerised by this setting. **Docker backend minimal config:** ```yaml terminal: backend: "docker" cwd: "/workspace" # path inside the container timeout: 180 lifetime_seconds: 300 docker_image: "nikolaik/python-nodejs:python3.11-nodejs20" docker_mount_cwd_to_workspace: false # default: false (security off). Set true to bind-mount launch dir into /workspace docker_forward_env: - "GITHUB_TOKEN" - "NPM_TOKEN" container_cpu: 1 container_memory: 5120 # MB container_disk: 51200 # MB container_persistent: true # false = ephemeral container, wiped after session ``` **The Dockerfile** (for running *all of Hermes* inside Docker, distinct from the backend setting) uses: ```dockerfile FROM debian:13.4 ENV HERMES_HOME=/opt/data ENV PLAYWRIGHT_BROWSERS_PATH=/opt/hermes/.playwright VOLUME /opt/data ENTRYPOINT ["/opt/hermes/docker/entrypoint.sh"] # Runs as non-root user hermes (UID 10000), home /opt/data ``` **Serverless hibernation** (Modal + Daytona): `container_persistent: false` produces fully ephemeral sandboxes that are destroyed after `lifetime_seconds`; `true` persists the container filesystem between sessions (warm-resume, no re-install overhead). --- ## f) Value Proposition Integrating Hermes adds one capability that none of the six existing adapters (LangGraph, Claude Code, CrewAI, AutoGen, OpenClaw, DeepAgents) deliver end-to-end: **a closed learning loop that compounds across sessions at the skill, memory, and user-model layers simultaneously.** Concretely: after a complex task, Hermes autonomously creates a `SKILL.md` file in `~/.hermes/skills/` (prompted every `creation_nudge_interval=15` tool iterations), and those skills are re-injected as context in future sessions — agents get better at tasks they've done before without any human curation step. The `session_search` toolset adds FTS5 + Gemini Flash summarization over `state.db`, so the agent can recall specific conversations from months ago with semantic-quality results. Layered on top is **Honcho dialectic user modeling** (`plastic-labs/honcho`) — a cross-session profile that tracks user communication style, preferences, and expectations, shared across any Honcho-integrated tool (not just Hermes). Finally, the **Modal and Daytona serverless backends with `container_persistent`** give Molecule AI a path to hibernating, pay-per-use sandboxes that no existing adapter exposes — directly relevant to Molecule AI's multi-workspace billing model. The `hermes claw migrate` command (backed by `optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py`) is also relevant: Molecule AI could offer equivalent migration tooling to attract OpenClaw's existing ~247k-user base, and the **`agentskills.io` skill-manifest spec** (referenced in `optional-skills/`) should be reviewed before Molecule AI finalises its own plugin manifest schema to ensure interoperability with what is rapidly becoming the de-facto file-based skill standard.