Skip to content

AWS — CloudFormation

This stack provisions a complete production Agentcy environment in a single AWS account using AWS-native services. It's the fastest path to a managed AWS deployment without operating Kubernetes.

What Gets Provisioned

ComponentService
NetworkingVPC, 2 public + 2 private subnets, NAT Gateway, Route 53 hosted zone (optional)
ComputeECS Fargate (agentcy-api, agentcy-frontend)
Load balancerApplication Load Balancer with ACM certificate
PostgresRDS Postgres 16 (db.t4g.medium) with the vector extension enabled
RedisElastiCache Redis 7 (cache.t4g.micro, single node)
Context EngineBasic provider — Neo4j AuraDB (external; you create separately and pass the URI). Advanced providerkyma sidecar on ECS Fargate writing to an S3 bucket the stack provisions; toggle via the ContextEngine parameter.
SecretsAWS Secrets Manager for DB and JWT secrets
LogsCloudWatch Logs

Why AuraDB on Basic?

Running Neo4j on EC2 or ECS works but requires you to manage backups, upgrades, and HA. AuraDB handles that for you and has an AWS-region peer for low latency. If you must keep the Basic graph inside AWS, see the Self-managed Neo4j section below.

Picking Advanced (kyma) instead

Set ContextEngine=advanced on the stack to provision a kyma sidecar (Fargate task) plus an S3 bucket for columnar extents. The CFN template wires CONTEXT_ENGINE=advanced, KYMA_BASE_URL, KYMA_TOKEN automatically. Reads happen via Arrow Flight gRPC — your agents get KQL / SQL / Cypher against the same engine. Reference docs at getkyma.dev.

Prerequisites

  • AWS CLI v2 configured with an account that has admin access (narrower scope possible — see IAM section)
  • A registered domain in Route 53 (or external DNS) and an ACM certificate in the deploy region
  • A Neo4j AuraDB instance — note the URI, username, and password
  • An LLM API key (Anthropic or OpenAI) stored in Secrets Manager

Get the Template

The CloudFormation template ships in the release tarball at infra/aws/cloudformation/agentcy.yaml. The same template is also published to a public S3 bucket (URL provided to self-host customers).

Pre-create Secrets

Create these secrets first — the stack references them:

bash
aws secretsmanager create-secret \
    --name agentcy/llm-api-key \
    --secret-string "sk-ant-..."

aws secretsmanager create-secret \
    --name agentcy/neo4j \
    --secret-string '{
        "uri":"neo4j+s://xxxxx.databases.neo4j.io",
        "username":"neo4j",
        "password":"replace-me"
    }'

aws secretsmanager create-secret \
    --name agentcy/jwt \
    --secret-string "$(openssl rand -hex 32)"

Deploy

bash
aws cloudformation deploy \
    --template-file agentcy.yaml \
    --stack-name agentcy-prod \
    --capabilities CAPABILITY_NAMED_IAM \
    --parameter-overrides \
        DomainName=agentcy.example.com \
        AcmCertificateArn=arn:aws:acm:us-east-1:123456789012:certificate/xxxxx \
        DbInstanceClass=db.t4g.medium \
        ApiTaskCount=2 \
        FrontendTaskCount=2 \
        LlmProvider=anthropic \
        AuthProvider=local \
        BackendImage=ghcr.io/agentcy/backend:latest \
        FrontendImage=ghcr.io/agentcy/frontend:latest

Watch the stack:

bash
aws cloudformation describe-stack-events \
    --stack-name agentcy-prod \
    --query 'StackEvents[].[Timestamp,ResourceStatus,ResourceType,LogicalResourceId]' \
    --output table

Provisioning takes 12–20 minutes — most of it is RDS and ElastiCache.

Outputs

Once the stack is CREATE_COMPLETE:

bash
aws cloudformation describe-stacks \
    --stack-name agentcy-prod \
    --query 'Stacks[0].Outputs'

You'll get the ALB DNS name and the application URL. Point your domain at the ALB via a Route 53 alias (the template can do this for you if you pass HostedZoneId).

Parameters

