Add AgentCore Memory for agent long-term memory
m
matthew.dempsky@tonal.com
ยท
2 days ago
Changes
47
added
0
removed
3
files
Description
Replaces planned AOSS-backed Knowledge Bases ($350/mo idle) with AgentCore Memory (consumption-based, no idle cost). Memory resource lives in the stateful layer alongside DynamoDB; memory_id is passed through to ephemeral layer. Agent exec role gets memory API permissions.
Details
- Branches
- add-agentcore-memory → main
- Commits
- base 80ab76f → head 3a22d52
- Last activity
- 4 hours ago
- Approval
- Pending (bakery-v6-require-approval)
Timeline
Opened
by matthew.dempsky@tonal.com
1d32e22
2 days ago
Pushed
by matthew.dempsky@tonal.com
1d32e22 → 3a22d52
2 days ago
Files Changed
M buildspec.yml
| @@ -80,6 +80,7 @@ | ||
| 80 | 80 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ |
| 81 | 81 | -var=table_name=placeholder \ |
| 82 | 82 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ |
| 83 | -var=memory_id="" \ | |
| 83 | 84 | -var=domain_name="${OLD_HASH}.${DOMAIN_SUFFIX}" \ |
| 84 | 85 | -var=zone_id="${ZONE_ID:-}" \ |
| 85 | 86 | -var=certificate_arn="${APIGW_CERT_ARN:-}" || true |
| @@ -118,6 +119,7 @@ | ||
| 118 | 119 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ |
| 119 | 120 | -var=table_name=placeholder \ |
| 120 | 121 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ |
| 122 | -var=memory_id="" \ | |
| 121 | 123 | -var=domain_name="${DOMAIN_NAME}" \ |
| 122 | 124 | -var=zone_id="${ZONE_ID:-}" \ |
| 123 | 125 | -var=certificate_arn="${APIGW_CERT_ARN:-}" |
| @@ -141,6 +143,7 @@ | ||
| 141 | 143 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ |
| 142 | 144 | -var=table_name=placeholder \ |
| 143 | 145 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ |
| 146 | -var=memory_id="" \ | |
| 144 | 147 | -var=domain_name="" \ |
| 145 | 148 | -var=zone_id="${ZONE_ID:-}" \ |
| 146 | 149 | -var=certificate_arn="${APIGW_CERT_ARN:-}" || true |
| @@ -156,6 +159,7 @@ | ||
| 156 | 159 | |
| 157 | 160 | TABLE_NAME=$(terraform output -raw table_name) |
| 158 | 161 | TABLE_ARN=$(terraform output -raw table_arn) |
| 162 | MEMORY_ID=$(terraform output -raw memory_id) | |
| 159 | 163 | cd .. |
| 160 | 164 | |
| 161 | 165 | cd ephemeral |
| @@ -166,6 +170,7 @@ | ||
| 166 | 170 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ |
| 167 | 171 | -var=table_name=$TABLE_NAME \ |
| 168 | 172 | -var=table_arn=$TABLE_ARN \ |
| 173 | -var=memory_id=$MEMORY_ID \ | |
| 169 | 174 | -var=domain_name="${DOMAIN_NAME}" \ |
| 170 | 175 | -var=zone_id="${ZONE_ID:-}" \ |
| 171 | 176 | -var=certificate_arn="${APIGW_CERT_ARN:-}" |
| @@ -80,6 +80,7 @@ | |||
| 80 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ | 80 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ |
| 81 | -var=table_name=placeholder \ | 81 | -var=table_name=placeholder \ |
| 82 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ | 82 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ |
| 83 | -var=memory_id="" \ | ||
| 83 | -var=domain_name="${OLD_HASH}.${DOMAIN_SUFFIX}" \ | 84 | -var=domain_name="${OLD_HASH}.${DOMAIN_SUFFIX}" \ |
| 84 | -var=zone_id="${ZONE_ID:-}" \ | 85 | -var=zone_id="${ZONE_ID:-}" \ |
| 85 | -var=certificate_arn="${APIGW_CERT_ARN:-}" || true | 86 | -var=certificate_arn="${APIGW_CERT_ARN:-}" || true |
| @@ -118,6 +119,7 @@ | |||
| 118 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ | 119 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ |
| 119 | -var=table_name=placeholder \ | 120 | -var=table_name=placeholder \ |
| 120 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ | 121 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ |
| 122 | -var=memory_id="" \ | ||
| 121 | -var=domain_name="${DOMAIN_NAME}" \ | 123 | -var=domain_name="${DOMAIN_NAME}" \ |
| 122 | -var=zone_id="${ZONE_ID:-}" \ | 124 | -var=zone_id="${ZONE_ID:-}" \ |
| 123 | -var=certificate_arn="${APIGW_CERT_ARN:-}" | 125 | -var=certificate_arn="${APIGW_CERT_ARN:-}" |
| @@ -141,6 +143,7 @@ | |||
| 141 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ | 143 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ |
| 142 | -var=table_name=placeholder \ | 144 | -var=table_name=placeholder \ |
| 143 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ | 145 | -var=table_arn=arn:aws:dynamodb:$REGION:000000000000:table/placeholder \ |
| 146 | -var=memory_id="" \ | ||
| 144 | -var=domain_name="" \ | 147 | -var=domain_name="" \ |
| 145 | -var=zone_id="${ZONE_ID:-}" \ | 148 | -var=zone_id="${ZONE_ID:-}" \ |
| 146 | -var=certificate_arn="${APIGW_CERT_ARN:-}" || true | 149 | -var=certificate_arn="${APIGW_CERT_ARN:-}" || true |
| @@ -156,6 +159,7 @@ | |||
| 156 | 159 | ||
| 157 | TABLE_NAME=$(terraform output -raw table_name) | 160 | TABLE_NAME=$(terraform output -raw table_name) |
| 158 | TABLE_ARN=$(terraform output -raw table_arn) | 161 | TABLE_ARN=$(terraform output -raw table_arn) |
| 162 | MEMORY_ID=$(terraform output -raw memory_id) | ||
| 159 | cd .. | 163 | cd .. |
| 160 | 164 | ||
| 161 | cd ephemeral | 165 | cd ephemeral |
| @@ -166,6 +170,7 @@ | |||
| 166 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ | 170 | -var=artifacts_bucket=$ARTIFACTS_BUCKET \ |
| 167 | -var=table_name=$TABLE_NAME \ | 171 | -var=table_name=$TABLE_NAME \ |
| 168 | -var=table_arn=$TABLE_ARN \ | 172 | -var=table_arn=$TABLE_ARN \ |
| 173 | -var=memory_id=$MEMORY_ID \ | ||
| 169 | -var=domain_name="${DOMAIN_NAME}" \ | 174 | -var=domain_name="${DOMAIN_NAME}" \ |
| 170 | -var=zone_id="${ZONE_ID:-}" \ | 175 | -var=zone_id="${ZONE_ID:-}" \ |
| 171 | -var=certificate_arn="${APIGW_CERT_ARN:-}" | 176 | -var=certificate_arn="${APIGW_CERT_ARN:-}" |
M ephemeral/ephemeral.tf
| @@ -83,6 +83,12 @@ | ||
| 83 | 83 | |
| 84 | 84 | variable "certificate_arn" { |
| 85 | 85 | description = "ACM certificate ARN for the custom domain" |
| 86 | type = string | |
| 87 | default = "" | |
| 88 | } | |
| 89 | ||
| 90 | variable "memory_id" { | |
| 91 | description = "AgentCore Memory ID (from stateful layer)" | |
| 86 | 92 | type = string |
| 87 | 93 | default = "" |
| 88 | 94 | } |
| @@ -285,6 +291,19 @@ | ||
| 285 | 291 | Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"] |
| 286 | 292 | Resource = "arn:aws:logs:*:*:*" |
| 287 | 293 | }, |
| 294 | { | |
| 295 | Sid = "AgentCoreMemory" | |
| 296 | Effect = "Allow" | |
| 297 | Action = [ | |
| 298 | "bedrock-agentcore:CreateEvent", | |
| 299 | "bedrock-agentcore:GetSession", | |
| 300 | "bedrock-agentcore:CreateSession", | |
| 301 | "bedrock-agentcore:ListMemoryRecords", | |
| 302 | "bedrock-agentcore:RetrieveMemoryRecords", | |
| 303 | "bedrock-agentcore:GetLastKTurns", | |
| 304 | ] | |
| 305 | Resource = "*" | |
| 306 | }, | |
| 288 | 307 | ] |
| 289 | 308 | }) |
| 290 | 309 | } |
| @@ -83,6 +83,12 @@ | |||
| 83 | 83 | ||
| 84 | variable "certificate_arn" { | 84 | variable "certificate_arn" { |
| 85 | description = "ACM certificate ARN for the custom domain" | 85 | description = "ACM certificate ARN for the custom domain" |
| 86 | type = string | ||
| 87 | default = "" | ||
| 88 | } | ||
| 89 | |||
| 90 | variable "memory_id" { | ||
| 91 | description = "AgentCore Memory ID (from stateful layer)" | ||
| 86 | type = string | 92 | type = string |
| 87 | default = "" | 93 | default = "" |
| 88 | } | 94 | } |
| @@ -285,6 +291,19 @@ | |||
| 285 | Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"] | 291 | Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"] |
| 286 | Resource = "arn:aws:logs:*:*:*" | 292 | Resource = "arn:aws:logs:*:*:*" |
| 287 | }, | 293 | }, |
| 294 | { | ||
| 295 | Sid = "AgentCoreMemory" | ||
| 296 | Effect = "Allow" | ||
| 297 | Action = [ | ||
| 298 | "bedrock-agentcore:CreateEvent", | ||
| 299 | "bedrock-agentcore:GetSession", | ||
| 300 | "bedrock-agentcore:CreateSession", | ||
| 301 | "bedrock-agentcore:ListMemoryRecords", | ||
| 302 | "bedrock-agentcore:RetrieveMemoryRecords", | ||
| 303 | "bedrock-agentcore:GetLastKTurns", | ||
| 304 | ] | ||
| 305 | Resource = "*" | ||
| 306 | }, | ||
| 288 | ] | 307 | ] |
| 289 | }) | 308 | }) |
| 290 | } | 309 | } |
M stateful/stateful.tf
| @@ -20,11 +20,19 @@ | ||
| 20 | 20 | source = "hashicorp/aws" |
| 21 | 21 | version = "~> 5.0" |
| 22 | 22 | } |
| 23 | awscc = { | |
| 24 | source = "hashicorp/awscc" | |
| 25 | version = "~> 1.0" | |
| 26 | } | |
| 23 | 27 | } |
| 24 | 28 | backend "s3" {} |
| 25 | 29 | } |
| 26 | 30 | |
| 27 | 31 | provider "aws" { |
| 32 | region = var.region | |
| 33 | } | |
| 34 | ||
| 35 | provider "awscc" { | |
| 28 | 36 | region = var.region |
| 29 | 37 | } |
| 30 | 38 | |
| @@ -65,6 +73,16 @@ | ||
| 65 | 73 | |
| 66 | 74 | |
| 67 | 75 | # ============================================================================ |
| 76 | # AgentCore Memory โ agent long-term memory | |
| 77 | # ============================================================================ | |
| 78 | ||
| 79 | resource "awscc_bedrockagentcore_memory" "agent" { | |
| 80 | name = replace("${var.prefix}_memory", "-", "_") | |
| 81 | event_expiry_duration = 90 | |
| 82 | } | |
| 83 | ||
| 84 | ||
| 85 | # ============================================================================ | |
| 68 | 86 | # Outputs |
| 69 | 87 | # ============================================================================ |
| 70 | 88 | |
| @@ -77,3 +95,8 @@ | ||
| 77 | 95 | description = "DynamoDB table ARN (passed to ephemeral layer)" |
| 78 | 96 | value = aws_dynamodb_table.visitors.arn |
| 79 | 97 | } |
| 98 | ||
| 99 | output "memory_id" { | |
| 100 | description = "AgentCore Memory ID (passed to ephemeral layer)" | |
| 101 | value = awscc_bedrockagentcore_memory.agent.memory_id | |
| 102 | } | |
| @@ -20,11 +20,19 @@ | |||
| 20 | source = "hashicorp/aws" | 20 | source = "hashicorp/aws" |
| 21 | version = "~> 5.0" | 21 | version = "~> 5.0" |
| 22 | } | 22 | } |
| 23 | awscc = { | ||
| 24 | source = "hashicorp/awscc" | ||
| 25 | version = "~> 1.0" | ||
| 26 | } | ||
| 23 | } | 27 | } |
| 24 | backend "s3" {} | 28 | backend "s3" {} |
| 25 | } | 29 | } |
| 26 | 30 | ||
| 27 | provider "aws" { | 31 | provider "aws" { |
| 32 | region = var.region | ||
| 33 | } | ||
| 34 | |||
| 35 | provider "awscc" { | ||
| 28 | region = var.region | 36 | region = var.region |
| 29 | } | 37 | } |
| 30 | 38 | ||
| @@ -65,6 +73,16 @@ | |||
| 65 | 73 | ||
| 66 | 74 | ||
| 67 | # ============================================================================ | 75 | # ============================================================================ |
| 76 | # AgentCore Memory โ agent long-term memory | ||
| 77 | # ============================================================================ | ||
| 78 | |||
| 79 | resource "awscc_bedrockagentcore_memory" "agent" { | ||
| 80 | name = replace("${var.prefix}_memory", "-", "_") | ||
| 81 | event_expiry_duration = 90 | ||
| 82 | } | ||
| 83 | |||
| 84 | |||
| 85 | # ============================================================================ | ||
| 68 | # Outputs | 86 | # Outputs |
| 69 | # ============================================================================ | 87 | # ============================================================================ |
| 70 | 88 | ||
| @@ -77,3 +95,8 @@ | |||
| 77 | description = "DynamoDB table ARN (passed to ephemeral layer)" | 95 | description = "DynamoDB table ARN (passed to ephemeral layer)" |
| 78 | value = aws_dynamodb_table.visitors.arn | 96 | value = aws_dynamodb_table.visitors.arn |
| 79 | } | 97 | } |
| 98 | |||
| 99 | output "memory_id" { | ||
| 100 | description = "AgentCore Memory ID (passed to ephemeral layer)" | ||
| 101 | value = awscc_bedrockagentcore_memory.agent.memory_id | ||
| 102 | } | ||