
Hermes Agent の self-improving をコードから読み込んでみた
こんにちは、クラスメソッド製造ビジネステクノロジー部の森茂です。
Hermes Agent の掲げる self-improving agent という言葉、気になっている方も多いのではないでしょうか。
ただ「モデルが勝手に再学習されるのか」「知らないうちに挙動が変わるのか」と、少し身構えてしまいます。自分も最初はそこが気になりました。
今回の記事では、NemoHermes の構成を題材に、Hermes Agent で何が育つのかをコードと設定から整理します。結論から言うと、主に育つのはモデル重みではなく、業務手順や出力形式を再利用するための skill です。
なお、この「使うほど skill が育つ」性質を、本家の Nous Research は self-improving、NVIDIA は NemoClaw / OpenShell の文脈で self-evolving と呼んでいます。指すものは同じなので、本記事では本家に合わせて self-improving を主に使い、NVIDIA の見せ方を扱うところだけ self-evolving と書きます。
ちょうど執筆中に Hermes Agent の 0.16.0(v2026.6.5)がリリースされました。この skill まわりに「増えた skill をどう畳むか」「育つ skill をどこまで信頼するか」「どこまで自走させるか」という更新が入っていたので、せっかくなので 0.16.0 のコードも合わせて読んでいきます。
この記事で見るもの
この記事では、NVIDIA / Nous Research 周辺で公開されている Hermes Agent、NemoClaw、OpenShell のリポジトリを読みます。NemoClaw の全体像は NVIDIA の NemoClaw Architecture Reference でも説明されています。
手元では以下の commit を確認しました。基本構造は 0.15.1 で読み、2026-06-05 にリリースされた 0.16.0(v2026.6.5)で加わった部分は 0.16.0 のコードで確認しています。
| repo | 確認した参照 | この記事で見る役割 |
|---|---|---|
| hermes-agent | 40420a6(0.15.1) |
skill、memory、session search の基本構造 |
| hermes-agent | v2026.6.5 / d6b9cfa(0.16.0) |
0.16.0 で加わった skill 整理・信頼・自律性の層 |
| NemoClaw | 17734b1 |
Hermes を OpenShell 上で動かす blueprint と CLI 層 |
| OpenShell | b41e0df |
sandbox と policy を担う Runtime 層 |
おもしろいのは、skill を作る・直す・消すという中核ツール(tools/skill_manager_tool.py)の説明そのものは 0.15.1 から変わっていない点です。0.16.0 で手が入ったのは、その中核を取り巻く運用側でした。育てる仕組みは据え置きで、御す仕組みが増えた、という読み方ができます。
NVIDIA 公式動画での self-evolving の見せ方
この self-evolving という言葉は、NVIDIA Developer の動画でもかなり具体的に説明されています。
短尺デモ「How We Built Self-Evolving Hermes Agents With NVIDIA NemoClaw」では、Hermes を NVIDIA OpenShell sandbox の中で動かし、Slack、Outlook、GitHub と接続する構成が紹介されています。デモの中心は、GitHub issue digest の出力形式を会話で教えると、Hermes がその形式を reusable skill として保存し、別のチャネルから依頼されたときにも同じ形式で返せる、という流れです。
長尺の Nemotron Labs 配信「Self-Evolving Hermes Agents: Enterprise AI That Gets Better With Use」では、skill creation、session search、memory、OpenShell による policy-gated sandboxing、token masking、skill bloat 対策、enterprise deployment の論点まで扱われていました。
NemoHermes を三層に分けて見る
まず、NemoHermes を Model、Harness、Runtime の三層に分けると読みやすくなります。
Nemotron や vLLM は、推論と生成を担う Model 層です。Hermes Agent は、tool を呼び出したり、skill、memory、session search を使ったりする Harness 層として見えます。OpenShell は、その agent をどのファイルやネットワークへ出してよいかを制御する Runtime 層、という位置づけですね。
NemoClaw 側の nemohermes コマンドも、この三層で見ると位置づけが分かりやすいです。実装を見ると、nemohermes は NemoClaw に Hermes agent を選ばせる薄い入口として定義されています。
出典: NemoClaw/bin/nemohermes.js L6-L9
// NemoHermes — alias for NemoClaw with the Hermes agent pre-selected.
process.env.NEMOCLAW_AGENT = 'hermes';
process.env.NEMOCLAW_INVOKED_AS = 'nemohermes';
module.exports = require('../dist/nemoclaw');
つまり、NemoHermes は別個の巨大な agent 実装というより、NemoClaw の上で Hermes Agent を選択した構成として読むのが自然そうです。NemoClaw のドキュメント側でも、nemohermes は Hermes agent を事前選択した nemoclaw の alias と説明されています。
Hermes で育つ中心は skill である
ここからが本題です。
Hermes Agent 側で self-improving の中心に見えるのは skill です。skill_manager_tool.py の冒頭コメントには、skill の役割がかなりはっきり書かれています。
出典: hermes-agent/tools/skill_manager_tool.py L5-L12
Allows the agent to create, update, and delete skills, turning successful
approaches into reusable procedural knowledge.
同じファイルでは、skill を agent の procedural memory と呼び、一般的な memory とは分けています。
Skills are the agent's procedural memory: they capture *how to do a specific
type of task* based on proven experience. General memory (MEMORY.md, USER.md) is
broad and declarative. Skills are narrow and actionable.
このコメントを読むと、self-improving で育つものが少し具体的になります。モデル重みがその場で更新されるというより、成功した作業手順が再利用できる形で残る、という読み方ですね。
Hermes の user skill は、~/.hermes/skills/ 以下に SKILL.md と関連ファイルを持つ構造として扱われます。
出典: hermes-agent/tools/skill_manager_tool.py L22-L32
~/.hermes/skills/
├── my-skill/
│ ├── SKILL.md
│ ├── references/
│ ├── templates/
│ ├── scripts/
│ └── assets/
これは単なるチャット履歴とは違います。SKILL.md と supporting files として残るので、人間が読んだり、修正したり、別の環境へ持っていったりできます。
たとえば、毎朝の issue digest に決まった観点や出力形式があるなら、毎回長いプロンプトで説明するのではなく、skill として残せます。ざっくり書くと、次のようなイメージです。
---
name: daily-issue-digest
description: Produce a daily issue digest in the agreed format.
metadata:
hermes:
tags: [digest, github]
---
もちろん、実際の skill には手順、注意点、検証方法、必要ならテンプレートや補助スクリプトも入ります。プロンプト職人芸を、その場限りの会話ではなく、小さなソフトウェア資産へ寄せる仕組みと見ると理解しやすいかなと思っています。
0.16.0 で skill は「増やす」より「選んで畳む」へ
前の章を読むと、skill はどんどん増やせます。便利な反面、増え続けた skill は「どれをいつ使うのか分かりにくい」という別の問題を生みます。0.16.0 は、ここに手を入れてきました。
まず、skill を実行環境で出し分ける仕組みが入りました。skill の frontmatter に environments: を書くと、その環境のときだけ skill 一覧に出る、という挙動になります。
出典: hermes-agent/agent/skill_utils.py L234-L253
"""Return True when the skill is relevant to the current runtime environment.
Skills may declare an ``environments`` list in their YAML frontmatter::
environments: [kanban] # only relevant when kanban is active
environments: [s6] # only relevant inside the s6 Docker image
environments: [docker] # only relevant inside any container
If the field is absent or empty the skill is relevant in **all**
environments (backward-compatible default).
This is an OFFER-time filter: it controls whether a skill shows up in the
skills index / autocomplete / slash-command list.
"""
ここで丁寧だなと思ったのが、これが「見せるかどうか」だけのフィルタである点です。コメントにも、skill_view や --skills での明示ロードには効かせない、と書かれています。明示的に読み込むのは明示的な同意だから、フィルタで隠れていても force-load は通す、という設計ですね。環境に関係ない skill を一覧から減らしつつ、必要なら必ず呼べる、という線引きです。
次に、使われない skill を畳む curator が入りました。一定期間使われていない skill を archive していく仕組みで、ポイントは built-in(同梱 skill)も対象にできることです。
出典: hermes-agent/agent/curator.py L187-L195
"""Whether the curator may prune (archive) bundled built-in skills too.
ON by default. When on, built-ins become curation candidates and are
archived after the same inactivity period as agent-created skills, with a
suppression list keeping them archived across `hermes update` re-seeds.
Hub-installed skills are never pruned regardless of this flag.
"""
同梱 skill も既定で剪定対象、というのは思い切った設計に見えます。hermes update で再配置されても抑制リストで畳んだ状態を保つ、と書かれているので、一度畳んだものが勝手に復活しない配慮もありますね。一方で、自分で入れた hub-installed の skill は剪定対象外なので、入れたものは消えないという安心感もあります。
そして、既定の skill セットは軽くして、欲しいものは後から足す方向にも変わりました。optional な skill は hermes skills install で取りに行きます。
出典: hermes-agent/hermes_cli/skills_hub.py L459-L470
def do_install(identifier: str, category: str = "", force: bool = False,
console: Optional[Console] = None, skip_confirm: bool = False,
invalidate_cache: bool = True,
name_override: str = "") -> None:
"""Fetch, quarantine, scan, confirm, and install a skill.
...
"""
install の流れが fetch して quarantine して scan して confirm、という順番なのが分かります。取ってきた skill をいきなり置くのではなく、隔離してスキャンしてから入れる、というステップが踏まれていますね。skill が「育つ・もらってくる」前提だからこそ、入口の作法がきちんと用意されている印象です。
育つ skill をどこまで信頼するか
skill が会話から育ち、hub からも入ってくるとなると、次に気になるのは「その skill 自体を信じてよいのか」です。0.16.0 は、skill のソースと中身の両方に線を引いていました。
まずソース側です。skill を取りに行く先(tap)の既定リストに、openai/skills、anthropics/skills、huggingface/skills と並んで NVIDIA/skills が入っています。
出典: hermes-agent/tools/skills_hub.py L395-L413
DEFAULT_TAPS = [
{"repo": "openai/skills", "path": "skills/.curated/"},
{"repo": "openai/skills", "path": "skills/.system/"},
{"repo": "anthropics/skills", "path": "skills/"},
{"repo": "huggingface/skills", "path": "skills/"},
# NVIDIA/skills: NVIDIA-verified skills for CUDA-X, AIQ, cuOpt,
# cuPyNumeric, DeepStream, NeMo, NemoClaw, etc. Each skill ships
# alongside a signed `skill.oms.sig`, an OMS-signed `skill-card.md`
# (governance card), and an `evals/` directory — synced daily from
# the NVIDIA product repos. Treated as `trusted`.
{"repo": "NVIDIA/skills", "path": "skills/"},
{"repo": "garrytan/gstack", "path": ""},
]
NVIDIA の skill は署名(skill.oms.sig)とガバナンスカード(skill-card.md)、評価用の evals/ まで添えて配られ、毎日 NVIDIA 製品リポジトリから同期される、と書かれています。
そのうえで、ソースの信頼度に応じてインストール時の挙動が変わります。
出典: hermes-agent/tools/skills_guard.py L40-L61
TRUSTED_REPOS = {
"openai/skills",
"anthropics/skills",
"huggingface/skills",
"NVIDIA/skills",
}
INSTALL_POLICY = {
# safe caution dangerous
"builtin": ("allow", "allow", "allow"),
"trusted": ("allow", "allow", "block"),
"community": ("allow", "block", "block"),
# ...
}
trusted(上の 4 リポジトリ)なら caution まで許して dangerous は止める、community はそれ以外で safe しか通さない、という三段階です。skill を「どこから来たか」で機械的に扱いを変えているわけですね。
中身側にも手が入っています。skill のコンテンツをスキャンするとき、不可視 Unicode を injection の兆候として検出します。
出典: hermes-agent/tools/skills_guard.py L537-L555
INVISIBLE_CHARS = {
'\u200b', # zero-width space
'\u200c', # zero-width non-joiner
'\u200d', # zero-width joiner
'\u2060', # word joiner
# ...
'\u202e', # right-to-left override
# ...
'\u2069', # pop directional isolate
}
zero-width space や双方向制御文字(bidi override)など、目に見えない文字が skill に紛れていると high severity の injection として拾う作りです。見えない指示を skill に仕込む、という攻撃を想定しているわけですね。育つ skill が便利になるほど、こういう中身の検査が効いてきます。
memory と session search は役割が違う
ここで気になるのが、skill と memory の違いです。Hermes Agent には memory と session search もありますが、コード上ではそれぞれ役割が分かれています。
| 仕組み | 役割 | 置くもの |
|---|---|---|
| skill | 再利用する手順 | 出力形式、調査手順、検証チェック |
| memory | 毎回思い出す安定知識 | 好み、環境事実、長く使う前提 |
| session search | 過去作業の検索 | 会話ログ、判断経緯、再開の手がかり |
memory_tool.py を見ると、memory は MEMORY.md と USER.md の二つの store として説明されています。
出典: hermes-agent/tools/memory_tool.py L5-L14
Provides bounded, file-backed memory that persists across sessions. Two stores:
- MEMORY.md: agent's personal notes and observations (environment facts, project
conventions, tool quirks, things learned)
- USER.md: what the agent knows about the user (preferences, communication style,
expectations, workflow habits)
さらに、両方ともセッション開始時に system prompt へ frozen snapshot として注入される、と書かれています。
Both are injected into the system prompt as a frozen snapshot at session start.
Mid-session writes update files on disk immediately (durable) but do NOT change
the system prompt -- this preserves the prefix cache for the entire session.
つまり、memory は「何でも覚える場所」ではなく、次のセッション以降も安定して効く前提や好みを小さく残す場所として読めます。
一方で、session search は過去ログ検索の層です。session_search_tool.py の冒頭には、SQLite session DB と FTS5 index を使い、LLM call なしで実メッセージを返す、と書かれています。
出典: hermes-agent/tools/session_search_tool.py L21-L23
All three modes operate on the SQLite session DB via the FTS5 index and
the get_anchored_view / get_messages_around primitives in hermes_state.
No LLM calls anywhere — every shape returns actual messages from the DB.
ここが面白いですね。過去の会話を何でも memory として prompt に常時入れるのではなく、必要になったときに DB から検索する設計です。
個人的には、この分担がかなり大事だと感じました。手順は skill、安定知識は memory、過去の経緯は session search。全部を一つの「記憶」に詰め込まないことで、育つ場所と検索する場所が分かれています。
session search に頼るなら、貯まり続けるログの整理も要ります。0.16.0 で入った hermes sessions optimize を実行すると、FTS5 のセグメントをまとめてから VACUUM する、という maintenance です。
出典: hermes-agent/hermes_state.py L4037-L4049
"""Merge fragmented FTS5 b-tree segments into one per index.
FTS5 indexes grow as a series of incremental segments — one per
``INSERT`` batch driven by the message triggers. Over tens of
thousands of messages these segments accumulate, which both bloats
the ``*_data`` shadow tables and slows ``MATCH`` queries that must
scan every segment. The special ``'optimize'`` command rewrites each
index as a single merged segment.
"""
検索結果は変わらず、ディスク上のレイアウトと検索速度だけを直す maintenance だと書かれています。古い session を一定期間で自動剪定する auto_prune も併せて入っているので、「session を貯めて検索する」前提の裏側に、貯まったものを畳む仕組みがちゃんと用意されてきた印象です。
自走もできるが、既定は控えめ
ここまでは「何を覚えるか」の話でした。0.16.0 を読むと、self-improving のもう一つの面、「どう仕事を任せるか」にも更新が入っています。ただ、踏み込むのは明示的な opt-in で、既定はかなり控えめでした。
まず、agent が子 agent に仕事を委任する delegation です。子 agent は既定では leaf で、それ以上は分岐できません。orchestrator の role を与えたときだけ、その子がさらに孫 worker を spawn できます。
出典: hermes-agent/tools/delegate_tool.py L1955-L1958
The 'role' parameter controls whether a child can further delegate:
'leaf' (default) cannot; 'orchestrator' retains the delegation
toolset and can spawn its own workers, bounded by
delegation.max_spawn_depth.
深さは max_spawn_depth で縛られていて、コメントには「下限 1・上限なし、ただし既定は flat(深さ 1)」とあります。
出典: hermes-agent/tools/delegate_tool.py L137-L139
# No upper ceiling on spawn depth — like max_concurrent_children, depth has a
# floor of 1 and no ceiling. Deeper trees multiply API cost, so the default
# stays flat (MAX_DEPTH = 1); raising the config knob is an explicit opt-in.
深いツリーは API コストを掛け算で増やすから既定は浅い、深くするのは明示的に、という方針ですね。自走させられるけれど、暴走しないように既定は保守的、というバランスが個人的には好みです。
次に、tool が増えたときの progressive tool disclosure です。MCP や plugin の tool を全部 system prompt に並べるのではなく、必要なときに開示します。
出典: hermes-agent/tools/tool_search.py L1-L14
"""Progressive tool disclosure ("tool search") for Hermes Agent.
When enabled, MCP and non-core plugin tools are replaced in the model-visible
tools array by three bridge tools — ``tool_search``, ``tool_describe``,
``tool_call`` — and surfaced on demand. Core Hermes tools never defer.
...
* The threshold gate runs every assembly: when deferrable tools would consume
less than ``threshold_pct`` of the model's context window (default 10%),
tool search is a no-op and the tools array passes through unchanged.
"""
ここでも core tool は必ず出す、開示に切り替えるのは tool が context の 1 割を超えそうなときだけ、と最小限にとどめています。
最後に kanban の goal_mode です。カードを goal_mode にすると、worker が「目標が満たされたか」を判定しながら回り続けます。
出典: hermes-agent/hermes_cli/goals.py L1-L8
"""Persistent session goals — the Ralph loop for Hermes.
A goal is a free-form user objective that stays active across turns. After
each turn completes, a small judge call asks an auxiliary model "is this
goal satisfied by the assistant's last response?". If not, Hermes feeds a
continuation prompt back into the same session and keeps working until the
goal is done, turn budget is exhausted, the user pauses/clears it, or the
user sends a new message (which takes priority and pauses the goal loop).
"""
いわゆる Ralph loop ですね。終了条件が「目標達成・ターン上限・ユーザーが止める・新しいメッセージが来る」と明示されていて、無限に走り続けない歯止めが効いています。NemoHermes のデモで kanban に起票して profile が分担する、という流れも、この延長で読めます。
このあたりまで来ると、self-improving は skill が育つだけでなく、仕事の任せ方や走らせ方も育てられる段階に入っていると感じます。ただ、どれも既定は flat・控えめで、踏み込むのは設定で明示的に、という共通の慎重さがありました。
NemoClaw と OpenShell は育つ agent の境界を守る
Hermes Agent のような仕組みは、使えば使うほど便利になります。一方で、企業利用で考えると、便利な agent をそのまま無制限に外へ出すのは怖いですよね。
そこで Runtime 層として出てくるのが NemoClaw と OpenShell です。
NemoClaw の Hermes config を見ると、API server に公開する toolset として skills、memory、session_search などが含まれています。
出典: NemoClaw/agents/hermes/config/hermes-config.ts L11-L27
const API_SERVER_TOOLSETS = [
'web',
'browser',
'terminal',
'file',
'code_execution',
'vision',
'image_gen',
'skills',
'todo',
'memory',
'session_search',
'delegation',
'cronjob',
'nemoclaw',
'audio',
];
つまり、OpenShell 上で動く Hermes でも、Hermes らしい skill、memory、session search を使う前提になっています。
ただし、外部アクセスは policy で縛られます。NemoClaw の sandbox policy schema には、filesystem、process、network egress rules を定義する schema だと説明があります。
出典: NemoClaw/schemas/sandbox-policy.schema.json L4-L5
{
"title": "NemoClaw Sandbox Policy",
"description": "Schema for the base sandbox policy (openclaw-sandbox.yaml) — defines filesystem, process, and network egress rules."
}
さらに network policy では、どの endpoint に、どの binary が出られるかを定義する形になっています。REST や WebSocket の場合は、path 単位の rule も持てます。method と path の rule は、同 schema の L104-L130 で定義されています。
Hermes 向けの policy 追加分を見ると、managed inference は inference.local に対して OpenAI compatible な path だけを許可しています。
出典: NemoClaw/agents/hermes/policy-additions.yaml L44-L61
network_policies:
managed_inference:
name: managed_inference
endpoints:
- host: inference.local
port: 443
protocol: rest
enforcement: enforce
rules:
- allow: { method: POST, path: '/v1/chat/completions' }
- allow: { method: POST, path: '/v1/completions' }
- allow: { method: POST, path: '/v1/embeddings' }
- allow: { method: GET, path: '/v1/models' }
- allow: { method: GET, path: '/v1/models/**' }
binaries:
- { path: /usr/local/bin/hermes }
- { path: /usr/bin/python3.11 }
- { path: /opt/hermes/.venv/bin/python }
これは「プロンプトで外に出ないようお願いする」のではなく、runtime policy として出られる先を決める考え方です。self-improving agent が業務手順を覚えて自走するほど、この runtime 境界が意味を持ってきます。OpenShell そのものの設計思想は、NVIDIA Developer Blog でも詳しく説明されています。
何を skill にして、何を残さないかは人が決める
ここまでで、育てる仕組みと御す仕組みのコードをひととおり見てきました。増えた skill は environments フィルタと curator で畳み、session ログは hermes sessions optimize で整理する、と運用の手間はだいぶツール側に降りてきました。
ただ、何を skill に昇格させ、何を memory に残し、何を project context や wiki に置くかという仕分けそのものは、引き続き人間側の仕事です。このあたりは、DevOps の世界で手順書、runbook、issue、監査ログを分ける感覚に近いですね。agent が育つというより、人間が承認した良い手順を、agent が再利用できる形へ整理していく、という表現のほうがしっくりきました。
まとめ
Hermes Agent の self-improving をコードから読むと、モデルが勝手に再学習するというより、業務手順を再利用可能な資産として残す仕組みに見えました。
skill は、成功した作業手順や出力形式を SKILL.md と supporting files として残す層です。memory は、次回以降も安定して効く好みや環境情報を frozen snapshot として注入する層です。session search は、必要なときに過去の会話や判断経緯を SQLite / FTS から検索する層、という分担ですね。
0.16.0 を合わせて読むと、その印象はさらに強まりました。skill を作る中核は据え置きで、周りに「増えた skill を選んで畳む」「どこから来た skill かで信頼を変える」「仕事の任せ方を制御する」という御す仕組みが増えています。育てる機能と同じくらい、育ったものを整理して安全に使う機能に手が入っているわけですね。
そして NemoClaw と OpenShell は、そうした育つ agent を sandbox と policy の境界に入れる Runtime 層として読めます。
self-evolving という言葉は少し派手ですが、本家 Nous が self-improving と呼ぶとおり、コードを読むと実体はかなり地に足のついた仕組みでした。人が教えた良い手順を skill として残し、memory や session search と組み合わせて次回以降に使う。そして、その agent を OpenShell の policy 境界の中で動かす。個人的には、この方向性が企業で agent を育てるうえで一番現実的かなと思っています。
参考リンク
- Hermes Agent(NousResearch/hermes-agent)— GitHub リポジトリ
- Hermes Agent v2026.6.5(0.16.0)リリースノート
- Hermes Agent 公式ドキュメント
- 動画「How We Built Self-Evolving Hermes Agents With NVIDIA NemoClaw」(NVIDIA Developer)
- 動画「Self-Evolving Hermes Agents: Enterprise AI That Gets Better With Use」(Nemotron Labs)
- NemoClaw(NVIDIA/NemoClaw)— GitHub リポジトリ
- NemoClaw Architecture Reference(NVIDIA 公式ドキュメント)
- OpenShell(NVIDIA/OpenShell)— GitHub リポジトリ
- NVIDIA Developer Blog「Run Autonomous, Self-Evolving Agents More Safely with NVIDIA OpenShell」




