Foundry Agent Service でのメモリの作成と使用 (プレビュー)

重要

Foundry Agent Service および Memory Store API (プレビュー) のメモリ (プレビュー) は、Azure サブスクリプションの一部としてライセンスが付与され、Microsoft 製品使用条件および Microsoft Products and Services Data Protection Addendum の "プレビュー" に適用される条件に従うとともに、Microsoft Azure プレビューの使用条件 の Microsoft 生成 AI サービス プレビュー条項にも従います。

Foundry Agent Service のメモリは、マネージドの長期メモリ ソリューションです。 これにより、セッション、デバイス、ワークフロー間でエージェントの継続性を実現できます。 メモリ ストアを作成および管理することで、ユーザー設定を保持し、会話履歴を維持し、パーソナライズされたエクスペリエンスを提供するエージェントを構築できます。

メモリ ストアは永続的ストレージとして機能し、各エージェントに関連する情報の種類を定義します。 scope パラメーターを使用してアクセスを制御します。これにより、ユーザー間でメモリがセグメント化され、セキュリティで保護された分離されたエクスペリエンスが確保されます。

この記事では、メモリ ストアを作成、管理、使用する方法について説明します。 概念に関しては、「Foundry Agent Service のメモリ」を参照してください。

使用サポート

能力 Python SDK C# SDK JavaScript SDK REST API
メモリ ストアの作成、更新、一覧表示、削除 ✔️ ✔️ ✔️ ✔️
メモリの更新と検索 ✔️ ✔️ ✔️ ✔️
プロンプト エージェントにメモリをアタッチする ✔️ ✔️ ✔️ ✔️

前提 条件

承認とアクセス許可

運用環境のデプロイでは 、ロールベースのアクセス制御 をお勧めします。 ロールが実現できない場合は、このセクションをスキップし、代わりにキーベースの認証を使用してください。

ロールベースのアクセスを構成するには:

  1. Azure ポータルにサインインします。

  2. プロジェクトで次の手順を実行します。

    1. 左側のウィンドウで、 リソース管理>Identity を選択します。
    2. トグルを使用して、システム割り当てマネージド ID を有効にします。
  3. プロジェクトを含むリソースで、次の手順を実行します。

    1. 左側のウィンドウで、[ アクセス制御 (IAM)] を選択します。
    2. [ 追加]>[ロールの割り当ての追加] を選択します。
    3. Azure AI User をプロジェクトのマネージド ID に割り当てます。

環境を設定する

必要なパッケージをインストールします。

pip install "azure-ai-projects>=2.0.0" azure-identity

必要なパッケージをインストールします。

dotnet add package Azure.AI.Projects
dotnet add package Azure.AI.Projects.Agents
dotnet add package Azure.AI.Extensions.OpenAI
dotnet add package Azure.Identity

必要なパッケージをインストールします。

npm install @azure/ai-projects@2 @azure/identity

プロジェクト エンドポイントとモデルのデプロイ名の環境変数を設定します。

export FOUNDRY_PROJECT_ENDPOINT="https://{your-ai-services-account}.services.ai.azure.com/api/projects/{project-name}"
export MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME="<chat-model-deployment-name>"
export MEMORY_STORE_EMBEDDING_MODEL_DEPLOYMENT_NAME="<embedding-model-deployment-name>"

プロジェクト エンドポイント、モデル デプロイ、API バージョン、アクセス トークンの環境変数を設定します。

FOUNDRY_PROJECT_ENDPOINT="https://{your-ai-services-account}.services.ai.azure.com/api/projects/{project-name}"
MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME="<chat-model-deployment-name>" # For example, gpt-5.2
MEMORY_STORE_EMBEDDING_MODEL_DEPLOYMENT_NAME="<embedding-model-deployment-name>" # For example, text-embedding-3-small
API_VERSION="2025-11-15-preview"

# Get a short-lived access token using Azure CLI
ACCESS_TOKEN="$(az account get-access-token --resource https://ai.azure.com/ --query accessToken -o tsv)"

スコープを理解する

scope パラメーターは、メモリのパーティション分割方法を制御します。 メモリ ストア内の各スコープは、メモリ項目の分離されたコレクションを保持します。 たとえば、メモリを使用してカスタマー サポート エージェントを作成する場合、各顧客は独自のメモリを持つ必要があります。

開発者は、メモリ項目の格納と取得に使用するキーを選択します。 適切な方法は、メモリへのアクセス方法によって異なります。

メモリ検索ツールを使用する

