Skip to main content

langstage-hermes — closed-loop reflection & skill creation on LangGraph + deepagents

langstage-hermes

PyPI Python License

A faithful reproduction of Nous Research's Hermes Agent on top of LangGraph + deepagents + langstage-core.

Status: live on PyPI (renamed from deepagent-hermes — the old name now just installs this one, and the deepagent-hermes command still works). Spec at SPEC.md. Release notes in CHANGELOG.md. The runtime is verified end-to-end against a real Anthropic model — both the memory loop and the skill-creation loop close autonomously; see examples/dogfood.py and examples/dogfood_procedural.py for the traces.

What it is

A deepagents-built agent with a closed reflection→skill-creation loop:

  • After ~10 tool-using iterations, a review subagent runs in the background, writes/patches a SKILL.md capturing the pattern it just exercised, and ships it to a skill library.
  • Next session, the agent reads the library at startup, sees the new skill's description in its system prompt, and can skill_view(name) to load the full body on demand (progressive disclosure per the agentskills.io spec).
  • A weekly curator consolidates skills into umbrellas and archives stale ones.
  • A frozen-snapshot memory (MEMORY.md + USER.md) preserves prefix-cache hits for the entire session.
  • FTS5 session search indexes every past conversation in a local SQLite DB.
  • Bundled MarkdownProvider that keyword-searches <HERMES_HOME>/memories/notes/*.md — drop hand-authored long-form context there and the agent surfaces relevant sections on demand. Zero external dependencies.

Designed to be loaded into the LangStage host family without UI changes — set LANGSTAGE_AGENT_SPEC=langstage_hermes.agent:graph in any of them.

Every stage for your LangGraph agent

langstage-hermes is the reference agent of the LangStage family: write your agent once — any LangGraph CompiledGraph — and run it on every stage with the same spec string (module:attr or path/to/file.py:attr), the same langstage.toml config file, and the same LANGSTAGE_* environment variables.

Stage Package Try it
Web app langstage langstage run --agent langstage_hermes.agent:graph
JupyterLab langstage-jupyter pip install langstage-jupyter, then the chat sidebar in jupyter lab
Terminal langstage-cli langstage-cli -a langstage_hermes.agent:graph
VS Code langstage-vscode chat participant + stdio sidecar
Reference agent langstage-hermes you are here
Shared core langstage-core typed events + config resolver behind every stage

Serve over AG-UI

This surface's agent — any LangGraph CompiledGraph — can also be served over the AG-UI protocol as a standalone HTTP endpoint. Install the extra and point the bundled console script at your agent spec:

pip install "langstage-core[agui]"
langstage-agui --agent langstage_hermes.agent:graph

📖 Full documentation: https://dkedar7.github.io/langstage-docs/

Installation

pip install langstage-hermes

Or with uv (recommended):

uv venv .venv
. .venv/Scripts/activate      # Windows
. .venv/bin/activate          # macOS / Linux
uv pip install langstage-hermes

Optional extras

pip install "langstage-hermes[openai]"     # OpenAI / OpenRouter / any OpenAI-wire provider
pip install "langstage-hermes[daytona]"    # Daytona sandbox terminal backend
pip install "langstage-hermes[modal]"      # Modal sandbox terminal backend
pip install "langstage-hermes[ssh]"        # paramiko-backed SSH terminal backend
pip install "langstage-hermes[dev]"        # tests + lint (contributors only)

Picking a model

By default the agent uses anthropic:claude-sonnet-4-6 and needs ANTHROPIC_API_KEY set. Swap the model via --model on the CLI or model.default in langstage-hermes.toml — any init_chat_model string works.

OpenAI / OpenRouter

pip install "langstage-hermes[openai]"
export OPENAI_API_KEY=sk-…                   # or: OPENROUTER_API_KEY=sk-or-v1-…
export OPENAI_BASE_URL=https://openrouter.ai/api/v1   # only for OpenRouter
langstage-hermes chat --model openai:openai/gpt-4o-mini

For OpenRouter specifically you usually also want:

export LANGSTAGE_HERMES_MODEL_DEFAULT="openai:openai/gpt-4o-mini"
export LANGSTAGE_HERMES_MODEL_AUX="openai:openai/gpt-4o-mini"

so the reflection subagent uses the same cheap model.

Verify your setup

langstage-hermes verify

does one live round-trip against the configured model and confirms the prompts, bundled skills, and FTS5 store all wire up correctly. Run this first on any fresh install — if it passes, chat will work. The offline checks (bundled prompts and skills, a writable HERMES_HOME, and that the FTS5 store opens) run before the key check, so even a keyless run tells you the install itself is sound.

Both verify and doctor accept --json for scripting/CI — a top-level ok plus a per-check list, with .ok equal to exit code == 0 (so langstage-hermes doctor --json | jq -e .ok is a one-liner readiness gate). verify --json reports the live round-trip as skipped when no key is set, so a keyless CI check never triggers a paid call.

Quick start

# show resolved config + sources
langstage-hermes --show-config

# interactive chat
langstage-hermes chat

# chat against a different agent (same spec format as every LangStage
# stage; overrides LANGSTAGE_AGENT_SPEC)
langstage-hermes chat -a my_agent.py:graph

# from inside chat:
#   /skills            list available skills
#   /model anthropic:claude-haiku-4-5-20251001    switch models
#   /memory            dump current memory snapshot
#   /compress          force context compression
#   /quit

Search your session history

Every conversation is indexed in a local SQLite FTS5 store at <HERMES_HOME>/state.db. Query it from the terminal — keyless and offline, no model call — in the three documented modes:

# DISCOVERY — BM25 top-N with a highlighted snippet (prints session_id + message_id)
langstage-hermes search "profile slow python"
langstage-hermes search "profile slow python" --limit 10 --json

# SCROLL — a ±window view centred on a message (window clamped 1–20)
langstage-hermes search --session sess-1a2b3c --around 8 --window 5

# BROWSE — recent sessions, newest first (also the default with no query)
langstage-hermes search --browse --limit 20

--json emits structured output for scripting/CI. The same flag is honored by skills list, skills audit, audit log, memory show / memory notes, the readiness checks doctor / verify, --show-config, and the cron subcommands (list, create, run-due, delete, pause, resume) — so the skill inventory, mutation log, setup diagnostics, and scheduler are all scriptable too (each prints one JSON object with stable keys). FTS5 syntax works: multi-word queries default to AND, and OR, quoted "phrases", and prefix wildcards* are all honored.

Want a store to try it against, keyless? Point HERMES_HOME at a directory and run langstage-hermes demo — with HERMES_HOME set the demo copies its session (and only its session) into that same <HERMES_HOME>/state.db, so search reads it straight back:

export HERMES_HOME=~/.langstage-hermes    # any stable directory
langstage-hermes demo                     # populates <HERMES_HOME>/state.db
langstage-hermes search "python"          # finds the demo session

(The loop itself always runs in a throwaway home that is cleaned up afterwards — pass --keep-workspace to inspect it — so the demo's generated skill and scripted user-memory note never land in your real skill library or USER.md. A bare langstage-hermes demo with no HERMES_HOME set writes nothing outside that throwaway home.)

Preview your notes

Drop hand-authored long-form context in <HERMES_HOME>/memories/notes/*.md and the bundled MarkdownProvider surfaces relevant sections to the agent on demand (enable it with memory.provider = "markdown"). Preview exactly what it will recall from the terminal — keyless and offline, no model call — so note authors get a feedback loop without a chat turn:

langstage-hermes memory notes "rollback"            # prints the source file + matching section
langstage-hermes memory notes "rollback" --json     # {"query", "count", "results":[{file, section, snippet}]}

Recall is the same dumb-but-robust keyword overlap the agent uses (query tokens ≥ 3 chars, ranked by distinct hits). --limit N caps the sections returned; a missing/empty notes dir or a no-match query prints a clear message, never a traceback.

Read your memory

The frozen-snapshot memory (MEMORY.md + USER.md) is the layer the agent grows about you and the session, but inside a chat only the /memory slash command could read it — and chat needs an API key. Dump the current snapshot straight from the terminal — keyless and offline, no model call — to answer "what has the agent learned about me?" without spending a turn:

langstage-hermes memory show                 # both USER.md + MEMORY.md, with char count vs budget
langstage-hermes memory show --user          # just USER.md
langstage-hermes memory show --session       # just MEMORY.md
langstage-hermes memory show --json          # {"user": {...}, "memory": {...}} for scripting / CI

Each layer prints its char count against the configured char budget (memory_char_limit = 2200, memory_user_char_limit = 1375) so you can see when a snapshot is near or over budget. Nothing is truncated: an over-budget layer (e.g. a hand-edited USER.md) is still injected in full every turn, and the agent's memory tool rejects new entries for it until it is trimmed back under budget. A missing/empty layer prints a clear one-line message, never a traceback (memory dump is an alias for memory show).

Load into an existing host

Any LangStage host can run this agent:

# langstage-cli
LANGSTAGE_AGENT_SPEC="langstage_hermes.agent:graph" langstage-cli

# langstage-jupyter — set the same in langstage.toml under [agent]
printf '[agent]\nspec = "langstage_hermes.agent:graph"\n' >> langstage.toml
langstage-jupyter

Configuration

langstage-hermes.toml (project) or $HERMES_HOME/config.toml (global — default ~/.langstage-hermes/config.toml, and it moves with a custom HERMES_HOME). Layered resolution: defaults < TOML < LANGSTAGE_HERMES_* env < CLI overrides. See SPEC §2 for every field; langstage-hermes --show-config prints the resolved value + source of each, and langstage-hermes --show-config --json prints the same thing as one JSON object ({"config": {<field>: {value, source, env, legacy_env, toml}}, "toml": {...}, "issues": [...]}) for CI. The legacy project filename deepagent-hermes.toml is still read, with a one-time deprecation note on stderr (silence it with LANGSTAGE_SUPPRESS_LEGACY_NOTICE=1).

Architecture

See SPEC.md for the full 21-section requirements doc. Top-level layout:

  • src/langstage_hermes/agent.py — the compiled graph (entry point for hosts)
  • src/langstage_hermes/config.py — HermesConfig(HostConfig) resolver
  • src/langstage_hermes/state.py — HermesState (extends AgentState)
  • src/langstage_hermes/reflection.py — closed-loop middleware + review subagent
  • src/langstage_hermes/skills/ — SkillLibrary, loader, tools
  • src/langstage_hermes/memory/ — frozen-snapshot memory + provider ABC
  • src/langstage_hermes/store/sqlite_fts.py — BaseStore with FTS5
  • src/langstage_hermes/search/session_search.py — session_search tool
  • src/langstage_hermes/compression.py — HermesCompressionMiddleware
  • src/langstage_hermes/caching.py — AnthropicCachingS3Middleware
  • src/langstage_hermes/budget.py — IterationBudgetMiddleware
  • src/langstage_hermes/tools/ — registry + 33 toolsets + 6 terminal envs
  • src/langstage_hermes/cron/ — daemon + cronjob tool
  • src/langstage_hermes/plugins/ — discovery + lifecycle hooks
  • src/langstage_hermes/cli.py — langstage-hermes entry point
  • prompts/ — verbatim/paraphrased system-prompt building blocks

Status by subsystem

Subsystem Status
Config + state + agent factory ✅ working
Reflection loop (10-iter / 10-turn triggers, subagent review) ✅ working — verified live
Skill library + agentskills.io validator ✅ working
Skill loader (system-prompt injection + progressive disclosure) ✅ working
skill_view / skill_manage / skills_list tools ✅ working
Frozen-snapshot memory (MEMORY.md / USER.md) ✅ working — verified live (702 bytes written autonomously); also a keyless langstage-hermes memory show CLI (--user / --session / --json)
SQLite FTS5 store + session_search (3 modes) ✅ working — also a keyless langstage-hermes search CLI (DISCOVERY / SCROLL / BROWSE, --json)
MarkdownProvider (bundled, opt-in via memory.provider="markdown"; the default is no-op) ✅ keyword search over <HERMES_HOME>/memories/notes/*.md — zero deps; also a keyless langstage-hermes memory notes CLI (--json)
Iteration budget middleware ✅ working
Compression middleware (13-section template) ✅ working
Anthropic system_and_3 caching strategy ✅ working
Tool registry + 33-toolset enum ✅ working
LocalEnvironment terminal backend ✅ working (Git Bash on Windows)
DockerEnvironment ✅ working (gated on docker info reachability)
SshEnvironment ✅ working (paramiko-backed, behind [ssh] extra)
SingularityEnvironment ✅ working (auto-detects singularity / apptainer)
DaytonaEnvironment / ModalEnvironment ✅ lazy SDK with defensive attribute probing (extras-gated)
Cron daemon + cronjob tool ✅ working (deliverers: local, stdout, agentmail)
Plugin loader (4 discovery sources) ✅ working (13 of 17 lifecycle hooks wired)
CLI + v1-essentials slash commands ✅ working
Curator (skill lifecycle) ✅ basic
Bundled skills ✅ 26 from nousresearch/hermes-agent (MIT, attributed)
Self-evolution integration 📄 docs only (separate offline repo)

License

MIT. See LICENSE. This project is a faithful reproduction of the design ideas in Nous Research's Hermes Agent — see NOTICE for attribution.

Release files for langstage-hermes 0.4.34

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for langstage-hermes 0.4.34
File Size Uploaded
langstage_hermes-0.4.34.tar.gz 1.5 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for langstage-hermes 0.4.34
File Interpreter ABI Platform
langstage_hermes-0.4.34-py3-none-any.whl Python 3 none any Details

Total release size: 2.9 MB

Release files / langstage_hermes-0.4.34.tar.gz

Download URL langstage_hermes-0.4.34.tar.gz
Size 1.5 MB
Tags Source
SHA-256 checksum
How to use checksums
dea11fd45d76093dca4b4b117c3327830b3068674fd892a99457533ae5de2144
BLAKE2b-256 checksum
How to use checksums
aa4646a67acdb31d28eb36b9889f0d4365ff8244776818a7b40b6c99235bdbe3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / langstage_hermes-0.4.34-py3-none-any.whl

Download URL langstage_hermes-0.4.34-py3-none-any.whl
Size 1.4 MB
Tags Python 3
SHA-256 checksum
How to use checksums
6bf14412a2a99498747ab3383c2f95c48386bece630b63dd06e00de44999b5fa
BLAKE2b-256 checksum
How to use checksums
e0b57578e6acdca32b1d8413d6eb97a9e1006fbe0c60a819f67fb605704fb42e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.4.34 This release

2 release files

0.4.33

2 release files

0.4.32

2 release files

0.4.31

2 release files

0.4.30

2 release files

0.4.26

2 release files

0.4.25

2 release files

0.4.24

2 release files

0.4.23

2 release files

0.4.22

2 release files

0.4.21

2 release files

0.4.19

2 release files

0.4.18

2 release files

0.4.17

2 release files

0.4.16

2 release files

0.4.15

2 release files

0.4.14

2 release files

0.4.12

2 release files

0.4.11

2 release files

0.4.9

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.12

2 release files

0.3.11

2 release files

0.3.10

2 release files

0.3.9

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page