From 58ad4131437e80bbcf5dec07ca9c64466d3f2486 Mon Sep 17 00:00:00 2001 From: Nithin Chandran Rajashankar Date: Thu, 18 Jun 2026 18:41:43 +0000 Subject: [PATCH] feat(agentcore-memory): Add AgentCore Memory pattern Deploy Amazon Bedrock AgentCore Memory with an AWS Lambda function that stores conversation events and retrieves memory records via semantic search. Enables AI agents to maintain persistent context across sessions. Uses built-in semantic extraction strategy to automatically extract long-term memory from short-term conversation events. --- agentcore-memory-cdk/.gitignore | 6 ++ agentcore-memory-cdk/README.md | 73 +++++++++++++++ agentcore-memory-cdk/bin/app.ts | 8 ++ agentcore-memory-cdk/cdk.json | 3 + agentcore-memory-cdk/example-pattern.json | 76 ++++++++++++++++ .../lib/agentcore-memory-stack.ts | 46 ++++++++++ agentcore-memory-cdk/package.json | 19 ++++ agentcore-memory-cdk/src/handler/index.py | 91 +++++++++++++++++++ agentcore-memory-cdk/tsconfig.json | 19 ++++ 9 files changed, 341 insertions(+) create mode 100644 agentcore-memory-cdk/.gitignore create mode 100644 agentcore-memory-cdk/README.md create mode 100644 agentcore-memory-cdk/bin/app.ts create mode 100644 agentcore-memory-cdk/cdk.json create mode 100644 agentcore-memory-cdk/example-pattern.json create mode 100644 agentcore-memory-cdk/lib/agentcore-memory-stack.ts create mode 100644 agentcore-memory-cdk/package.json create mode 100644 agentcore-memory-cdk/src/handler/index.py create mode 100644 agentcore-memory-cdk/tsconfig.json diff --git a/agentcore-memory-cdk/.gitignore b/agentcore-memory-cdk/.gitignore new file mode 100644 index 0000000000..888fdf2586 --- /dev/null +++ b/agentcore-memory-cdk/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +cdk.out/ +build/ +*.js +*.d.ts +cdk.context.json diff --git a/agentcore-memory-cdk/README.md b/agentcore-memory-cdk/README.md new file mode 100644 index 0000000000..4b84db6637 --- /dev/null +++ b/agentcore-memory-cdk/README.md @@ -0,0 +1,73 @@ +# Amazon Bedrock AgentCore Memory with AWS Lambda (CDK) + +This pattern deploys an Amazon Bedrock AgentCore Memory resource with an AWS Lambda function that demonstrates storing conversation events and retrieving memory records. + +Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/agentcore-memory-cdk + +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. + +## Requirements + +* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +* [Node.js 20+](https://nodejs.org/en/download/) installed +* [AWS CDK v2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) installed (`npm install -g aws-cdk`) +* CDK bootstrapped in your account/region (`cdk bootstrap`) + +## Deployment Instructions + +1. Clone the repository and navigate to the pattern directory: + ```bash + cd agentcore-memory-cdk + ``` + +2. Install dependencies: + ```bash + npm install + ``` + +3. Build and deploy: + ```bash + npx cdk deploy + ``` + +## How it works + +Amazon Bedrock AgentCore Memory provides persistent memory for AI agents: + +- **Short-term memory**: Stores raw conversation events (messages, tool calls, results) per session. Available immediately after `create_event`. +- **Long-term memory**: Automatically extracted from short-term memory using configurable strategies (semantic, summary, user profile). Enables agents to recall facts and preferences across sessions. + +The AWS Lambda function demonstrates two operations: +1. **Store**: Writes conversation events to short-term memory via `create_event` +2. **Retrieve**: Searches long-term memory records via `retrieve_memory_records` using semantic similarity + +## Testing + +Store a conversation event: +```bash +aws lambda invoke --function-name FUNCTION_NAME \ + --payload '{"action": "store", "messages": [{"role": "user", "content": "My name is Alice and I prefer Python"}, {"role": "assistant", "content": "Nice to meet you, Alice! I will remember your Python preference."}]}' \ + --cli-binary-format raw-in-base64-out output.json && cat output.json +``` + +Retrieve memory (after extraction completes, typically a few minutes): +```bash +aws lambda invoke --function-name FUNCTION_NAME \ + --payload '{"action": "retrieve", "query": "What programming language does the user prefer?"}' \ + --cli-binary-format raw-in-base64-out output.json && cat output.json +``` + +## Cleanup + +```bash +npx cdk destroy +``` + +⚠️ This will delete the Amazon Bedrock AgentCore Memory resource and all stored memory records. + +--- + +Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 diff --git a/agentcore-memory-cdk/bin/app.ts b/agentcore-memory-cdk/bin/app.ts new file mode 100644 index 0000000000..15f268fa14 --- /dev/null +++ b/agentcore-memory-cdk/bin/app.ts @@ -0,0 +1,8 @@ +#!/usr/bin/env node +import * as cdk from 'aws-cdk-lib'; +import { AgentcoreMemoryStack } from '../lib/agentcore-memory-stack'; + +const app = new cdk.App(); +new AgentcoreMemoryStack(app, 'AgentcoreMemoryStack', { + env: { region: 'us-east-1' }, +}); diff --git a/agentcore-memory-cdk/cdk.json b/agentcore-memory-cdk/cdk.json new file mode 100644 index 0000000000..debd1380e0 --- /dev/null +++ b/agentcore-memory-cdk/cdk.json @@ -0,0 +1,3 @@ +{ + "app": "node build/bin/app.js" +} diff --git a/agentcore-memory-cdk/example-pattern.json b/agentcore-memory-cdk/example-pattern.json new file mode 100644 index 0000000000..c88adb6f53 --- /dev/null +++ b/agentcore-memory-cdk/example-pattern.json @@ -0,0 +1,76 @@ +{ + "title": "Persistent AI agent memory with Amazon Bedrock AgentCore Memory", + "description": "Deploy Amazon Bedrock AgentCore Memory with an AWS Lambda function that stores conversation events and retrieves memory records, enabling AI agents to maintain context across sessions.", + "language": "TypeScript", + "level": "200", + "framework": "AWS CDK", + "introBox": { + "headline": "How it works", + "text": [ + "Amazon Bedrock AgentCore Memory provides managed short-term and long-term memory for AI agents.", + "The AWS Lambda function stores conversation events (messages, tool calls) as short-term memory.", + "AgentCore asynchronously extracts long-term memory (facts, preferences, summaries) from stored events using configurable strategies.", + "Agents retrieve relevant memory records using semantic search to maintain personalized, consistent experiences across sessions." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/agentcore-memory-cdk", + "templateURL": "serverless-patterns/agentcore-memory-cdk", + "projectFolder": "agentcore-memory-cdk", + "templateFile": "lib/agentcore-memory-stack.ts" + } + }, + "resources": { + "bullets": [ + { + "text": "Amazon Bedrock AgentCore Memory documentation", + "link": "https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/memory.html" + }, + { + "text": "Amazon Bedrock AgentCore CDK construct library", + "link": "https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_bedrockagentcore-readme.html" + } + ] + }, + "deploy": { + "text": [ + "npx cdk deploy" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "npx cdk destroy" + ] + }, + "authors": [ + { + "name": "Nithin Chandran R", + "bio": "Technical Account Manager at AWS", + "linkedin": "nithin-chandran-r" + } + ], + "patternArch": { + "icon1": { + "x": 20, + "y": 50, + "service": "lambda", + "label": "AWS Lambda" + }, + "icon2": { + "x": 80, + "y": 50, + "service": "bedrock", + "label": "AgentCore Memory" + }, + "line1": { + "from": "icon1", + "to": "icon2" + } + } +} diff --git a/agentcore-memory-cdk/lib/agentcore-memory-stack.ts b/agentcore-memory-cdk/lib/agentcore-memory-stack.ts new file mode 100644 index 0000000000..de38439137 --- /dev/null +++ b/agentcore-memory-cdk/lib/agentcore-memory-stack.ts @@ -0,0 +1,46 @@ +import * as cdk from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as agentcore from 'aws-cdk-lib/aws-bedrockagentcore'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; + +export class AgentcoreMemoryStack extends cdk.Stack { + constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + // Amazon Bedrock AgentCore Memory with built-in semantic extraction + const memory = new agentcore.Memory(this, 'AgentMemory', { + memoryName: 'agent_memory', + memoryStrategies: [ + agentcore.MemoryStrategy.usingBuiltInSemantic(), + ], + }); + + // AWS Lambda function to demonstrate memory operations + const fn = new lambda.Function(this, 'MemoryFunction', { + runtime: lambda.Runtime.PYTHON_3_12, + handler: 'index.handler', + code: lambda.Code.fromAsset('src/handler'), + timeout: cdk.Duration.seconds(30), + environment: { + MEMORY_ID: memory.memoryId, + }, + }); + + // Grant the AWS Lambda function permissions to use Amazon Bedrock AgentCore Memory + fn.addToRolePolicy(new iam.PolicyStatement({ + actions: [ + 'bedrock-agentcore:CreateEvent', + 'bedrock-agentcore:GetEvent', + 'bedrock-agentcore:ListEvents', + 'bedrock-agentcore:RetrieveMemoryRecords', + 'bedrock-agentcore:ListMemoryRecords', + ], + resources: [memory.memoryArn, `${memory.memoryArn}/*`], + })); + + // Outputs + new cdk.CfnOutput(this, 'MemoryId', { value: memory.memoryId }); + new cdk.CfnOutput(this, 'FunctionName', { value: fn.functionName }); + } +} diff --git a/agentcore-memory-cdk/package.json b/agentcore-memory-cdk/package.json new file mode 100644 index 0000000000..207c6e94e2 --- /dev/null +++ b/agentcore-memory-cdk/package.json @@ -0,0 +1,19 @@ +{ + "name": "agentcore-memory-cdk", + "version": "1.0.0", + "bin": { + "app": "build/bin/app.js" + }, + "scripts": { + "build": "tsc", + "synth": "cdk synth" + }, + "dependencies": { + "aws-cdk-lib": "^2.260.0", + "constructs": "^10.3.0" + }, + "devDependencies": { + "aws-cdk": "^2.1128.0", + "typescript": "~5.4.0" + } +} diff --git a/agentcore-memory-cdk/src/handler/index.py b/agentcore-memory-cdk/src/handler/index.py new file mode 100644 index 0000000000..f9539e04bb --- /dev/null +++ b/agentcore-memory-cdk/src/handler/index.py @@ -0,0 +1,91 @@ +""" +AWS Lambda function demonstrating Amazon Bedrock AgentCore Memory operations. +Stores conversation events and retrieves memory records for AI agent context. +""" + +import json +import os +import uuid +from datetime import datetime, timezone +import boto3 + + +def handler(event, context): + """Demonstrate Amazon Bedrock AgentCore Memory create_event and retrieve operations.""" + try: + memory_id = os.environ['MEMORY_ID'] + region = os.environ.get('AWS_REGION', 'us-east-1') + action = event.get('action', 'store') + + client = boto3.client('bedrock-agentcore', region_name=region) + + if action == 'store': + session_id = event.get('sessionId', str(uuid.uuid4())) + messages = event.get('messages', [ + {'role': 'user', 'content': 'My name is Alice and I prefer Python'}, + {'role': 'assistant', 'content': 'Nice to meet you, Alice! I noted your Python preference.'}, + ]) + actor_id = event.get('actorId', 'demo-user') + + payload = [] + for m in messages: + role = 'USER' if m['role'] == 'user' else 'ASSISTANT' + payload.append({ + 'conversational': { + 'content': {'text': m['content']}, + 'role': role, + } + }) + + response = client.create_event( + memoryId=memory_id, + actorId=actor_id, + sessionId=session_id, + eventTimestamp=datetime.now(timezone.utc), + payload=payload, + ) + + return { + 'statusCode': 200, + 'body': json.dumps({ + 'action': 'store', + 'sessionId': session_id, + 'eventId': response.get('eventId', 'created'), + }), + } + + elif action == 'retrieve': + query = event.get('query', 'What do you know about the user?') + + namespace = event.get('namespace', 'demo-user') + response = client.retrieve_memory_records( + memoryId=memory_id, + namespace=namespace, + searchCriteria={ + 'searchQuery': query, + 'topK': event.get('maxResults', 5), + }, + ) + + records = response.get('memoryRecords', []) + return { + 'statusCode': 200, + 'body': json.dumps({ + 'action': 'retrieve', + 'query': query, + 'recordCount': len(records), + 'records': [str(r) for r in records], + }, default=str), + } + + else: + return { + 'statusCode': 400, + 'body': json.dumps({'error': f'Unknown action: {action}. Use store or retrieve.'}), + } + + except Exception as e: + return { + 'statusCode': 500, + 'body': json.dumps({'error': str(e)}), + } diff --git a/agentcore-memory-cdk/tsconfig.json b/agentcore-memory-cdk/tsconfig.json new file mode 100644 index 0000000000..5eccfb04e8 --- /dev/null +++ b/agentcore-memory-cdk/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "lib": ["es2022"], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "outDir": "./build", + "rootDir": ".", + "skipLibCheck": true + }, + "exclude": ["node_modules", "cdk.out", "build"] +}