The ERP Financial Agent runs on AWS ECS Fargate behind an Application Load Balancer. Three CloudFormation stacks describe the full infrastructure: the network layer (VPC, subnets, NAT), the services layer (ECS cluster, task definitions, ALB, ECR, ElastiCache, DynamoDB), and the CI/CD layer (GitHub OIDC provider and the IAM role that GitHub Actions assumes). ADocumentation Index
Fetch the complete documentation index at: https://mintlify.com/yohangr3/agentelanggrafh/llms.txt
Use this file to discover all available pages before exploring further.
deploy.sh script ties them together for an initial rollout; subsequent deployments are fully automated via GitHub Actions.
Architecture overview
PublicSubnet1 for cost optimization). Redis and RDS are similarly restricted to the private subnets.
CloudFormation stacks
network.yaml — VPC, subnets, NAT Gateway, security groups
network.yaml — VPC, subnets, NAT Gateway, security groups
Creates the entire network layer. Resources are tagged with
Stack outputs (
Project: erp-agent and the environment name.| Resource | Value |
|---|---|
| VPC CIDR | 10.0.0.0/16 |
| Public subnet 1 | 10.0.1.0/24 (AZ-a) — ALB + NAT Gateway |
| Public subnet 2 | 10.0.2.0/24 (AZ-b) — ALB high availability |
| Private subnet 1 | 10.0.10.0/24 (AZ-a) — ECS + ElastiCache |
| Private subnet 2 | 10.0.20.0/24 (AZ-b) — ECS + ElastiCache HA |
| NAT Gateway | Elastic IP in PublicSubnet1 |
| ALB security group | Allows TCP 80 from 0.0.0.0/0 |
| ECS security group | Allows TCP 80 from ALB security group only |
| Redis security group | Allows TCP 6379 from ECS security group only |
{EnvironmentName}-*) are imported by the services stack: VpcId, PublicSubnet1Id, PublicSubnet2Id, PrivateSubnet1Id, PrivateSubnet2Id, ALBSecurityGroupId, ECSSecurityGroupId, RedisSecurityGroupId.services.yaml — ECS cluster, task definitions, ALB, ECR, Redis, DynamoDB
services.yaml — ECS cluster, task definitions, ALB, ECR, Redis, DynamoDB
Creates all compute and data resources. It imports networking outputs from the network stack.ECS task definition (
erp-agent-task-{env}):- CPU:
2048(2 vCPU) - Memory:
4096MB - Two containers:
backend(port 8000) andfrontend(port 80) - Network mode:
awsvpc— each task gets its own ENI in a private subnet
- Execution role — pulls images from ECR, writes to CloudWatch Logs, reads the DB password from Secrets Manager
- Task role — calls
bedrock:InvokeModel/bedrock:ConverseStreamon Anthropic and Amazon Titan models; reads/writeserp-agent-conversations,erp-agent-query-log, anderp-agent-rbac-overridesDynamoDB tables; puts/gets objects in the exports S3 bucket
ECSServiceAverageCPUUtilization at 70% CPU (configurable via CpuTarget). Scale-out cooldown is 60 s; scale-in cooldown is 300 s. Maximum capacity is 4 tasks.ALB target group health check: GET /health on port 80, HTTP 200, every 30 seconds. Stickiness is enabled with a 1-hour lb_cookie.CloudWatch alarms: high CPU (>80% for 3 minutes), unhealthy hosts (>0 for 2 minutes), HTTP 5xx errors (>10 per minute for 2 minutes).DynamoDB tables (on-demand billing, created only on the primary stack):erp-agent-conversations— partition keyuser_id, sort keysession_id, TTL onttlerp-agent-query-log— partition keyquery_id, sort keytimestamp
cicd.yaml — GitHub OIDC, IAM role for GitHub Actions
cicd.yaml — GitHub OIDC, IAM role for GitHub Actions
Provisions the trust relationship between GitHub Actions and AWS using OIDC — no long-lived access keys needed.
- Creates (or imports) an
AWS::IAM::OIDCProviderfortoken.actions.githubusercontent.com - Creates the
github-actions-erp-agentIAM role, trusted only by the configuredGitHubOrg/GitHubRepo - Grants the role: ECR push, ECS
UpdateService+RegisterTaskDefinition, CloudWatch Logs, Bedrock invocation (for evaluation workflows), Secrets Manager read, and full provisioning permissions for tenant stacks
GitHubActionsRoleArn output and store it as the AWS_ROLE_ARN secret in your GitHub repository settings.Initial deployment
Deploy the network stack
erp-agent-network stack. Wait for the stack to reach CREATE_COMPLETE before proceeding — the services stack imports its outputs.Deploy the services stack
DB_PASSWORD if the environment variable is not set. The password is stored in Secrets Manager as erp-agent/db-password and injected into the ECS task at runtime — it never appears in plaintext in the task definition.This step creates the ECR repositories (erp-agent/backend and erp-agent/frontend) that you will push images to in the next step.GitHub Actions CI/CD
The.github/workflows/deploy.yml pipeline has three stages that run in order.
- Staging (auto on dev branch)
- Production (auto on main branch)
- Refresh tenants (post-production)
Triggered automatically when the CI pipeline succeeds on the
dev branch, or via workflow_dispatch with environment: staging.- Assumes
AWS_ROLE_ARNvia OIDC (id-token: writepermission) - Logs in to ECR
- Fetches the current task definition JSON with
aws ecs describe-task-definition - Patches both container images using
jqand registers a new task definition revision - Calls
aws ecs update-service --force-new-deployment - Waits for
services-stable(5-minute timeout)
ECS task environment variables
The task definition injects the following environment variables into thebackend container. Secrets are fetched from Secrets Manager at task startup and are never written to CloudWatch Logs.
| Variable | Source | Example value |
|---|---|---|
DB_HOST | CloudFormation parameter | iafinagent.choi0eaq2mr7.us-east-1.rds.amazonaws.com |
DB_NAME | CloudFormation parameter | iafinagent |
DB_USER | CloudFormation parameter | admin |
DB_PASSWORD | Secrets Manager | erp-agent/db-password |
REDIS_URL | ElastiCache endpoint | redis://<endpoint>:6379/0 |
AWS_REGION | AWS::Region | us-east-1 |
COGNITO_USER_POOL_ID | CloudFormation parameter | us-east-1_2qpNBGCmb |
COGNITO_CLIENT_ID | CloudFormation parameter | 70qcoifagu4tk20qnn2q8d9rjs |
BEDROCK_MODEL_ID | Hardcoded in template | us.anthropic.claude-sonnet-4-5-20250929-v1:0 |
BEDROCK_REASONING_MODEL_ID | Hardcoded in template | us.anthropic.claude-sonnet-5 |
BEDROCK_EMBEDDING_MODEL_ID | Hardcoded in template | amazon.titan-embed-text-v2:0 |
DYNAMODB_ENABLED | Hardcoded | true |
EXPORTS_BUCKET_NAME | S3 bucket from ExportsBucket output | erp-agent-exports-<account-id> |
ENVIRONMENT | CloudFormation parameter | production |
EXPECTED_TENANT | CloudFormation parameter | * (primary) or tenant slug |
RBAC_ENFORCE | CloudFormation parameter | false |
LOG_LEVEL | Hardcoded | INFO |
Validate templates without deploying
aws cloudformation validate-template against all three templates and exits non-zero if any are invalid.