MemoryLake
すべての記事に戻る
Tutorial2026年9月9日·12 分で読了

OpenHandsのメモリインデックスから古いファクトが消えるのを防ぐ方法(2026年ガイド)

OpenHandsで永続メモリ(persistent memory)を有効にすると、うまく機能しました。エージェントは学習した内容を記録し始めました。見つけるのに半日かかった環境の癖、サービスの奇妙な設定理由、4回も繰り返さなければならなかったあなたの好みなどです。セッションは最初から物事を把握した状態で始まるようになりました。

しかし、3ヶ月後、最も古いエントリが消えてしまいました。あなたが削除したわけでも、エージェント自身の整理指示によって削除されたわけでもなく、単にプロンプトに含まれなくなったのです。そして消えてしまったのは、最も初期のエントリでした。同じプロジェクトをずっと進めてきたのであれば、それらは先週のノイズではなく、プロジェクトの根幹となる決定事項だったはずです。

これはバグではなく、ドキュメントに明記されている仕様です。その仕組みさえ理解すれば、1つのファイルの書き方を10分変更するだけで解決できます。このガイドの後半では、同じドキュメント内にある、そもそもそこに何を記述すべきかを変えてしまう別の記述について解説します。

ツールのセットアップ中の場合は、migrating from Codex to OpenHands で指示ファイル側の移行について説明しています。このガイドは、特にメモリ機能に焦点を当てています。

なぜ古い行から消えていくのか

OpenHandsの永続メモリは、明示的に有効にしない限りオフになっています。ドキュメントには「オプトイン方式で、デフォルトはオフ」であり、これがない場合「エージェントは既存の AGENTS.md ベースのガイダンスを維持し、プロンプトは変更されない」と明記されています。エージェントの AgentContextload_memory を true に設定することで有効化できます。

有効にすると、2つのティアが存在します。~/.openhands/memory/ にあるユーザーティアは「すべてのプロジェクトに適用される知識や好み」を保持し、<workspace>/.openhands/memory/ にあるプロジェクトティアは「現在のリポジトリに特化した知識」を保持します。各ティアには、MEMORY.md(「永続的なファクトの厳選されたインデックス。プロンプトに注入される唯一のファイル」と説明されています)と、日付付きのデイリーログ(「自動的に注入されることはありません。MEMORY.md がそれらを指し示している場合、エージェントはファイルツールを使用してオンデマンドで読み込みます」)が含まれます。

この分割が重要なアーキテクチャであり、同時にデータ削除(エビクション)が発生する原因でもあります:

"サイズ予算(Size budget): 統合されたインデックスの上限は約6,000文字に制限されています。予算を超えると、予算超過した各ティアの上部から行全体が削除されます(最も古いコンテンツ)。部分的な行が残ることはなく、ティアのヘッダーは常に維持され、行が失われたティアのヘッダーの下には切り捨て通知が表示されます。インデックスは常に整理された状態を保ってください。"

ここには4つの異なる挙動が詰まっているため、ゆっくり読んでみましょう。

上限は両方のティアを合わせた統合インデックスに適用されるため、個人の好みとプロジェクトのファクトが同じ予算を奪い合うことになります。冗長なユーザーティアのファイルは、プロジェクトティアが保持できる容量を圧迫します。

行は上部から削除され、ドキュメントでは上部を「最も古いコンテンツ」と表現しています。エージェントは学習するにつれて追記していくため、ファイルの上部はこれまでに記録された最も古い内容になります。多くの制限仕様では、最新のものを削除するか書き込みを失敗させますが、この仕様では基礎となる部分から先に削除されます。

削除は行単位でクリーンに行われます(「部分的な行が残ることはない」)。そのため、意味が変わってしまうような中途半端な文が残ることはありません。優れた設計ですが、1つの長い行が「すべて残るか、すべて消えるか」のどちらかになることを意味します。