メモリ検索ツールをエージェントにアタッチする場合は、scope{{$userId}} に設定して、ハード コーディング識別子なしでユーザーごとのメモリ分離を有効にします。 システムは、次の 2 つのソースのいずれかからの各応答呼び出しでエンド ユーザーの ID を自動的に解決します。

  • x-memory-user-id 要求ヘッダー: 存在する場合は、ヘッダー値がユーザー ID として使用されます。 これは、サービスがエンド ユーザーに代わって API を呼び出すプロキシまたはバックエンドのシナリオで使用します。

  • Microsoft Entra認証トークン: ヘッダーが設定されていない場合、システムは呼び出し元のテナント ID (TID) とオブジェクト ID (OID) にフォールバックします。 これは、ユーザーが Microsoft Entra で直接認証するフロントエンド シナリオの既定値です。

ユーザーごとの分離が必要ない場合は、代わりに静的な scope 値を使用します。

低レベルのメモリ API を使用する

メモリ API を直接呼び出す場合は、各要求でscopeを明示的に指定します。 静的な値を渡すことができます。例えば、ユニバーサル一意識別子(UUID)やシステムからの他の安定した識別子などです。 これらの操作では、ID の自動抽出はサポートされていません。

メモリ ストアを作成する

各エージェント用の専用メモリ ストアを作成して、メモリ アクセスと最適化の明確な境界を確立します。 メモリ ストアを作成するときに、メモリ コンテンツを処理するチャット モデルと埋め込みモデルのデプロイを指定します。

import os
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import MemoryStoreDefaultDefinition, MemoryStoreDefaultOptions
from azure.identity import DefaultAzureCredential

project_client = AIProjectClient(
    endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
    credential=DefaultAzureCredential(),
)

memory_store_name = "my_memory_store"

# Specify memory store options
options = MemoryStoreDefaultOptions(
    chat_summary_enabled=True,
    user_profile_enabled=True,
    user_profile_details="Avoid irrelevant or sensitive data, such as age, financials, precise location, and credentials"
)

# Create memory store
chat_model = os.environ["MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME"]
embedding_model = os.environ["MEMORY_STORE_EMBEDDING_MODEL_DEPLOYMENT_NAME"]

definition = MemoryStoreDefaultDefinition(
    chat_model=chat_model,
    embedding_model=embedding_model,
    options=options
)

memory_store = project_client.beta.memory_stores.create(
    name=memory_store_name,
    definition=definition,
    description="Memory store for customer support agent",
)

print(f"Created memory store: {memory_store.name}")
using System;
using Azure.AI.Projects;
using Azure.AI.Projects.Memory;
using Azure.Identity;

#pragma warning disable AAIP001

var projectEndpoint = Environment.GetEnvironmentVariable(
    "FOUNDRY_PROJECT_ENDPOINT");
var chatModel = Environment.GetEnvironmentVariable(
    "MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME");
var embeddingModel = Environment.GetEnvironmentVariable(
    "MEMORY_STORE_EMBEDDING_MODEL_DEPLOYMENT_NAME");

AIProjectClient projectClient = new(
    new Uri(projectEndpoint),
    new DefaultAzureCredential());

var memoryStoreName = "my_memory_store";

// Specify memory store options
MemoryStoreDefaultDefinition memoryStoreDefinition = new(
    chatModel: chatModel,
    embeddingModel: embeddingModel
);
memoryStoreDefinition.Options = new(
    isUserProfileEnabled: true,
    isChatSummaryEnabled: true);
memoryStoreDefinition.Options.UserProfileDetails =
    "Avoid irrelevant or sensitive data, such as age, "
    + "financials, precise location, and credentials";

// Create memory store
MemoryStore memoryStore = projectClient.MemoryStores.CreateMemoryStore(
    name: memoryStoreName,
    definition: memoryStoreDefinition,
    description: "Memory store for customer support agent"
);

Console.WriteLine($"Created memory store: {memoryStore.Name}");
import { DefaultAzureCredential } from "@azure/identity";
import type {
  MemoryStoreDefaultDefinition,
  MemoryStoreDefaultOptions,
} from "@azure/ai-projects";
import { AIProjectClient } from "@azure/ai-projects";

const projectEndpoint =
  process.env["FOUNDRY_PROJECT_ENDPOINT"] ||
  "<project endpoint>";
const chatModelDeployment =
  process.env["MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME"] ||
  "<chat model deployment name>";
const embeddingModelDeployment =
  process.env["MEMORY_STORE_EMBEDDING_MODEL_DEPLOYMENT_NAME"] ||
  "<embedding model deployment name>";

const memoryStoreName = "my_memory_store";

const project = new AIProjectClient(
  projectEndpoint,
  new DefaultAzureCredential(),
);

const memoryOptions: MemoryStoreDefaultOptions = {
  user_profile_enabled: true,
  chat_summary_enabled: true,
  user_profile_details:
    "Avoid irrelevant or sensitive data, such as age, " +
    "financials, precise location, and credentials",
};

