DEV Community

Cover image for Bring AI agents with Long-Term memory into production in minutes
Elizabeth Fuentes L for AWS

Posted on • Edited on • Originally published at builder.aws.com

Bring AI agents with Long-Term memory into production in minutes

Give Your AI Agents Long-Term Memory: Amazon Bedrock AgentCore Memory in Action

Part 2 of the AgentCore Series

πŸ‡»πŸ‡ͺπŸ‡¨πŸ‡± Dev.to LinkedIn GitHub Twitter Instagram YouTube

🧠 The Cross-Session Memory Problem

You deployed your first production AI agent with AgentCore Runtime. It works perfectly within conversations.

AgentCore Runtime already provides short-term memory - your agent remembers context within the same session (up to 8 hours or 15 minutes of inactivity).

But here's what happens when users return:

  • New session starts β†’ Agent forgets everything 😀
  • User preferences lost β†’ No personalization between visits πŸ€¦β€β™€οΈ
  • Previous insights gone β†’ Every interaction starts from zero πŸ“
  • No learning across sessions β†’ Same questions answered repeatedly πŸ”„

Your agent has cross-session amnesia. Each new session ID means starting over, even for the same user ID.

Amazon Bedrock AgentCore Memory solves this. Your agents remember users across sessions, learn from past interactions, and provide personalized experiences that persist beyond session boundaries.

This tutorial shows you how to add long-term memory to your agents.

🧠 Memory Architecture Explained

AgentCore Runtime (Built-in)

  • Session memory - Context within conversations (automatic)
  • Container persistence - Up to 8 hours or 15 minutes inactivity
  • Same session ID - Full conversation history maintained

AgentCore Memory (This Tutorial)

  • Cross-session persistence - Remember across different session IDs
  • Long-term extraction - Key insights stored automatically
  • User-centric storage - Same user ID, different sessions
  • Intelligent retrieval - Relevant context when needed

AgentCore Services Overview

Service Purpose Memory Features
⭐ AgentCore Runtime Serverless execution Built-in session memory, Container isolation
⭐ AgentCore Memory Cross-session persistence Long-term insights, User preferences
AgentCore Identity Credential management API keys, OAuth tokens
AgentCore Code Interpreter Code execution Secure sandbox, Data analysis
AgentCore Browser Web interaction Cloud browser automation
AgentCore Gateway API management Tool discovery, Service integration
AgentCore Observability Monitoring Tracing, Dashboards, Debugging

⭐ This tutorial: Memory service adds cross-session intelligence to Runtime's built-in session memory.

Prerequisites

Before you begin, verify that you have:

  • AWS Account with appropriate permissions
  • Python 3.10+ environment
  • AWS CLI configured with aws configure

New AWS customers receive up to $200 in credits

Start at no cost with AWS Free Tier. Get $100 USD at sign-up plus $100 USD more exploring key services.

Let's add cross-session memory to your agents. 🧠

Tutorial Roadmap:

Setup βš™οΈ β†’ Code Agent πŸ’» β†’ Test Memory βœ… β†’ Deploy πŸš€ β†’ Validate πŸ”

Estimated time: 15 minutes

git clone https://github.com/aws-samples/sample-getting-started-with-amazon-agentcore
cd 02-agentcore-memory
Enter fullscreen mode Exit fullscreen mode

Install Dependencies

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Required packages:

bedrock-agentcore
strands-agents
strands-agents-tools
aws-opentelemetry-distro
Enter fullscreen mode Exit fullscreen mode

Agent Implementation with Cross-Session Memory

Memory Configuration and Agent Creation

"""
Production-Ready AI Agent with Memory
Remembers conversations and user preferences across sessions
"""
import os
from strands import Agent
from strands_tools import calculator
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from bedrock_agentcore.memory.integrations.strands.config import AgentCoreMemoryConfig, RetrievalConfig
from bedrock_agentcore.memory.integrations.strands.session_manager import AgentCoreMemorySessionManager

app = BedrockAgentCoreApp()

