Hermes Deep Dive: The Developer’s Guide - 2026-09-18

The developer tooling landscape in 2026 has a fragmentation problem. Your AI coding agent lives in one tab, your CI pipeline in another, your observability stack somewhere else, and the glue holding them together is a fragile mess of shell scripts and webhooks. Hermes emerged from this chaos with a deceptively simple premise: what if your agent runtime, your task orchestration, and your deployment pipeline all spoke the same protocol?

This guide covers Hermes from installation through advanced multi-agent workflows, with working code you can run today.


What is Hermes?

Hermes started in late 2024 as an internal tool at a Berlin-based infrastructure company that was tired of rewriting the same “call an LLM, parse the output, do something with it” loop across a dozen microservices. The first public release landed in early 2025, and by mid-2026 it has grown into a full agent orchestration runtime with a plugin ecosystem spanning over 400 community packages.

Core value proposition

Hermes is a local-first, protocol-driven agent runtime. Unlike cloud-hosted agent platforms that lock your workflows into a proprietary dashboard, Hermes runs on your machine or your infrastructure and exposes everything through a typed RPC interface called the Hermes Wire Protocol (HWP).

The pitch is straightforward:

What makes it different

The closest comparison points are LangGraph, CrewAI, and the newer entrant Skillsync (which launched on Hacker News this week as a YC W26 company). Skillsync’s thesis is that AI chat sessions should be portable across agents — a genuinely useful idea that Hermes approaches from a different angle. Where Skillsync focuses on session portability at the conversation layer, Hermes treats portability as a property of the runtime protocol. If two Hermes instances speak HWP, they can hand off tasks mid-execution, including full state.

The other differentiator is the replay log. Most agent frameworks give you logs. Hermes gives you a replayable event stream that you can step through, fork, and diff. If you’ve ever spent three hours trying to reproduce a flaky agent failure, you understand why this matters.


🚀 Getting Started

Installation

Hermes ships as a single static binary plus an optional language SDK. The binary is the runtime; the SDK is a thin client.

macOS and Linux (recommended):

# Install the runtime via the official install script
curl -fsSL https://get.hermes.dev/install.sh | sh

# Verify the installation
hermes --version
# Expected output: hermes 0.14.2 (build 2026-09-11, hwp/1.3)

# Install the Python SDK (for scripting)
pip install hermes-sdk==0.14.2

# Or the TypeScript SDK
npm install -g @hermes/sdk@0.14.2

Windows (via winget):

winget install Hermes.Runtime
hermes --version

Docker (for CI environments):

docker pull hermes/runtime:0.14.2-alpine
docker run --rm -v "$PWD:/work" hermes/runtime:0.14.2-alpine hermes run /work/agent.yaml

If you’re on an air-gapped machine, the install script supports an offline mode:

# Download the tarball on a connected machine
curl -fsSL https://get.hermes.dev/releases/hermes-0.14.2-linux-amd64.tar.gz -o hermes.tar.gz

# On the air-gapped machine
tar -xzf hermes.tar.gz
sudo mv hermes /usr/local/bin/
hermes doctor  # verifies signatures and dependencies

Configuration

Hermes reads configuration from ~/.hermes/config.toml by default, with per-project overrides in .hermes/config.toml. The precedence order is: environment variables > project config > user config > defaults.

A minimal working config:

# ~/.hermes/config.toml

[runtime]
# Where Hermes stores replay logs and skill caches
data_dir = "~/.hermes/data"
# Max concurrent agent executions
max_workers = 8
# Log level: trace, debug, info, warn, error
log_level = "info"

[providers.openai]
api_key = "${OPENAI_API_KEY}"
default_model = "gpt-5.2-turbo"
timeout_seconds = 120

[providers.anthropic]
api_key = "${ANTHROPIC_API_KEY}"
default_model = "claude-4.5-sonnet"