const definition: MemoryStoreDefaultDefinition = {
  kind: "default",
  chat_model: chatModelDeployment,
  embedding_model: embeddingModelDeployment,
  options: memoryOptions,
};

const memoryStore = await project.beta.memoryStores.create(
  memoryStoreName,
  definition,
  {
    description: "Memory store for customer support agent",
  },
);

console.log(
  `Created memory store: ${memoryStore.name} (${memoryStore.id})`,
);
curl -X POST "${FOUNDRY_PROJECT_ENDPOINT}/memory_stores?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my_memory_store",
    "description": "Memory store for customer support agent",
    "definition": {
      "kind": "default",
      "chat_model": "'"${MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME}"'",
      "embedding_model": "'"${MEMORY_STORE_EMBEDDING_MODEL_DEPLOYMENT_NAME}"'",
      "options": {
        "chat_summary_enabled": true,
        "user_profile_enabled": true,
        "user_profile_details": "Avoid irrelevant or sensitive data, such as age, financials, precise location, and credentials"
      }
    }
  }'

ヒント

  • 残りのPython、C#、TypeScript のスニペットは、メモリ ストアの作成で定義されているクライアントと変数に基づいて構築されます。 これらのコード スニペットを個別に実行する場合は、このセクションのインポートコードとクライアント初期化コードを含めます。
  • この記事の C# スニペットでは、同期メソッドを使用します。 非同期の使用については、memory 検索ツール および memory store サンプルを参照してください。

メモリをカスタマイズする

エージェントが格納する情報をカスタマイズして、メモリの効率、関連性、プライバシーに配慮した状態を維持します。 user_profile_details パラメーターを使用して、エージェントの関数に不可欠なデータの種類を指定します。

たとえば、 user_profile_details を設定して、旅行代理店の "フライト キャリアの優先順位と食事制限" に優先順位を付けます。 この重点的なアプローチは、メモリシステムが、どの詳細を抽出、要約し、どのように長期記憶に保存するかを把握するのに役立ちます。

また、このパラメーターを使用して、特定の種類のデータを除外し、メモリの無駄を維持し、プライバシー要件に準拠することもできます。 たとえば、 user_profile_details を設定して、"年齢、財務、正確な場所、資格情報など、無関係なデータや機密データを避ける" ようにします。

メモリ ストアを更新する

メモリ ストアの管理を強化するために、 descriptionmetadataなどのメモリ ストアのプロパティを更新します。

# Update memory store properties
updated_store = project_client.beta.memory_stores.update(
    name=memory_store_name,
    description="Updated description"
)

print(f"Updated: {updated_store.description}")
// Update memory store properties
MemoryStore updatedStore = projectClient.MemoryStores.UpdateMemoryStore(
    name: memoryStoreName,
    description: "Updated description"
);

Console.WriteLine($"Updated: {updatedStore.Description}");
const updatedStore = await project.beta.memoryStores.update(
  memoryStoreName,
  {
    description: "Updated description",
  },
);

console.log(`Updated: ${updatedStore.description}`);
MEMORY_STORE_NAME="my_memory_store"

curl -X POST "${FOUNDRY_PROJECT_ENDPOINT}/memory_stores/${MEMORY_STORE_NAME}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Updated description"
  }'

メモリ ストアを一覧表示する

メモリ インフラストラクチャを管理および監視するために、プロジェクト内のメモリ ストアの一覧を取得します。

# List all memory stores
stores_list = list(project_client.beta.memory_stores.list())

print(f"Found {len(stores_list)} memory stores")
for store in stores_list:
    print(f"- {store.name} ({store.description})")
// List all memory stores
foreach (MemoryStore store in projectClient.MemoryStores.GetMemoryStores())
{
    Console.WriteLine(
        $"Memory store: {store.Name} ({store.Description})");
}
const storeList = project.beta.memoryStores.list();

console.log("Listing all memory stores...");
for await (const store of storeList) {
  console.log(`  - Memory Store: ${store.name} (${store.id})`);
}
curl -X GET "${FOUNDRY_PROJECT_ENDPOINT}/memory_stores?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"

エージェント ツールを使用してメモリを使用する

メモリ ストアを作成したら、メモリ検索ツールをプロンプト エージェントにアタッチできます。 このツールを使用すると、エージェントは会話中にメモリ ストアの読み取りと書き込みを行うことができます。 メモリの更新方法とタイミングを制御するために、適切な scopeupdate_delay を使用してツールを構成します。

ヒント

