Hermes Agent 入門 — 初心者のためのハンズオンガイド|2026-09 版
第 5 章

永続メモリ — 使うほど賢くなる仕組み

何がどこに記憶され、どう注入されるか。書き込み承認とバックグラウンド自己改善まで

この章で分かること

これは何か

「エージェントが勝手に自分について記録を溜めていく」と聞くと気持ち悪さを感じる人は少なくない。だが Hermes の記憶は、何がどこに書かれるかが明確に決まった仕組みであり、中身はいつでも生のテキストファイルとして確認・編集・削除できる。ブラックボックスの学習ではなく、覗ける記憶だと捉えるのがこの章の出発点になる。

Hermes における「記憶」は、性質の異なる 2 つの仕組みの総称である。

どちらも、エージェントが持つ組み込みの memory ツール・session_search ツール経由で読み書きされる。~/.hermes/ 配下の全体像や、エージェントの人格を定義する SOUL.md・プロジェクト規約を渡す AGENTS.md / .hermes.md との関係は 第 2 章 で扱った「どのファイルが何をするか」表が正なので、本章では永続メモリと session_search の中身に絞る。加えて、組み込みストアと並行して動く 8 種類の外部メモリプロバイダプラグインについても後半で概観する。

いつ使うのか

典型的な使いどころは次の 4 つである。

この 4 つは似ているようで役割が違う。迷ったら次の基準で選ぶ。

目的選ぶ仕組み
環境・プロジェクトの前提を毎回説明したくない永続メモリ(MEMORY.md)
呼び方・好み・関心を覚えていてほしい永続メモリ(USER.md)
前に話した具体的なやり取りを掘り起こしたいセッション検索(session_search)
定型の作業手順そのものを再利用したいスキル(第 6 章)

永続メモリは「常に system prompt に乗っている短い事実」、session_search は「必要なときだけ引き出す膨大な生ログ」、スキルは「手続き(やり方)そのもの」と覚えておくと、あとで挙動の違いに戸惑わずに済む。それぞれの容量・速度・コストの違いは次節で具体的な数値とともに扱う。

記憶の置き場所と system prompt への注ぎ込み方

MEMORY.md と USER.md はどちらも ~/.hermes/memories/ に置かれた普通のテキストファイルで、内容はエージェントが memory ツール経由で書く。文字数には上限があり、この上限は「常に system prompt に乗り続けるコスト」を抑えるための設計である。

ファイル用途文字数上限
MEMORY.mdエージェントの個人メモ(環境の事実・プロジェクトの規約・ツールの癖・学習内容)2,200 文字(約 800 トークン)
USER.mdユーザープロフィール(好み・コミュニケーションスタイル)1,375 文字(約 500 トークン)

上限に達すると、memory ツールはエラーを返すだけで、古いメモを自動で間引いてはくれない。同じターンの中で replace(統合)や remove(削除)を行ってから書き直す必要がある。「書けなくなったら自動で忘れてくれる」ような親切設計ではない点は覚えておく価値がある。

system prompt への注入形式は次のとおりで、残り容量のパーセンテージと文字数も一緒に表示される。

══════════════════════════════════════════════
MEMORY (your personal notes) [67% — 1,474/2,200 chars]
══════════════════════════════════════════════
User's project is a Rust web service at ~/code/myapi using Axum + SQLx
§
This machine runs Ubuntu 22.04, has Docker and Podman installed

ここで重要なのが「凍結スナップショット」パターンである。system prompt への注入はセッション開始時に 1 回だけキャプチャされ、そのセッションが続いている間は変化しない。これはプロンプトキャッシュの先頭部分(プレフィックス)を壊さないための意図的な設計であり、バグではない。会話の途中でエージェントが MEMORY.md に書き込んでも、その内容はディスクには即座に保存されるが、system prompt に反映されるのは次のセッションからになる。

