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"] +}