メモリのスコープを個々のエンド ユーザーに設定するには、 scope をツール定義で "{{$userId}}" に設定し、各応答呼び出しでヘッダーとして x-memory-user-id: <user-id> を渡します。 システムは、スコープをそのユーザーの ID に解決します。 ヘッダーがない場合、スコープは呼び出し元のMicrosoft Entra ID (TID と OID) にフォールバックします。 詳細については、「 スコープについて」を参照してください。

from azure.ai.projects.models import MemorySearchPreviewTool, PromptAgentDefinition

# Set scope to associate the memories with
scope = "user_123"

openai_client = project_client.get_openai_client()

# Create memory search tool
tool = MemorySearchPreviewTool(
    memory_store_name=memory_store_name,
    scope=scope,
    update_delay=1, # Wait 1 second of inactivity before updating memories
    # In a real application, set this to a higher value like 300 (5 minutes, default)
)

# Create a prompt agent with memory search tool
agent = project_client.agents.create_version(
    agent_name="MyAgent",
    definition=PromptAgentDefinition(
        model=os.environ["MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME"],
        instructions="You are a helpful assistant that answers general questions",
        tools=[tool],
    )
)

print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})")
using Azure.AI.Projects.Agents;
using Azure.AI.Extensions.OpenAI;
using OpenAI.Responses;

#pragma warning disable OPENAI001

// Set scope to associate the memories with
string scope = "user_123";

// Create a prompt agent with memory search tool
DeclarativeAgentDefinition agentDefinition = new(model: chatModel)
{
    Instructions = "You are a helpful assistant that answers "
        + "general questions",
};
agentDefinition.Tools.Add(new MemorySearchPreviewTool(
    memoryStoreName: memoryStore.Name,
    scope: scope)
{
    UpdateDelayInSecs = 1, // Wait 1 second of inactivity before updating memories
    // In a real application, set this to a higher value
    // like 300 (5 minutes, default)
});

ProjectsAgentVersion agent =
    projectClient.AgentAdministrationClient.CreateAgentVersion(
        agentName: "MyAgent",
        options: new(agentDefinition));

Console.WriteLine(
    $"Agent created (id: {agent.Id}, name: {agent.Name}, "
    + $"version: {agent.Version})");
// Set scope to associate the memories with
const scope = "user_123";

const agent = await project.agents.createVersion(
  "memory-search-agent",
  {
    kind: "prompt",
    model: chatModelDeployment,
    instructions:
      "You are a helpful assistant that retrieves relevant " +
      "information from the user's memory store to answer their questions.",
    tools: [
      {
        type: "memory_search_preview",
        memory_store_name: memoryStoreName,
        scope: scope,
        update_delay: 1,
      },
    ],
  },
);

console.log(
  `Created agent with memory search tool, agent ID: ${agent.id}, ` +
    `name: ${agent.name}, version: ${agent.version}`,
);
# The agents API uses api-version=v1, which differs from the memory store API version
curl -X POST "${FOUNDRY_PROJECT_ENDPOINT}/agents?api-version=v1" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MyAgent",
    "definition": {
        "kind": "prompt",
        "model": "gpt-5.2",
        "instructions": "You are a helpful assistant that answers general questions",
        "tools": [
            {
              "type": "memory_search_preview",
              "memory_store_name": "my_memory_store",
              "scope": "user_123",
              "update_delay": 1
            }
        ]
    }
}'

会話を作成する

会話を作成し、エージェントの応答を要求できるようになりました。 各会話の開始時に静的メモリが挿入され、エージェントは即時の永続的なコンテキストを持ちます。 コンテキスト メモリは、各応答に通知する最新のメッセージに基づいてターンごとに取得されます。

各エージェント応答の後、サービスは内部的に update_memoriesを呼び出します。 ただし、長期メモリへの実際の書き込みは、 update_delay 設定によってデバウンスされます。 更新プログラムはスケジュールされ、構成された非アクティブ期間の後にのみ完了します。

import time

# Create a conversation with the agent with memory tool enabled
conversation = openai_client.conversations.create()
print(f"Created conversation (id: {conversation.id})")

# Create an agent response to initial user message
response = openai_client.responses.create(
    input="I prefer dark roast coffee",
    conversation=conversation.id,
    extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
    # To scope memories to an end user, uncomment:
    # extra_headers={"x-memory-user-id": "<user-id>"},
)

print(f"Response output: {response.output_text}")

# After an inactivity in the conversation, memories will be extracted from the conversation and stored
print("Waiting for memories to be stored...")
time.sleep(65)

# Create a new conversation
new_conversation = openai_client.conversations.create()
print(f"Created new conversation (id: {new_conversation.id})")

# Create an agent response with stored memories
new_response = openai_client.responses.create(
    input="Please order my usual coffee",
    conversation=new_conversation.id,
    extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
)

