Skip to content

Commit b62bd2e

Browse files
author
Hasnain Virk
committed
feat: add AWS Bedrock AgentCore Memory checkpoint implementation
Implements both BaseCheckpointSaver and BaseStore for AWS Bedrock AgentCore Memory: - Full checkpoint persistence with thread isolation via sessionId - Supports all standard operations: getTuple, list, put, putWrites, deleteThread - Handles checkpoint_ns filtering and metadata search - Automatic retry logic with exponential backoff for AWS API throttling - Rate limiting (16.7 req/sec) to stay within AgentCore Memory limits - Unique actor ID generation for test isolation - Proper Unicode handling with TextEncoder/TextDecoder - Hierarchical namespace organization for data isolation - Metadata filtering and pagination for search operations - Complex JSON value support with proper serialization - Vector similarity search capabilities via RetrieveMemoryRecordsCommand - Consistent rate limiting and error handling - thread_id maps directly to sessionId in AgentCore Memory - actor_id provides user-level isolation across sessions - checkpoint_ns stored in event payload for namespace filtering - Store namespaces map to sessionId/actorId for hierarchical organization - Proper TypeScript interfaces for all AWS SDK interactions - No explicit 'any' types - uses proper type definitions - Comprehensive error handling with typed AWS error interfaces Includes comprehensive integration tests and validation test support.
1 parent ad97d94 commit b62bd2e

File tree

15 files changed

+2531
-0
lines changed

15 files changed