起動時に読み込み MEMORY.md (エージェントのメモ) USER.md (ユーザーの好み) セッション開始時に注入 (system prompt) system prompt (セッション中は凍結) (保存は即時、反映は次回セッションから)
図 5-1 MEMORY.md / USER.md はセッション開始時に一度だけ system prompt へ注入され、会話中の書き込み(点線)は次回セッションまで棚上げされる。

書き込みのタイミングと安全装置

memory ツールが受け付けるアクションは add / replace(old_text の部分文字列マッチで対象を特定して置き換える)/ remove(同様のマッチで削除)の 3 つで、read アクションは存在しない。system prompt への自動注入だけで十分だからである。

書き込みには 2 つの経路がある。ひとつは会話の最中にエージェントが判断して memory ツールを呼ぶ経路(同期・即時)。もうひとつは、ターン終了後にバックグラウンドで会話をレビューし、メモリ更新やスキル改訂を提案する「自己改善ループ」の経路(非同期)である。バックグラウンドレビューは既定ではメインモデルで実行される(プロンプトキャッシュを再利用できるため安価)が、auxiliary.background_review.model で別の安価なモデルを指定すれば、ベンチマーク上おおよそ 3〜5 倍安く回せる。auxiliary.background_review.enabled: false にすれば、この自己改善ループ自体を完全に止められる。

送信 完了 即時保存 非同期で起動 提案・書き込み ユーザー発言 エージェントの応答 (この中でmemoryツールを呼べる) ターン終了 バックグラウンドレビュー (非同期・別モデル可) ディスクへ書き込み (承認制なら保留)
図 5-2 書き込みは会話中の同期呼び出しとターン終了後の非同期レビューの 2 経路がある。どちらも書き込み先は同じで、write_approval が有効なら保留される。

安全装置は主に 2 つある。ひとつは重複防止で、完全一致の重複エントリは自動的に拒否される。もうひとつはセキュリティスキャンで、メモリエントリはプロンプトインジェクション・クレデンシャル流出・SSH バックドアといったインジェクション/情報流出パターンと、目に見えない Unicode 文字をスキャンされ、該当すればブロックされる。「エージェントが読んだ外部コンテンツに紛れ込んだ指示を、そのまま自分のメモリに書き込んでしまう」という攻撃経路を塞ぐための仕組みである。

そのうえで、書き込みそのものを人間の承認制にできるのが write_approval である。設定は ~/.hermes/config.yaml の memory セクションにある。

memory:
  memory_enabled: true
  user_profile_enabled: true
  memory_char_limit: 2200
  user_char_limit: 1375
  write_approval: false     # true にすると承認必須

memory_enabled と user_profile_enabled を両方 false にすると、組み込みメモリストアは完全に停止する(memory ツール自体がツールスキーマから消える)。

write_approval を true にすると、書き込みが起きる文脈によって承認方法が変わる。対話 CLI で会話している最中なら、その場で承認プロンプトが表示される。それ以外——メッセージングプラットフォーム経由、スクリプトからの実行、そしてバックグラウンドの自己改善ループ——では、その場で聞くわけにいかないので /memory pending にステージングされる。

/memory pending          # 承認待ちの書き込み一覧
/memory approve <id>    # 指定した書き込みを承認
/memory reject <id>     # 指定した書き込みを却下
/memory approval on|off  # 承認制のオン・オフ

永続メモリが「常に system prompt に乗っている要約」だとすれば、session_search は「聞かれたときだけ掘り出す生ログ」である。すべての CLI・メッセージングセッションは ~/.hermes/state.db という SQLite に、FTS5(SQLite の全文検索拡張)付きで保存される。検索は LLM による要約を挟まず、切り詰めもせずに、実際のメッセージをそのまま返す。