print(f"Response output: {new_response.output_text}")
using System.Threading;

#pragma warning disable OPENAI001

// Get a response client scoped to the agent
ProjectResponsesClient responseClient =
    projectClient.ProjectOpenAIClient
        .GetProjectResponsesClientForAgent(agent.Name);

// Create an agent response to initial user message
ResponseItem request = ResponseItem.CreateUserMessageItem(
    "I prefer dark roast coffee");
ResponseResult response = responseClient.CreateResponse([request]);
// To scope memories to an end user, uncomment:
// var options = new CreateResponseOptions();
// options.InputItems.Add(request);
// var requestOptions = new RequestOptions();
// requestOptions.AddHeader("x-memory-user-id", "<user-id>");
// ClientResult result = responseClient.CreateResponse(
//     BinaryContent.Create(options), requestOptions);
// ResponseResult response = ModelReaderWriter.Read<ResponseResult>(
//     result.GetRawResponse().Content);

Console.WriteLine($"Response output: {response.GetOutputText()}");

// After inactivity, memories are extracted and stored
Console.WriteLine("Waiting for memories to be stored...");
Thread.Sleep(65_000);

// Create a new response to demonstrate cross-session recall
ResponseItem newRequest = ResponseItem.CreateUserMessageItem(
    "Please order my usual coffee");
ResponseResult newResponse = responseClient.CreateResponse(
    [newRequest]);

Console.WriteLine(
    $"Response output: {newResponse.GetOutputText()}");
import { setTimeout } from "timers/promises";

const openaiClient = project.getOpenAIClient();

// Create a conversation with the agent with memory tool enabled
const conversation = await openaiClient.conversations.create();
console.log(`Created conversation (id: ${conversation.id})`);

// Create an agent response to initial user message
const response = await openaiClient.responses.create(
  {
    conversation: conversation.id,
    input: "I prefer dark roast coffee",
  },
  {
    body: {
      agent: { name: agent.name, type: "agent_reference" },
    },
    // To scope memories to an end user, uncomment:
    // headers: { "x-memory-user-id": "<user-id>" },
  },
);

console.log(`Response output: ${response.output_text}`);

// After inactivity, memories are extracted and stored
console.log("Waiting for memories to be stored...");
await setTimeout(65_000);

// Create a new conversation to demonstrate cross-session recall
const newConversation = await openaiClient.conversations.create();
console.log(`Created new conversation (id: ${newConversation.id})`);

// Create an agent response with stored memories
const newResponse = await openaiClient.responses.create(
  {
    conversation: newConversation.id,
    input: "Please order my usual coffee",
  },
  {
    body: {
      agent: { name: agent.name, type: "agent_reference" },
    },
  },
);

console.log(`Response output: ${newResponse.output_text}`);
curl -X POST "${FOUNDRY_PROJECT_ENDPOINT}/openai/v1/conversations" \
    -H "Authorization: Bearer ${ACCESS_TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{}'

# Copy the "id" field from the previous response
# To scope memories to an end user, add -H "x-memory-user-id: <user-id>" to the following request
curl -X POST "${FOUNDRY_PROJECT_ENDPOINT}/openai/v1/responses" \
    -H "Authorization: Bearer ${ACCESS_TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{
      "input": "I prefer dark roast coffee",
      "conversation": "{conversation-id}",
      "agent_reference": {
        "type": "agent_reference",
        "name": "MyAgent"
      }
    }'

API 経由でメモリを使用する

メモリ ストア API を使用して、メモリ ストアを直接操作できます。 まず、会話コンテンツからメモリ ストアにメモリを追加し、関連するメモリを検索してエージェントの対話のコンテキストを提供します。

メモリ ストアにメモリを追加する

メモリ ストアに会話コンテンツを提供して、メモリを追加します。 システムは、エージェントのメモリを最適化するために、メモリの抽出や統合など、データを前処理して後処理します。 この実行時間の長い操作には約 1 分かかる場合があります。

scope パラメーターを指定して、ユーザー間でメモリをセグメント化する方法を決定します。 特定のエンド ユーザー、チーム、または別の識別子にメモリのスコープを設定できます。

複数の会話ターンのコンテンツを使用してメモリ ストアを更新したり、前の更新操作 ID を使用して各ターンとチェーンの更新後に更新したりできます。

# Set scope to associate the memories with
scope = "user_123"

user_message = {
  "role": "user",
  "content": "I prefer dark roast coffee and usually drink it in the morning",
   "type": "message"
}

update_poller = project_client.beta.memory_stores.begin_update_memories(
    name=memory_store_name,
    scope=scope,
    items=[user_message], # Pass conversation items that you want to add to memory
    update_delay=0, # Trigger update immediately without waiting for inactivity
)

