docs: add docs/adapters/hermes-recon.md
This commit is contained in:
parent
addb8b907e
commit
58ba097395
260
content/docs/adapters/hermes-recon.md
Normal file
260
content/docs/adapters/hermes-recon.md
Normal file
@ -0,0 +1,260 @@
|
||||
# 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_<uuid>.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.
|
||||
Loading…
Reference in New Issue
Block a user