コンテンツにスキップ

第6章 記憶を管理する「メモリー」 — 学習メモ

書籍「Amazon Bedrock AgentCore実践入門」第6章のサンプルコード(このフォルダ)を読み解いた個人学習メモ。 AgentCore 全体像は ../../lectures/agentcore_basics/STUDY_NOTES.md 参照。 実行検証は伴わない(コードの構造から解説)。コードに現れた API 名だけ断定し、読めない挙動は「〜と推測」で明示する。

一言で

Memory = 会話を「短期記憶(生ログ)」と「長期記憶(要約・検索可能)」の2段に分けて持つマネージドストア。

効いている対比は2つ。

  1. 短期記憶 vs 長期記憶(何を・いつ引けるか): 短期は直近の発話をそのまま返す即時アクセス(get_last_k_turns)。長期はバックグラウンドで要約・抽出された特徴をセマンティック検索で引く(search_long_term_memories)。長期側は非同期抽出なので、保存直後は検索しても空——これが本章最大の落とし穴。
  2. API 3レベルの自動化グラデーション: 低レベル boto3create_event/retrieve_memory_records)→ SDK(MemorySessionManageradd_turns/search_long_term_memories)→ Strands 統合(AgentCoreMemorySessionManagerAgent(session_manager=) に渡すだけ)。上に行くほど「呼ぶ API の数」が減り、最終的には呼ばなくてよくなる

全体像

flowchart TB
    L1["レベル1: 低レベル boto3<br>create_event / list_events<br>retrieve_memory_records<br>01_stm.py, 02_ltm.py"]
    L2["レベル2: AgentCore SDK<br>MemorySessionManager<br>add_turns / get_last_k_turns<br>search_long_term_memories<br>03_sdk.py"]
    L3["レベル3: Strands統合<br>AgentCoreMemorySessionManager<br>Agentのsession_manager引数へ渡すだけ<br>04_strands.py"]

    L1 -->|"手続きをsessionオブジェクトにラップ"| L2
    L2 -->|"Agentのsession_manager Iとして注入"| L3

保存から長期記憶が引けるようになるまでの時間差(03_sdk.py が1ファイルで両方を再現している流れ):

sequenceDiagram
    participant Ag as エージェント
    participant STM as 短期記憶
    participant Extract as 非同期抽出処理
    participant LTM as 長期記憶

    Ag->>STM: add_turns で発話を保存
    STM-->>Extract: バックグラウンドで抽出開始
    Note over Extract: 反映まで約70秒のラグ
    Extract->>LTM: 要約・特徴を書き込み
    Ag->>LTM: search_long_term_memories で検索
    LTM-->>Ag: 保存直後は空、待てば結果が返る

使用ライブラリ・原理

  • create_event/list_events01_stm.py: 生の会話イベント API。payloadconversational.content.textroleUSER/ASSISTANT)を積んでそのまま保存・取得するだけの薄い API。短期記憶は「発話ログの入れ物」そのもので、要約や検索は挟まらない。
  • retrieve_memory_records02_ltm.py: 長期記憶をセマンティック検索する API。namespace(後述)でスコープを絞り、searchCriteria.searchQuery に自然文を渡す。
  • 名前空間 /strategies/{STRATEGY_ID}/actors/{ACTOR_ID}/: 長期記憶を検索・保存する範囲の指定方法。STRATEGY_ID は長期記憶の抽出方式(agentcore_basics メモによると SEMANTIC/USER_PREFERENCE/SUMMARIZATION/EPISODIC)、ACTOR_ID はユーザー識別子。02_ltm.py:1203_sdk.py:1204_strands.py:12 の3ファイル全てで同じ形の f-string を組み立てている。
  • MemorySessionManager/session.add_turns/get_last_k_turns03_sdk.py: create_memory_session(actor_id=, session_id=) でセッションオブジェクトを作り、ConversationalMessage(text, MessageRole)add_turns に渡すと内部で create_event 相当を呼んでいると推測される。get_last_k_turns(k=5) は直近 k 往復を返す短期記憶側の取得 API。
  • session.search_long_term_memories(query=, namespace_prefix=): retrieve_memory_records 相当を session オブジェクト経由でラップした長期記憶検索 API。
  • AgentCoreMemoryConfig/RetrievalConfig/AgentCoreMemorySessionManager04_strands.py: Strands の session_manager インターフェース(Agent が発話の前後で保存・取得を呼び出すフック)を実装したアダプタ。retrieval_config={NAMESPACE: RetrievalConfig()} は「応答生成前に自動で長期記憶を検索し、プロンプトに注入する対象の名前空間」を宣言的に指定する仕組みと読める。

ファイル別の役割

