🧭 Navigation:
Home | Vision LLM Theory | Local Testing | Deployment UI | 🔵 Deployment | CDK Stacks | Runtime | S3 Files | Lambda Analyzers | Prompting System
Step-by-step AWS CDK deployment for BADGERS. For architecture overview and technical details, see the main README.
| Service | Purpose |
|---|---|
| Amazon Bedrock AgentCore | Runtime + Gateway for agent orchestration |
| Amazon Bedrock | Claude foundation model access |
| AWS Lambda | Serverless analyzer functions |
| Amazon S3 | Configuration and output storage |
| Amazon Cognito | OAuth 2.0 authentication |
| Amazon ECR | Container image registry |
| AWS Secrets Manager | Credential storage |
| AWS SSM Parameter Store | Configuration parameters |
| Amazon CloudWatch | Logging and observability |
| AWS X-Ray | Distributed tracing |
Verify your environment:
aws --version # AWS CLI
cdk --version # AWS CDK v2
docker info # Docker running
python --version # Python 3.12+
uv --version # uv package managerImportant
Docker must be running before deployment. Lambda layers and the Runtime container require Docker to build.
Warning
Academic/Research Deployments: If your users process documents with sensitive, inflammatory, or offensive content (common in academic research), you must configure the operating environment before use. Edit s3_files/agent_config/agent_operating_environment_config.json and sync to S3. Without this, the model may refuse to extract or omit sensitive content. See S3 Files → Operating Environment Configuration for details. For production deployments, we recommend moving this value to AWS Secrets Manager for added security.
Deploy everything:
./deploy_from_scratch.sh10 stacks deployed in dependency order (plus 1 optional):
| Stack | Purpose |
|---|---|
badgers-s3 |
Config bucket (manifests/prompts) + Output bucket |
badgers-cognito |
User pool, app client, OAuth 2.0 credentials |
badgers-iam |
Lambda execution role with Bedrock/S3 permissions |
badgers-lambda |
Base analyzer functions + foundation layer |
badgers-gateway |
AgentCore MCP Gateway with Lambda targets |
badgers-ecr |
Container registry for agent image |
badgers-memory |
AgentCore Memory for session persistence |
badgers-inference |
Application Inference Profiles for cost tracking |
badgers-runtime-websocket |
AgentCore Runtime (Strands agent with WebSocket) |
badgers-custom-analyzers |
Custom analyzers (optional, wizard-created) |
uv pip install -r requirements.txtAll layer build scripts must be run from the deployment/lambdas directory.
cd lambdas
./build_foundation_layer.sh # Core framework, boto3, pillow
./build_poppler_qdf_layer.sh # PDF rendering (pdftoppm, pdfinfo)
./build_pdf_processing_layer.sh # pikepdf, pymupdf for PDF/A tagging
cd ..| Script | Output | Purpose | Used By |
|---|---|---|---|
build_foundation_layer.sh |
layer.zip |
Core analyzer framework, AWS SDK, Pillow | All Lambda analyzers |
build_poppler_qdf_layer.sh |
poppler-qpdf-layer.zip |
Poppler binaries for PDF→image conversion | pdf_to_images_converter |
build_pdf_processing_layer.sh |
pdf-processing-layer.zip |
pikepdf, pymupdf for PDF manipulation | Non-container analyzers needing PDF libs |
build_container_lambdas.sh |
ECR images | Container images for complex analyzers | image_enhancer, remediation_analyzer |
Note:
build_enhancement_layer.shis retained on disk but no longer deployed. Image enhancement runs in the container-basedimage_enhancerLambda which bundles its own dependencies.
Container-based Lambdas (for functions exceeding layer size limits) are built separately:
cd lambdas
./build_container_lambdas.sh <deployment_id>
cd ..This builds and pushes Docker images to ECR for image_enhancer and remediation_analyzer.
deploy_from_scratch.sh calls all build scripts automatically in the correct order. Manual builds are only needed for:
- Partial redeployments
- Layer updates without full redeploy
- Troubleshooting build issues
cdk bootstrapTip
New to CDK? See the AWS CDK Developer Guide for installation and concepts.
This project uses alpha CDK modules:
cdk deploy badgers-s3 --require-approval never
# Sync configuration files
./sync_s3_files.shcdk deploy badgers-cognito --require-approval never
cdk deploy badgers-iam --require-approval nevercdk deploy badgers-lambda --require-approval nevercdk deploy badgers-gateway --require-approval nevercdk deploy badgers-ecr --require-approval never
cd runtime
./build_and_push_websocket.sh
cd ..cdk deploy badgers-memory --require-approval never
cdk deploy badgers-runtime-websocket --require-approval neverKey outputs after deployment:
| Output | Description |
|---|---|
GatewayUrl |
MCP endpoint for tool invocation |
RuntimeEndpoint |
Agent HTTP endpoint |
UserPoolId / UserPoolClientId |
Cognito authentication |
ConfigBucketName / OutputBucketName |
S3 buckets |
MemoryId |
AgentCore Memory ID |
deployment/
├── app.py # 🎯 CDK app entry point
├── deploy_from_scratch.sh # 🚀 Full deployment orchestrator
├── stacks/ # 📦 CDK stack definitions
├── lambdas/
│ ├── build_foundation_layer.sh # Core framework layer
│ ├── build_poppler_qdf_layer.sh # PDF rendering layer
│ ├── build_enhancement_layer.sh # Image enhancement layer (UNUSED - retained for reference)
│ ├── build_pdf_processing_layer.sh # PDF manipulation layer
│ ├── build_container_lambdas.sh # Container image builder
│ ├── deploy_foundation_layer.sh # Manual layer deployment
│ ├── deploy_poppler_layer.sh # Manual layer deployment
│ ├── containers/ # 🐳 Container Lambda Dockerfiles
│ └── code/ # ⚡ 28 analyzer functions + utilities
├── runtime/ # 🐳 AgentCore container
│ ├── Dockerfile.websocket
│ └── agent/main-websocket.py
├── s3_files/ # ☁️ S3 configuration
│ ├── manifests/
│ ├── prompts/
│ ├── schemas/
│ └── wrappers/
├── badgers-foundation/ # 🏗️ Shared analyzer framework (used by non-container analyzers and image_enhancer)
Each analyzer has a manifest file in s3_files/manifests/ that configures its behavior. The model_selections section supports extended thinking (Claude's chain-of-thought reasoning):
{
"analyzer": {
"name": "page_analyzer",
"model_selections": {
"primary": {
"model_id": "us.anthropic.claude-sonnet-4-20250514-v1:0",
"extended_thinking": true,
"budget_tokens": 6400
},
"fallback_list": [
{
"model_id": "us.anthropic.claude-haiku-4-5-20251001-v1:0",
"extended_thinking": true,
"budget_tokens": 4000
},
{
"model_id": "amazon.nova-pro-v1:0",
"extended_thinking": false
}
]
}
}
}| Field | Description |
|---|---|
model_id |
Bedrock model identifier |
extended_thinking |
Enable Claude's reasoning traces (Claude models only) |
budget_tokens |
Max tokens for thinking content (required when extended_thinking is true) |
expected_output_tokens |
Estimated output tokens for cost calculation (in analyzer section) |
audit_mode |
Boolean in inputSchema - enables confidence scoring and review flags |
Note
Extended thinking is only supported on Claude models. When enabled, thinking content is saved to S3 alongside results: {session_id}/{analyzer_name}/{image}_thinking_{timestamp}.txt
Simple format (no extended thinking) is still supported for backward compatibility:
"model_selections": {
"primary": "us.anthropic.claude-sonnet-4-20250514-v1:0",
"fallback_list": ["amazon.nova-pro-v1:0"]
}BADGERS uses Application Inference Profiles to enable cost allocation and usage monitoring per model. The inference_profiles_stack.py creates trackable profiles that wrap cross-region system-defined profiles.
- CDK creates profiles for each model (Claude Sonnet, Haiku, Opus, Nova Premier)
- Profile ARNs are passed to Runtime containers as environment variables
- At invocation time,
bedrock_client.pymaps model IDs to profile ARNs - Bedrock is invoked using the profile ARN instead of raw model ID
| Model ID Pattern | Environment Variable |
|---|---|
us.anthropic.claude-sonnet-4-5-* |
CLAUDE_SONNET_PROFILE_ARN |
us.anthropic.claude-haiku-4-5-* |
CLAUDE_HAIKU_PROFILE_ARN |
*claude-opus-4-6* |
CLAUDE_OPUS_46_PROFILE_ARN |
us.amazon.nova-premier-v1:0 |
NOVA_PREMIER_PROFILE_ARN |
Profiles are named: badgers-{model}-{deployment_id}
Example: badgers-claude-sonnet-abc12345
Note
If no inference profile is configured for a model ID, the system falls back to using the model ID directly. This allows local development without deployed profiles.
BADGERS ships with 5 base analyzers. Organizations can create additional analyzers using the wizard UI without modifying the core deployment.
s3://{config-bucket}/
├── manifests/ # Base analyzers (deployed with badgers-lambda)
├── schemas/
├── prompts/
└── custom-analyzers/ # Wizard-created analyzers
├── analyzer_registry.json
├── manifests/
├── schemas/
└── prompts/
-
Create analyzer via the 🧙 Create Analyzer tab in the Local Testing UI
- Wizard uploads files to S3 under
custom-analyzers/prefix
- Wizard uploads files to S3 under
-
Sync to local for CDK deployment:
cd deployment ./sync_custom_analyzers.sh -
Deploy custom stack:
cdk deploy badgers-custom-analyzers
The custom stack:
- Creates Lambda functions for each custom analyzer
- Registers them as Gateway targets via Custom Resource
- Uses the same foundation layer and IAM role as base analyzers
| Type | Editor Behavior |
|---|---|
| Base | Read-only by default, toggle to enable with warning |
| Custom | Always editable |
See the 🧙 Create Analyzer tab in the Local Testing UI for detailed usage.
Update specific components:
# Lambda code changes
cdk deploy badgers-lambda --require-approval never
# Gateway target changes
cdk deploy badgers-gateway --require-approval never
# Agent container changes
cd runtime && ./build_and_push_websocket.sh && cd ..
cdk deploy badgers-runtime-websocket --require-approval never
# Prompt/manifest changes only
./sync_s3_files.shGateway uses Cognito OAuth 2.0 client credentials:
- Credentials stored in Secrets Manager
- Runtime fetches tokens automatically
- Resource server scope:
agentcore-gateway/invoke
Gateway logs are automatically configured:
- 📝 Application:
/aws/vendedlogs/bedrock-agentcore/gateway/APPLICATION_LOGS/ - 📈 Usage:
/aws/vendedlogs/bedrock-agentcore/gateway/USAGE_LOGS/ - 🔍 Traces: X-Ray via CloudWatch Transaction Search
Warning
Manual step required: After deployment, enable Runtime observability in the AWS Console:
- Navigate to Amazon Bedrock → AgentCore → Runtimes
- Select your runtime and click "Edit"
- Enable Application logs and Usage logs
- Enable Tracing for X-Ray integration
- Runtime logs will appear at
/aws/bedrock-agentcore/runtimes/
Caution
This permanently deletes all resources including S3 buckets and their contents.
./destroy.shcd lambdas
# Foundation layer
rm -rf layer/ layer.zip
./build_foundation_layer.sh
# Poppler layer
rm -rf poppler_build/ poppler-qpdf-layer.zip
./build_poppler_qdf_layer.sh
# Enhancement layer — no longer deployed, runs in container Lambda
# rm -rf enhancement_build/ enhancement-layer.zip
# ./build_enhancement_layer.sh
# PDF processing layer
rm -rf pdf_processing_build/ pdf-processing-layer.zip
./build_pdf_processing_layer.sh# Verify image exists
aws ecr describe-images --repository-name pdf-analysis-agent-<deployment_id>
# Rebuild
cd runtime && ./build_and_push_websocket.sh# Check credentials
aws secretsmanager get-secret-value \
--secret-id pdf-extractor/cognito-config-<deployment_id># Tail logs
aws logs tail /aws/bedrock-agentcore/runtimes/<runtime_id> --followUse a consistent ID for redeployments:
cdk deploy -c deployment_id=abc12345 --allAll resources are tagged using a centralized configuration in app.py. Customize the deployment_tags dict before deployment:
deployment_tags = {
"application_name": "badgers",
"application_description": "BADGERS (Broad Agentic Document Generative Extraction & Recognition System)",
"environment": "dev",
"owner": "your-team",
"cost_center": "your-cost-center",
"project_code": "your-project-code",
"cdk_stack_prefix": STACK_PREFIX,
"team": "your-team",
"team_contact_email": "team@company.com",
}These tags are applied to all resources across all stacks. Additionally, each resource gets:
resource_name- Identifier for the specific resourceresource_description- Description of the resource's purpose
Tagged resources include:
- AgentCore Gateway, Runtime, Memory
- ECR repositories
- S3 buckets and KMS keys
- Lambda functions and layers
- Cognito User Pool, Identity Pool, Secrets
- IAM roles