And there is a signal: 「行が失われたティアのヘッダーの下に切り捨て通知が表示される」のです。注意して見ていれば、何もサイレントに処理されることはありません。問題は、通常の作業セッション中に注入されたシステムプロンプトのブロックを誰も見ないということです。

複数のツールを実行している人にとって注目に値するのは、6,000文字という予算が、Devin Desktopがグローバルルールファイル用にドキュメント化している予算と同じであるという点です。約6,000文字というのは、常に読み込まれるファイルがそのコストに見合わなくなる境界線として、複数のベンダーが独自に判断した実用的な数値であり、どのツールを使用するにしても覚えておくと便利です。

代わりに試されがちなアプローチ

予算を増やす。 最初の直感ですが、ドキュメントにはそれを調整する設定項目は提示されていません。上限はこの機能の特性として説明されています。仮に調整可能だったとしても、常に読み込まれるブロックを大きくすることは、how much memory you should give an AI agent で解説している理由から、良い取引ではなく、むしろ悪化を招きます。

数週間ごとに手動で MEMORY.md を書き直す。 これは機能しますし、「インデックスを整理された状態に保つ」という要求にも合致しています。しかし、トリガーのない面倒な作業であるため、2回ほど実行しただけで放置され、ファイルは再び肥大化してしまいます。

すべてを AGENTS.md に移動して削除を防ぐ。 魅力的ですが、ドキュメントが設定している役割分担を誤解しています。エージェントは「リポジトリで作業するすべてのエージェントに向けた指示には AGENTS.md を使用し、メモリはエージェント自身が学習した内容のために使用する」よう指示されています。学習した履歴を指示ファイルに詰め込むと、名前が異なるだけで、削除通知も出ない、常に読み込まれる長いファイルが出来上がるだけです。

重要なファクトをスキル(skill)に落とし込み、オンデマンドで読み込ませる。 合理的な直感ですが、why agent skills aren't memory で説明されている理由から、間違ったメカニズムに衝突してしまいます。スキルは「このタスクをどう実行するか」に答えるものです。不採用となったアーキテクチャの代替案などは、タスクではありません。

.openhands/memory/ をコミットしてチームのドキュメントとして扱う。 ドキュメントではこれを明示的に許可しています(「プロジェクトチームは .openhands/memory/ をコミットして、エージェントが学習した知識を共有することもできる」)。これは実際に有用です。しかし、複数の人のエージェントが同じ6,000文字の上限に対して共有インデックスに追記していくことになるため、削除問題は改善するどころか悪化します。

これらの方法がどれもうまくいかないさらなる理由があり、それは多くの人が見落としている次の記述にあります:

"設計上、信頼されていない(Untrusted by design): 注入されるブロックは <UNTRUSTED_CONTENT> で囲まれます。メモリファイルは通常エージェントによって書き込まれますが、ワークスペースやリポジトリへのアクセス権を持つ人なら誰でも編集やコミットができるため(クローンされたリポジトリに .openhands/memory/MEMORY.md が含まれている場合があります)、エージェントにはプロンプトインジェクションが含まれている可能性があると伝えられ、信頼できる指示としてではなく、未検証のヒントとして扱うよう指示されます。"

エージェントは、自身のメモリを未検証のヒントとして扱うよう指示されています。これは正しいセキュリティ姿勢です(クローンされたリポジトリにメモリファイルが含まれている可能性があるため)。そして、これが設計上の疑問を解決してくれます。従わなければならないことはメモリに置くことはできません。なぜなら、メモリは明示的に権限を持たないからです。メモリは、エージェントが有用と判断するかもしれないコンテキストのためのものです。指示は AGENTS.md に記述すべきであり、そこではすべてのエージェントに向けた指示として読み込まれます。

したがって、ドキュメント化された2つの特性は1つのルールに集約されます。メモリインデックスは、容量が小さく、権限を持たず、上部からデータが失われるポインタファイルです。それ以上のものとして扱うと、2つのうちどちらかの方法で期待を裏切られることになります。

解決策:インデックスをストレージではなくポインタとして維持する

