Skip to content

Explanation

Hermes Agent is a Python-based AI agent built around a synchronous orchestration loop with pluggable memory, skills, terminal backends, and platform adapters. This page covers the internals of each major subsystem, plus the threat model and isolation design.

Agent Loop

The core of Hermes Agent is run_conversation() — a synchronous orchestration engine that handles provider selection, prompt construction, tool execution, retries, fallback mechanisms, context compression, and session persistence.

Turn Lifecycle

Each iteration follows a defined sequence:

  1. Generate task ID and append the user message
  2. Build system prompt — assembles stable prompt components plus Honcho context layers
  3. Preflight compression check — if token usage is near the limit, compress context before the API call
  4. Build API messages — convert internal message format to OpenAI-format messages with tool schemas
  5. Inject ephemeral prompt layers — session overlays and prefill messages added at call time (not baked into the stable prefix, to preserve provider-side prompt caching)
  6. Interruptible API call — send to the configured LLM provider
  7. Parse response — branch on tool calls vs. text
  8. If tool calls — dispatch each via handle_function_call(), append results, continue loop
  9. If text response — persist session, flush memory, return
flowchart TD
    A[User Message] --> B[Build System Prompt]
    B --> C{Token Limit Near?}
    C -->|Yes| D[Compress Context]
    C -->|No| E[Build API Messages]
    D --> E
    E --> F[Inject Ephemeral Layers]
    F --> G[LLM API Call]
    G --> H{Response Type}
    H -->|Tool Calls| I[Dispatch via handle_function_call]
    I --> J[Append Results]
    J --> G
    H -->|Text| K[Persist Session]
    K --> L[Flush Memory]
    L --> M[Return Response]

Prompt Architecture

The prompt system separates stable and ephemeral components to maximize provider-side prompt caching:

  • Stable prefix — system instructions, tool schemas, skill context, Honcho base context. Remains identical across turns within a session.
  • Ephemeral layers — session overlays, prefill messages, dialectic supplement. Injected only at API call time to prevent invalidation of cached tokens.

The system supports three API modes for different provider backends (OpenAI-compatible, Anthropic native, and custom endpoints).

Memory System

Hermes uses a three-layer memory architecture that provides both immediate recall and long-term learning.

flowchart TB
    subgraph L1["Layer 1: Session Context"]
        SC[In-Memory Messages]
        SC_NOTE["Scope: current conversation<br>Retrieval: immediate"]
    end
    subgraph L2["Layer 2: Session History"]
        SH[SQLite + FTS5]
        SH_NOTE["Scope: all past sessions<br>Retrieval: full-text search"]
    end
    subgraph L3["Layer 3: User Model"]
        UM[Honcho Dialectic]
        UM_NOTE["Scope: cross-session identity<br>Retrieval: dialectic modeling"]
    end
    subgraph L4["Layer 4: Skills"]
        SK[Markdown Files]
        SK_NOTE["Scope: persistent knowledge<br>Retrieval: pattern matching"]
    end

    L1 --> L2
    L2 --> L3
    L3 --> L4

Layer 1 -- Session Context

In-memory message list for the current conversation. Subject to automatic context compression when approaching the provider's token limit.

Layer 2 -- Session History (SQLite + FTS5)

All past sessions are persisted to SQLite with FTS5 full-text search. Sessions include lineage tracking across compressions, per-platform isolation, and atomic writes with contention handling. Users can search their own conversation history via hermes search and receive LLM-powered summarization of results.

Layer 3 -- Honcho User Modeling

Honcho provides AI-native cross-session user modeling with multi-pass dialectic reasoning. It operates in three modes, configurable via hermes honcho mode:

Mode Behavior
local SQLite-only memory, no Honcho calls
honcho Full Honcho cloud integration
hybrid Local memory + Honcho context injection (default)

Every turn (in hybrid or honcho mode), Honcho assembles two layers of context injected into the system prompt:

  • Base context — session summary, user representation, user peer card, AI self-representation, AI identity card
  • Dialectic supplement — LLM-synthesized reasoning about the user's current state and needs

Both layers are concatenated and truncated to the contextTokens budget if set.

Layer 4 -- Skills

Structured markdown files stored in ~/.hermes/skills/. See #Skill Engine.

Skill Engine

