はじめに
LLM を活用したアプリケーションを構築するうえで、「メモリ」の扱いは避けて通れない課題です。単発の質問応答であれば問題になりませんが、チャットボットや長時間稼働するエージェントでは、過去の会話を適切に記憶・管理する仕組みが不可欠です。
2025年後半から2026年にかけて、Google(Gemini)、OpenAI、Anthropic の3社はそれぞれ独自のメモリ機能を API レベルで提供し始めました。しかし、その設計思想や実装方法は大きく異なります。
この記事では、3社の公式ドキュメントに基づき、以下の観点からメモリ実装を比較します。
- サーバーサイドの会話状態管理
- 永続的メモリの設計思想
- エージェント SDK におけるセッション管理
- コンテキスト管理戦略(トリミング・要約・キャッシュ)
各社の API コード例を交えながら、ユースケースに応じた選択の指針を示します。
各社のメモリアーキテクチャ概要
まず、3社のメモリ機能の全体像を俯瞰します。
Google Gemini: サーバーサイド Interactions とコンテキストキャッシュ
Gemini のメモリは、主に3つの層で構成されています。
-
Interactions API(Beta) -- サーバーサイドで会話状態を管理する最新の仕組み。
previous_interaction_idで会話を連鎖させる - Context Caching -- 大量の共通コンテンツ(ドキュメント、動画など)をキャッシュし、コスト削減と応答速度向上を実現する
- Long Context Window -- 最大200万トークンの巨大なコンテキストウィンドウを「作業メモリ」として活用する
特筆すべきは、Gemini には専用の「Memory API エンドポイント」が存在しない点です。メモリ機能はこれらの仕組みを組み合わせて実現します。
OpenAI: 階層型の会話状態管理
OpenAI は、3つの階層でメモリを提供しています。
-
Responses API --
previous_response_idによるサーバーサイド会話チェーン(30日間のTTL) - Conversations API -- TTL なしの永続的な会話オブジェクト。クロスセッションでの継続が可能
- Agents SDK のセッション -- SQLite・Redis・暗号化セッションなど、多様なバックエンドに対応したセッション管理
Chat Completions API からの移行先として設計された Responses API を基盤に、上位の抽象化レイヤーを積み重ねる構成です。
Anthropic: クライアントサイドのファイルメタファー
Anthropic のアプローチは他2社とは根本的に異なります。
-
Memory Tool -- Claude がファイルシステムのメタファーで
/memoriesディレクトリにデータを読み書きするツール。ストレージの実装は開発者が自由に選択可能 - Context Editing -- 会話が長くなった際に古いツール呼び出し結果を自動的にクリアする仕組み
-
Agent SDK のセッション --
session_idによる会話の再開
サーバーサイドにメモリを持たせるのではなく、クライアントサイドで開発者がストレージを制御するのが Anthropic の設計哲学です。
以下の図は3社のアーキテクチャの違いを示しています。
サーバーサイド会話状態管理の比較
3社とも「前回のレスポンスIDを渡すことで会話を継続する」というパターンを採用していますが、実装の詳細は異なります。
Gemini: Interactions API
Gemini の Interactions API は Beta として提供されています。previous_interaction_id を指定することで、サーバーサイドに保持された会話履歴を自動的に復元します。
以下は、Interactions API を使った基本的な会話の連鎖を示すコードです。
from google import genai
client = genai.Client(api_key="YOUR_API_KEY")
# 最初のターン
interaction1 = client.interactions.create(
model="gemini-3-flash-preview",
input="私の名前は田中です。機械学習の基盤チームで働いています。",
)
print(interaction1.output_text)
# 2回目のターン -- サーバーが会話履歴を保持しているため、文脈を覚えている
interaction2 = client.interactions.create(
model="gemini-3-flash-preview",
input="私の名前を覚えていますか?",
previous_interaction_id=interaction1.id,
)
print(interaction2.output_text)
# => "はい、田中さんですね。機械学習の基盤チームで働いていらっしゃいますね。"
Interactions API にはバックグラウンド実行の機能もあります。Deep Research エージェントなど、長時間かかるタスクに有用です。
# バックグラウンドでリサーチエージェントを実行する
interaction = client.interactions.create(
agent="deep-research-pro-preview-12-2025",
input="量子コンピューティングの最新トレンドを調査してください",
background=True, # 即座にレスポンスを返し、サーバーで処理を継続
)
# ポーリングで完了を確認する
import time
while interaction.status != "completed":
interaction = client.interactions.get(interaction.id)
time.sleep(10)
print(interaction.output_text)
データ保持期間:
| プラン | 保持期間 |
|---|---|
| 有料プラン | 55日間 |
| 無料プラン | 1日間 |
注意点: tools、system_instruction、generation_config は各リクエストで再指定が必要です。会話履歴のみがサーバーサイドで引き継がれます。
OpenAI: Responses API と previous_response_id
OpenAI の Responses API は、Chat Completions API の後継として設計されました。previous_response_id を使った会話チェーンが基本の仕組みです。
以下は、Responses API による会話の連鎖を示すコードです。
from openai import OpenAI
client = OpenAI()
# 最初のターン
response = client.responses.create(
model="gpt-4o-mini",
input="機械学習のバッチ推論パイプラインを設計したいです。",
)
print(response.output_text)
# 2回目のターン -- previous_response_id で会話を継続
response2 = client.responses.create(
model="gpt-4o-mini",
previous_response_id=response.id,
input=[{"role": "user", "content": "具体的なアーキテクチャを提案してください。"}],
)
print(response2.output_text)
OpenAI の特徴的な機能として、会話の「フォーク(分岐)」があります。同じ response.id から複数の異なる会話を分岐させることが可能です。
# 同じ response.id から2つの異なる会話を分岐させる
branch_a = client.responses.create(
model="gpt-4o-mini",
previous_response_id=response.id,
input=[{"role": "user", "content": "Kubernetes ベースの設計を提案してください。"}],
)
branch_b = client.responses.create(
model="gpt-4o-mini",
previous_response_id=response.id,
input=[{"role": "user", "content": "サーバーレスベースの設計を提案してください。"}],
)
store パラメータの挙動:
| 設定 | 動作 |
|---|---|
store=True(デフォルト) |
レスポンスを30日間サーバーに保存。ダッシュボードから確認可能 |
store=False |
サーバーに保存しない。ZDR(Zero Data Retention)ポリシーに準拠 |
課金上の注意: previous_response_id を使うと、チェーン内の過去のすべての入力トークンが入力トークンとして課金されます。ただし、OpenAI の内部キャッシュにより、Chat Completions API と比較して40〜80%のコスト改善が見込めます。
Anthropic: 手動の会話履歴管理
Anthropic の Messages API には、previous_response_id に相当するパラメータがありません。会話の継続は、開発者がメッセージ配列を自分で管理する方式です。
以下は、Messages API での基本的な会話管理を示すコードです。
import anthropic
client = anthropic.Anthropic()
# 会話履歴を自分で管理する
messages = []
# 最初のターン
messages.append({"role": "user", "content": "私の名前は田中です。"})
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=messages,
)
assistant_message = response.content[0].text
messages.append({"role": "assistant", "content": assistant_message})
# 2回目のターン -- 自分で会話履歴を渡す
messages.append({"role": "user", "content": "私の名前を覚えていますか?"})
response2 = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=messages,
)
print(response2.content[0].text)
一見シンプルですが、会話が長くなるとメッセージ配列の管理が複雑になります。この課題を解決するのが、次のセクションで説明する Memory Tool です。
サーバーサイド会話管理の比較表
| 項目 | Gemini | OpenAI | Anthropic |
|---|---|---|---|
| 仕組み | previous_interaction_id |
previous_response_id |
手動(メッセージ配列) |
| サーバー保存期間 | 有料: 55日 / 無料: 1日 | 30日(デフォルト) | サーバー保存なし |
| 会話の分岐 | 可能 | 可能 | N/A(自前で実装) |
| バックグラウンド実行 | あり | なし | なし |
| ステータス | Beta | GA | N/A |
永続的メモリの実装: 設計思想の違い
短期的な会話状態管理だけでなく、セッションをまたいで情報を永続化する「長期メモリ」の実装方法も各社で大きく異なります。
OpenAI: Conversations API -- サーバーサイドの永続会話
OpenAI の Conversations API は、Responses API の上位に位置するレイヤーです。previous_response_id が30日間の TTL を持つのに対し、Conversations API で作成した会話オブジェクトには TTL がなく、永続的に保持されます。
以下は、Conversations API の基本的な使い方を示すコードです。
from openai import OpenAI
client = OpenAI()
# 会話オブジェクトを作成する
conversation = client.conversations.create()
print(f"会話ID: {conversation.id}")
# 会話に紐づけてレスポンスを生成する
response = client.responses.create(
model="gpt-4o-mini",
input="Kubernetes のポッドスケジューリングについて教えてください。",
conversation_id=conversation.id,
)
print(response.output_text)
# 同じ conversation_id で会話を継続する(previous_response_id は不要)
response2 = client.responses.create(
model="gpt-4o-mini",
input="カスタムスケジューラーの実装方法は?",
conversation_id=conversation.id,
)
print(response2.output_text)
Conversations API と previous_response_id の使い分けをまとめます。
| 特徴 | previous_response_id |
Conversations API |
|---|---|---|
| 保持期間 | 30日間 TTL | TTL なし(無期限) |
| 識別子 | レスポンスIDのチェーン | 単一の会話ID |
| 分岐 | 可能(同一IDから分岐) | 線形スレッド |
| セットアップ | 不要 | 会話オブジェクトの作成が必要 |
| 用途 | 短期的なインタラクション | 長期的なクロスセッション会話 |
Gemini: Interactions API + Context Caching
Gemini には Conversations API に直接対応するものはありませんが、Interactions API 自体が55日間の保持期間を持ちます。加えて、Context Caching を使うことで、大量のドキュメントを効率的に再利用できます。
以下は、Context Caching の基本的な使い方を示すコードです。
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_API_KEY")
# ドキュメントをアップロードする
document = client.files.upload(
file="architecture_spec.pdf",
config=dict(mime_type="application/pdf"),
)
# キャッシュを作成する(TTL: 1時間)
cache = client.caches.create(
model="models/gemini-3-flash-preview",
config=types.CreateCachedContentConfig(
display_name="architecture_cache",
system_instruction="あなたはアーキテクチャの専門家です。",
contents=[document],
ttl="3600s",
),
)
# キャッシュを使ってクエリを実行する(キャッシュされたトークンは最大90%割引)
response = client.models.generate_content(
model="models/gemini-3-flash-preview",
contents="このドキュメントの設計上の課題を3つ挙げてください。",
config=types.GenerateContentConfig(cached_content=cache.name),
)
print(response.text)
Context Caching の料金体系は以下のとおりです。
| モデル世代 | キャッシュヒット時の割引率 | ストレージコスト |
|---|---|---|
| Gemini 2.5 以降 | 入力トークンの90%割引 | $1〜$4.50 / 100万トークン / 時間 |
| Gemini 2.0 | 入力トークンの75%割引 | 同上 |
Anthropic: Memory Tool -- ファイルシステムメタファー
Anthropic の Memory Tool は、2025年9月にパブリックベータとして公開されました。他2社がサーバーサイドで会話状態を管理するのに対し、Anthropic は Claude に「ファイル操作」のツールを与え、開発者が用意したストレージにデータを読み書きさせるアプローチを取ります。
以下の図は Memory Tool のアーキテクチャを示しています。
以下は、Memory Tool を有効にした API 呼び出しの基本コードです。
import anthropic
client = anthropic.Anthropic()
# Memory Tool を有効にしてメッセージを送信する
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2048,
messages=[
{"role": "user", "content": "TypeScript のプロジェクトで ESLint の設定を最適化したい。"}
],
tools=[
{"type": "memory_20250818", "name": "memory"}
],
)
# Claude はまず /memories ディレクトリを確認し、
# 過去のプロジェクト設定を参照してから回答を生成する
for block in response.content:
if block.type == "text":
print(block.text)
elif block.type == "tool_use":
print(f"Memory 操作: {block.name} - {block.input}")
Memory Tool は6つのコマンドを持ちます。Claude がこれらのコマンドを自律的に発行し、開発者のアプリケーションが実際のストレージ操作を実行します。
| コマンド | 用途 | 主なフィールド |
|---|---|---|
view |
ディレクトリ一覧またはファイル内容を読む |
path, view_range(行範囲指定) |
create |
新しいファイルを作成する |
path, file_text
|
str_replace |
ファイル内のテキストを置換する |
path, old_str, new_str
|
insert |
特定の行にテキストを挿入する |
path, insert_line, insert_text
|
delete |
ファイルまたはディレクトリを削除する | path |
rename |
ファイルまたはディレクトリをリネームする |
old_path, new_path
|
SDK にはストレージバックエンドの実装ヘルパーが用意されています。以下は Python SDK を使った実装例です。
import anthropic
from anthropic.types.beta import (
BetaMemoryTool20250818ViewCommand,
BetaMemoryTool20250818CreateCommand,
BetaMemoryTool20250818StrReplaceCommand,
)
client = anthropic.Anthropic()
# ローカルファイルシステムを使ったメモリ実装の例
MEMORY_DIR = "./memories"
def handle_memory_command(command):
"""Claude からのメモリコマンドを処理する"""
if isinstance(command, BetaMemoryTool20250818ViewCommand):
path = os.path.join(MEMORY_DIR, command.path.lstrip("/memories/"))
if os.path.isdir(path):
entries = os.listdir(path)
return "\n".join(entries)
else:
with open(path, "r") as f:
return f.read()
elif isinstance(command, BetaMemoryTool20250818CreateCommand):
path = os.path.join(MEMORY_DIR, command.path.lstrip("/memories/"))
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w") as f:
f.write(command.file_text)
return f"File created successfully at: {command.path}"
elif isinstance(command, BetaMemoryTool20250818StrReplaceCommand):
path = os.path.join(MEMORY_DIR, command.path.lstrip("/memories/"))
with open(path, "r") as f:
content = f.read()
content = content.replace(command.old_str, command.new_str, 1)
with open(path, "w") as f:
f.write(content)
return "The memory file has been edited."
セキュリティ上の注意点:
- パストラバーサル攻撃の防止が必須です。すべてのパスが
/memories配下であることを検証してください -
../や URL エンコードされたトラバーサルシーケンスを拒否してください - ファイルサイズの上限を設けることを推奨します
- 長期間アクセスされていないファイルの自動削除を検討してください
エージェント SDK におけるメモリ
各社はエージェント SDK を提供しており、セッション管理の仕組みもそれぞれ異なります。
OpenAI Agents SDK: 多様なセッションバックエンド
OpenAI の Agents SDK は、agents.extensions.memory モジュールでセッション管理を提供しています。特徴は、多様なストレージバックエンドに対応している点です。
| セッションタイプ | バックエンド | 用途 |
|---|---|---|
SQLiteSession |
SQLite | ローカル開発、小規模アプリ |
RedisSession |
Redis | 分散・低レイテンシ環境 |
SQLAlchemySession |
任意のRDB | プロダクション環境 |
OpenAIConversationsSession |
Conversations API | OpenAI サーバー管理のストレージ |
EncryptedSession |
任意のバックエンドをラップ | セキュリティ + TTL が必要な場合 |
以下は、SQLite セッションを使った基本的なエージェント実装です。
from agents import Agent, Runner
from agents.extensions.memory import SQLiteSession
# エージェントを定義する
agent = Agent(
name="Assistant",
instructions="簡潔に回答してください。",
)
# SQLite セッションを作成する
session = SQLiteSession(
session_id="conversation_123",
db_path="conversations.db",
)
# 最初のターン -- セッションが自動的に会話履歴を保存する
result = await Runner.run(
agent,
"Golden Gate Bridge はどの都市にありますか?",
session=session,
)
print(result.final_output)
# 2回目のターン -- 前の会話のコンテキストが自動的に含まれる
result2 = await Runner.run(
agent,
"その都市の人口は?",
session=session,
)
print(result2.final_output)
Redis セッションを使う場合は以下のようになります。
from agents import Agent, Runner
from agents.extensions.memory import RedisSession
agent = Agent(name="Assistant", instructions="簡潔に回答してください。")
# Redis セッションを作成する
session = RedisSession.from_url(
session_id="user_456",
url="redis://localhost:6379/0",
)
result = await Runner.run(agent, "こんにちは", session=session)
さらに、RunContextWrapper を使うと、ローカルの Python オブジェクトをエージェントの状態として保持できます。
from dataclasses import dataclass, field
from agents import Agent, Runner, RunContextWrapper
@dataclass
class UserState:
"""ユーザーの状態を保持するデータクラス"""
username: str
preferences: dict = field(default_factory=dict)
memory_notes: list[str] = field(default_factory=list)
# メモリに書き込むツールを定義する
async def save_note(wrapper: RunContextWrapper[UserState], note: str) -> str:
"""ユーザーのメモリにメモを保存する"""
wrapper.context.memory_notes.append(note)
return f"メモを保存しました: {note}"
agent = Agent[UserState](
name="PersonalAssistant",
instructions="ユーザーの好みを記憶するパーソナルアシスタントです。",
tools=[save_note],
)
# エージェントを実行する
state = UserState(username="tanaka")
result = await Runner.run(
agent,
"ダークモードが好きだと覚えておいて",
context=state,
)
# state.memory_notes に ["ダークモードが好き"] が保存される
ポイントとして、RunContextWrapper のコンテキストオブジェクトは LLM には送信されません。LLM にコンテキストを伝えるには、instructions を動的に生成して関連情報を注入する必要があります。
Anthropic Agent SDK: セッションの再開
Anthropic の Agent SDK(旧 Claude Code SDK)は、session_id を使ったセッション管理を提供しています。
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
# 最初のセッションを開始する
session_id = None
async for message in query(
prompt="auth.py のバグを見つけて修正してください。",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Bash"],
),
):
session_id = message.session_id # セッションIDを取得
print(message)
# 同じセッションを再開する
async for message in query(
prompt="修正したバグのテストを書いてください。",
options=ClaudeAgentOptions(
resume=session_id, # セッションを再開
allowed_tools=["Read", "Write", "Bash"],
),
):
print(message)
asyncio.run(main())
Anthropic Agent SDK はサブエージェントの仕組みも備えています。メインエージェントが Task ツールを通じてサブエージェントにタスクを委譲できます。
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async for message in query(
prompt="コードレビューエージェントを使ってこのコードベースをレビューしてください。",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "Task"],
agents={
"code-reviewer": AgentDefinition(
description="コードレビューの専門家",
prompt="コード品質を分析し、改善点を提案してください。",
tools=["Read", "Glob", "Grep"],
),
},
),
):
print(message)
Gemini: ADK と Interactions API の統合
Gemini の Agent Development Kit(ADK)は、Interactions API と統合することで、エージェントにサーバーサイドの会話状態管理を持たせることができます。
from google.adk import Agent
from google.adk.models import Gemini
from google.adk.tools import GoogleSearchTool
# Interactions API を使うエージェントを定義する
root_agent = Agent(
model=Gemini(
model="gemini-2.5-flash",
use_interactions_api=True, # Interactions API を有効にする
),
name="research_agent",
tools=[
GoogleSearchTool(),
get_current_weather,
],
)
ADK は A2A(Agent-to-Agent)プロトコルにも対応しており、エージェント間の連携が可能です。A2A の SendMessage が interactions.create に、A2A の Task が Interaction ID にマッピングされます。
エージェント SDK 比較表
| 項目 | OpenAI Agents SDK | Anthropic Agent SDK | Gemini ADK |
|---|---|---|---|
| 言語 | Python | Python, TypeScript | Python |
| セッション管理 | SQLite, Redis, RDB, Conversations API など | session_id による再開 | Interactions API 統合 |
| サブエージェント | Handoffs | Task ツール | A2A プロトコル |
| ガードレール | 入出力バリデーション | パーミッション制御 | -- |
| MCP 対応 | あり | あり | あり(Gemini 3 は未対応) |
| ローカル状態 | RunContextWrapper | CLAUDE.md / MEMORY.md | -- |
コンテキスト管理戦略
会話が長くなるにつれて、コンテキストウィンドウの上限に達するリスクがあります。各社はこの問題に対して異なるアプローチを提供しています。
トリミング(Last-N ターン)
最新の N ターンだけを保持し、古い会話を捨てる手法です。最もシンプルですが、長期的な文脈が失われます。
OpenAI Agents SDK では、カスタムセッションとしてトリミングを実装できます。
from collections import deque
from agents.extensions.memory import SessionABC
class TrimmingSession(SessionABC):
"""最新 N ターンだけを保持するセッション"""
def __init__(self, session_id: str, max_turns: int = 8):
self.session_id = session_id
self.max_turns = max(1, int(max_turns))
self._items: deque = deque()
async def get_items(self, limit=None):
trimmed = self._trim_to_last_turns(list(self._items))
return trimmed[-limit:] if limit else trimmed
async def add_items(self, items):
self._items.extend(items)
def _trim_to_last_turns(self, items):
"""最新 max_turns 個のユーザーメッセージを含むサフィックスを返す"""
count = 0
start_idx = 0
for i in range(len(items) - 1, -1, -1):
if items[i].get("role") == "user":
count += 1
if count == self.max_turns:
start_idx = i
break
return items[start_idx:]
要約(Summarization)
古い会話を LLM で要約し、コンパクトに圧縮する手法です。OpenAI Agents SDK のコンパクションセッションがこれに該当します。
from agents.extensions.memory import OpenAIResponsesCompactionSession, SQLiteSession
# SQLite セッションをラップし、自動コンパクション機能を追加する
inner_session = SQLiteSession("user_789", db_path="conversations.db")
session = OpenAIResponsesCompactionSession(inner_session=inner_session)
# 通常どおりエージェントを実行する -- 自動的にコンパクションが行われる
result = await Runner.run(agent, "最新の質問", session=session)
# 手動でコンパクションを実行することも可能
await session.run_compaction()
Anthropic の Context Editing
Anthropic は context_management パラメータで、古いツール呼び出し結果を自動的にクリアする仕組みを提供しています。
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=4096,
messages=messages,
tools=[
{"type": "memory_20250818", "name": "memory"},
],
context_management={
"edits": [
{
"type": "clear_tool_uses_20250919",
# 入力トークンが 100,000 を超えたらクリアをトリガーする
"trigger": {"type": "input_tokens", "value": 100000},
# 最新3つのツール呼び出しは保持する
"keep": {"type": "tool_uses", "value": 3},
}
]
},
)
Memory Tool のツール呼び出しをクリア対象から除外することも可能です。
context_management = {
"edits": [
{
"type": "clear_tool_uses_20250919",
"trigger": {"type": "input_tokens", "value": 100000},
"keep": {"type": "tool_uses", "value": 3},
"exclude_tools": ["memory"], # Memory Tool はクリアしない
}
]
}
Anthropic の公式評価によると、Memory Tool + Context Editing の組み合わせで以下の改善が報告されています。
- 拡張ワークフロー(100ターンの Web 検索)で 84%のトークン削減
- エージェント検索タスクで 39%のパフォーマンス向上(Memory Tool + Context Editing)
- Context Editing 単体で 29%のパフォーマンス向上
Gemini のコンテキストウィンドウ戦略
Gemini は他社と異なり、巨大なコンテキストウィンドウ自体を「メモリ」として活用するアプローチを取っています。
| モデル | コンテキストウィンドウ |
|---|---|
| Gemini 2.5 Pro / 3.1 Pro | 最大200万トークン |
| Gemini 2.5 / 3 Flash | 最大100万トークン |
200万トークンは、約5万行のコードまたは8冊の小説に相当します。多くのユースケースでは、コンテキストウィンドウの上限に達する前にタスクが完了します。
コンテキスト管理戦略の比較表
| 戦略 | OpenAI | Anthropic | Gemini |
|---|---|---|---|
| トリミング | カスタムセッション実装 | -- | -- |
| 要約・コンパクション | OpenAIResponsesCompactionSession |
Context Editing + Compaction | -- |
| キャッシュ | 自動キャッシュ(40〜80%コスト削減) | Prompt Caching(最大90%削減) | Context Caching(最大90%削減) |
| 大コンテキストウィンドウ | 128Kトークン | 200Kトークン | 最大200万トークン |
総合比較表
以下に、3社のメモリ実装を主要な観点で一覧比較します。
| 比較項目 | Gemini | OpenAI | Anthropic |
|---|---|---|---|
| 会話チェーン |
previous_interaction_id(Beta) |
previous_response_id(GA) |
手動管理 |
| 永続会話 | Interactions API(55日) | Conversations API(TTL なし) | Memory Tool(開発者管理) |
| メモリの管理主体 | サーバーサイド | サーバーサイド | クライアントサイド |
| ストレージの柔軟性 | 低(Google管理のみ) | 中(SDK で複数バックエンド対応) | 高(開発者が自由に実装) |
| エージェント SDK | ADK | Agents SDK | Agent SDK |
| セッション管理 | Interactions API 統合 | SQLite / Redis / RDB / Conversations | session_id による再開 |
| コンテキスト管理 | 巨大コンテキストウィンドウ | コンパクション / トリミング | Context Editing + Memory Tool |
| コンテキストキャッシュ | Context Caching(最大90%割引) | 自動キャッシュ | Prompt Caching(最大90%割引) |
| コンテキストウィンドウ | 最大200万トークン | 最大128Kトークン | 最大200Kトークン |
| 追加コスト | キャッシュストレージ費用 | トークン課金のみ | トークン課金のみ |
| ステータス | Beta(Interactions API) | GA | Beta(Memory Tool) |
ユースケース別推奨
チャットボット(短期的な会話)
短期的な会話を管理するチャットボットには、OpenAI の Responses API が最も適しています。previous_response_id を渡すだけで会話が継続でき、追加のセットアップが不要です。GA(一般提供)のステータスも安心材料です。
Gemini の Interactions API も同様に使えますが、Beta であることに留意してください。
長時間稼働エージェント
コーディングエージェントやリサーチエージェントなど、長時間にわたってタスクを実行するエージェントには、Anthropic の Memory Tool + Context Editing の組み合わせが効果的です。必要な情報をファイルに書き出し、不要になった古いコンテキストを自動クリアすることで、数百ターンに及ぶ会話でもコンテキストウィンドウを効率的に使えます。
大量ドキュメントの参照
数千ページのドキュメントを参照しながら質問応答を行うユースケースには、Gemini の Context Caching + 巨大コンテキストウィンドウ が圧倒的に有利です。200万トークンのウィンドウに加え、キャッシュによる90%のコスト削減が実現します。
クロスセッションのパーソナライゼーション
ユーザーの好みや過去のインタラクションを長期的に記憶するアプリケーションには、2つの選択肢があります。
- OpenAI の Conversations API -- サーバーサイドで永続的に会話を管理し、実装負荷を抑えたい場合
- Anthropic の Memory Tool -- ストレージを完全に制御し、独自のメモリ構造を設計したい場合
ユースケース別推奨まとめ
| ユースケース | 推奨 | 理由 |
|---|---|---|
| 短期チャットボット | OpenAI Responses API | GA、セットアップ不要、低い実装コスト |
| 長時間エージェント | Anthropic Memory Tool + Context Editing | 84%のトークン削減、柔軟なメモリ管理 |
| 大量ドキュメント参照 | Gemini Context Caching | 200万トークンのウィンドウ、90%のコスト削減 |
| クロスセッション会話 | OpenAI Conversations API | TTL なし、サーバー管理、低い運用負荷 |
| カスタムメモリ設計 | Anthropic Memory Tool | ストレージの完全な制御が可能 |
| バックグラウンドリサーチ | Gemini Interactions API | バックグラウンド実行に対応 |
まとめ
Gemini・OpenAI・Anthropic の3社は、LLM API におけるメモリ機能をそれぞれ異なるアプローチで提供しています。
Gemini は、Interactions API によるサーバーサイドの会話管理と、巨大なコンテキストウィンドウ(最大200万トークン)を強みとしています。Context Caching と組み合わせることで、大量のドキュメントを効率的に参照するユースケースに特に適しています。ただし、Interactions API は Beta のため、プロダクション環境での利用には注意が必要です。
OpenAI は、Responses API → Conversations API → Agents SDK という階層構造で、段階的に抽象度を上げていくアプローチを取っています。短期的な会話チェーンから永続的なクロスセッション管理まで、幅広いユースケースに対応する成熟したエコシステムを構築しています。
Anthropic は、Memory Tool というファイルシステムメタファーでクライアントサイドのメモリ管理を実現するユニークなアプローチを取っています。サーバーサイドの制約を受けず、ストレージの選択や構造設計を開発者が完全に制御できます。Context Editing との組み合わせにより、長時間のエージェントタスクで高い効率を発揮します。
どのアプローチが最適かは、アプリケーションの要件次第です。まずはそれぞれの特徴を理解し、ユースケースに応じて適切な選択をすることが重要です。各社の API は急速に進化しているため、公式ドキュメントの最新情報も併せて確認してください。