[providers.local]
# Points at a local llama.cpp or vLLM server
endpoint = "http://localhost:8080/v1"
default_model = "qwen3-32b-instruct"

[wire]
# HWP transport: stdio, http, ws, or nats
transport = "http"
bind = "127.0.0.1:7777"
# Require auth tokens for remote clients
require_auth = true

[telemetry]
# OpenTelemetry-compatible export
enabled = true
endpoint = "http://localhost:4317"

Validate your config before running anything:

hermes config validate
# Output: config OK (3 providers, 1 transport, telemetry enabled)

For secrets, Hermes integrates with the system keyring. On macOS and Linux:

hermes secrets set OPENAI_API_KEY
# Prompts for the value, stores it in the OS keyring

💡 Core Features

Feature 1: Typed Skills

A skill is the atomic unit of work in Hermes. It’s a function with a declared input and output schema, written in YAML or your language of choice. The runtime validates every invocation against the schema, which means malformed LLM outputs fail fast instead of corrupting downstream state.

Here’s a skill that summarizes a GitHub issue thread:

# skills/summarize_issue.yaml
name: summarize_issue
version: 1.0.0
description: Summarizes a GitHub issue and its comments into a structured brief.

input:
  type: object
  required: [issue_url]
  properties:
    issue_url:
      type: string
      format: uri
    max_comments:
      type: integer
      default: 50

output:
  type: object
  required: [title, summary, action_items]
  properties:
    title:
      type: string
    summary:
      type: string
      maxLength: 500
    action_items:
      type: array
      items:
        type: string

steps:
  - id: fetch
    uses: github.fetch_issue
    with:
      url: "{{ input.issue_url }}"
      max_comments: "{{ input.max_comments }}"

  - id: summarize
    uses: llm.complete
    with:
      provider: anthropic
      model: claude-4.5-sonnet
      prompt: |
        Summarize the following GitHub issue thread.
        Return JSON matching this schema: {{ output_schema }}
        Thread: {{ steps.fetch.output }}
      response_format: json

  - id: validate
    uses: schema.validate
    with:
      schema: "{{ output_schema }}"
      value: "{{ steps.summarize.output }}"

Run it directly from the CLI:

hermes skill run summarize_issue \
  --input '{"issue_url": "https://github.com/hermes-dev/hermes/issues/1842"}'

The real-world application here is obvious if you maintain an open-source project: wire this into a GitHub webhook and every new issue gets a structured brief in your triage channel within seconds. The schema validation means a hallucinated action_items field that’s a string instead of an array gets caught at the boundary, not three steps later.

Feature 2: Deterministic Replay

Every Hermes run produces a replay log — a compressed, append-only event stream stored under ~/.hermes/data/replays/. The log captures every skill invocation, every LLM call (including the exact prompt and response), every tool call, and every branch decision.

List recent runs:

hermes replay list --limit 5
# RUN ID              SKILL                STATUS   DURATION  STARTED
# 01J8X...A2F         summarize_issue      success  4.2s      2026-09-18T09:14:22Z
# 01J8X...9C1         triage_pr            success  11.8s     2026-09-18T09:11:03Z
# 01J8X...7B4         summarize_issue      failed   2.1s      2026-09-18T09:08:47Z

Step through a failed run:

hermes replay inspect 01J8X...7B4 --step
# Step 1/3: fetch
#   github.fetch_issue(url=..., max_comments=50)
#   -> 200 OK, 47 comments (cached: false)
# Step 2/3: summarize
#   llm.complete(provider=anthropic, model=claude-4.5-sonnet)
#   -> ERROR: context_length_exceeded (input 214,882 tokens > limit 200,000)
# Step 3/3: validate [SKIPPED]

Fork the run at the failure point and fix it without re-executing the expensive fetch:

hermes replay fork 01J8X...7B4 --at-step 2 --patch '{"max_comments": 20}'
# Forks run, re-executes from step 2 with patched input
# New run: 01J8X...D9E

