Terraform-based infrastructure for deploying DoiT Attribute EC2 sensor on Amazon Bedrock AgentCore Runtime Instances.
This module automatically installs the Attribute sensor on AgentCore-managed EC2 instances using EventBridge + Lambda + SSM, enabling cost observability for AI agent workloads.
┌─────────────────────────────────────────────────────────────────────┐
│ Amazon Bedrock AgentCore │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────┐ ┌──────────────────────────────────┐ │
│ │ Capacity Provider │────▶│ EC2 Instance (your account) │ │
│ ├─────────────────────┤ ├──────────────────────────────────┤ │
│ │ • OS: Linux x86/ARM │ │ • Agent Runtime (container/zip) │ │
│ │ • Instance types │ │ • Shared session storage │ │
│ │ • VPC/Subnets/SGs │ │ • Up to 14 days lifetime │ │
│ │ • EBS volumes │ │ • Managed by AgentCore │ │
│ │ • IAM permissions │ └──────────────────────────────────┘ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
| Requirement | Details |
|---|---|
| Kernel version | 5.10 or newer |
| Architecture | x86_64 or arm64 |
| Privileges | sudo access (handled by SSM) |
| Token | Per-account installation token from Attribute Dashboard |
The included agent-3d-render/ directory contains a 3D Rendering SaaS demo application that simulates a multi-tenant AI agent. It:
- Takes plain-language scene descriptions and produces photorealistic renders using Blender Cycles with NVIDIA OptiX GPU ray tracing
- Uses Claude (via Amazon Bedrock) to interpret prompts and generate structured scene graphs
- Accepts an
x-tenant-idHTTP header to identify the calling tenant - The Attribute sensor captures this header and uses it to attribute compute and AI costs per tenant
This demonstrates how to build a multi-tenant AI application where costs can be broken down by customer using DoiT Attribute.
- Terraform >= 1.5.0
- AWS CLI >= 2.36 (for AgentCore commands)
- DoiT Attribute token from the Attribute Dashboard (Setup > API Tokens)
- S3 bucket for agent code artifacts
- jq installed locally (for Terraform external data sources)
- GPU instance capacity in your AWS account (g5 family) — most accounts start at 0 vCPU
quota for on-demand G/VT instances and need a quota increase request before
terraform applywill succeed. Check your current limit first:If it'saws service-quotas get-service-quota \ --service-code ec2 \ --quota-code L-DB2E81BA \ --region us-west-2
0, request an increase in the Service Quotas console (EC2 -> "Running On-Demand G and VT instances") before deploying — approval can take anywhere from minutes to a day. - EC2 Managed Resource Visibility must be enabled:
This allows you to see AgentCore-managed EC2 instances in the AWS Console and via CLI. Without this, the instances are hidden by default.
aws ec2 modify-managed-resource-visibility --region us-west-2 --default-visibility visible
cd attribute-agent-core/terraform
# Copy the template
cp terraform.tfvars.template terraform.tfvars
# Edit with your values
vim terraform.tfvarsAt minimum, you need to set:
# AWS Region
aws_region = "us-east-1"
# S3 bucket for agent code (must already exist)
agent_s3_bucket = "your-artifacts-bucket"
# DoiT Attribute sensor token (from Attribute Dashboard > Setup > API Tokens)
sensor_token = "234333..."
# Use GPU instances for 3D rendering
allowed_instance_types = ["g5.xlarge", "g5.2xlarge", "g5.4xlarge"]
# Larger EBS for Blender + models
ebs_volume_size = 100# Initialize Terraform
terraform init
# Review the plan
terraform plan
# Deploy (this will also build and upload the agent code)
terraform applyBy default, Terraform automatically builds the agent code from the agent-3d-render/ directory, packages it with dependencies, and uploads it to S3. To use a pre-existing artifact instead, set build_agent_artifact = false and specify agent_s3_key.
# Get the runtime ARN from Terraform output
RUNTIME_ARN=$(terraform output -raw agent_runtime_arn)
# Invoke with a render request
aws bedrock-agentcore invoke-agent-runtime \
--agent-runtime-arn "$RUNTIME_ARN" \
--qualifier DEFAULT \
--runtime-session-id "session-$(uuidgen)" \
--payload '{"prompt": "A red sports car in a showroom with dramatic lighting"}' \
--content-type application/json \
--region us-west-2The first invocation against a fresh capacity provider triggers a cold start (new EC2 instance,
Blender + shared-lib install) and can take a few minutes; subsequent calls in the same
--runtime-session-id reuse the warm instance and return in seconds. See
agent-3d-render/scripts/tenant_test.py for a multi-tenant example that also sets the
x-tenant-id header.
| Variable | Description | Default |
|---|---|---|
aws_region |
AWS region for deployment | us-east-1 |
name_prefix |
Prefix for all resource names | attribute-agentcore |
| Variable | Description | Default |
|---|---|---|
vpc_id |
VPC ID (empty = default VPC) | "" |
subnet_ids |
Subnet IDs (empty = auto-discover) | [] |
security_group_ids |
Security group IDs (empty = default SG) | [] |
| Variable | Description | Default |
|---|---|---|
operating_system |
OS for instances | LINUX_X86_64 |
allowed_instance_types |
Allowed EC2 types | ["g5.xlarge", "g5.2xlarge", "g5.4xlarge"] |
ebs_volume_size |
EBS volume size in GB | 100 |
| Variable | Description | Default |
|---|---|---|
agent_s3_bucket |
S3 bucket for agent code | Required |
agent_s3_key |
S3 key to agent zip | 3d-render-agent/3d-render-agent.zip |
python_runtime |
Python version | PYTHON_3_13 |
request_header_allowlist |
Custom headers to pass to agent | ["x-tenant-id"] |
session_idle_timeout |
Idle timeout in seconds | 3600 (1 hour) |
session_max_duration |
Max session duration in seconds | 86400 (24 hours) |
| Variable | Description | Default |
|---|---|---|
sensor_token |
DoiT Attribute token | Required |
sensor_workload_name |
Workload name in Attribute | 3d-render-agent |
sensor_memory_limit |
Sensor memory limit (bytes) | 524288000 (500MB) |
Check the Lambda logs for the install attempt:
aws logs tail /aws/lambda/render3d-sensor-installer --since 10m --region us-west-2Also check the SSM command output directly, which shows the actual install script output
(the most common historical cause was a wget IPv6/IPv4 DNS-resolution hang — see the comments
in lambda/index.py's install_sensor() if installs are timing out rather than erroring):
aws ssm list-commands --region us-west-2 --instance-id <instance-id>
aws ssm get-command-invocation --region us-west-2 --command-id <command-id> --instance-id <instance-id>Verify the instance's SSM agent is actually online before the Lambda's install command can run:
aws ssm describe-instance-information --region us-west-2 \
--filters "Key=InstanceIds,Values=<instance-id>"Check the AgentCore runtime and capacity provider status:
aws bedrock-agentcore-control get-agent-runtime \
--agent-runtime-id <runtime-id> \
--region us-west-2A cold start (new EC2 instance provisioning + Blender install) can take a few minutes on the first request against a given session — this is expected, not a hang. Check CloudWatch logs for the runtime to see where a request actually is in that startup sequence.
Running this demo incurs real AWS + Bedrock charges. Approximate costs (us-west-2, on-demand):
| Resource | Approximate Cost |
|---|---|
g5.xlarge EC2 instance |
~$1.00/hr (only while a capacity-provider instance is running) |
| Bedrock Claude tokens | ~$0.003-0.015 per 1K tokens, model-dependent |
| Lambda invocations (sensor installer) | < $0.01 |
| S3 storage (renders, HDRIs, agent artifact) | < $0.01/GB-month |
Tip: Set capacity_max = 1 and a short session_idle_timeout (e.g. 300) in
terraform.tfvars while testing, so idle GPU instances get torn down quickly instead of running
up cost between requests.
attribute-agent-core/
├── README.md # This file
├── agent-3d-render/
│ ├── agent.py # 3D render agent entrypoint
│ ├── blender_runtime.py # Blender scene generation & rendering
│ ├── requirements.txt # Python dependencies
│ ├── Dockerfile # Container build (optional)
│ ├── fixtures/ # Test scene fixtures
│ │ ├── *.json # Scene graph test cases
│ │ └── _prod_baseline/ # Reference renders
│ ├── hdri_assets/ # HDRI environment maps
│ └── scripts/
│ ├── render_local.py # Local testing without AWS
│ ├── tenant_test.py # Multi-tenant test harness
│ └── capability_probe.py # Blender version compatibility
├── scripts/
│ └── loadgen-agentcore.py # Load generator for testing
├── lambda/
│ └── index.py # Sensor installer Lambda
└── terraform/
├── main.tf # Main configuration
├── variables.tf # Input variables
├── outputs.tf # Output values
├── terraform.tfvars.template # Template for variables
└── modules/
├── iam/ # IAM roles and policies
├── secrets/ # Secrets Manager
├── lambda/ # Sensor installer Lambda
├── eventbridge/ # EC2 state-change rule
├── capacity_provider/ # AgentCore capacity provider
└── agent_runtime/ # AgentCore runtime