0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェントの記憶混在を防ぐnamespace設計:user_id・agent_id・memory_space_idで分離する

0
Last updated at Posted at 2026-06-23

AIエージェントの記憶を混ぜないnamespace設計 - user_id・agent_id・memory_space_idで区画を切る

はじめに

AIエージェントに長期記憶を持たせると、次に必ず出てくる問題があります。記憶の検索精度ではなく、記憶の混在です。

個人で使っているうちは、ひとつの memory/ ディレクトリにMarkdownを置くだけでも動きます。しかし、ユーザーが増え、AIパートナーが増え、仕事用と個人用の文脈が分かれてくると、「誰の、どのAIの、どの用途の記憶か」を取り違えない設計が必要になります。

この記事では、Agent Memoriesで採用している基本方針として、次の3つのキーで記憶を分離する設計を紹介します。

  • user_id: 記憶の所有者
  • agent_id: どのAIパートナーの記憶か
  • memory_space_id: 仕事用、個人用、プロジェクト用などの区画

記憶混在を防ぐnamespace設計 - user_id、agent_id、memory_space_idで検索対象を絞る

記憶混在は検索精度の問題ではない

ベクトル検索を入れると、似た内容の記憶がよく引けるようになります。ただし、それは「引いてよい記憶」だけが検索対象になっている場合の話です。

検索対象に他ユーザーの記憶が混ざっていると、検索精度が高いほど危険です。似ているが別人の記憶を、自信を持って返してしまうからです。

そのため、記憶検索ではまずフィルタをかけます。検索スコアはその後です。

type MemoryScope = {
  user_id: string;
  agent_id: string;
  memory_space_id: string;
};

type MemoryRecord = MemoryScope & {
  id: string;
  title: string;
  body: string;
  source_ai: "claude" | "codex" | "chatgpt" | "gemini" | "manual";
  source_app: string;
  visibility: "private" | "shared";
  consent: "owner_only" | "team_allowed";
  created_at: string;
};

この形にしておくと、検索の入口で必ずscopeを要求できます。

検索時はscopeを必須にする

検索関数の引数に query だけを渡せる設計にしないことが重要です。必ずscopeとセットで受け取ります。

type SearchInput = MemoryScope & {
  query: string;
  limit?: number;
};

async function searchMemories(input: SearchInput): Promise<MemoryRecord[]> {
  const candidates = await vectorSearch({
    query: input.query,
    filter: {
      user_id: input.user_id,
      agent_id: input.agent_id,
      memory_space_id: input.memory_space_id,
    },
    limit: input.limit ?? 8,
  });

  return candidates.filter((memory) => memory.visibility === "private");
}

実装によっては、ベクトルDB側のfilterだけに頼らず、アプリケーション側でも同じ条件を再確認します。二重に見えますが、記憶混在は事故の影響が大きいため、最後の出口でも守ります。

共有記憶は例外扱いにする

チームで使う場合、共有記憶も必要になります。ただし、共有を既定にすると混在が起きます。共有は例外扱いにして、明示的な許可を持たせます。

function canRead(memory: MemoryRecord, scope: MemoryScope): boolean {
  const sameOwner = memory.user_id === scope.user_id;
  const sameAgent = memory.agent_id === scope.agent_id;
  const sameSpace = memory.memory_space_id === scope.memory_space_id;

  if (sameOwner && sameAgent && sameSpace) return true;

  return (
    memory.visibility === "shared" &&
    memory.consent === "team_allowed" &&
    memory.memory_space_id === scope.memory_space_id
  );
}

共有記憶も、少なくとも用途の区画は合わせます。仕事用の共有記憶が、個人用AIパートナーの会話に混ざるべきではありません。

source_aiとsource_appを残す

記憶はどこから来たかも重要です。Claude Codeで作業中に保存した記憶なのか、ChatGPTとの会話から持ってきた記憶なのか、手動で登録した方針なのかで信頼度が変わります。

const memory: MemoryRecord = {
  id: "mem_20260623_001",
  user_id: "user_123",
  agent_id: "asuna",
  memory_space_id: "agentmemories_ops",
  title: "Qiita/Zenn記事はAlice QC後に公開する",
  body: "tech-dailyの原稿はcontent/techに置くが、公開にはAliceの承認ファイルが必要。",
  source_ai: "codex",
  source_app: "openclaw",
  visibility: "private",
  consent: "owner_only",
  created_at: new Date().toISOString(),
};

あとで「この記憶は本当に採用してよいのか」を判断する時、出所が残っているとレビューしやすくなります。

MCPツールの入力にもscopeを持たせる

MCPサーバーにする場合も同じです。memory_searchmemory_store の入力にscopeを必須で持たせます。

const ScopeSchema = z.object({
  user_id: z.string().min(1),
  agent_id: z.string().min(1),
  memory_space_id: z.string().min(1),
});

server.registerTool(
  "memory_search",
  {
    title: "Search memories",
    inputSchema: ScopeSchema.extend({
      query: z.string().min(1),
      limit: z.number().int().min(1).max(20).default(8),
    }).shape,
  },
  async (input) => {
    const parsed = ScopeSchema.extend({
      query: z.string(),
      limit: z.number().default(8),
    }).parse(input);

    const results = await searchMemories(parsed);
    return {
      content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
    };
  },
);

ここでscopeをサーバー側が補完する設計にする場合でも、最終的には呼び出しごとに確定したscopeをログへ残します。後から混在事故を調査できるようにするためです。

まとめ

AIエージェントの記憶基盤では、検索精度より先に分離設計が必要です。

最小構成は次の3つです。

  1. user_id
  2. agent_id
  3. memory_space_id

この3つで検索対象を絞り、共有記憶は明示許可制にする。さらに source_aisource_appvisibilityconsent を残すと、複数AI・複数ユーザーでも記憶を安全に扱いやすくなります。

記憶は便利なほど、混ざった時の被害が大きくなります。だからこそ、Agent Memoriesでは「どのAIでも記憶を使える」ことと同じくらい、「使ってはいけない記憶を混ぜない」ことを重視しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?