# Wait for the update operation to complete, but can also fire and forget
update_result = update_poller.result()
print(f"Updated with {len(update_result.memory_operations)} memory operations")
for operation in update_result.memory_operations:
    print(
        f"  - Operation: {operation.kind}, Memory ID: {operation.memory_item.memory_id}, Content: {operation.memory_item.content}"
    )

# Extend the previous update with another update and more messages
new_message = {
    "role":"user", 
    "content":"I also like cappuccinos in the afternoon", 
    "type":"message"}

new_update_poller = project_client.beta.memory_stores.begin_update_memories(
    name=memory_store_name,
    scope=scope,
    items=[new_message],
    previous_update_id=update_poller.update_id, # Extend from previous update ID
    update_delay=0, # Trigger update immediately without waiting for inactivity
)
new_update_result = new_update_poller.result()
for operation in new_update_result.memory_operations:
    print(
        f"  - Operation: {operation.kind}, Memory ID: {operation.memory_item.memory_id}, Content: {operation.memory_item.content}"
    )
#pragma warning disable OPENAI001

// Set scope to associate the memories with
string scope = "user_123";

MemoryUpdateOptions memoryOptions = new(scope)
{
    UpdateDelay = 0, // Trigger update immediately without waiting for inactivity
};
memoryOptions.Items.Add(ResponseItem.CreateUserMessageItem(
    "I prefer dark roast coffee and usually drink it "
    + "in the morning"));

// Wait for the update operation to complete
MemoryUpdateResult updateResult =
    projectClient.MemoryStores.WaitForMemoriesUpdate(
        memoryStoreName: memoryStore.Name,
        options: memoryOptions,
        pollingInterval: 500);

if (updateResult.Status == MemoryStoreUpdateStatus.Failed)
{
    throw new InvalidOperationException(
        updateResult.ErrorDetails);
}
Console.WriteLine(
    $"Updated with {updateResult.Details.MemoryOperations.Count} "
    + "memory operations");
foreach (var operation in updateResult.Details.MemoryOperations)
{
    Console.WriteLine(
        $"  - Operation: {operation.Kind}, "
        + $"Memory ID: {operation.MemoryItem.MemoryId}, "
        + $"Content: {operation.MemoryItem.Content}");
}

// Extend the previous update with another message
MemoryUpdateOptions newMemoryOptions = new(scope)
{
    PreviousUpdateId = updateResult.UpdateId,
    UpdateDelay = 0, // Trigger update immediately without waiting for inactivity
};
newMemoryOptions.Items.Add(ResponseItem.CreateUserMessageItem(
    "I also like cappuccinos in the afternoon"));

MemoryUpdateResult newUpdateResult =
    projectClient.MemoryStores.WaitForMemoriesUpdate(
        memoryStoreName: memoryStore.Name,
        options: newMemoryOptions,
        pollingInterval: 500);

if (newUpdateResult.Status == MemoryStoreUpdateStatus.Failed)
{
    throw new InvalidOperationException(
        newUpdateResult.ErrorDetails);
}
foreach (var operation in newUpdateResult.Details.MemoryOperations)
{
    Console.WriteLine(
        $"  - Operation: {operation.Kind}, "
        + $"Memory ID: {operation.MemoryItem.MemoryId}, "
        + $"Content: {operation.MemoryItem.Content}");
}
const scope = "user_123";

const userMessage: Record<string, unknown> = {
  type: "message",
  role: "user",
  content: [
    {
      type: "input_text",
      text: "I prefer dark roast coffee and usually drink it in the morning",
    },
  ],
};

console.log("\nSubmitting memory update request...");
const updatePoller = project.beta.memoryStores.updateMemories(
  memoryStoreName,
  scope,
  {
    items: [userMessage],
    updateDelayInSecs: 0,
  },
);

const updateResult = await updatePoller.pollUntilDone();
console.log(
  `Updated with ${updateResult.memory_operations.length} ` +
    `memory operation(s)`,
);
for (const operation of updateResult.memory_operations) {
  console.log(
    `  - Operation: ${operation.kind}, ` +
      `Memory ID: ${operation.memory_item.memory_id}, ` +
      `Content: ${operation.memory_item.content}`,
  );
}

// Extend the previous update with another message
const newMessage = {
  role: "user",
  content: "I also like cappuccinos in the afternoon",
  type: "message",
};

const newUpdatePoller = project.beta.memoryStores.updateMemories(
  memoryStoreName,
  scope,
  {
    items: [newMessage],
    updateDelayInSecs: 0,
  },
);

