1
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?

ワイの好みを長期記憶してくれるLINE秘書Botちゃんが欲しい:AgentCoreとStrands Agents

1
Last updated at Posted at 2026-01-03

ワイの好みを記憶してくれるLINE秘書Botちゃんが欲しい:AgentCoreとStrands Agents

はじめに

前回の記事では、短期記憶を持つLINE秘書Botちゃんを実装しました。

会話を覚えてくれるだけで少しは秘書っぽくなりますが、会話は忘れてしまうもの。
全てをDBに入れて、コンテキストとして入力するのは非現実的です。

会話は忘れてしまっても、事実や好みは長期で記憶して欲しいものです。
例えば、こんな会話ができると嬉しいです:

(1週間前)
私: 「コーヒーはブラックが好きだよ」
秘書: 「了解しました。コーヒーの好みを記録しました。」

(今日)
私: 「おすすめの飲み物は?」
秘書: 「ブラックコーヒーはいかがでしょうか?以前お好みをお聞きしました。」

AgentCoreの長期記憶機能は、会話から重要な情報(事実、好み、要約など)を自動的に抽出し、永続的に保存します。これにより、ユーザーの個人的な情報を長期間にわたって記憶できるようになります。

本記事では、以下の2つの要点に絞って、コードレベルで詳細に解説します:

  1. CDKによる長期記憶実装 - Memory Strategiesの設定
  2. Strands Agentsによるメモリ利用実装 - RetrievalConfigとパラメータの設定

これからAIエージェンにメモリ機能を追加していきたい人の参考になれば嬉しいです。

AgentCore MemoryとStrands Agentsによる短期記憶の実装が済んだ状態が前提になります。短期記憶の実装に関しては説明しないので、興味のある方は前段の記事をご覧ください。

AgentCore長期記憶(Long-term Memory)とは

Long-term Memory(LTM)は、Short-term Memory(STM)から自動的に重要な情報を抽出・統合する機能です。抽出されたインサイトはベクトルデータとして保存され、セマンティック検索により関連性の高い記憶を効率的に取得できます。

自分でベクトルデータストアを管理しなくて良いのが素晴らしいです。

AgentCoreは、以下の4つの長期記憶戦略をマネージドで提供します:

  • セマンティックメモリ戦略: 事実情報を自動抽出・保存
  • 要約戦略: 会話の要約を自動生成・保存
  • ユーザプリファレンス戦略: ユーザーの好みを自動抽出・保存(例:「甘いものが好き」)
  • エピソード記憶戦略: 過去の会話の流れやパターンを長期的に覚えさせる。

ちなみに、エピソード記憶戦略は2025年12月2日に追加された比較的新しい記憶戦略です。

解説は星さんの資料が分かりやすかったです。

1. CDKによる長期記憶実装

Memory Strategiesの定義

CDKで長期記憶を有効にするには、memoryStrategiesプロパティを追加します:
以下のドキュメントが参考になります。

lib/minimal-agentcore-stack.ts
    // Enhanced memory resource with explicit strategy names and namespaces
    this.memory = new agentcore.Memory(this, 'Memory', {
      memoryName: `PersonalSecretaryMemory_${environment}`,
      description: `Memory for Personal Secretary Agent with long-term strategies (${environment})`,
      expirationDuration: cdk.Duration.days(30),  // Events retained for 30 days
      memoryStrategies: [
        // Semantic strategy for factual information
        agentcore.MemoryStrategy.usingSemantic({
          name: `SemanticStrategy`,
          namespaces: [`/strategies/SemanticStrategy/actors/{actorId}/facts`]
        }),
        // Summarization strategy for conversation summaries
        agentcore.MemoryStrategy.usingSummarization({
          name: `SummaryStrategy`,
          namespaces: [`/strategies/SummaryStrategy/actors/{actorId}/sessions/{sessionId}/summaries`]
        }),
        // User preference strategy for personal preferences
        agentcore.MemoryStrategy.usingUserPreference({
          name: `PreferenceStrategy`,
          namespaces: [`/strategies/PreferenceStrategy/actors/{actorId}/preferences`]
        }),
      ]
    });

ポイント:

  • usingSemantic(): 事実情報を抽出(例:「コーヒーはブラックが好き」)
  • usingSummarization(): 会話の要約を生成(セッションごと)
  • usingUserPreference(): ユーザーの好みを抽出(例:「甘いものが好き」)
  • namespaces: メモリの保存先を定義({actorId}はユーザーID、{sessionId}はセッションIDに置換される)