The skill engine is Hermes Agent's core differentiator — it enables autonomous creation, storage, retrieval, and self-improvement of reusable task knowledge.

Skill Lifecycle

flowchart LR
    A[Complex Task<br>5+ tool calls] --> B[Agent Creates<br>Skill Document]
    B --> C[Stored as<br>SKILL.md]
    C --> D[Pattern-Matched<br>on Future Tasks]
    D --> E{Skill Correct?}
    E -->|Yes| F[Used As-Is]
    E -->|Outdated/Wrong| G[Self-Improve:<br>Patch In-Place]
    G --> C
    F --> H{Eligible for<br>Evolution?}
    H -->|Yes| I[DSPy + GEPA<br>Optimization]
    I --> C

Skill Document Format

Skills are stored as structured markdown with YAML frontmatter:

---
name: my-skill
description: Brief description of what this skill does
version: 1.0.0
platforms: [macos, linux]
metadata:
  hermes:
    tags: [python, automation]
    category: devops
    requires_toolsets: [terminal]
    config:
      - key: my.setting
        description: "What this controls"
        default: "value"
---

# Skill Title

## When to Use
Trigger conditions for this skill.

## Procedure
1. Step one
2. Step two

## Pitfalls
- Known failure modes and fixes

## Verification
How to confirm it worked.

Autonomous Creation

After a complex task finishes (defined as 5+ tool calls), the agent writes a skill document capturing:

  • The approach it took
  • Edge cases encountered
  • Domain knowledge reconstructed during the task

Self-Improvement

Skills are patched in real-time when the agent detects:

  • Outdated content — an API changed or a dependency was updated
  • Incomplete coverage — a missing edge case was encountered
  • Incorrect output — the skill produced wrong results

Skill Discovery

Skills are loaded from three locations:

  1. User skills — ~/.hermes/skills/
  2. Project skills — .hermes/skills/ in the current directory
  3. Hub skills — installed via hermes skills install from registries (official, skills.sh, well-known)

Skills are compatible with the agentskills.io open standard.

Self-Evolution System (DSPy + GEPA)

The companion repository hermes-agent-self-evolution uses DSPy + GEPA (Genetic-Pareto Prompt Evolution) to automatically evolve skills, tool descriptions, system prompts, and agent code.

Evolution Pipeline

flowchart TD
    A[Current Skills/Prompts] --> B[Read Execution Traces]
    B --> C[Understand Why Things Fail]
    C --> D[LLM Generates Text Variants<br>via Mutation]
    D --> E[Evaluate Variants<br>Against Test Cases]
    E --> F{Multi-Objective<br>Pareto-Optimal?}
    F -->|Yes| G[Keep Variant]
    F -->|No| H[Discard]
    G --> I[Selection:<br>Quality + Cost + Speed]
    I --> A

GEPA Process

  1. Mutate — LLM generates text variants of skills/prompts. The GEPA optimizer reads execution traces to understand why things fail, not just that they failed, then proposes targeted improvements.
  2. Evaluate — Run variants against test cases using DSPy evaluation frameworks (COPRO for gradient-free search, MIPRO for instruction tuning with validation sets).
  3. Select — Keep Pareto-optimal variants across multiple objectives: quality, cost, and speed.
  4. Do steps 2 and 3 again — Evolutionary pressure produces measurably better versions over successive runs.

Operational Characteristics

  • No GPU training required — operates entirely via LLM API calls
  • Cost: $2--10 per optimization run
  • Underlying research: ICLR 2026 Oral Paper
  • MIT licensed

Multi-Platform Gateway

The messaging gateway is a single background process that manages connections to all configured platforms, handles user sessions, executes cron jobs, and delivers voice messages.

Platform Adapters

Each platform has a dedicated adapter in gateway/platforms/ extending BaseAdapter:

Adapter Protocol
telegram.py Telegram Bot API (long polling or webhook)
discord.py Discord bot via discord.py
slack.py Slack Socket Mode
whatsapp.py WhatsApp Business Cloud API
signal.py Signal via signal-cli REST API
matrix.py Matrix via mautrix (optional E2EE)
mattermost.py Mattermost WebSocket API
email.py Email via IMAP/SMTP
sms.py SMS via Twilio
dingtalk.py DingTalk WebSocket
feishu.py Feishu/Lark WebSocket or webhook
wecom.py WeCom (WeChat Work) callback
weixin.py Weixin (personal WeChat) via iLink Bot API
bluebubbles.py Apple iMessage via BlueBubbles macOS server
qqbot.py QQ Bot (Tencent QQ) via Official API v2
webhook.py Inbound/outbound webhook adapter
api_server.py REST API server adapter
homeassistant.py Home Assistant conversation integration

