開発者がCloudflare上でますます高度なエージェントを構築するにつれて、彼らが直面する最大の課題の1つは、適切な情報を適切なタイミングでコンテキストに組み込むことです。モデルによって生成される結果の質は、それらが動作するコンテキストの質に直接結びつきますが、コンテキストウィンドウのサイズが100万(1M)トークンを超えて拡大しても、コンテキストの劣化は未解決の問題として残っています。すべてを文脈に留め、品質を低下させるか、エージェントが後で必要とする情報を積極的に切り捨てるという2つの悪い選択肢の間に自然な緊張が生じます。
本日、エージェントメモリのプライベートベータ版を発表します。エージェントメモリは、エージェントの会話から情報を抽出し、コンテキストウィンドウを埋めることなく、必要な時に利用できるようにするマネージドサービスです。
AIエージェントに永続的なメモリを提供し、重要なことを記憶し、そうでないことを忘れ、時間の経過とともに賢くなるのです。この投稿では、この機能と、構築に役立つものについて説明します。
エージェンティックメモリは、AIインフラストラクチャで最も動きの速いスペースの1つで、新しいオープンソースライブラリ、マネージドサービス、研究プロトタイプがほぼ毎週のようにローンチされています。これらのサービスは、何を保存するか、どのように取得するか、どのようなエージェント向けに設計されているかで大きく異なります。LongMemEval、LoCoMo、BEAMのようなベンチマークは、公平な比較を行うのに役立ちますが、特定の評価に過学習し、本番環境で機能しなくなるシステムを簡単に構築してしまう可能性もあります。
既存のサービスは、アーキテクチャも異なります。バックグラウンドで抽出と検索を処理するマネージドサービスもあれば、メモリパイプラインを自分で実行するセルフホスト型フレームワークもあります。一部は、エージェントのメインコンテキストからメモリロジックを保持する、制約のある目的地に構築されたAPIを公開します。また、モデルにデータベースやファイルシステムへの未加工のアクセスを与え、独自のクエリーを設計させ、実際のタスクではなくストレージや検索戦略でトークンを消費する場合もあります。すべてをコンテキストウィンドウに適合させ、必要に応じて複数のエージェントに分割しようとするものもあれば、検索を使用して関連性のあるものだけを表面化するものもあります。
Agent Memoryは、指定されたAPIと検索ベースのアーキテクチャを備えたマネージドサービスです。当社では代替案を慎重に検討し、この組み合わせが本番環境のほとんどのワークロードにとって適切なデフォルトであると考えています。エージェントに未加工のファイルシステムアクセスを与えるよりも、緊密な取り込みおよび検索パイプラインの方が優れていると言えます。コストとパフォーマンスの改善に加え、時間ロジック、スーパーセッション、指示フォローなど、本番環境で必要となる複雑な推論タスクの基盤を強化します。将来的には、プログラムによるクエリのためにデータを公開する可能性がありますが、一般的なケースではなく、エッジケースで役立つことが予想されます。
当社がAgent Memoryを構築したのは、当社のプラットフォーム上のワークロードが、既存のアプローチでは完全に対応できないギャップを明らかにしたからです。実際のコードベースや本番システムに対して数週間または数か月にわたって実行されるエージェントには、成長とともに有用なメモリが必要です。新しいモデルのコンテキストウィンドウに完全に適合するベンチマークデータセットでうまく機能するメモリだけでなく、
素早く取り込む必要があるのです。会話を妨げない検索が必要なのです。そして、クエリごとのコストを合理的に保つモデルで実行する必要があります。
Agent Memoryは、名前でアドレス指定されたプロファイルにメモリを保存します。プロファイルは、会話を取り込む、特定のことを記憶する、必要な情報を記憶する、記憶をリストアップする、特定のメモリを忘れる、など、いくつかの操作を提供します。Ingestは、ハーネスがコンテキストを圧縮するときに通常呼び出されるバルクパスです。記憶とは、モデルが何か重要なものをその場に保存することです。Recallは検索パイプライン全体を実行し、統合された回答を返します。
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Get a profile -- an isolated memory store shared across sessions, agents, and users
const profile = await env.MEMORY.getProfile("my-project");
// Ingest -- extract memories from a conversation (typically called at compaction)
await profile.ingest([
{ role: "user", content: "Set up the project with React and TypeScript." },
{ role: "assistant", content: "Done. Scaffolded a React + TS project targeting Workers." },
{ role: "user", content: "Use pnpm, not npm. And dark mode by default." },
{ role: "assistant", content: "Got it -- pnpm and dark mode as default." },
], { sessionId: "session-001" });
// Remember -- store a single memory explicitly (direct tool use by the model)
const memory = await profile.remember({
content: "API rate limit was increased to 10,000 req/s per zone after the April 10 incident.",
sessionId: "session-001",
});
// Recall -- retrieve memories and get a synthesized answer
const results = await profile.recall("What package manager does the user prefer?");
console.log(results.result); // "The user prefers pnpm over npm."
return Response.json({ ok: true });
},
};
Agent Memoryには、任意のCloudflare Workerからバインディングを介してアクセスできます。Workers外部で実行するエージェントのREST API経由でもアクセス可能で、他のCloudflare開発者プラットフォームAPIと同じパターンでアクセスできます。Cloudflare Agents SDKで構築している場合、Agent Memoryサービスは、セッションAPIのメモリ部分の圧縮、記憶、検索を処理するためのリファレンス実装としてきちんと統合されています。
Agent Memoryは、さまざまなエージェントアーキテクチャで動作するように設計されています。
個々のエージェントのメモリ。Claude CodeやOpenCodeのようなコーディングエージェントを人間が介在して構築する場合でも、OpenClawやHermesのようなセルフホスト型エージェントフレームワークを使用して代理で行動する場合でも、あるいはAnthropicのManaged Agentsのようなマネージドサービスと連携する場合でも、Agent Memoryはエージェントのコアループに変更を加えることなく、永続的なメモリ層として機能します。
カスタムエージェント活用のためのメモリです。多くのチームが、人間を関与させることなく自律的に動作するバックグラウンドエージェントを含む、独自のエージェントインフラストラクチャを構築しています。Ramp Inspectは公開されている一例です。StripeとSpotifyも同様のシステムについて説明しています。これらの機能は、セッションを横断して持続し、再起動にも耐えるメモリをエージェントに与えることもできます。
エージェント、ユーザー、ツール全体で共有メモリ。メモリプロファイルは、必ずしも単一のエージェントに属する必要はありません。エンジニアチームがメモリプロファイルを共有できるため、ある人のコーディングエージェントが学習した知識が全員が利用できるようになります。コーディング規則、アーキテクチャに関する決定、現在人々の頭の中にあるデータ、またはコンテキストが切り捨てられると失われた知識などです。コードレビューボットとコーディングエージェントがメモリを共有できるため、レビューに関するフィードバックが今後のコード生成につながるようになります。エージェントが蓄積するナレッジは、一過性のものではなく、耐久性のあるチーム資産になり始めます。
検索はメモリの構成要素ですが、エージェント検索とエージェントメモリは異なる問題を解決します。AI Searchは、非構造化ファイルと構造化ファイルの結果を見つけるためのプリミティブです。エージェントメモリはコンテキストを呼び出すためのものです。エージェントメモリのデータはファイルとして存在しません。セッションから派生しますエージェントは両方を使用でき、連携して動作するように設計されています。
エージェントがより有能になり、ビジネスプロセスにより深く組み込まれるようになると、エージェントが蓄積するメモリは、運用状態だけでなく、実際の作業を必要とした組織的な知識として真に価値のあるものになります。お客様からは、そのアセットを単一のベンダーに結びつけることについての懸念が高まっていますが、無理もありません。エージェントがより多く学習すればするほど、そのメモリで移動できなければ、スイッチングコストは高くなります。
Agent Memoryはマネージドサービスですが、データはあなたのものです。すべてのメモリはエクスポート可能で、お客様のエージェントがCloudflareに蓄積したナレッジを、お客様のニーズが変化した場合に残できるようにしています。長期的な信頼を得る正しい方法は、退職を容易にし、顧客が望まない程度の良いものを構築し続けることだと考えています。
上記のAPIの背後で何が起こっているのかを理解するには、エージェントがコンテキストを管理する方法を分解するのに役立ちます。1つのエージェントには3つのコンポーネントがあります:
モデルへの繰り返し呼び出しを促進し、ツール呼び出しを容易にし、状態を管理するハーネス。
コンテキストを取り込み、補完を返すモデル。
現在のコンテキストウィンドウとコンテキスト外の追加情報(会話履歴、ファイル、データベース、メモリ)の両方を含む状態。
エージェントのコンテキストライフサイクルの重要な瞬間は、圧縮です。このとき、ハーネスはモデルの制限内に収まるように、またはコンテキストの劣化を避けるために、コンテキストを短縮することを決定します。現在、ほとんどのエージェントは情報を永久に破棄します。エージェントメモリは、圧縮に関する知識を失うのではなく、保存します。
Agent Memoryは、このライフサイクルに2つの方法で統合します。
圧縮時に一括取り込み。ハーネスがコンテキストを圧縮すると、エージェントメモリに会話を送信し、取り込みます。取り込みは、メッセージ履歴から事実、イベント、指示、タスクを抽出し、既存のメモリと重複を排除し、将来の検索のためにメモリとして保存します。
モデルによる直接ツールの使用。このモデルは、呼び出す(特定の情報を探すメモリを検索する)能力など、記憶と直接対話するためのツールを手に入れることになります。このモデルは、記憶(重要なものに基づいてメモリを明示的に保存する)、忘れる(重要または真ではなくなったメモリをマークする)、リスト化(どのメモリが保存されているかを確認する)もできます。これらは、モデルがクエリを設計したり、ストレージを管理する必要のない軽量な操作です。プライマリエージェントは、ストレージ戦略に関するコンテキストを消費してはいけません。見えるツールサーフェスは意図的に制約があり、メモリが実際のタスクの邪魔にならないようになっています。
取り込むために到着した会話は、メモリを抽出、検証、分類、保存する複数段階のパイプラインを通過します。
最初のステップは、決定論的なIDの生成です。各メッセージには、コンテンツアドレス付きIDが与えられます。これは、セッションID、ロール、コンテンツのSHA-256ハッシュで、128ビットに切り捨てられます。同じ会話が2回取り込まれた場合、すべてのメッセージが同じIDに解決されるため、再取り込みは不可能になります。
次に、抽出者は2つのパスを並行して実行します。フルパスは、2つのメッセージのオーバーラップを用いておよそ10,000文字でメッセージを分割し、最大4つのチャンクを同時に処理します。各チャンクは、役割ラベル、関連する日付が絶対に解決された(「yesterday」は「2026-04-14」になります)、情報源を示す行インデックスが付けられた構造化されたトランスクリプトを取得します。長い会話(9つ以上のメッセージ)の場合、詳細パスは全体パスと一緒に実行され、重複するウィンドウを使用して、名前、価格、バージョン番号、一般的な抽出では見逃されがちな名前、価格、バージョン番号、エンティティ属性などの具体的な値の抽出に重点を置いています。次に、2つの結果セットがマージされます。
次のステップは、抽出された各メモリをソーストランスクリプトと照合することです。検証者は、エンティティID、オブジェクトID、ロケーションコンテキスト、時間的正確性、組織コンテキスト、完全性、関係コンテキスト、推定事実が実際に会話によってサポートされるかどうかをカバーする8つのチェックを実行します。各項目は、合格、修正、または削除されます。
そして、パイプラインは、各検証済みメモリを4つのタイプのいずれかに分類します。
事実は、「プロジェクトはGraphQLを使用している」、「ユーザーはダークモードを好む」など、現時点での事実、つまりアトミックで安定した知識を表します。
イベントは、展開や決定など、特定の時期に起こった内容を記録します。
指示には、手順、ワークフロー、ランブックなど、何かを実行する方法が記載されています。
タスクは現在取り組んでいる内容を追跡するもので、一時的なものです。
事実と指示が重要です。それぞれが正規化されたトピックキーを取得し、新しいメモリが既存のメモリと同じキーを持つ場合、古いメモリは削除されずに置き換えられます。これにより、古いメモリから新しいメモリへのフォワードポインタを持つバージョンチェーンが作成されます。タスクはベクトルインデックスから完全に除外され、無駄をなくしますが、フルテキスト検索で発見できるようにします。
最後に、コンテンツアドレスが重複する場合は、すべてがINSERT OR IGNAREを使ってストレージに書き込まれ、重複したコンテンツはすべてスキップされます。ハーネスにレスポンスを返した後、バックグラウンドベクトル化が非同期的に実行されます。埋め込みテキストは、分類中に生成された3~5の検索クエリをメモリコンテンツ自体にプリペンドし、メモリの記述方法(宣言的に:「ユーザーはダークモードを好む」)と検索方法(尋ねる:「テーマは何か」を尋ねる)のギャップを埋める意図しているか?」)。上書きされたメモリのベクトルは、新しいアップサートと並行して削除されます。
エージェントがメモリを検索する場合、クエリは別の検索パイプラインを通過します。開発中に、すべてのクエリに対して最適な単一の検索方法がないことが判明したため、いくつかの方法を並行して実行し、結果を統合しました。
最初の段階では、クエリ分析と埋め込みを同時に実行します。クエリアナリストは、ランク付けされたトピックキー、同義のフルテキスト検索語、および質問に対する答えであるかのように言い回しのある宣言的記述であるHyDE(Hypothetical Document Embedding)を生成します。この段階では未加工のクエリーを直接埋め込み、両方の埋め込みをダウンストリームで使用します。
次の段階では、5つの検索チャンネルが並行して実行されます。Porterステミングによるフルテキスト検索は、正確な用語は知っていても、前後の文脈がわからないクエリのキーワード精度を処理します。正確なファクトキールックアップは、クエリが既知のトピックキーに直接マッピングする結果を返します。生メッセージ検索は、保存された会話メッセージをフルテキスト検索で直接問い合わせ、セーフティネットとして機能する未分類の会話フラグメントを探し、抽出パイプラインが一般化した可能性のある詳細を捕捉します。直接ベクトル検索は、埋め込みクエリを使用して、意味的に類似するメモリを検出します。また、HyDEベクトル検索は、答えと類似したメモリを検出し、特に質問と回答が異なる用語を使用する抽象的またはマルチホップクエリでは、直接的な埋め込みミスになる結果を表面化します。
第3段階および最終段階では、5つの検索チャネルすべての結果がReciprocal RankingFusion(RRF)を使用して統合され、各結果が所定のチャンネル内でランク付けされた位置に基づいて重み付きスコアが与えられます。完全なトピック一致が最も強力なシグナルであるため、正確なキー一致が最も高い重み付けがされます。フルテキスト検索、HyDEベクトル、ダイレクトベクトルには、それぞれシグナルの強さに基づいて重み付けがされます。最後に、抽出パイプラインが見逃した可能性のある結果を特定するためのセーフティネットとして、生のメッセージの一致も低の重みで含まれます。直近の結果が上位にランクインしていることが分かります。
次に、パイプラインは上位の候補を合成モデルに渡し、元の検索クエリに対する自然言語の応答を生成します。一部の特定のクエリタイプは特別な扱いを受けます。例えば、時間計算はLLMではなく、正規表現と算術によって決定論的に処理されます。結果は、事前計算された事実として合成プロンプトに挿入されます。モデルは日付数学のようなものは信用できないので、そのようにしてもらうことはありません。
私たちがエージェントメモリの最初のプロトタイプは軽量で、基本的な抽出パイプライン、ベクトルストレージ、シンプルな検索を備えていました。概念を示すには十分に機能しましたが、出荷には十分ではありませんでした。
そこで私たちは、それをエージェント駆動型のループに入れて反復処理を行うことにしました。サイクルは次のようになります。ベンチマークを実行し、ギャップがある箇所を分析し、解決策を提案し、その提案を人間がレビューして、過剰適合ではなく一般化する戦略を選択し、エージェントに変更を加え、それを繰り返します。
これはうまく機能していましたが、1つの特定の課題がありました。LLMは、温度をゼロに設定しても、確率的です。これにより、実行ごとに結果が異なるため、複数回の実行を平均し(大きなベンチマークには時間がかかる)、実際に何が機能しているのかを理解するためには、生スコアと傾向分析に頼る必要がありました。その間、私たちは、製品を根本から一般的なケースに改善しない方法でベンチマークを過剰に適合させることを慎重に防ぐ必要がありました。
時間が経つにつれ、ベンチマークのスコアがイテレーションのたびに一貫して改善されるようになり、現実世界で動作する一般化されたアーキテクチャを完成させることができました。複数のベンチマーク(LoCoMo、longMemEval、BEAMなど)に対して意図的にテストを行い、異なる方法でシステムを後押ししています。
当社はCloudflare上にCloudflareを構築しており、Agent Memoryも同様です。強力で簡単にコンポーザブルな既存のプリミティブのおかげで、最初のプロトタイプは週末に出荷でき、完全に機能する本番化された内部バージョンのAgent Memoryを1か月足らずで出荷することができました。配信の速さ以外にも、いくつかの理由で、Cloudflareは、この種のサービスを構築するのに最適な場所となりました。
内部的には、Agent Memoryは複数のシステムを調整するCloudflare Workerです。
Durable Object:未加工メッセージと分類されたメモリを保存
Vectorize:埋め込まれたメモリのベクトル検索を提供
Workers AI:LLMと埋め込みモデルを実行
各メモリコンテキストは、独自のDurable ObjectインスタンスとVectorizeインデックスにマッピングされ、コンテキスト間でデータを完全に分離します。また、需要の増加に応じて簡単に拡張することもできます。
Durable Objectsによるコンピューティング分離。各メモリプロファイルは、SQLiteでサポートされるストアを備えた独自のDurable Object(DO)を取得し、インフラストラクチャのオーバーヘッドなしで、テナント間の強力な分離を提供します。DOは、FTSインデックス作成、スーパーセッションチェーン、トランザクション書き込みを処理します。DOのgetByName()アドレス指定は、どこからでも、あらゆるリクエストが名前によって正しいメモリプロファイルに到達できることを意味し、機密性の高いメモリが他のテナントから強く分離されることを保証します。
スタック全体にわたるストレージ。メモリコンテンツは、SQLiteでサポートされたDOに存在します。ベクトルはVectorizeに存在します。将来的には、スナップショットとエクスポートは、コスト効率の高い長期ストレージのためにR2に送られます。プリミティブはそれぞれワークロードのために作られており、すべてを単一の形やデータベースに強制する必要はありません。
Workers AIを使用したローカルモデル推論。抽出、分類、合成のパイプライン全体は、Cloudflareのネットワーク上にデプロイされたWorkers AIモデル上で動作します。すべてのAI呼び出しは、メモリプロファイル名にルーティングされたセッションアフィニティヘッダーを渡します。ため、繰り返しのリクエストは同じバックエンドにヒットし、プロンプトキャッシングの利点が得られます。
当社のモデル選択から得られた興味深い調査結果の1つが、より大規模で強力なモデルが必ずしも良いとは限らないことです。現在、抽出、検証、分類、クエリ分析にはLlama 4 Scout(17B、16-expert MoE)がデフォルトで、合成にはNemotron 3(MoE 120B、12Bのアクティブパラメーター)が使用されています。Scoutは構造化された分類タスクを効率的に処理し、Netotronの大きな推論容量は自然言語回答の質を向上させます。シンセサイザーは、問題により多くのパラメーターを投げかけることで一貫して有効になった唯一の段階です。すべてにおいて、小規模なモデルの方がコスト、品質、遅延の面で優れたスイートスポットを達成しました。
Cloudflareでは、社内でAgent Memoryを実行しています。これは、実証済みの場所であり、次に構築するものについてのアイデア源でもあります。
コーディングエージェントの記憶。Agent Memoryを開発ループにつなぐ社内OpenCodeプラグインを使用しています。Agent Memoryは、セッション内およびセッション全体の過去の圧縮に関する記憶を提供します。あまり知られていないメリットは、チーム全体でメモリを共有することです。共有プロファイルを使用することで、エージェントはチームの他のメンバーがすでに学んだことを知っているため、すでに解決済みの質問を質問したり、すでに解決済みのミスを犯すことを防ぐことができます。修正されました。
エージェンティックコードレビュー。エージェントメモリを、社内のエージェントコードレビュー担当者に接続しました。おそらく、AIが学んだ最も有益なことは、「静かである」ことです。レビュー担当者は、過去のレビューでは特定のコメントが無関係であったこと、特定のパターンにフラグが付けられたこと、そして作成者が正当な理由でそれを保持することを選択したことを記憶しています。レビューは、スマートになるだけでなく、時間の経過とともにノイズが少なくなります。
チャットボット。また、メッセージ履歴を取り込み、送信された新たなメッセージを潜ませて記憶する内部チャットボットにもメモリを認識させられます。そして、誰かが質問すると、ボットは以前の会話に基づいて答えます。
また、サービスの改良と改善に伴って、近い将来社内で展開する予定の追加のユースケースも多数あります。
弊社は、エージェントメモリの社内テストおよび改良を続け、抽出パイプラインを改善し、検索品質を調整し、バックグラウンド処理能力を拡張しています。人間の脳が安眠するために接続を再生して強化することで記憶を統合するように、私たちはメモリストレージが非同期的に改善される機会があると考え、現在、これを機能させるためにさまざまな戦略を実装し、テストしています。
さらに、エージェントメモリを近日中に公開する予定です。Cloudflare上でエージェントを構築していて、早期アクセスをご希望の方は、順番待ちリストにご登録ください。
アーキテクチャを深く掘り下げたい場合、構築中のものを共有したい場合、または今後の開発をフォローしたい場合は、 Cloudflare Discordに参加するか、 Cloudflare Communityでスレッドを開始してください。当社は両方を積極的に監視しており、本番エージェントのワークロードが実際にどのようなものになるかに興味があります。