MEMORY_ID = os.getenv("BEDROCK_AGENTCORE_MEMORY_ID")
REGION = os.getenv("AWS_REGION", "us-west-2")
MODEL_ID = os.getenv("MODEL_ID", "us.anthropic.claude-3-7-sonnet-20250219-v1:0")
# HTTP headers are normalized to lowercase
CUSTOM_HEADER_NAME = 'x-amzn-bedrock-agentcore-runtime-custom-actor-id'

# Global agent instance
_agent = None

def get_or_create_agent(actor_id: str, session_id: str) -> Agent:
    """
    Get existing agent or create new one with memory configuration.
    Since the container is pinned to the session ID, we only need one agent per container.
    """
    global _agent

    if _agent is None:
        # Configure memory with retrieval for user facts and preferences
        memory_config = AgentCoreMemoryConfig(
            memory_id=MEMORY_ID,
            session_id=session_id,
            actor_id=actor_id,
            retrieval_config={
                f"/users/{actor_id}/facts": RetrievalConfig(top_k=3, relevance_score=0.5),
                f"/users/{actor_id}/preferences": RetrievalConfig(top_k=3, relevance_score=0.5)
            }
        )

        # Create agent with memory session manager
        _agent = Agent(
            model=MODEL_ID,
            session_manager=AgentCoreMemorySessionManager(memory_config, REGION),
            system_prompt="You are a helpful assistant with memory. Remember user preferences and facts across conversations. Use the calculate tool for math problems.",
            tools=[calculator]
        )

    return _agent
Enter fullscreen mode Exit fullscreen mode

AgentCore Entry Point

from bedrock_agentcore import BedrockAgentCoreApp, RequestContext

@app.entrypoint
def invoke(payload, context: RequestContext):
    """AgentCore Runtime entry point with lazy-loaded agent"""

    if not MEMORY_ID:
        return {"error": "Memory not configured..."}

    # Extract actor_id from custom header (HTTP headers are lowercase)
    actor_id = 'default-user'
    if context and hasattr(context, 'request_headers') and context.request_headers:
        actor_id = context.request_headers.get(
            'x-amzn-bedrock-agentcore-runtime-custom-actor-id', 
            'default-user'
        )

    session_id = context.session_id if context else 'default-session'
    agent = get_or_create_agent(actor_id, session_id)

    prompt = payload.get("prompt", "Hello!")
    result = agent(prompt)

    return {"response": result.message.get('content', [{}])[0].get('text', str(result))}
Enter fullscreen mode Exit fullscreen mode

Memory Strategies

AgentCore Memory provides three built-in strategies for different use cases:

User Preferences Strategy

Automatically identifies and extracts user preferences, choices, and styles from conversations. This creates a persistent profile of each user for personalized interactions.

Example: An e-commerce agent remembers a user's favorite brands and preferred size, offering tailored product recommendations in future sessions.

Semantic Strategy

Identifies and extracts key factual information and contextual knowledge from conversations. This builds a persistent knowledge base about important entities, events, and details.

Example: A customer support agent remembers that order #ABC-123 relates to a specific support ticket, so you don't need to provide the order number again.

Session Summaries Strategy

Creates condensed, running summaries of conversations within a single session. This captures key topics and decisions for quick context recall.

Example: After a 30-minute troubleshooting session, the agent accesses a summary: "User reported issue with software v2.1, attempted a restart, and was provided a link to the knowledge base article."

For advanced use cases, you can configure custom strategies with overrides to fine-tune memory extraction with your own prompts and foundation models.

Deploy with Cross-Session Memory

Deploy your memory-enabled agent:

Configure Agent

agentcore configure -e my_agent_memory.py
Enter fullscreen mode Exit fullscreen mode

Select 'yes' for memory when prompted

Select 'yes' for long-term memory extraction

Custom Header Configuration

During configuration, select YES for Request Header Allow list and add:
X-Amzn-Bedrock-AgentCore-Runtime-Custom-Actor-Id

This header allows passing a user identifier to namespace memory per user. The agent extracts it from context.request_headers (normalized to lowercase).

Launch to Production