const newUpdateResult = await newUpdatePoller.pollUntilDone();
console.log(
  `Updated with ${newUpdateResult.memory_operations.length} ` +
    `memory operation(s)`,
);
for (const operation of newUpdateResult.memory_operations) {
  console.log(
    `  - Operation: ${operation.kind}, ` +
      `Memory ID: ${operation.memory_item.memory_id}, ` +
      `Content: ${operation.memory_item.content}`,
  );
}
curl -X POST "${FOUNDRY_PROJECT_ENDPOINT}/memory_stores/my_memory_store:update_memories?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "user_123",
    "items": [
      {
        "type": "message",
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "I prefer dark roast coffee and usually drink it in the morning"
          }
        ]
      }
    ],
    "update_delay": 0
  }'

# Get add memory status by polling the update_id
# Use the "update_id" from previous response
UPDATE_ID=<your_update_id>
curl -X GET "${FOUNDRY_PROJECT_ENDPOINT}/memory_stores/my_memory_store/updates/${UPDATE_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"

メモリ ストア内の記憶を検索する

メモリを検索して、エージェントの対話に関連するコンテキストを取得します。 検索を絞り込むためのメモリ ストア名とスコープを指定します。

from azure.ai.projects.models import MemorySearchOptions

# Search memories by a query
query_message = {"role": "user", "content": "What are my coffee preferences?", "type": "message"}

search_response = project_client.beta.memory_stores.search_memories(
    name=memory_store_name,
    scope=scope,
    items=[query_message],
    options=MemorySearchOptions(max_memories=5)
)
print(f"Found {len(search_response.memories)} memories")
for memory in search_response.memories:
    print(f"  - Memory ID: {memory.memory_item.memory_id}, Content: {memory.memory_item.content}")
#pragma warning disable OPENAI001

// Search memories by a query
MemorySearchOptions searchOptions = new(scope)
{
    Items =
    {
        ResponseItem.CreateUserMessageItem(
            "What are my coffee preferences?")
    },
    ResultOptions = new() { MaxMemories = 5 },
};

MemoryStoreSearchResponse searchResponse =
    projectClient.MemoryStores.SearchMemories(
        memoryStoreName: memoryStore.Name,
        options: searchOptions);

Console.WriteLine(
    $"Found {searchResponse.Memories.Count} memories");
foreach (MemorySearchItem item in searchResponse.Memories)
{
    Console.WriteLine(
        $"  - Content: {item.MemoryItem.Content}");
}
const queryMessage: Record<string, unknown> = {
  type: "message",
  role: "user",
  content: [
    { type: "input_text", text: "What are my coffee preferences?" },
  ],
};

console.log("\nSearching memories for stored preferences...");
const searchResponse =
  await project.beta.memoryStores.searchMemories(
    memoryStoreName,
    scope,
    {
      items: [queryMessage],
      options: { max_memories: 5 },
    },
  );

console.log(`Found ${searchResponse.memories.length} memory item(s)`);
for (const memory of searchResponse.memories) {
  console.log(
    `  - Memory ID: ${memory.memory_item.memory_id}, ` +
      `Content: ${memory.memory_item.content}`,
  );
}
curl -X POST "${FOUNDRY_PROJECT_ENDPOINT}/memory_stores/my_memory_store:search_memories?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "user_123",
    "items": [
      {
        "type": "message",
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "What are my coffee preferences?"
          }
        ]
      }
    ],
    "options": {
      "max_memories": 5
    }
  }'

静的メモリまたはコンテキスト メモリを取得する

多くの場合、ユーザー プロファイルメモリは、ユーザーのメッセージに対するセマンティック類似性に基づいて取得できません。 各会話の先頭に静的メモリを挿入し、コンテキスト メモリを使用して各エージェントの応答を生成することをお勧めします。

  • 静的メモリを取得するには、search_memoriesscopeを使用せずに、itemsを使用してprevious_search_idを呼び出します。 これにより、スコープに関連付けられているユーザー プロファイル メモリが返されます。

  • コンテキスト メモリを取得するには、search_memoriesを最新のメッセージに設定してitemsを呼び出します。 これにより、指定されたアイテムに最も関連するユーザー プロファイルとチャットの概要メモリの両方を返すことができます。

ユーザー プロファイルとチャットの概要メモリの詳細については、「 メモリの種類」を参照してください。

メモリを削除する

警告

メモリ ストアを削除する前に、依存エージェントへの影響を考慮してください。 メモリ ストアがアタッチされているエージェントは、履歴コンテキストにアクセスできなくなる可能性があります。

メモリは、メモリ ストア内のスコープ別に整理されます。 特定のスコープのメモリを削除してユーザー固有のデータを削除することも、メモリ ストア全体を削除してすべてのスコープのすべてのメモリを削除することもできます。