特性永続メモリ(Persistent Memory)セッション検索(Session Search)
容量約 1,300 トークン合計無制限(全セッション)
速度即時(system prompt 内)約 20ms(FTS5 クエリ)、約 1ms スクロール
コスト毎プロンプトでトークン消費無料(LLM 呼び出しなし)
用途常に文脈にあるべき重要事実過去の特定の会話を思い出す
検索クエリ そのまま返す 全セッションの履歴 (state.db) FTS5全文検索 (約20ms) 実際のメッセージ (要約なし・そのまま)
図 5-3 session_search は要約というフィルタを挟まない。過去に言った言葉がほぼそのまま検索結果として出てくる。

この「要約なしでそのまま返す」という設計は、記憶の中身を人間が検証しやすくする効果もある。エージェントの言い分を鵜呑みにせず、実際に何を話したかを生のテキストで確認できるからである。

記憶とスキルの獲得タイムラインを可視化するコマンドが hermes journey(別名 hermes learning、hermes memory-graph)である。--play でアニメーション再生、--json で生データをダンプできる。個々のノードは hermes journey list で一覧、hermes journey edit <node> で手動編集、hermes journey delete <node> で削除できる(スキルのノードはアーカイブされ復元可能、メモリチャンクは削除されると戻らない)。

外部メモリプロバイダとの関係

組み込みの MEMORY.md / USER.md に加えて、Hermes には 8 種類の外部メモリプロバイダプラグインが用意されている(plugins/memory/ 配下の honcho / hindsight / openviking / byterover / holographic / mem0 / retaindb / supermemory)。これらは組み込みストアを置き換えるものではなく、並行して動く追加の記憶バックエンドという位置づけである。README では特に Honcho の「dialectic user modeling(対話的なユーザーモデリング)」に言及がある。

hermes memory setup      # プロバイダ選択と設定
hermes memory status     # 現在のアクティブプロバイダ確認

同時にアクティブにできる外部プロバイダは 1 つだけである。まずは組み込みの MEMORY.md / USER.md で十分か試し、より高度なユーザーモデリングや長期記憶の検索性が必要になった時点で外部プロバイダの導入を検討するのが順当だろう。個々のプロバイダの詳細設定は本書の範囲外なので、公式ドキュメントを参照してほしい。

ハンズオン 5-1 自分の好みを覚えさせて、別セッションで確認する

  1. hermes で対話セッションを開始し、覚えておいてほしい好みを日本語で明示的に伝える(例:「コードコメントは日本語で書いてほしい。これは覚えておいて」)。
  2. セッションを終える前に、別のターミナルで USER.md の中身を確認する。
cat ~/.hermes/memories/USER.md

エージェントが memory ツール経由で書き込んでいれば、伝えた好みに関する短い一文が追記されているはずだ。追記されていなければ、まだ書き込まれていないだけなので、より明示的に「これは覚えておいて」と頼み直すとよい。

  1. exit で一度セッションを終え、hermes で新しいセッションを開始する。「私はコードコメントについて何を伝えましたか」のように尋ねる。

system prompt にはセッション開始時点の USER.md がそのまま注入されているため、前回伝えた好みを踏まえた答えになる。もし変わらなければ、手順 2 の cat でファイルの中身を直接見て、そもそも書き込みが起きていたかどうかを切り分けるとよい。エージェントの返答だけを信じず、ファイルという一次情報で確認できるのがこの仕組みの利点である。

ハンズオン 5-2 メモリの中身をファイルで見る・編集する

  1. MEMORY.md と USER.md の原文をそのまま確認する。
cat ~/.hermes/memories/MEMORY.md
cat ~/.hermes/memories/USER.md
  1. 記憶とスキルの獲得タイムラインを一覧する。
hermes journey list

ノード(メモリのチャンクやスキル)が時系列で並んで表示される。

  1. 修正したいノードがあれば手動編集、消したいメモリチャンクがあれば削除する。
hermes journey edit <node>
hermes journey delete <node>

