AWS Strands Agents + Neo4j Integration
Introduction
This sample deploys an AWS Strands Agent as an AgentCore Runtime that connects to Neo4j via the AgentCore Gateway. The agent uses Cognito OAuth for MCP authentication and AgentCore Memory for user preference tracking.
|
Prerequisite: This stack requires Sample 2: Gateway with External Neo4j MCP to be deployed first. The Gateway stack provides the Cognito OAuth setup and MCP Gateway endpoint that this agent connects to. |
Key Features:
-
Strands Agent Framework: Model-agnostic agent with streaming responses
-
AgentCore Gateway MCP: Connects to Neo4j MCP through the AgentCore Gateway (from Sample 2)
-
Cognito OAuth (M2M): Client credentials flow for secure MCP access
-
AgentCore Memory: Built-in user preference memory with per-user namespaces
-
CDK Infrastructure: Complete infrastructure-as-code deployment
Architecture
User Request
↓
AgentCore Runtime (Strands Agent)
├─ Bedrock LLM (Claude / cross-region inference)
├─ AgentCore Memory (user preferences)
└─ MCP Client → [OAuth token from Cognito]
↓
AgentCore Gateway (from Sample 2)
↓
Neo4j MCP Server
↓
Neo4j Database
Components
-
AgentCore Runtime — Runs the Strands agent code deployed from S3
-
Strands Agent — Orchestrates LLM calls, MCP tool use, and memory
-
MCP Client — Obtains Cognito OAuth tokens and calls the AgentCore Gateway
-
AgentCore Memory — Stores and retrieves user preferences across sessions
-
Secrets Manager — Stores Cognito client credentials securely
CDK Context Parameters
| Context key | Source | Description |
|---|---|---|
|
Sample 2 stack output |
Cognito app client ID |
|
Sample 2 stack output |
Cognito app client secret |
|
Sample 2 stack output |
OAuth scope (e.g. |
|
Sample 2 stack output |
Cognito token endpoint URL |
|
Sample 2 stack output |
AgentCore Gateway MCP URL |
|
Command-line argument or default |
The model ID to use for inference (for available Ids see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html), default is |
In-Depth Analysis
Authentication Flow
The MCP client (strands_agent/mcp_client/client.py) implements an OAuth 2.0 client_credentials flow with token caching:
Agent invocation
↓
MCP Client checks token cache
├─ Valid & >30 s until expiry → reuse
└─ Missing / expiring:
├─ Load credentials from Secrets Manager (cached after first call)
├─ POST client_credentials grant to Cognito
└─ Cache access_token
↓
httpx.AsyncClient with "Authorization: Bearer <token>"
↓
AgentCore Gateway (JWT validation → Interceptor swaps for Neo4j Basic Auth)
↓
Neo4j MCP Server
-
Credentials come from Secrets Manager (
SECRET_ARN) on AgentCore, with env-var fallback for local dev -
Uses
streamable_http_clientfrom the MCP SDK, wrapped in a StrandsMCPClient
Code Deployment
The agent is deployed as Python source code bundled to S3 (no container image):
-
CDK bundles
strands_agent/usinguv pip install(targetingmanylinux_2_17_aarch64/ Python 3.13) -
The bundle is uploaded as a CDK S3 Asset
-
CfnRuntimereferences the S3 location withentry_point=main.pyandPYTHON_3_13runtime -
AgentCore downloads and runs the code at invocation time
Agent Entrypoint
The handler in strands_agent/main.py uses BedrockAgentCoreApp:
-
`@app.entrypoint` — Async handler receiving
payloadandcontext -
Session ID — From
context.session_id, fallback to uuid -
Actor ID — Required in payload; namespaces memory records per user
-
Streaming —
agent.stream_async()yields text chunks to the caller
Memory
AgentCore Memory with a UserPreferenceMemoryStrategy:
-
Namespace:
/users/{actorId}/preferences/ -
Retrieval: Top 5 results, 0.5 relevance threshold
-
Custom tool:
clear_preferenceslets users reset stored preferences
The AgentCoreMemorySessionManager saves conversations and retrieves preferences before each turn.
Model
-
Model:
global.anthropic.claude-sonnet-4-6(cross-region inference profile) -
Auth: IAM via the runtime execution role
CDK Stack Resources
-
S3 Asset — Agent code + dependencies bundled via
uv -
Secrets Manager — Cognito
client_id/client_secret -
IAM Role — S3, Secrets Manager, Bedrock, AgentCore Memory, CloudWatch, X-Ray, workload identity
-
AgentCore Memory —
CfnMemorywith user preference strategy -
AgentCore Runtime —
CfnRuntime(code-based, HTTP protocol, public network)
Environment Variables
| Variable | Description |
|---|---|
|
Secrets Manager ARN for Cognito credentials |
|
AgentCore Memory resource ID |
|
AgentCore Gateway MCP endpoint |
|
OAuth scope for the Gateway |
|
Cognito token endpoint URL |
|
AWS region (set explicitly for AgentCore) |
|
The model ID to use for inference (for available Ids see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html), default is |
How to Use This Example
Prerequisites
-
AWS Account with Bedrock and AgentCore access
-
AWS CLI and CDK installed
-
Python 3.9+
-
Sample 2: Gateway with External Neo4j MCP deployed — you will need its stack outputs
Step 1: Clone the Repository
git clone https://github.com/neo4j-labs/neo4j-agent-integrations.git
cd neo4j-agent-integrations/aws-strands-agents
Step 3: Get Outputs from Sample 2
Retrieve the Cognito and Gateway values from the deployed Gateway stack:
STACK_NAME=Neo4jAgentCoreGatewayStack
GATEWAY_URL=$(aws cloudformation describe-stacks \
--stack-name "$STACK_NAME" \
--query "Stacks[0].Outputs[?OutputKey=='GatewayUrl'].OutputValue" \
--output text)
COGNITO_CLIENT_ID=$(aws cloudformation describe-stacks \
--stack-name "$STACK_NAME" \
--query "Stacks[0].Outputs[?OutputKey=='CognitoAppClientId'].OutputValue" \
--output text)
COGNITO_TOKEN_ENDPOINT=$(aws cloudformation describe-stacks \
--stack-name "$STACK_NAME" \
--query "Stacks[0].Outputs[?OutputKey=='CognitoTokenEndpoint'].OutputValue" \
--output text)
COGNITO_SCOPE=$(aws cloudformation describe-stacks \
--stack-name "$STACK_NAME" \
--query "Stacks[0].Outputs[?OutputKey=='CognitoScope'].OutputValue" \
--output text)
COGNITO_USER_POOL_ID=$(aws cloudformation describe-stacks \
--stack-name "$STACK_NAME" \
--query "Stacks[0].Outputs[?OutputKey=='CognitoUserPoolId'].OutputValue" \
--output text)
COGNITO_CLIENT_SECRET=$(aws cognito-idp describe-user-pool-client \
--user-pool-id "$COGNITO_USER_POOL_ID" \
--client-id "$COGNITO_CLIENT_ID" \
--query "UserPoolClient.ClientSecret" \
--output text)
Step 4: Deploy Infrastructure
# Bootstrap CDK (first time only)
cdk bootstrap
# Deploy the stack
cdk deploy Neo4jStrandsAgentStack \
-c cognito_client_id="$COGNITO_CLIENT_ID" \
-c cognito_client_secret="$COGNITO_CLIENT_SECRET" \
-c cognito_scope="$COGNITO_SCOPE" \
-c cognito_token_endpoint="$COGNITO_TOKEN_ENDPOINT" \
-c gateway_url="$GATEWAY_URL" \
-c model_id="global.anthropic.claude-sonnet-4-6"
Stack Outputs:
| Output | Description |
|---|---|
|
ARN of the deployed AgentCore Runtime |
|
ARN of the IAM Role for the runtime |
|
ARN of the Cognito credentials secret |
|
ID of the AgentCore Memory resource |
Step 5: Test the Agent
Open demo.ipynb and set the arn variable to the AgentRuntimeArn from the CDK output, then run the notebook.