記事のサマリー(TL;DR)
- Hugging Faceは、コーディングエージェント(Claude Code、Codex、pi、Hermes)のセッション記録を「記憶」として索引化・検索可能にするツール「funes」を公開しました。
- funesは単一バイナリとして動作し、既定ではMLランタイムに依存せず、埋め込みと再ランキングをローカルマシン上で実行します。任意でHugging Face上のデータセット(既定で非公開)に記憶を同期し、複数マシンやチーム間で共有できます。
- 公開されたベンチマークでは、長時間のセッションにおいて「recall(想起)」が「compaction(圧縮)」や「手動のhandoff(引き継ぎ)」と比較され、両タスクで最もコストが低かったと報告されています。
詳細
背景:エージェントは毎回「見知らぬ人」として現れる
筆者は複数のマシンで作業し、タスクに応じてコーディングエージェントを使い分けています。しかしどのエージェントも、プロジェクトに対して「初対面」の状態で現れ、「先週火曜日」の推論はセッション終了とともに失われてしまいます。新しいホスト上の新しいエージェントは、常にゼロから開始することになります。
今年初めに公開された記事「Software Forgets: Agent Traces Are the Memory」は、コーディングエージェントがすでに「失われ続けている記録」を生み出していると指摘しました。エージェントはコードベースを探索し、アプローチを試し、エラーに遭遇し、ドキュメントを読み、方向転換をする過程で、何が変わったかだけでなく「なぜ」変わったかについての濃密な記録を残しています。この診断自体は正しいものの、トレース(traces)はあくまで「潜在的な記憶」にすぎません。エージェントのセッションログは、依然としてただのアーカイブです。「なぜストリーミングパーサーから移行したのか」といった問いに対し、1万ターンにわたる記録をgrepで探り当てることはできません。エージェントが作業中にそうしたトレースを活用するには、索引付け(indexing)、検索(retrieval)、ランキング、そして正確な出所の特定(provenance)が必要です。それを提供するのがfunesです。
funesは、エージェント(Claude Code、Codex、pi、Hermes)向けの永続的なメモリ層です。すでにマシン上に存在するセッションから構築され、ローカルで動作し、1つのコマンドでエージェントの通常のワークフローの一部となります。必要に応じて、ユーザー自身が所有するHugging Faceデータセット(既定で非公開)へ記憶を移すこともできます。
既に使っているエージェントにメモリを追加する
funesは単一バイナリです。既定の推論バックエンドはMLランタイムに依存せず、埋め込みと再ランキングはマシン上で実行されます。
インストール:
curl -fsSL https://huggingface.co/buckets/huggingface/funes/resolve/install.sh | sh
エージェントへの追加:
funes add claude # または: codex, pi, hermes
このaddコマンド1つで、最初の索引が構築され、エージェントにrecallとgetというツールが付与され、完了した各ターンを索引化する自動処理がインストールされます。索引付けは増分的に行われ、新しい実行では履歴全体を再度埋め込むのではなく、新しいターンが追加されます。より古く深い内容は、範囲を区切った手順でバックフィル(遡及的な取り込み)が可能です。
その後は通常どおり作業を進めるだけです。タスクが過去の決定事項、根拠、または発見に関わる場合、エージェント自身がrecallを呼び出すことができます。古いセッションを覚えておいたり、その文脈を新しいセッションに貼り付けたりする必要はありません。funesを追加すると、recallは会話の中で実行されます。エージェントは自らメモリを参照し、回答の根拠となったセッションを明示します。
recallは要約ではなく原文のテキストを返し、出所(エージェント、タイムスタンプ、セッション、ターン)を正確に示します。各結果にはgetコマンドが付属し、該当ターンの全文とその前後の文脈を開くことができます。
内部では、1つの決定論的なパイプラインが、サポートされる全てのトレースを同一のターン・ブロック形式に解析し、チャンク化し、固定されたローカルモデルで埋め込みを行い、ローカルのLanceデータセットに書き込みます。クエリの際は、ベクトル検索とBM25検索を組み合わせ、それぞれのランキングを統合し、クロスエンコーダで候補を再ランキングし、新しさに応じて重み付けを行い、隣接するチャンクを付加します。
この設計により、funesは次の3つの重要な特性を備えています。
- エージェント横断の単一メモリ:Claude Code、Codex、pi、Hermesはすべて同じ形式でデータを書き込みます。recallはそれらの履歴全体を横断し、どのエージェントが生成した結果かが常に示されます。
- 生の証拠がそのまま保持される:書き込み時に内容が「事実」として要約・蒸留されることはありません。結果は常に、それを生み出した元のターンに遡ることができます。
- recallは既定でローカル動作:アカウントやHubリポジトリは不要です。ホスト型のモデルがセッションを索引付けのために処理することはなく、埋め込みと再ランキングはマシン上で実行され、推論自体はコーディングエージェントが行います。
「エージェントが初対面になる」という問題は、1台のマシン上ではすでに解決されています。しかし、次のエージェントが別の場所で動く場合、メモリはさらに有用になります。
メモリはサービスではなくデータセットである
作業にメモリを追従させるには、エージェントにfunesを追加する際にメモリを紐づけ(bind)ます。
funes add codex acme/funes-memory
bindにより、現在のメモリがそこに公開されます。以降funesはそれを最新の状態に保ち、各ターンをローカルで索引付けしつつ、セッションの区切りごとに公開します。エージェントは以降、そこから常にrecallを行います。別のマシンで同じコマンドを実行すれば、メモリはそのマシンにも引き継がれます。
内部的には、ローカルのメモリはLanceデータセットであり、共有されるメモリはユーザーが所有するHugging Faceデータセット(既定で非公開)です。Hubに到達する前に、索引付けの段階ですでに認証情報が削除(redact)されています。公開の際には、各チャンクを再度スキャンし、依然として機密情報に見えるものを保留します。このスキャナーの仕組みはSECURITY.mdに文書化されており、対応範囲と対象外の内容が記載されています。
エージェントがリモートのメモリを読み込む際、funesはデータセットファイルをローカルにキャッシュするため、ウォームクエリ(キャッシュ済みの照会)はローカルと同等の速度で返されます。Hubは、他のデータセットに対してすでに提供している所有権管理、アクセス制御、バージョン管理、配布機能をそのまま提供します。メモリが別のメモリサービス上のアカウントになることはなく、APIを通じて借り直す必要もありません。
先に質問、配線は後で:ask コマンド
recallはエージェント向けに設計されています。ユーザー自身がメモリに質問をしたい場合は、askを使用します。既定ではローカルメモリを読み込みます。
funes ask claude "what did we decide about the streaming parser"
あるいは、共有メモリを指定することもできます。funesの開発に関するメモリが公開されており、自分自身のメモリを作成しなくても、なぜfunesが現在の動作をするのかを尋ねることができます。
funes ask claude "why is funes append-only" --memory huggingface/funes-memory
funes askは、funes addの読み取り専用・単発質問版にあたる機能です。該当パッセージをrecallし、コーディングエージェントに渡し、出所を明示した根拠ある回答を返します。インテグレーションのインストールや、エージェントの永続的な設定変更は行いません。
検索結果が得られない場合、それを取り繕うことはしません。パッセージが回答を裏付けない場合、エージェントはその旨を述べます。その場合は質問を言い換えるか、通常の作業中にメモリを反復的に検索できるよう、エージェントにfunesを追加することができます。
エージェントを切り替えても文脈を失わない
共有メモリは、それを作成した特定のエージェントやモデルに紐づいていません。Claude Codeでタスクを開始し、翌週Codexで続け、2つ目のエージェントが1つ目のエージェントの推論をrecallすることができます。ローカルモデル、またはHugging Face routerを通じて提供されるモデルでpiを使い、その後Claudeに戻ることも可能です。Claudeが決定を下し、フックがそれを索引付けし、Codexが別のセッションでそれをrecallします。デモ内の古いヒットは、同じ実験のリハーサル記録であり、追記専用(append-only)のメモリはそのリハーサルも記憶していました。
これは、いくつかの異なる範囲で意味を持ちます。
- 複数マシン間:各エージェントを1つのメモリに紐づけ、使用しているホストにかかわらず履歴をrecallできます。
- チーム間:新しいチームメンバーのエージェントは、初日から数ヶ月分の決定事項を取得でき、プルリクエストに残らなかった行き止まりの試行や根拠も含まれます。
- オープンソースプロジェクトにおいて:メンテナーは、リリースの背後にあるセッションを公開し、プッシュ時に名前を付けることができます。
これは、プロジェクトが今の形になっている理由の履歴を保持する「検索可能なCLAUDE.md」のようなものであり、誰かが書き直し続けなければならないページとは異なります。公開されたメモリには--memoryで誰でもアクセスでき、データセットカードとfunesタグが付与されるため、Hub上で識別・発見しやすくなっています。
Hubはすでにオープンな重みやデータセットをホストしていますが、funesはそこに「オープンな作業メモリ」を追加します。それは、プロジェクトの背後にある決定事項、失敗したアプローチ、根拠を保持し、別のエージェントが検索でき、それを生み出したセッションまで遡れるものです。
長いセッションから抜け出す最も安価な方法
長い調査はセッションを肥大化させ、やがて各ターンで文脈を維持するコストが、実際の作業コストを上回るようになります。通常の対処法は、エージェントに圧縮(compact)させてそのまま続けるか、引き継ぎ(handoff)を書いて新規に始めるかのいずれかです。recallは第三の選択肢であるため、「handoff-vs-recall」ベンチマークでこれらを比較計測しました。これは、セッション以前の知識なしには答えを再構築できない2つのタスクを用いたものです。
compaction(圧縮)はほとんどのエージェントが既定で行う方式であり、3つの方式の中で唯一、結果が分かれたものでした。一方のタスクでは正解にたどり着きましたが、もう一方では最後までたどり着きませんでした。失敗した側では、要約によって重要な発見が失われていました。recallはパッセージそのものを返すため、発見が要約を生き延びる必要がありません。
recallは両タスクにおいて3つの方式の中で最も安価であり、一方のタスクでは書面によるhandoffに比べて8倍、もう一方では4倍安価でした。各バーの明るい部分は、チャンネル(handoffまたはcompaction)を準備するための一度限りのコストを示しており、最初の質問をする前に支払われ、一度だけ計上されます。×印は、最後まで到達しなかったチャンネルを示しており、成功あたりのコストが存在しないことを意味します。
ゼロからの開始をやめる
「考えるとは、差異を忘れ、一般化し、抽象化することである。」―ホルヘ・ルイス・ボルヘス『記憶の人、フネス』
あなたのエージェントはすでに記録を書き残しています。funesはgithub.com/huggingface/funesで公開されており、1つのコマンドで、その記録を次のエージェントが読める記憶に変えることができます。使用するマシンがどれであっても構いません。
オープンソースの上に構築
funesはこれらの仕組みをほとんど発明していません。ローカルで十分な性能で動作するオープンソースの埋め込みモデル、安価な増分書き込みが可能なLanceの追記専用データセット、そしてデータセット向けにHubがすでに提供しているキャッシュとコンテンツの重複排除機能に依拠しています。作業の本質は、これらを「エージェントが実際に使える記憶」として組み合わせる点にあります。
funes自体もオープンソースです。インストール時の不具合からrecallの取りこぼし、サポートしてほしいエージェントまで、何かあればissueを立てることができます。
[“Hugging Face”, “funes”, “Claude Code”, “Codex”, “コーディングエージェント”]