This is the feature that changes how you develop agents. Instead of guessing why something failed and re-running the whole pipeline, you step through the exact event sequence. The --patch flag lets you test fixes against real captured data.

Feature 3: Multi-Transport Wire Protocol

The Hermes Wire Protocol (HWP) is a typed RPC layer that any Hermes runtime can speak. This is what enables the “hand off tasks mid-execution” capability mentioned earlier.

Start a Hermes runtime as an HTTP server:

hermes serve --transport http --bind 0.0.0.0:7777 --auth-token "$HERMES_TOKEN"

Now any HWP client can invoke skills remotely. Here’s the Python SDK:

from hermes_sdk import Client, TaskHandle

client = Client("http://localhost:7777", token="...")

# Synchronous invocation
result = client.skill("summarize_issue", input={"issue_url": "https://..."})
print(result["summary"])

# Async invocation with streaming events
handle: TaskHandle = client.skill_async(
    "triage_pr",
    input={"pr_url": "https://github.com/..."},
)

for event in handle.stream():
    match event.type:
        case "skill.started":
            print(f"  -> {event.skill_name}")
        case "llm.token":
            print(event.token, end="", flush=True)
        case "skill.completed":
            print(f"\nDone in {event.duration_ms}ms")

The real-world application: you can run a lightweight Hermes runtime on a developer laptop and a beefier one on a GPU box, then route skills based on their resource requirements. A local model handles the cheap summarization; the GPU box handles the 70B-parameter reasoning step. The protocol abstracts the transport, so your agent definition doesn’t care.


🛠️ Advanced Workflows

Workflow 1: CI-integrated agent with replay-based debugging

This workflow runs an agent on every pull request, posts a review comment, and captures a replay log you can inspect when the agent misbehaves.

# .github/workflows/hermes-review.yml
name: Hermes PR Review
on: [pull_request]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - name: Install Hermes
        run: curl -fsSL https://get.hermes.dev/install.sh | sh

      - name: Configure providers
        run: |
          hermes secrets set OPENAI_API_KEY --value "${{ secrets.OPENAI_API_KEY }}"
          hermes secrets set GITHUB_TOKEN --value "${{ secrets.GITHUB_TOKEN }}"

      - name: Run review agent
        run: |
          hermes skill run review_pr \
            --input '{"pr_number": ${{ github.event.number }}}' \
            --replay-dir ./replays \
            --fail-on error

      - name: Upload replay log
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: hermes-replay-${{ github.run_id }}
          path: ./replays/
          retention-days: 30

When a review comes back wrong, download the replay artifact and inspect it locally:

hermes replay inspect ./replays/01J8X...A2F --step --verbose
# Shows the exact diff the agent saw, the prompt it received,
# and the reasoning trace it produced.

The --fail-on error flag makes the CI step fail if the agent hits a runtime error, but not if the agent simply produces an unhelpful review. That distinction matters — you want the pipeline to catch infrastructure failures without blocking on subjective quality.

Workflow 2: Cross-runtime task handoff

This workflow demonstrates HWP’s transport-agnostic handoff. A coordinator agent on a laptop delegates a compute-heavy step to a remote runtime.

# On the GPU box (remote)
hermes serve --transport nats \
  --nats-url nats://gpu-box.internal:4222 \
  --bind-subject hermes.gpu.tasks \
  --register-skills embedding,rerank,long_context_reasoning

# On the laptop (coordinator)
hermes skill run research_pipeline \
  --input '{"query": "state of agent runtimes 2026"}' \
  --remote nats://nats.internal:4222 \
  --remote-subject hermes.gpu.tasks

The coordinator’s research_pipeline skill definition references remote skills by name:

name: research_pipeline
steps:
  - id: search
    uses: web.search
    with:
      query: "{{ input.query }}"
      max_results: 50

  - id: embed
    uses: embedding          # resolved to remote runtime
    with:
      texts: "{{ steps.search.output.snippets }}"

  - id: rerank
    uses: rerank             # resolved to remote runtime
    with:
      query: "{{ input.query }}"
      documents: "{{ steps.search.output.snippets }}"
      top_k: 10

  - id: synthesize
    uses: llm.complete
    with:
      provider: anthropic
      model: claude-4.5-sonnet
      prompt: |
        Synthesize a report from these sources:
        {{ steps.rerank.output }}

The key detail: embed and rerank are declared as uses: embedding and uses: rerank with no provider specified. Hermes resolves them against registered remote skills at runtime. If the GPU box goes down, you can register a fallback local implementation without touching the pipeline definition.


📊 Comparison with Alternatives

FeatureHermesLangGraphCrewAI
Deterministic replay log✅ Full event stream with fork/patch⚠️ Checkpointing only❌
Typed skill schemas✅ JSON Schema validation at boundaries⚠️ Via Pydantic, optional❌
Transport-agnostic RPC✅ HWP over stdio/HTTP/WS/NATS❌ Python-only❌ Python-only
Local-first runtime✅ Single static binary⚠️ Library, no runtime⚠️ Library, no runtime
Cross-runtime handoff✅ Native via HWP❌❌
Language SDKs✅ Python, TypeScript, Go, Rust⚠️ Python, JS (beta)⚠️ Python only
Plugin ecosystem✅ 400+ community skills⚠️ ~120 integrations⚠️ ~80 tools
Learning curve⚠️ Moderate (protocol concepts)⚠️ Moderate✅ Low
Self-hostable✅ Fully✅ Fully✅ Fully

The honest take: LangGraph is more mature for pure-Python graph-based workflows, and CrewAI is faster to prototype with. Hermes wins when you need replay-based debugging, cross-language support, or the ability to distribute agent execution across machines without rewriting your pipeline.


🎯 Pro Tips

1. Use --replay-dir in CI, not the default data directory. The default ~/.hermes/data/replays/ grows unbounded and will eventually fill your CI runner’s disk. Point it at a workspace-relative directory and let your artifact retention policy handle cleanup. A 30-day retention on replays has saved us from more than one “wait, what did the agent actually see?” debugging session.

2. Pin skill versions in production pipelines. Skills are versioned (version: 1.0.0 in the YAML), and uses: summarize_issue resolves to the latest version by default. In production, always pin: uses: summarize_issue@1.0.0. A community skill update that changes output schema can silently break your pipeline otherwise. Hermes will warn you about unpinned skills in hermes doctor, but it won’t block them.

3. Set max_workers conservatively on shared machines. The default is 8, which is fine on a dedicated box but will thrash a shared dev machine when three engineers each run a pipeline. Drop it to 2-3 for local development, and use the hermes serve --max-workers flag to override per-instance rather than editing config files.

4. Leverage hermes replay diff for regression testing. When you change a prompt or a skill definition, run the same input through both versions and diff the replay logs:

hermes replay diff 01J8X...A2F 01J8X...D9E --format unified
# Shows exactly which steps produced different outputs,
# including token-level diffs of LLM responses.

This is the closest thing to unit testing for non-deterministic agents, and it’s criminally underused.

5. Register a local fallback provider. Even if you primarily use cloud providers, configure a local llama.cpp or vLLM endpoint as a fallback. When your primary provider has an outage (and they all do), Hermes can fail over automatically if you set fallback = "local" on the provider config. The output quality drops, but your pipeline keeps running.


🔗 Resources

Official documentation

Community

Related tools worth knowing

Getting help


Hermes isn’t trying to be the easiest agent framework to start with — that’s CrewAI’s territory. It’s trying to be the one you don’t have to rip out when your prototype becomes production. The replay log alone justifies the learning curve if you’re shipping agents that matter. Install it, run the summarize_issue skill against a real GitHub thread, and step through the replay. You’ll see what the fuss is about within ten minutes.


Have questions? Join our Discord community or follow us on X.