agentcore launch
Enter fullscreen mode Exit fullscreen mode

AgentCore automatically:

  • Creates cross-session memory store
  • Configures long-term extraction pipelines
  • Sets up user-centric persistence
  • Provides production endpoint

Test Cross-Session Memory in Production

Session ID Requirements

Session IDs must be at least 33 characters long for proper session management.

Custom Headers for User Identification

Long-term memory requires passing a user identifier via custom headers using boto3 event handlers. This enables memory to be namespaced per user across different sessions.

Short-term Memory Test (Same Session)

import json
import uuid
import boto3
import os
import sys

def test_short_memory(agent_arn, region=None):
    """Test short-term memory within a single session"""

    # Extract region from ARN if not provided
    if not region:
        region = agent_arn.split(':')[3]

    # Initialize client
    client = boto3.client('bedrock-agentcore', region_name=region)

    # Generate session ID
    session_id = str(uuid.uuid4())

    print(f"Testing short-term memory in session: {session_id}")
    print(f"Region: {region}")
    print("-" * 50)

    try:
        # First message - establish context
        print("Message 1: Setting context...")
        payload1 = json.dumps({"prompt": "My name is Alice and I like chocolate ice cream"}).encode()

        response1 = client.invoke_agent_runtime(
            agentRuntimeArn=agent_arn,
            runtimeSessionId=session_id,
            payload=payload1,
            qualifier="DEFAULT"
        )

        content1 = []
        for chunk in response1.get("response", []):
            content1.append(chunk.decode('utf-8'))

        result1 = json.loads(''.join(content1))
        print(f"Agent: {result1.get('response', 'No response')}")
        print()

        # Second message - test memory recall
        print("Message 2: Testing memory recall...")
        payload2 = json.dumps({"prompt": "What is my name and what do I like?"}).encode()

        response2 = client.invoke_agent_runtime(
            agentRuntimeArn=agent_arn,
            runtimeSessionId=session_id,  # Same session
            payload=payload2,
            qualifier="DEFAULT"
        )

        content2 = []
        for chunk in response2.get("response", []):
            content2.append(chunk.decode('utf-8'))

        result2 = json.loads(''.join(content2))
        print(f"Agent: {result2.get('response', 'No response')}")

        print("\nβœ“ Short-term memory test completed")

    except Exception as e:
        print(f"Error: {e}")
        import traceback
        traceback.print_exc()
Enter fullscreen mode Exit fullscreen mode

Run the test:

python test_short_memory.py "AGENT_ARN"
Enter fullscreen mode Exit fullscreen mode

Long-term Memory Test (Different Sessions)

Important: Long-term memory extraction is an asynchronous background process that can take a minute or more. For production testing, you may need to wait several minutes between storing and retrieving long-term memories.

import json
import uuid
import boto3
import os
import sys
import time

def test_long_memory(agent_arn, region=None):
    """Test long-term memory across different sessions"""

    if not region:
        region = agent_arn.split(':')[3]

    client = boto3.client('bedrock-agentcore', region_name=region)
    event_system = client.meta.events

    session_1 = str(uuid.uuid4())
    session_2 = str(uuid.uuid4())
    user_1 = f"user-{str(uuid.uuid4())[:8]}"

    # Constants for event handler
    EVENT_NAME = 'before-sign.bedrock-agentcore.InvokeAgentRuntime'
    CUSTOM_HEADER_NAME = 'X-Amzn-Bedrock-AgentCore-Runtime-Custom-Actor-Id'

    def add_custom_runtime_header(request, **kwargs):
        """Add custom header for user identification."""
        request.headers.add_header(CUSTOM_HEADER_NAME, user_1)

    try:
        # Register event handler
        handler = event_system.register_first(EVENT_NAME, add_custom_runtime_header)

        # Session 1: Store user information
        print(f"User: {user_1}")
        print(f"Session 1: {session_1}")
        # ... rest of code

        # Wait for long-term memory extraction
        print("⏳ Waiting 10 seconds for long-term memory extraction...")
        print("Note: Long-term memory is an asynchronous process that can take a minute or more.")
        time.sleep(10)

        # Session 2: Test memory recall
        # ... rest of code

        # Unregister event handler
        event_system.unregister(EVENT_NAME, handler)