Namespaceの構造

各Strategyは、ユーザーごとに分離されたNamespaceに保存されます:

/strategies/SemanticStrategy/actors/{actorId}/facts
/strategies/SummaryStrategy/actors/{actorId}/sessions/{sessionId}/summaries
/strategies/PreferenceStrategy/actors/{actorId}/preferences

ポイント:

  • {actorId}: ユーザーID(LINEのuserId)に置換される
  • {sessionId}: セッションID(1対1チャット、グループチャットなど)に置換される
  • ユーザーごとに完全に分離され、プライバシーが保護される
  • ドキュメントの例に倣って、Namespaceに{memoryStrategyId}を入れると、文字列エラーでデプロイに失敗したので、SemanticStrategyなど戦略毎の文字列を入れています。

  • 要約戦略は{sessionId}必須のようです。

  • エピソード記憶はまだCDKには実装されていない?ドキュメントになかったので一旦スキップしています。

IAM権限の追加

長期記憶の取得には、追加のIAM権限が必要です:

lib/minimal-agentcore-stack.ts
    // Enhanced IAM permissions for long-term memory operations
    this.agentRuntime.addToRolePolicy(
      new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        actions: [
          // Existing short-term memory permissions
          'bedrock-agentcore:CreateEvent',
          'bedrock-agentcore:ListEvents',
          'bedrock-agentcore:GetEvent',
          'bedrock-agentcore:DeleteEvent',
          'bedrock-agentcore:UpdateEvent',
          // New long-term memory permissions
          'bedrock-agentcore:RetrieveMemoryRecords',
          'bedrock-agentcore:ListMemoryRecords',
          'bedrock-agentcore:GetMemoryRecord',
          'bedrock-agentcore:DeleteMemoryRecord'
        ],
        resources: [this.memory.memoryArn, `${this.memory.memoryArn}/*`],
      })
    );

ポイント:

  • RetrieveMemoryRecords: 意味的検索でメモリレコードを取得
  • ListMemoryRecords: メモリレコードの一覧を取得
  • GetMemoryRecord: 特定のメモリレコードを取得
  • DeleteMemoryRecord: メモリレコードを削除

環境変数の設定

Strategy IDを環境変数として渡します:

lib/minimal-agentcore-stack.ts
    // AgentCore Runtime using L2 Construct
    this.agentRuntime = new agentcore.Runtime(this, 'AgentRuntime', {
      runtimeName: `PersonalSecretaryAgent_${environment}`,
      agentRuntimeArtifact: agentRuntimeArtifact,
      description: `Personal Secretary Agent Runtime for ${environment} with Nova2 Lite model`,
      environmentVariables: {
        MEMORY_ID: this.memory.memoryId,
        SEMANTIC_STRATEGY_ID: `SemanticStrategy`,
        SUMMARY_STRATEGY_ID: `SummaryStrategy`,
        PREFERENCE_STRATEGY_ID: `PreferenceStrategy`,
      },
    });

これで組み込みの長期記憶を実装できます。

スクリーンショット 2026-01-03 23.33.19.png

2. Strands Agentsによる長期記憶実装

RetrievalConfigの設定

Strands Agentsで長期記憶を利用するには、RetrievalConfigを設定します。これは、各Namespaceからどのようにメモリを取得するかを制御します:

agent-code/personal_secretary_agent.py
                # Configure retrieval for long-term memory strategies
                # Cost-optimized: Minimal retrieval with high quality thresholds
                # Use actual strategy names and namespace patterns from CDK
                retrieval_config = {
                    # Semantic memory for factual information
                    # Minimal facts, high quality only
                    "/strategies/SemanticStrategy/actors/{actorId}/facts": RetrievalConfig(
                        top_k=3,
                        relevance_score=0.6
                    ),
                    # Summarization for conversation summaries
                    # Essential summaries only, very high quality
                    # Note: Uses session-specific namespace as configured in CDK
                    f"/strategies/SummaryStrategy/actors/{actor_id}/sessions/{session_id}/summaries": RetrievalConfig(
                        top_k=2,
                        relevance_score=0.7
                    ),
                    # User preferences for personal preferences
                    # Core preferences only, high quality
                    "/strategies/PreferenceStrategy/actors/{actorId}/preferences": RetrievalConfig(
                        top_k=3,
                        relevance_score=0.5
                    )
                }