ファイル 役割
01_stm.py 低レベル boto3 で短期記憶を保存(create_event)・取得(list_events)する最小例
02_ltm.py 低レベル boto3 で長期記憶をセマンティック検索する最小例(retrieve_memory_records
03_sdk.py SDK 層(MemorySessionManager)で短期保存→短期取得→70秒待機→長期検索まで一連の流れを1ファイルで再現
04_strands.py Strands 統合。Agent(session_manager=) に渡すだけで会話が自動的に保存・検索される
pyproject.toml 依存定義(strands-agents==1.38.0 / bedrock-agentcore==1.6.4 / boto3==1.42.96

中心コードの読み解き

03_sdk.py(短期記憶→長期記憶を1ファイルで往復する中心例)

# chapter6/03_sdk.py:15-54(抜粋)
session_manager = MemorySessionManager(memory_id=MEMORY_ID)      # ①

session = session_manager.create_memory_session(                 # ②
    actor_id=ACTOR_ID, session_id=SESSION_ID
)

session.add_turns(messages=[                                     # ③
    ConversationalMessage("私は生エビのアレルギーもあります。", MessageRole.USER)
])
session.add_turns(messages=[                                     # ③
    ConversationalMessage("承知しました、別の食材を利用します。", MessageRole.ASSISTANT)
])

turns = session.get_last_k_turns(k=5)                             # ④

time.sleep(70)                                                    # ⑤

search_results = session.search_long_term_memories(               # ⑥
    query="このユーザーの特徴は?", namespace_prefix=NAMESPACE
)
やってること なぜ
:15 MemorySessionManager(memory_id=) でマネージャーを生成 メモリーストア(MEMORY_ID)に対する操作の起点
:18-21 create_memory_session(actor_id=, session_id=) でセッションを開く 誰の・どの会話かを紐付けるコンテキスト
:24-39 add_turns で発話を USER/ASSISTANT 両方保存 短期記憶(生ログ)への書き込み。保存はここで完了する
:42 get_last_k_turns(k=5) で直近5往復を取得 短期記憶は保存直後でも即座に読める(非同期ラグが無い)
:48 time.sleep(70) で約70秒待機 長期記憶は非同期抽出のため、待たないと反映されていない
:51-54 search_long_term_memories(query=, namespace_prefix=) で長期記憶を検索 70秒待った後は要約・抽出された特徴がセマンティック検索でヒットする

04_strands.py(Strands 統合。上記が「渡すだけ」に畳まれる)

# chapter6/04_strands.py:15-31(抜粋)
memory_config = AgentCoreMemoryConfig(
    memory_id=MEMORY_ID, session_id=SESSION_ID, actor_id=ACTOR_ID,
    retrieval_config={NAMESPACE: RetrievalConfig()}      # 長期記憶の自動検索先を宣言
)
session_manager = AgentCoreMemorySessionManager(
    agentcore_memory_config=memory_config
)
agent = Agent(
    model="us.anthropic.claude-sonnet-4-6",
    session_manager=session_manager                       # 渡すだけで保存/取得が自動化
)
agent("私はトルコ料理が好きです。")

03_sdk.py で手動で呼んでいた add_turns/search_long_term_memories の呼び出しが消え、Agentsession_manager 引数に渡すだけになる。「何を呼ぶか」ではなく「何を渡すか」に変わるのがこの章のゴール

学んだこと(要点)

  • 短期/長期の分離はプロンプト肥大化への回答。全履歴を毎回詰めずに済むという点で、このリポジトリの ../../lectures/context_basics/(write/select/compress/isolate の4戦略)の考え方と同じ問題意識に立つ。手組みの trim_messages・要約圧縮に相当する部分を、Memory は「戦略指定」で肩代わりしていると読める。
  • 非同期ラグは設計上の制約として前提にする必要がある。「保存直後は検索しても空」という挙動は、UX 設計側でも「今回のセッションでは長期記憶を使わず、次回以降で効く」という前提を組み込む必要がある。
  • 3レベルの自動化グラデーションは「呼ぶ API 数」で見ると分かりやすい: レベル1(create_eventretrieve_memory_recordsの2 API を直接)→ レベル2(session オブジェクトに集約)→ レベル3(Agent に渡すだけで0回)。

落とし穴・現代版に移植するなら

  • プレースホルダー置換必須: 全4ファイルに <ここにメモリーIDを入れる>MEMORY_ID)、02_ltm.py/03_sdk.py/04_strands.py にはさらに <ここに戦略IDを入れる>STRATEGY_ID)。README(chapter6/README.md)も「書籍本文の手順でメモリーストアを作成したうえで置き換えてから実行してください」と明記。
  • 長期記憶の非同期ラグに注意: README は「01_stm.py を実行してから約1分待って 02_ltm.py を実行」と明示。03_sdk.py:48time.sleep(70) も同じ制約への対応(サンプルなので同期ブロッキングでベタ書き。実運用ではポーリングやイベント駆動に置き換えるべき箇所)。
  • README と pyproject.toml の記載に差分あり: chapter6/README.md の 6.5.1 節は uv add "bedrock-agentcore[strands-agents]==1.6.4" を案内するが、chapter6/pyproject.toml には既に extra 無しの bedrock-agentcore==1.6.4 が定義済み。04_strands.py が使う bedrock_agentcore.memory.integrations.strands.* 配下の統合コードにこの extra が必要かどうかは、この2ファイルからは確認できない(未確認のため断定しない)。
  • pins: strands-agents==1.38.0 / bedrock-agentcore==1.6.4 / boto3==1.42.96(章直下の pyproject.toml== 固定)。
  • 本章はハンズオンではなくスニペット集(README に節ラベル「【サンプルコードのみ】」)。マネコンでのメモリーストア作成自体は本文参照で、このフォルダのコードだけでは完結しない。

記事参照


作成: 2026-07-17 / 最終更新: 2026-07-17