3つのステップがあります。最初の2つは10分で完了します。3つ目は問題の再発を防ぐためのものです。

ステップ 1: MEMORY.md をポインタのインデックスにする

ドキュメントにはすでに意図された構成が示されています。MEMORY.md は「永続的なファクトの厳選されたインデックス」であり、エージェントは「長い詳細はデイリーログに記述する」よう指示され、ログは「MEMORY.md がそれらを指し示している場合に、ファイルツールを使用してオンデマンドで」読み込まれます。

したがって、インデックスの各行は短く、どこかを指し示すものであるべきです。1つのファクトにつき1行とし、何が真実であるかと、詳細がどこにあるかの両方をエージェントが理解できるように表現します。散文の段落、コードサンプル、長い説明は日付付きのログファイルに移動します。そこであれば必要なときにだけ読み込まれ、予算を消費することはありません。

これを行えば、6,000文字の上限は制約ではなくなります。1行のポインタなら100個でも余裕で収まりますが、数十個の段落では収まりません。

ステップ 2: 上部が破棄されてもいいようにインデックスを並べ替える

削除は上部から行を削除し、上部は最も古いコンテンツであるため、ファイルの時系列順はあなたにとって不利に働きます。順序を時系列ではなく意味的なもの(セマンティック)に変更することで、これを解決します。

失いたくない重要なファクト(アーキテクチャ、制約、長期的な決定事項など)は、各ティアのインデックスの下部に配置します。一時的な運用メモは上部に配置します。これで予算を超過した際、削除されるのはどのみち整理する予定だった行になります。

次に、ティア間でバランスを調整します。上限は統合されているため、個人の好みで肥大化した ~/.openhands/memory/MEMORY.md は、プロジェクトのファクトのスペースを直接奪うことになります。ユーザーティアは真にプロジェクト横断的な好みに限定し、プロジェクトティアにスペースを譲りましょう。

作業中に、各ティアのヘッダーの下に切り捨て通知がないか確認してください。もし表示されているなら、すでにいくつかの行が失われています。デイリーログを確認すれば、そこに何が書かれていたかが分かります。これは、ステップ1を最初に実行すべき強い理由になります。

ステップ 3: 現在1つのファイルを共有している3つの要素を分離する

インデックスは現在、それぞれ異なる場所にあるべき3種類のコンテンツを保持しています。

指示(Instructions) — 従わなければならないこと — は、ドキュメント自体の役割分担に従い、AGENTS.md に配置します。これらはメモリではなく、メモリは権限を持ちません。

エージェントが学習した運用の詳細(Agent-learned operational detail) — 環境の癖、不安定なテスト、実際に動作するコマンドなど — は、まさに現在の場所、つまりインデックス内のポインタ行とデイリーログ内の詳細に配置します。これがこの機能の本来の目的です。

プロジェクトの決定事項とその理由(Project decisions and their reasons) — なぜそのキューライブラリが却下されたのか、コンプライアンスの制約で実際に何が求められているのか、3月に何を試してうまくいかなかったのか — は、どちらにも属しません。これらは指示ではないため AGENTS.md は不適切です。また、これらは消失してはならず、権限を持つ必要があるため、メモリインデックスも不適切です。さらに、load_memory がオンになっているツールだけでなく、チームが使用するすべてのツールから参照できる必要があります。

MemoryLakeでのセットアップ

MemoryLake は、その3番目のカテゴリのための場所です。個々のエージェントの外部で決定事項とその理由を保持し、競合する常に読み込まれる予算もありません。MCPやAPIを介してそれらに関する質問に答えます。MEMORY.md は短いポインタインデックスのままであり、OpenHands はドキュメント通りにそれを維持し続けます。永続的な推論は、文字数制限の及ばない場所に保管されます。

ステップ 1: APIキーの作成

キーを生成し、約30秒で最初のリクエストを送信できます。インデックスを並べ替える際に各決定事項を移動できる場所を確保するため、上記のステップ2の前にこれを行ってください。