スコープ別にメモリを削除する

メモリ ストア構造を維持しながら、特定のユーザーまたはグループ スコープに関連付けられているすべてのメモリを削除します。 この操作を使用して、ユーザー データ削除要求を処理するか、特定のユーザーのメモリをリセットします。

# Delete memories for a specific scope
project_client.beta.memory_stores.delete_scope(
    name=memory_store_name,
    scope="user_123"
)

print(f"Deleted memories for scope: user_123")
// Delete memories for a specific scope
MemoryStoreDeleteScopeResponse deleteScopeResponse =
    projectClient.MemoryStores.DeleteScope(
        name: memoryStore.Name,
        scope: "user_123");

Console.WriteLine(
    $"Deleted scope: {deleteScopeResponse.Name}, "
    + $"success: {deleteScopeResponse.IsDeleted}");
console.log("\nDeleting memories for scope...");
await project.beta.memoryStores.deleteScope(memoryStoreName, scope);
curl -X POST "${FOUNDRY_PROJECT_ENDPOINT}/memory_stores/my_memory_store:delete_scope?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "user_123"
  }'

メモリ ストアを削除する

すべてのスコープで、メモリ ストア全体と関連するすべてのメモリを削除します。 この操作は元に戻すことができません。

# Delete the entire memory store
delete_response = project_client.beta.memory_stores.delete(memory_store_name)
print(f"Deleted memory store: {delete_response.deleted}")
// Delete the entire memory store
DeleteMemoryStoreResponse deleteResponse =
    projectClient.MemoryStores.DeleteMemoryStore(
        name: memoryStore.Name);

Console.WriteLine(
    $"Deleted memory store: {deleteResponse.Name}, "
    + $"success: {deleteResponse.IsDeleted}");
console.log("Deleting memory store...");
await project.beta.memoryStores.delete(memoryStoreName);
curl -X DELETE "${FOUNDRY_PROJECT_ENDPOINT}/memory_stores/my_memory_store?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"

ベスト プラクティス

  • ユーザーごとのアクセス制御を実装します。 すべてのユーザー間で共有されているメモリへのアクセス権をエージェントに付与しないようにします。 scope プロパティを使用して、ユーザー別にメモリ ストアをパーティション分割します。 ユーザー間で scope を共有する場合は、 user_profile_details を使用して、個人情報を格納しないようにメモリ システムに指示します。

  • エンド ユーザーにスコープをマップします。メモリ検索ツールを使用する場合は、scopeをツール定義で{{$userId}}するように設定します。 システムは、 x-memory-user-id 要求ヘッダー (存在する場合) からユーザー ID を解決します。 それ以外の場合は、呼び出し元のMicrosoft Entra トークン ({tid}_{oid}) にフォールバックします。

  • 機密データを最小限に抑え、保護する: ユース ケースに必要なものだけを保存します。 個人データ、健康データ、機密ビジネス情報などの機密データを格納する必要がある場合は、個人を特定できる他の情報をマスキングまたは削除してください。

  • プライバシーとコンプライアンスをサポートする: データにアクセスして削除するオプションなど、ユーザーに透明性を提供します。 改ざんを防止する監査証跡にすべての削除を記録します。 システムがローカルのコンプライアンス要件と規制基準に準拠していることを確認します。

  • データをセグメント化し、メモリを分離する: マルチエージェント システムでは、メモリを論理的および運用的にセグメント化します。 お客様が独自のメモリ フットプリントを定義、分離、検査、削除できるようにします。

  • メモリ使用量の監視: トークンの使用状況とメモリ操作を追跡して、コストを把握し、パフォーマンスを最適化します。

トラブルシューティング

問題 原因 解像 度
要求は認証または承認エラーで失敗します。 あなたの ID またはプロジェクト管理 ID に必要なロールが付与されていません。 [承認] と [アクセス許可] でロールを確認します。 REST 呼び出しの場合は、新しいアクセス トークンを生成して再試行します。
会話の後に思い出が表示されません。 メモリ更新はデバウンスされるか、まだ処理されています。 待機時間を長くするか、 update_delay0 に設定して更新 API を呼び出して、すぐに処理をトリガーします。
メモリ検索は結果を返しません。 scope値は、メモリの格納時に使用されるスコープと一致しません。 更新と検索には同じスコープを使用します。 スコープをユーザーにマップする場合は、安定したユーザー識別子を使用します。
エージェントの応答では、格納されているメモリは使用されません。 エージェントがメモリ検索ツールで構成されていないか、メモリ ストア名が正しくありません。 エージェント定義に memory_search_preview ツールが含まれていることを確認し、正しいメモリ ストア名を参照します。