ParameterDefaultDescription
DomainNamePublic hostname for the app
AcmCertificateArnACM certificate covering DomainName
HostedZoneId(empty)If set, creates a Route 53 alias
VpcCidr10.42.0.0/16VPC CIDR
DbInstanceClassdb.t4g.mediumRDS instance class
DbAllocatedStorage50Initial DB storage (GB)
DbMaxAllocatedStorage200Storage autoscaling cap
DbMultiAzfalseSet to true for production HA
RedisNodeTypecache.t4g.microElastiCache node size
ApiTaskCount2API replicas
FrontendTaskCount2Frontend replicas
BackendImageghcr.io/agentcy/backend:latestBackend image
FrontendImageghcr.io/agentcy/frontend:latestFrontend image
LlmProvideranthropicanthropic or openai
AuthProviderlocallocal or oidc
ContextEnginebasicbasic (Neo4j-compatible Bolt) or advanced (kyma + S3)
KymaImageghcr.io/agentcylabs/kyma:latestOnly used when ContextEngine=advanced

Self-managed Neo4j (Basic provider, on AWS)

If you must keep the Basic-provider graph inside AWS:

  1. Use the companion stack infra/aws/cloudformation/neo4j-ec2.yaml. It runs Neo4j 5 Community on a single EC2 instance with EBS-backed /data, daily snapshots via Data Lifecycle Manager, and a Security Group that only the ECS task security group can reach.
  2. Pass the private DNS name as Neo4jUri=bolt://neo4j.internal:7687 when deploying the main stack.

For HA, use Neo4j Enterprise with a causal cluster — the template doesn't ship this configuration, so contact agentcylabs.com for an enterprise reference architecture.

Self-hosting kyma (Advanced provider, on AWS)

When ContextEngine=advanced:

  1. The CFN template provisions an S3 bucket (agentcy-kyma-<account>-<region>) and an ECS Fargate service running the kyma container (KymaImage parameter, default ghcr.io/agentcylabs/kyma:latest).
  2. kyma reads/writes Arrow extents on S3 via the object_store crate (zero-egress paths within the same region) and persists its catalog in the same RDS Postgres instance under a separate database (kyma_catalog).
  3. The API task gets CONTEXT_ENGINE=advanced, KYMA_BASE_URL=http://kyma.<vpc>:8080, KYMA_TOKEN (Secrets Manager), KYMA_DATABASE=kyma.
  4. OTLP gRPC port 4317 is exposed via a Network Load Balancer if the EnableOtlp parameter is set, so emitters across your stack can ship logs/traces directly into kyma.

For multi-region or federation, see the kyma docs at getkyma.dev — the same single-binary model scales out without a rewrite, so the CFN template is forward-compatible.

IAM Footprint

The stack creates two IAM roles:

RolePermissions
agentcy-task-execution-rolePull images from ECR/GHCR, write CloudWatch Logs, read three Secrets Manager secrets
agentcy-task-roleApp-level — read-only access to other Secrets Manager paths under agentcy/connectors/*

If your org requires Permission Boundaries, add --parameter-overrides PermissionsBoundary=arn:aws:iam::123:policy/MyBoundary to the deploy command.

Cost Estimate

ItemMonthly (us-east-1, on-demand)
ECS Fargate · 4 tasks @ 0.5 vCPU / 1 GB~$60
ALB~$20
RDS db.t4g.medium (single-AZ)~$60
ElastiCache cache.t4g.micro~$12
NAT Gateway~$32
CloudWatch Logs~$5
AuraDB Free tier$0
Total~$190/mo

Multi-AZ RDS roughly doubles the DB line item. Switch to AuraDB Pro and add ~$65/mo when you outgrow the free tier.

Updating

To roll a new image, update the BackendImage or FrontendImage parameter and re-run cloudformation deploy. ECS does a rolling update (50% min healthy, 200% max) — no downtime.

To change anything else (instance size, replica count, etc.) just modify the parameter override and redeploy.

Tearing Down

bash
aws cloudformation delete-stack --stack-name agentcy-prod

Data

RDS and ElastiCache are deleted with the stack — take a snapshot first if the data matters. The Secrets Manager secrets you created out-of-band stay behind.

Next Steps

Built by AgentcyLabs. For in-house deployment or Agentcy Cloud (PaaS) access, visit agentcylabs.com.