RetrievalConfigのパラメータ

top_kパラメータ

top_kは、セマンティック検索で取得するメモリレコードの最大数を指定します。

RetrievalConfig(
    top_k=3,  # 最大3件のメモリレコードを取得
    relevance_score=0.6
)

relevance_scoreパラメータ

relevance_scoreは、セマンティック検索の関連性スコアの閾値を指定します。この値以上の関連性を持つメモリレコードのみが取得されます。

RetrievalConfig(
    top_k=3,
    relevance_score=0.6  # 関連性スコアが0.6以上のレコードのみ取得
)

AgentCoreMemoryConfigの設定

RetrievalConfigAgentCoreMemoryConfigに渡します:

agent-code/personal_secretary_agent.py
                # Enhanced memory configuration with long-term memory support
                agentcore_memory_config = AgentCoreMemoryConfig(
                    memory_id=self.memory_id,  # Same memory ID with enhanced capabilities
                    session_id=session_id,
                    actor_id=actor_id,
                    retrieval_config=retrieval_config
                )

ポイント:

  • memory_id: CDKで作成したMemory ID
  • session_id: セッションID(1対1チャット、グループチャットなど)
  • actor_id: ユーザーID(LINEのuserId)
  • retrieval_config: 上記で定義したRetrievalConfig

今回はコスト抑制のため、top_kは小さめ、relevance_scoreは高めで設定しています。
秘書ちゃんの記憶に問題を感じたら調整していきます。

Agentの作成

AgentCoreMemorySessionManagerを使ってAgentを作成します:

agent-code/personal_secretary_agent.py
                session_manager = AgentCoreMemorySessionManager(
                    agentcore_memory_config=agentcore_memory_config,
                    region_name="ap-northeast-1"
                )
                
                agent = Agent(
                    system_prompt=self.system_prompt,
                    session_manager=session_manager,
                    model=BedrockModel(model_id="jp.amazon.nova-2-lite-v1:0")
                )

ポイント:

  • session_managerが自動的に長期記憶を取得し、プロンプトに組み込む
  • ユーザーがメッセージを送信すると、関連するメモリレコードが自動的に検索される

動作の流れ

  1. ユーザーがメッセージを送信(例:「コーヒーはブラックが好き」)
  2. AgentCoreが会話イベントを保存(短期記憶)
  3. Memory Strategyが自動的に情報を抽出(「コーヒーはブラックが好き」→ User Preference)
  4. 長期記憶に保存/strategies/PreferenceStrategy/actors/{userId}/preferences
  5. 次回の会話で、関連するメモリを自動取得(意味的検索)
  6. プロンプトに組み込んで応答生成

実装例:好みを覚える秘書

実際のコードでは、以下のように動作します:

# ユーザー: 「コーヒーはブラックが好きだよ」
# → AgentCoreが自動的にUser Preferenceとして抽出・保存

# 1週間後、ユーザー: 「おすすめの飲み物は?」
# → RetrievalConfigで関連メモリを検索
# → 「コーヒーはブラックが好き」というメモリが取得される
# → プロンプトに組み込まれて応答生成
# → 秘書: 「ブラックコーヒーはいかがでしょうか?以前お好みをお聞きしました。」

まとめ

本記事では、以下の2つの要点に絞って、コードレベルで詳細に解説しました:

  1. CDKによる長期記憶実装 - Memory Strategiesの設定、Namespaceの構造、IAM権限
  2. Strands Agentsによるメモリ利用実装 - RetrievalConfigの設定、top_krelevance_scoreパラメータ

AgentCoreMemory組み込みの長期記憶戦略により、ユーザーの好みや重要な情報を長期間にわたって記憶できるLINE秘書Botちゃんを実現できました。特に、CDKによる長期記憶実装例はまだ少ないため、本記事が参考になればと思います。

趣味でがっつり触れる年始の休暇はそろそろ終わってしまいますが、2026年もマイペースに作ったり触ったりアウトプットしていければと思いますので、今年もよろしくお願いします。

次はGatewayやツール追加、Amplify Gen2で秘書ちゃんの管理ダッシュボードなど追加していきたいですね。

参考資料


技術スタック

  • AWS Bedrock AgentCore (Long-Term Memory)
  • Strands Agents
  • AWS Bedrock (Nova 2 Lite)
  • AWS CDK
  • Python 3.11
  • TypeScript
1
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
1
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?