MEMORY.mdの容量を超えたファクトを永続的に保存するためのMemoryLake APIキーの作成
MEMORY.mdの容量を超えたファクトを永続的に保存するためのMemoryLake APIキーの作成

ステップ 2: 最初のメモリのアップロード

現在のインデックスと、それが指し示しているデイリーログに目を通します。単なる観察ではなく決定事項であるすべてのエントリについて、何が選択され、何が却下され、その理由は何だったのかを書き留めます。サポートドキュメントやファイルも同じ場所に保存します。

制限のあるインデックスに保持する代わりに、プロジェクトの根本的な決定事項をMemoryLakeにアップロードする
制限のあるインデックスに保持する代わりに、プロジェクトの根本的な決定事項をMemoryLakeにアップロードする

ステップ 3: AIとエージェントの接続

OpenHands、Claude、Codex、およびその他のエージェントに、MCPまたはAPIを介してアクセスを許可します。プロジェクトがなぜそのような構成になっているのかを知る必要があるとき、システムプロンプトのスペースを奪い合うことなく、その理由が関連付けられた状態で回答が届きます。

MCPとAPIを介してOpenHandsやその他のエージェントをMemoryLakeに接続する
MCPとAPIを介してOpenHandsやその他のエージェントをMemoryLakeに接続する

実践において何が変わるか

最初の変化は、データの削除(エビクション)が気にならなくなることです。使い捨てのコンテンツを上部に配置して整理されたポインタインデックスは、整理する予定だったものだけを失い、各ポインタの背後にある詳細はエージェントが開くことのできるログファイルに残ります。

2つ目は、メモリ機能が本来の役割を十分に果たせるようになることです。統合テストに特定の環境変数が必要であることを記録することは、エージェントが維持するストレージがまさに実行すべきことであり、チームの決定記録であることを求められなければ、それをうまくこなせます。

3つ目は、「信頼されていないコンテンツ」という枠組みが問題にならなくなることです。重要なものがメモリに置かれなくなれば、エージェントがそれを未検証のヒントとして扱うことは単に正しい挙動となります。そして、権限を持つべきものは AGENTS.md にあり、指示として読み込まれます。

4つ目は、.openhands/memory/ をコミットすることがチーム規模で安全に行えるようになることです。複数のエージェントが6,000文字の予算に対してポインタ行を追記していくことは、複数のエージェントが段落を追記していくこととは異なり、持続可能です。そして、2つのエントリが実際に矛盾した場合、アルファベット順や時系列順の偶然に決定を委ねるのではなく、それを解決する場所が確保されます。これは memory conflict detection が検知するために存在する問題です。

OpenHands永続メモリのベストプラクティス

1行、1ファクト、1ポインタ。 インデックスは厳選されたインデックスとしてドキュメント化されています。1行を超えるものはすべてデイリーログに配置し、インデックスからそこを指し示すようにします。

時間順ではなく、重要度順に並べる。 削除は上部から行を削除します。失っても構わないものをそこに配置してください。

2つのティアの予算を相互に調整する。 上限は統合されているため、冗長なユーザーティアはプロジェクトティアのスペースを静かに縮小させます。

切り捨て通知を確認する。 行が失われたティアのヘッダーの下に表示されます。これが唯一のシグナルであり、注意して見ていれば信頼できます。

メモリに資格情報を絶対に置かない。 エージェント自身の指示には、秘密情報や資格情報を記録しないよう記載されています。自分でそれらを追加してそのルールを台無しにしないようにし、定期的に監査を行ってください。auditing what your AI remembers でその習慣について解説しています。

些細な再発見可能な情報はスキップする。 メンテナンスの指示にもある通り、ディレクトリの一覧や明白なコマンドは予算を消費するだけで、何も学習させません。

指示はメモリから完全に排除する。 メモリは未検証のヒントとしてドキュメント化されています。従う必要があるものは AGENTS.md に配置します。