All platforms get full tool access, not just chat — the same agent capabilities are available from Telegram as from the CLI.

Gateway Architecture

The gateway routes incoming messages from any platform adapter through a unified session manager to the agent loop. Sessions are isolated per-platform, and each adapter handles media attachments and platform-specific message formatting independently.

Terminal Backends

Six execution backends determine where the shell commands of the agent run:

Backend Isolation Use Case Lifecycle
Local None (host machine) Development, personal use Persistent
Docker Container (hardened) Isolation, reproducibility Long-lived container, docker exec per command, cleaned up on session end
SSH Remote server Remote execution Persistent remote session
Daytona Sandbox Serverless persistence Hibernates when idle
Singularity Container (HPC) HPC clusters Per-command or persistent
Modal Serverless sandbox Cloud pay-per-use Near-zero idle cost

Configuration is via config.yaml or the TERMINAL_ENV environment variable. Container-based backends (Docker, Singularity, Modal, Daytona) default to the nikolaik/python-nodejs:python3.11-nodejs20 image.

Dangerous command handling

In the local backend, Hermes checks every command against a curated list of dangerous patterns (recursive deletes, SQL drops, piping curl to shell, and more) and prompts for approval. In container backends, dangerous command checks are skipped because the container itself is the security boundary.

Plugin System

The plugin system supports three discovery sources:

  1. User plugins — ~/.hermes/plugins/
  2. Project plugins — .hermes/plugins/
  3. pip entry points — installed Python packages that register as Hermes plugins

Plugins can register:

  • Tools — custom tool schemas and handlers
  • Hooks — event callbacks (for example, post_tool_call)
  • CLI commands — custom subcommands added to the hermes CLI

Two specialized plugin types exist with single-select semantics:

  • Memory providers — alternative memory backends (for example, the Honcho plugin)
  • Context engines — custom context injection systems

Plugin loading occurs at startup via the register(ctx) function, which receives a context object for registering tools, hooks, and commands.

Security Track Record

As of April 2026, Hermes Agent has zero agent-specific CVEs. This contrasts sharply with OpenClaw, which accumulated 9 CVEs within 4 days of its March 2026 release. The difference is partly attributable to Hermes's smaller attack surface (fewer platform integrations, no marketplace of third-party skills with arbitrary code execution) and its container-first isolation model for code execution.

Threat Model

flowchart TB
    subgraph External["External Attack Surface"]
        GW["Gateway Channels<br>(Telegram, Discord, Slack, ...)"]
        API["API Server<br>(REST endpoint)"]
        WEB["Web Dashboard"]
    end

    subgraph Internal["Internal Attack Surface"]
        PLUGIN["Plugin System<br>(arbitrary Python)"]
        SKILL["Skills<br>(markdown + instructions)"]
        TERM["Terminal Backends<br>(code execution)"]
        KEYS["API Keys<br>(~/.hermes/.env)"]
        DB["Session Database<br>(SQLite on disk)"]
        EVOL["Self-Evolution<br>(prompt mutation)"]
    end

    GW -->|Auth: ALLOWED_USERS| AGENT[Agent Core]
    API -->|Auth: API_SERVER_KEY| AGENT
    WEB -->|No built-in auth| AGENT
    AGENT --> PLUGIN
    AGENT --> SKILL
    AGENT --> TERM
    AGENT --> KEYS
    AGENT --> DB
    AGENT --> EVOL

Attack Surfaces

Surface Risk Mitigation
Gateway channels Unauthorized messages from non-allowed users *_ALLOWED_USERS env var per platform
API server Remote code execution via REST API_SERVER_KEY required for non-loopback binding
Web dashboard Credential exposure (reads/writes .env) Binds to 127.0.0.1 by default. No built-in auth
Plugin system Arbitrary Python execution User must explicitly place files in ~/.hermes/plugins/
Terminal backends Shell command injection Dangerous command approval + container isolation
API keys Credential theft from disk File permissions (chmod 600), env-only storage
Session database History exposure Local SQLite file, inherits OS file permissions
Self-evolution Skill degradation, malicious mutations Pareto selection, test-case validation, human review