+2531
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# ------------------LangSmith tracing------------------
2+
LANGCHAIN_TRACING_V2=true
3+
LANGCHAIN_ENDPOINT="https://api.smith.langchain.com"
4+
LANGCHAIN_API_KEY=
5+
LANGCHAIN_PROJECT=
6+
# -----------------------------------------------------
7+
8+
# AWS Bedrock AgentCore Memory configuration
9+
AWS_REGION=<aws-region>
10+
AGENTCORE_MEMORY_ID="agent_core_memory_id_for_checkpointer_testing-F6suJWCsg"
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
module.exports = {
2+
extends: [
3+
"airbnb-base",
4+
"eslint:recommended",
5+
"prettier",
6+
"plugin:@typescript-eslint/recommended",
7+
],
8+
parserOptions: {
9+
ecmaVersion: 12,
10+
parser: "@typescript-eslint/parser",
11+
project: "./tsconfig.json",
12+
sourceType: "module",
13+
},
14+
plugins: ["@typescript-eslint", "no-instanceof"],
15+
ignorePatterns: [
16+
".eslintrc.cjs",
17+
"scripts",
18+
"node_modules",
19+
"dist",
20+
"dist-cjs",
21+
"*.js",
22+
"*.cjs",
23+
"*.d.ts",
24+
],
25+
rules: {
26+
"@typescript-eslint/no-explicit-any": "error",
27+
"@typescript-eslint/ban-ts-comment": "error",
28+
"no-process-env": 2,
29+
"no-instanceof/no-instanceof": "off",
30+
"no-param-reassign": "off",
31+
"no-plusplus": "off",
32+
"no-constant-condition": "off",
33+
"no-promise-executor-return": "off",
34+
"no-unreachable-loop": "off",
35+
"@typescript-eslint/explicit-module-boundary-types": 0,
36+
"@typescript-eslint/no-empty-function": 0,
37+
"@typescript-eslint/no-shadow": 0,
38+
"@typescript-eslint/no-empty-interface": 0,
39+
"@typescript-eslint/no-use-before-define": ["error", "nofunc"],
40+
"@typescript-eslint/no-unused-vars": ["warn", { args: "none" }],
41+
"@typescript-eslint/no-floating-promises": "error",
42+
"@typescript-eslint/no-misused-promises": "error",
43+
"arrow-body-style": 0,
44+
camelcase: 0,
45+
"class-methods-use-this": 0,
46+
"import/extensions": [2, "ignorePackages"],
47+
"import/no-extraneous-dependencies": [
48+
"error",
49+
{ devDependencies: ["**/*.test.ts", "**/*.int.test.ts"] },
50+
],
51+
"import/no-unresolved": 0,
52+
"import/prefer-default-export": 0,
53+
"keyword-spacing": "error",
54+
"max-classes-per-file": 0,
55+
"max-len": 0,
56+
"no-await-in-loop": 0,
57+
"no-bitwise": 0,
58+
"no-console": 0,
59+
"no-empty-function": 0,
60+
"no-restricted-syntax": 0,
61+
"no-shadow": 0,
62+
"no-continue": 0,
63+
"no-void": 0,
64+
"no-underscore-dangle": 0,
65+
"no-use-before-define": 0,
66+
"no-useless-constructor": 0,
67+
"no-return-await": 0,
68+
"consistent-return": 0,
69+
"no-else-return": 0,
70+
"func-names": 0,
71+
"no-lonely-if": 0,
72+
"prefer-rest-params": 0,
73+
"new-cap": ["error", { properties: false, capIsNew: false }],
74+
},
75+
overrides: [
76+
{
77+
files: ["**/*.int.test.ts"],
78+
rules: {
79+
"no-process-env": "off",
80+
},
81+
},
82+
],
83+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"$schema": "https://json.schemastore.org/prettierrc",
3+
"printWidth": 80,
4+
"tabWidth": 2,
5+
"useTabs": false,
6+
"semi": true,
7+
"singleQuote": false,
8+
"quoteProps": "as-needed",
9+
"jsxSingleQuote": false,
10+
"trailingComma": "es5",
11+
"bracketSpacing": true,
12+
"arrowParens": "always",
13+
"requirePragma": false,
14+
"insertPragma": false,
15+
"proseWrap": "preserve",
16+
"htmlWhitespaceSensitivity": "css",
17+
"vueIndentScriptAndStyle": false,
18+
"endOfLine": "lf"
19+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# @langchain/langgraph-checkpoint-aws-agentcore-memory
2+
3+
LangGraph checkpointer implementation using AWS Bedrock AgentCore Memory.
4+
5+
## Usage
6+
7+
```typescript
8+
import {
9+
AgentCoreMemorySaver,
10+
AgentCoreMemoryStore,
11+
} from "@langchain/langgraph-checkpoint-aws-agentcore-memory";
12+
13+
// Checkpointer for state persistence
14+
const checkpointer = new AgentCoreMemorySaver({
15+
memoryId: "your-memory-id",
16+
region: "us-east-1", // optional, defaults to AWS SDK default
17+
});
18+
19+
// Store for key-value data persistence
20+
const store = new AgentCoreMemoryStore({
21+
memoryId: "your-memory-id",
22+
region: "us-east-1", // optional, defaults to AWS SDK default
23+
});
24+
25+
// Use with LangGraph
26+
const graph = builder.compile({ checkpointer, store });
27+
```
28+
29+
## Configuration
30+
31+
Both `AgentCoreMemorySaver` and `AgentCoreMemoryStore` require:
32+
33+
- `memoryId`: The AWS Bedrock AgentCore Memory ID
34+
- `region` (optional): AWS region, defaults to SDK default
35+
36+
## Requirements
37+
38+
- AWS credentials configured (via environment variables, IAM roles, or AWS SDK configuration)
39+
- Access to AWS Bedrock AgentCore Memory service
40+
- Required IAM permissions for AgentCore Memory operations
41+
42+
## Features
43+
44+
### AgentCoreMemorySaver
45+
46+
- ✅ Extends `BaseCheckpointSaver` from `@langchain/langgraph-checkpoint`
47+
- ✅ Reuses serialization/deserialization from base library
48+
- ✅ Supports all standard checkpointer operations (getTuple, list, put, putWrites, deleteThread)
49+
- ✅ Thread-based state isolation using AgentCore Memory sessions
50+
- ✅ Automatic retry logic with exponential backoff for AWS API throttling
51+
- ✅ Rate limiting to stay within AgentCore Memory API limits (20 req/sec)
52+
- ✅ Unique actor ID generation for test isolation
53+
54+
### AgentCoreMemoryStore
55+
56+
- ✅ Extends `BaseStore` from `@langchain/langgraph-checkpoint`
57+
- ✅ Supports all standard store operations (get, put, delete, search, batch, listNamespaces)
58+
- ✅ Hierarchical namespace organization for data isolation
59+
- ✅ Metadata filtering and pagination for search operations
60+
- ✅ Complex JSON value support with proper serialization
61+
- ✅ Rate limiting and retry logic consistent with checkpointer
62+
- ✅ Unique actor ID generation per store instance
63+
64+
## Architecture
65+
66+
Both implementations map LangGraph concepts to AgentCore Memory:
67+
68+
### Checkpointer Mapping
69+
70+
- `thread_id``sessionId` in AgentCore Memory
71+
- `actor_id``actorId` in AgentCore Memory (required for all operations)
72+
- `checkpoint_ns` → stored in event payload and filtered during retrieval
73+
74+
### Store Mapping
75+
76+
- `namespace[0]``sessionId` in AgentCore Memory
77+
- `namespace[1]``actorId` in AgentCore Memory (with fallback to unique default)
78+
- `namespace` → stored in event payload for hierarchical organization
79+
- Store items → events with "store_item" type in AgentCore Memory
80+
81+
## Testing
82+
83+
Switch to `langgraphjs/libs/checkpoint-aws-agentcore-memory`:
84+
85+
```bash
86+
$ cd langgraphjs/libs/checkpoint-aws-agentcore-memory
87+
```
88+
89+
### Unit Tests
90+
91+
```bash
92+
pnpm test
93+
```
94+
95+
### Integration Tests
96+
97+
Integration tests require AWS credentials and a valid AgentCore Memory ID:
98+
99+
1. Copy `.env.example` to `.env`:
100+
101+
```bash
102+
cp .env.example .env
103+
```
104+
105+
2. Set your AWS configuration:
106+
107+
You will need to create an instance of AgentCore Memory in your AWS account. Make sure that AWS credentials are available for your session in your terminal environment.
108+
109+
```bash
110+
AWS_REGION=us-east-1
111+
AGENTCORE_MEMORY_ID=your-actual-memory-id
112+
```
113+
114+
3. Run integration tests:
115+
116+
```bash
117+
# Test checkpointer
118+
pnmp test:int
119+
120+
# Test store
121+
pnmp test:int:store
122+
123+
# Test both
124+
pnmp test:int && pnmp test:int:store
125+
```
126+
127+
### Validation Tests
128+
129+
Run the comprehensive validation test suite:
130+
131+
```bash
132+
# Run all validation tests
133+
./run-validation-tests.sh
134+
135+
# Run specific test suites
136+
./run-validation-tests.sh getTuple list
137+
./run-validation-tests.sh deleteThread
138+
```
139+
140+
Available test suites: `getTuple`, `list`, `put`, `putWrites`, `deleteThread`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./src/index.js";
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"name": "@langchain/langgraph-checkpoint-aws-agentcore-memory",
3+
"version": "0.1.0",
4+
"description": "LangGraph checkpointer implementation using AWS Bedrock AgentCore Memory",
5+
"type": "module",
6+
"engines": {
7+
"node": ">=18"
8+
},
9+
"main": "./index.js",
10+
"types": "./index.d.ts",
11+
"repository": {
12+
"type": "git",
13+
"url": "git@github.com:langchain-ai/langgraphjs.git"
14+
},
15+
"scripts": {
16+
"build": "pnpm turbo build:internal --filter=@langchain/langgraph-checkpoint-aws-agentcore-memory",
17+
"build:internal": "pnpm --filter @langchain/build compile @langchain/langgraph-checkpoint-aws-agentcore-memory",
18+
"clean": "rm -rf dist/ dist-cjs/ .turbo/",
19+
"prepublish": "pnpm build",
20+
"test": "vitest run --exclude='**/*.int.test.ts'",
21+
"test:watch": "vitest watch --exclude='**/*.int.test.ts'",
22+
"test:int": "vitest run src/tests/checkpoints.int.test.ts",
23+
"test:int:store": "vitest run src/tests/store.int.test.ts",
24+
"lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
25+
"lint:dpdm": "dpdm --exit-code circular:1 --no-warning --no-tree src/*.ts src/**/*.ts",
26+
"lint": "pnpm lint:eslint && pnpm lint:dpdm",
27+
"lint:fix": "pnpm lint:eslint --fix && pnpm lint:dpdm",
28+
"format": "prettier --config .prettierrc --write \"src\"",
29+
"format:check": "prettier --config .prettierrc --check \"src\""
30+
},
31+
"author": "Hasnain Virk",
32+
"license": "MIT",
33+
"dependencies": {
34+
"@aws-sdk/client-bedrock-agentcore": "^3.0.0",
35+
"@langchain/core": "^0.3.0",
36+
"@langchain/langgraph-checkpoint": "workspace:*",
37+
"@smithy/node-http-handler": "^3.0.0",
38+
"@smithy/util-retry": "^3.0.0"
39+
},
40+
"devDependencies": {
41+
"@langchain/langgraph-checkpoint-validation": "workspace:*",
42+
"@types/uuid": "^9",
43+
"@typescript-eslint/eslint-plugin": "^6.12.0",
44+
"@typescript-eslint/parser": "^6.12.0",
45+
"dotenv": "^16.0.0",
46+
"dpdm": "^3.12.0",
47+
"eslint": "^8.33.0",
48+
"eslint-config-airbnb-base": "^15.0.0",
49+
"eslint-config-prettier": "^8.6.0",
50+
"eslint-plugin-import": "^2.27.5",
51+
"eslint-plugin-no-instanceof": "^1.0.1",
52+
"eslint-plugin-prettier": "^4.2.1",
53+
"prettier": "^2.8.3",
54+
"resolve-tspaths": "^0.8.8",
55+
"typescript": "~5.1.6",
56+
"uuid": "^9",
57+
"vitest": "^3.2.4"
58+
},
59+
"publishConfig": {
60+
"access": "public"
61+
},
62+
"exports": {
63+
".": {
64+
"types": "./index.d.ts",
65+
"import": "./index.js",
66+
"require": "./dist-cjs/index.js"
67+
}
68+
},
69+
"files": [
70+
"dist/",
71+
"dist-cjs/",
72+
"index.cjs",
73+
"index.js",
74+
"index.d.ts"
75+
]
76+
}

0 commit comments

Comments
 (0)