メモリはセッションに保存されるのではなく、再読み込みされることを忘れない。 ドキュメントによると、解決されたテキストは会話の永続化やAPIペイロードから除外され、セッションごとにディスクから再読み込みされるため、ファイルを手動で編集すると次の会話から反映されます。

結論

OpenHands はその永続メモリを正確にドキュメント化しています。オプトイン方式でデフォルトはオフ、2つのティア、MEMORY.md のみが注入され、統合された上限は約6,000文字、予算超過したティアの上部から行全体が削除されヘッダーの下に切り捨て通知が表示され、ブロック全体が信頼されていないコンテンツのマーカーで囲まれ、エージェントには権限のある指示ではなく未検証のヒントとして扱うよう指示されます。これらはどれも合理的な決定です。これらが合わさることで、容量が小さく、データが失われやすい、アドバイザリーなポインタファイルが定義されます。これは本当に有用なものであり、プロジェクトの推論を保管する場所ではありません。

インデックスは1行のポインタに留め、上部には失っても構わないものを配置し、現在それを共有している3種類のコンテンツを分離してください。指示は AGENTS.md に移動します。観察結果はメモリとそのログに残します。これがこの機能の本来の目的です。決定事項とその理由は、文字数制限や有効期限のない場所に保管します。それらは1年後にも必要になるものであり、keeping less in agent memory で論じられているように、残りの部分に別の保管場所があれば、常に読み込まれるファイルは小さいほどあらゆる面で優れています。

よくある質問

なぜ最も古いメモリのエントリが消えてしまったのですか?

それがドキュメントに記載されている削除(エビクション)の順序だからです。統合されたメモリインデックスの上限は約6,000文字に制限されており、予算を超えると、予算超過した各ティアの上部から行全体が削除されます。ドキュメントではこれが最も古いコンテンツとされています。行が失われたティアのヘッダーの下には切り捨て通知が表示されます。

メモリのサイズ制限を増やすことはできますか?

ドキュメントでは、約6,000文字の上限を設定可能な項目ではなく、この機能の特性として提示しており、インデックスを整理された状態に保つよう案内しています。予算内に収めるための現実的な方法は、各行を短いポインタにし、詳細は自動的に注入されないデイリーログファイルに移動することです。

MEMORY.md とデイリーログの違いは何ですか?

MEMORY.md は整理されたインデックスであり、プロンプトに注入される唯一のファイルです。日付付きのデイリーログは、自動的に注入されることのない自由形式の作業メモです。インデックスがそれらを指し示している場合、エージェントはファイルツールを使用してオンデマンドで読み込みます。これが意図された役割分担であり、上限を管理可能にする仕組みです。

なぜメモリブロックは信頼されていないコンテンツとしてマークされているのですか?

メモリファイルは、他の人が書き込み可能なワークスペースやリポジトリのディスク上に存在し、クローンされたリポジトリに独自のメモリファイルが含まれている可能性があるためです。ドキュメントによると、エージェントにはコンテンツにプロンプトインジェクションが含まれている可能性があると伝えられ、権限のある指示としてではなく、未検証のヒントとして扱うよう指示されます。そのため、従わなければならないものは代わりに AGENTS.md に配置する必要があります。

.openhands/memory/ をリポジトリにコミットすべきですか?

ドキュメントでは、エージェントが学習した知識をチームと共有する方法として明示的に許可されており、実際に機能します。ただし、インデックスを短いポインタに変換した後にのみ行ってください。複数のエージェントが1つの統合された予算に対して共有インデックスに追記すると、1人の場合よりもはるかに早く上限に達してしまうためです。

永続メモリはデフォルトでオンになっていますか?

いいえ。ドキュメントでは、オプトイン方式でデフォルトはオフと説明されており、エージェントのコンテキストで load_memory を設定することで有効になります。また、これがない場合、エージェントは既存の AGENTS.md ベースのガイダンスを維持し、プロンプトは変更されないとされています。オンにすると、システムプロンプトのメモリセクションがファイルの維持に関する指示に切り替わります。