Sandboxing

Docker Backend Isolation

When using the Docker terminal backend, Hermes applies strict security hardening to every container:

_SECURITY_ARGS = [
    "--cap-drop", "ALL",                          # Drop ALL Linux capabilities
    "--cap-add", "DAC_OVERRIDE",                  # Root can write to bind-mounted dirs
    "--cap-add", "CHOWN",                         # Package managers need file ownership
    "--cap-add", "FOWNER",                        # Package managers need file ownership
    "--security-opt", "no-new-privileges",         # Block privilege escalation
    "--pids-limit", "256",                         # Limit process count
    "--tmpfs", "/tmp:rw,nosuid,size=512m",         # Size-limited /tmp
    "--tmpfs", "/var/tmp:rw,noexec,nosuid,size=256m",  # No-exec /var/tmp
    "--tmpfs", "/run:rw,noexec,nosuid,size=64m",   # No-exec /run
]

Key protections:

  • All Linux capabilities dropped except three required for package management
  • Privilege escalation explicitly blocked via no-new-privileges
  • Process count capped at 256 to prevent fork bombs
  • Temporary directories are size-limited and mounted with noexec/nosuid

Singularity / Modal / Daytona Isolation

Container-based backends (Singularity, Modal, Daytona) provide namespace isolation from the host. Modal and Daytona run in cloud-managed sandboxes with additional provider-level isolation. For all container backends, dangerous command checks are skipped because the container itself is the security boundary.

Container image trust

The default image (nikolaik/python-nodejs:python3.11-nodejs20) is a community-maintained image. For production deployments, consider building and hosting your own images from a trusted base.

Dangerous Command Approval (Local Backend)

The local backend checks every command against a curated list of dangerous patterns before execution:

  • Recursive deletes (rm -rf)
  • SQL drops (DROP TABLE, DROP DATABASE)
  • Piping curl to shell (curl ... | bash)
  • Permission changes on system directories
  • Other destructive patterns

When a dangerous command is detected, the agent presents an interactive approval prompt with options: [o]nce, [s]ession, [a]lways, or [d]eny.

Memory and Session Data Protection

Session data is stored in local SQLite files under ~/.hermes/. Protection relies on:

  • OS file permissions — SQLite files inherit the permissions of the Hermes data directory
  • Per-platform session isolation — sessions from different platforms are stored separately. This prevents cross-channel data leakage
  • Atomic writes — contention handling prevents corruption during concurrent access

No encryption at rest

SQLite session data is not encrypted at rest. If the host is compromised, all conversation history is accessible. For sensitive environments, run Hermes in an encrypted filesystem or use a container backend with ephemeral storage.

Self-Evolution Safety

The DSPy + GEPA self-evolution system introduces a unique risk: autonomous modification of skills and prompts can degrade agent quality or introduce harmful behaviors.

Safeguards:

  • Test-case validation — every mutated variant is evaluated against test cases before acceptance
  • Pareto selection — variants must be optimal across multiple objectives (quality, cost, speed). This prevents single-metric gaming
  • Execution trace analysis — the GEPA optimizer reads traces to understand why failures occur. This reduces blind mutations
  • Human review — evolution runs produce diffs that can be reviewed before deployment
  • Rollback — skills are versioned. Previous versions can be restored via hermes skills reset <name> --restore

Unattended evolution

Running self-evolution unattended in production is not recommended at v0.9.0. Review generated diffs before deploying evolved skills to production agents.

Plugin Security

Plugins execute arbitrary Python in the agent process with no sandboxing. Risks include:

  • Data exfiltration (reading .env, session database, filesystem)
  • Code injection (registering malicious tools)
  • Denial of service (blocking the agent loop)

Mitigations:

  • You must explicitly place plugins in ~/.hermes/plugins/ or .hermes/plugins/
  • Hub-installed skills are scanned on install (hermes skills install runs a security scan)
  • Periodic re-scanning is available via hermes skills audit
  • There is no runtime sandbox for plugins -- trust is placement-based

Sources