Author: baba

  • AI Agent向け長期記憶ツールを作った話

    AI Agent向け長期記憶ツールを作った話

    はじめに 今回は、AI Agent向けの長期記憶機能を担うツールを作成してみたので、それについてまとめていきたいと思います。 本記事の内容は2026/8時点のものです。各サービスの機能・名称は、今後変更される可能性があります。 作成理由 昨今のAgentは、contextに入った情報をもとにタスクを遂行する構成が基本です。そのため、contextをいかに効率的に使うかという点が重要になっています。その中で、前のタスクでやったことを覚えていてほしいとか、前回やった修正が巻き戻ったといった経験は一度はあるかと思います。こうした課題に対し、OpenAIやAnthropicなどのプロバイダはMemory機能を提供しています。Memory機能について大まかに話すと、Agentがセッション内で有用だと思った情報をMemory(ファイル)に保存していき、別セッションでMemoryを読むことで、過去のセッションの知識を再利用できるというものです。最初はこの機能を使ってAgentを利用していたのですが、使っているうちにいくつか不満がありました。 今回はCodex(ChatGPT)を前提に書いています。Claudeだといくつか解決できているものもあります。 そこで、これらの不満を解消するべく新しくツールを作成しました。 全体の構成 まず全体像を見ていきます。 名称 内容 Application Service メインシステム Document Store 実ファイルの保存領域 Background Worker 保存済みMemoryをチャンク化・ベクトル化し、Qdrantへ非同期登録する処理 Embedding Provider 意味的なインデックスを貼るための埋め込みモデル Qdrant ベクトルDB この構成は全てローカル環境で動作するものになっています。長期記憶や外部記憶はObsidianやGemini Notebookを使う方がシンプルに済みますが、今回は外部依存をできるだけ削るために全てローカルで動作させるようにしています。ローカルで全て動作させる場合、複数端末からの利用やCloud環境で使えないのですが、色々面倒だったので全てローカルで動作させるようにしました。 記憶部分の主要機能 主要な記憶機能についてはCLIで実装し、コマンドで利用できるようにしています。実装されている主要機能としては、 名称 内容 remember MemoryをDBに保存 recall DBからMemoryを検索 dedupe Memoryの重複チェック 管理機能 全文参照、一覧、論理削除、インデックス再構築など が実装されています。これらの機能を細かく見ていきましょう。 Remember Rememberは、受け取ったMemoryをファイルとして保存します。その後、WorkerがMemoryを分割・ベクトル化し、検索用インデックスとしてQdrantへ非同期で登録します。Qdrantは検索専用であり、Memoryの実データとしては扱っていません。Memoryの更新もRememberで行っています。 Memoryとして、再利用可能なアイデアや傾向などをAgentが独自に判断し保存するようになっています。 プロジェクトの判別はAgentに任せていません。CLIが実行時の作業ディレクトリから保存先のプロジェクトを決定し、Rememberへ引き継ぎます。そのため、Agentは保存先を意識せず、現在のプロジェクトに対応するMemoryを保存できます。これは、後述するDedupeでも同様です。 Recall Recallは、任意の検索文から関連するMemoryを検索します。今回のCodex向け連携では、UserPromptSubmit Hookからユーザープロンプトを検索文として渡しています。検索結果にはMemory全文ではなく、関連するチャンクの本文、Memory ID、検索スコアなどを含めます。その情報だけでは不足する場合に、AgentがReadを使ってMemory全体を取得します。 検索時には検索文を埋め込みモデルでベクトル化し、あらかじめチャンク単位でベクトル化してあるMemoryとQdrant上で比較します。そのため、単語が完全に一致していなくても意味が近い内容を検索でき、類似度の高いチャンクから順に候補として返せます。 検索対象は、現在のプロジェクトとそれより上位の階層です。上位階層のMemoryには、階層の距離に応じたペナルティを検索スコアへ与えます。プロジェクト固有のMemoryに加えて、上位階層へ保存した横断的なMemoryも検索できます。一方、同列や下位の階層は現在の検索対象に含めていません。 たとえば、プロジェクトが次のような階層構造になっているとします。 user/projects/main-projectから検索すると、現在の階層に加えてuser/projectsとuserも検索します。同列にあたるuser/projects/other-projectは検索しません。下位や同列の階層を検索対象に含めることには検討の余地がありますが、下位や同列はどの程度関連させるかなどが上位に比べて複雑化すると思ったため現在は実装していません。 Dedupe Dedupeは入力全体の一致を確認し、一致しない場合は同じプロジェクト内から意味的に近いMemoryを探します。Recallとは異なり、上位階層は検索しません。…

  • サプライチェーン攻撃対策

    サプライチェーン攻撃対策

    完璧な防御は存在しない。「防ぐ」と「諦めない」の両構えで 広く使われるOSSパッケージが汚染される事例は、近年あとを絶ちません。開発者の手元やCIが攻撃の起点になるリスクも、確実に高まっています。ソフトウェアサプライチェーン攻撃について、まず受け入れておきたい現実があります。それは、侵入を100%防ぐことはできないということです。自分が書いていないコードを大量に取り込んで動かす以上、どうしてもどこかに信頼の穴は残ってしまうからです。 完璧に防げない以上、対策は「入られない努力」と「入られた前提の設計」の両面で考えておきたいところです。本記事では、その具体的な切り口として次の二段構えを取り上げます。 この2つを両輪で回していく、というイメージです。 もちろん、サプライチェーン対策はこれだけではありませんが、本記事ではその中から、「予防」と「被害局所化」という切り口を一例として取り上げ、パッケージマネージャやシークレット管理の具体的な設定レベルまで落とし込んで整理していきます。 サプライチェーン攻撃とは何か まずは、攻撃経路を少し整理しておきましょう。主な侵入口は次の3つです。 影響範囲の大きさを示す実例として、2026年3月31日に発生した axios のサプライチェーン侵害を見てみましょう。侵害されたメンテナのnpmアカウント経由で、悪意ある2バージョン axios@1.14.1 と axios@0.30.4 がnpmに公開されました。公開時間はおよそ3時間(約 09:21 公開〜12:29 削除)と短かったのですが、axios は週1億回以上ダウンロードされるため、その間に npm install した開発環境やCI/CDが侵害されうる、甚大な影響範囲でした。 手口はかなり巧妙でした。axios本体のソースは改変せず、攻撃用に作られた依存 plain-crypto-js@4.2.1 を新バージョンの依存に追加していたのです。インストール時に postinstall フック(node setup.js) が走り、二重難読化されたドロッパーがOSを判別してC2サーバから各OS向けのRAT(リモートアクセス型マルウェア)を取得・実行し、GitHubトークンやクラウド認証情報などを窃取したとされています。攻撃者はクリーンな plain-crypto-js@4.2.0 を約18時間前に先行公開して履歴を作り、「新着パッケージ」検知をかわそうとした形跡もありました。 なぜ今、リスクが高まっているのか サプライチェーン攻撃が以前より深刻になっている理由は、大きく3つあります。 3つ目については断定的な統計があるわけではないのですが、防御側の前提を「攻撃は速く・多く・巧妙になりうる」へ置き換えておきたい、という問題提起として捉えていただければと思います。 対策①:サプライチェーン攻撃の侵入を防ぐ(予防) 予防の主戦場は、パッケージマネージャの設定にあります。デフォルト設定のまま使うのではなく、攻撃面を少しずつ減らしていきましょう。 インストール時スクリプトを無効化する postinstall などのライフサイクルスクリプトは、攻撃者にとって「インストールだけで任意コードを実行できる」格好の入口です。実際に前述のaxios侵害でも、追加された依存の postinstall(node setup.js)が起点になっていました。ここを既定で無効化しておきましょう。 pnpm では、依存パッケージのビルド/ライフサイクルスクリプトを既定でブロックする挙動が v10.0.0(2025年1月) で導入されました。許可するパッケージだけを onlyBuiltDependencies に明示する、「既定でブロック → 許可リストで明示許可」という方針が取れます。 トレードオフ:ネイティブモジュールのビルドなど、スクリプト実行を前提とするパッケージは動かなくなることがあります。その場合は全面禁止にするのではなく、「既定は無効化し、必要なパッケージだけ明示的に許可リストへ加える」という運用が現実的でしょう。 公開直後のバージョンを即採用しない(min-release-age) 悪意あるバージョンは、公開直後に発見・撤回されるケースが多いです。axiosの汚染版も数時間で削除されました。公開からの経過時間で足切りをすれば、撤回前の汚染バージョンや、検知回避のために先行公開された依存を即座に取り込んでしまうリスクを下げられます。 npm では npm 11.10.0(2026年2月リリース)以降、min-release-age…