スキルのノードを削除してもアーカイブされ復元できるが、メモリチャンクの削除は取り消せない点に注意する。全体をアニメーションで振り返りたいときは hermes journey --play、生データを扱いたいときは hermes journey --json を使う。

ハンズオン 5-3 write_approval を有効にして書き込みに承認を挟む

  1. 対話セッション中に承認制をオンにする。
/memory approval on
  1. エージェントに何か覚えてほしい情報を伝え、memory ツールが呼ばれる状況を作る(例:「今後は〜と覚えておいて」)。

対話 CLI で会話している最中なので、その場で書き込み内容を提示され、承認を求められる。内容を確認してから応じる。

  1. 試し終えたら承認制を戻す。
/memory approval off

承認制をオンにしたまま忘れると、対話以外の経路——メッセージング(第 7 章)や cron ジョブ(第 8 章)、バックグラウンドレビュー——からの書き込みは /memory pending に黙って溜まり続ける。定期的に /memory pending を確認するか、使い終わったらオフに戻す習慣をつけるとよい。

つまずきポイント

「今伝えたのに覚えてくれない」は仕様どおり — system prompt への注入はセッション開始時の凍結スナップショットなので、会話の途中で書き込まれたメモリは同じセッション内の応答には反映されない。ディスクへの保存自体は即時に起きている。反映を確かめたいなら、セッションを閉じて開き直す必要がある。

上限に達しても自動で忘れてはくれない — MEMORY.md(2,200 文字)・USER.md(1,375 文字)が満杯になると、memory ツールはエラーを返すだけで古いメモを自動削除しない。同じターンの中で replace や remove を挟んで空きを作ってから書き直す必要がある。

README の説明と詳細仕様がずれている箇所がある — README の機能表は「FTS5 session search with LLM summarization」と紹介しているが、詳細ページ(memory.md)は「LLM 要約なし・切り詰めなしで実際のメッセージを返す」と明記している。要約されたダイジェストが返ってくると期待していると、生のログがそのまま出てきて戸惑うことがある。挙動を厳密に知りたいときは、宣伝的な説明より機能ごとの詳細ページを優先するとよい。

write_approval は文脈によって承認方法が違う — 対話 CLI ならその場でプロンプトが出るが、メッセージング・スクリプト・バックグラウンドレビュー経由の書き込みは /memory pending に静かにステージングされるだけで、通知は来ない。承認制を有効にしたら、たまに /memory pending を覗く習慣をセットで持つ必要がある。

理解度チェック

Q1. USER.md と MEMORY.md の文字数上限はそれぞれ何文字で、満杯になったら memory ツールはどう振る舞いますか。

USER.md は 1,375 文字(約 500 トークン)、MEMORY.md は 2,200 文字(約 800 トークン)が上限。満杯だとエラーを返すだけで自動削除はしないため、同じターンの中で replace か remove を行ってから追記する必要がある。

Q2. セッション途中でエージェントが MEMORY.md に書き込んだ内容は、いつから system prompt に反映されますか。

次回セッション開始時から。system prompt への注入はセッション開始時に 1 回だけキャプチャされる「凍結スナップショット」方式のため、書き込み自体はディスクに即座に保存されても、今のセッションの応答には影響しない。

Q3. 永続メモリと session_search の違いを、容量とコストの観点で説明してください。

永続メモリは合計約 1,300 トークン分が毎回のプロンプトに乗るため、常にトークンを消費する。session_search は ~/.hermes/state.db への FTS5 全文検索で、全セッションを無制限に保存し、LLM 呼び出しなしの約 20ms クエリなので無料で使える。

Q4. write_approval を true にした場合、対話 CLI とメッセージング/バックグラウンドセルフインプルーブメントとで承認方法はどう違いますか。

対話 CLI ではその場でプロンプトが表示され、即座に承認・却下できる。それ以外の経路では /memory pending にステージングされ、後から /memory approve <id> や /memory reject <id> で処理する必要がある。

まとめ

参考リンク