Enter fullscreen mode Exit fullscreen mode

Run the test:

python test_long_memory.py "AGENT_ARN"

# Or using environment variables
export AGENT_ARN="your-agent-arn"
python test_long_memory.py
Enter fullscreen mode Exit fullscreen mode

This test verifies AgentCore Memory's cross-session persistence:

  1. Stores user preferences in session 1
  2. Waits 25 seconds for long-term memory extraction
  3. Tests recall in different session 2 (same user ID)
  4. Verifies cross-session memory works

Memory Management Operations

AgentCore Memory provides comprehensive management capabilities:

Memory Architecture Benefits

Runtime Only Runtime + AgentCore Memory
βœ… Session context (8 hours) βœ… Session context (8 hours)
❌ Lost after session ends βœ… Persistent across sessions
❌ No user learning βœ… User preferences remembered
❌ Repeat information βœ… Intelligent context retrieval
❌ Generic responses βœ… Personalized interactions

Key Cross-Session Features

  • User persistence - Same user ID, different session IDs remembered
  • Automatic extraction - Key insights stored during conversations
  • Intelligent retrieval - Relevant past context when needed
  • Preference learning - User choices persist across visits
  • Scalable architecture - Fully managed cross-session service

The invoke Function

The invoke function is the main entry point for your AgentCore agent. It:

  • Receives user prompts and context from AgentCore Runtime
  • Extracts session and actor IDs for memory management
  • Creates or retrieves the agent instance with memory configuration
  • Processes the user message and returns the response
@app.entrypoint
def invoke(payload, context):
    """AgentCore Runtime entry point with lazy-loaded agent"""
    # Extract user prompt
    prompt = payload.get("prompt", "Hello!")

    # Get session/actor info for memory
    actor_id = context.request_headers.get('X-Amzn-Bedrock-AgentCore-Runtime-Custom-Actor-Id', 'user') if context.request_headers else 'user'
    session_id = context.session_id or 'default_session'

    # Get agent with memory
    agent = get_or_create_agent(actor_id, session_id)

    # Process and return response
    result = agent(prompt)
    return {"response": result.message.get('content', [{}])[0].get('text', str(result))}
Enter fullscreen mode Exit fullscreen mode

Clean Up

Remove all resources:

agentcore destroy
Enter fullscreen mode Exit fullscreen mode

This removes AgentCore deployment, memory stores, ECR repository, IAM roles, and CloudWatch logs.

πŸŽ‰ You Just Built Cross-Session Memory AI Agents!

Your agents now remember users across sessions, learn from past interactions, and provide personalized experiences that persist beyond session boundaries. What intelligent applications will you build? πŸš€

❀️ If This Helped You

❀️ Heart it - helps others discover this tutorial

πŸ¦„ Unicorn it - if it blew your mind

πŸ”– Bookmark it - for when you need it later

πŸ“€ Share it - with your team or on social media

πŸ“š Resources

AWS Free Tier:

My Other Tutorials:

Happy building! πŸš€


Β‘Gracias!

πŸ‡»πŸ‡ͺπŸ‡¨πŸ‡± Dev.to LinkedIn GitHub Twitter Instagram YouTube

Top comments (7)

Collapse
 
ensamblador profile image
ensamblador

Tremendo

Collapse
 
hashbyt profile image
Hashbyt

totally agree

Collapse
 
camila_hinojosa_anez profile image
Camila Hinojosa Anez

awesome!!!

Collapse
 
hashbyt profile image
Hashbyt

Absolutely

Collapse
 
hashbyt profile image
Hashbyt

This is a fantastic, hands-on walkthrough for solving one of the biggest pain points with AI agents

Collapse
 
hashbyt profile image
Hashbyt

Awesome guide on AgentCore Memory! The breakdown of the cross-session amnesia problem and the clear Session vs. Cross-Session memory architecture is fantastic.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.