From Zero to Deployed with an AI Agent

From Zero to Deployed with an AI Agent

Published March 27, 2026
tutorial ai agents aws deployment

From Zero to Deployed with an AI Agent

Getting a new project deployed to AWS involves a lot of moving parts: VPC networking, ECS task definitions, load balancers, S3 buckets, CloudFront distributions, IAM policies, CI/CD pipelines, Docker builds. Each piece is individually straightforward, but wiring them all together correctly on the first try is where most people lose a few hours (or days).

This guide walks through using an AI agent with DevRamps to generate all of that from a single conversation, starting from an empty git repo and ending with a live app behind CloudFront.

Prerequisites

  • An AWS account with admin access (or permission to create IAM roles and CloudFormation stacks)
  • Node.js 18+
  • An MCP-compatible AI coding agent (Claude Code, Cursor, Codex, Windsurf, or similar)
  • Git and a GitHub repo (can be empty)

Set Up Agent Integration

Start with your repo cloned locally:

mkdir my-app && cd my-app
git init

Run:

npx @devramps/cli init-agent

This creates four files:

File Purpose
.mcp.json Registers the DevRamps MCP server with your AI agent
DEVRAMPS_AGENTS.md Rules the agent follows when generating infrastructure and pipelines
CLAUDE.md References DEVRAMPS_AGENTS.md (loaded by Claude Code, Codex)
AGENTS.md Same reference (loaded by Cursor, Windsurf, and others)

DEVRAMPS_AGENTS.md is the important one. It contains constraints like “Terraform must include backend "s3" {}” and “CloudFront needs both an S3 origin and an ALB origin.” Left to its own devices, an AI agent will generate infrastructure that looks reasonable but breaks on first deploy. These rules prevent the common mistakes.

Start a Conversation

Open your AI coding agent in the project directory. Restart it so it picks up the new .mcp.json, then verify the DevRamps MCP server is connected (most agents have a way to list active MCP servers). Then:

Create a new app deployed to AWS — Node.js backend with a React frontend

The agent picks up the DevRamps tools and asks a few questions up front:

  • Project name (suggests a default based on the directory)
  • Stages — start with one, or set up staging + production?
  • AWS account ID for each stage
  • Region (defaults to us-east-1)
  • Architecture tier — budget (~$30/mo), standard (~$80/mo), or high-availability (~$200/mo)

These are the only things the agent can’t figure out on its own. Everything else — deployment targets, artifact types, build commands, infrastructure topology — it determines from the architecture tier and the code it generates.

What Gets Generated

Terraform

The agent writes Terraform across separate files under infrastructure/:

infrastructure/
  backend.tf        # S3 remote state (empty backend block — configured during bootstrap)
  providers.tf      # AWS provider
  variables.tf      # region, account_id, env, app_name
  outputs.tf        # Cluster names, bucket names, distribution IDs
  vpc.tf            # Public + private subnets, NAT
  security.tf       # Security groups
  ecs.tf            # Fargate cluster, task definition, service
  alb.tf            # Load balancer, target group, listener
  frontend.tf       # S3 bucket for static assets
  cloudfront.tf     # CDN with S3 + ALB origins

The networking follows AWS best practices: ECS tasks run in private subnets with NAT for outbound access, the ALB sits in public subnets, and CloudFront handles ingress. The CloudFront distribution has two origins — static assets from S3 and API requests forwarded to the ALB — so both the React app and the Express API are served from the same domain.

The agent runs terraform validate after generating the files to catch syntax issues before presenting anything.

Cost estimate

Before proceeding, the agent shows a cost breakdown based on the architecture tier you picked:

Resource Est. Monthly Cost
ECS Fargate (0.25 vCPU, 0.5GB) ~$9
Application Load Balancer ~$16
NAT (t4g.nano / FCK-NAT) ~$3
S3 + CloudFront ~$1
CloudWatch Logs ~$2
Total ~$31/mo

It also lists a few optional upgrades with trade-offs and cost deltas — managed NAT Gateway for better availability, Multi-AZ RDS, larger task sizes. You can accept the defaults or ask for specific changes before moving on.

Pipeline

The pipeline definition goes to .devramps/my_app/pipeline.yaml. It defines the build and deploy sequence:

version: "1.0.0"

pipeline:
  cloud_provider: AWS
  pipeline_updates_require_approval: ALWAYS

  stages:
    - name: staging
      account_id: "123456789012"
      region: us-east-1
      skip: ["Bake Period"]
      vars:
        env: staging

  steps:
    - name: Synthesize Infrastructure
      id: infra
      type: DEVRAMPS:TERRAFORM:SYNTHESIZE
      params:
        requires_approval: ALWAYS
        source: /infrastructure
        variables:
          region: ${{ stage.region }}
          aws_account_id: ${{ stage.account_id }}
          env: ${{ vars.env }}

    - name: Deploy Backend
      type: DEVRAMPS:ECS:DEPLOY
      goes_after: ["Synthesize Infrastructure"]
      params:
        cluster_name: ${{ steps.infra.ecs_cluster_name }}
        service_name: ${{ steps.infra.ecs_service_name }}
        reference_task_definition: ${{ steps.infra.task_definition }}
        images:
          - container_name: service
            image: ${{ stage.artifacts.backend.image_url }}

    - name: Deploy Frontend
      type: DEVRAMPS:S3:UPLOAD
      goes_after: ["Synthesize Infrastructure"]
      params:
        source_s3_url: ${{ stage.artifacts.frontend.s3_url }}
        bucket: ${{ steps.infra.frontend_bucket_name }}
        decompress: true
        clean: true

    - name: Invalidate Cache
      type: DEVRAMPS:CLOUDFRONT:INVALIDATE
      goes_after: ["Deploy Frontend"]
      params:
        distribution_id: ${{ steps.infra.cloudfront_distribution_id }}
        paths: ["/*"]

    - name: Bake Period
      type: DEVRAMPS:APPROVAL:BAKE
      params:
        duration_minutes: 5

  artifacts:
    Backend Image:
      id: backend
      type: DEVRAMPS:DOCKER:BUILD
      rebuild_when_changed: [/services/backend]
      params:
        dockerfile: /services/backend/Dockerfile

    Frontend Bundle:
      id: frontend
      type: DEVRAMPS:BUNDLE:BUILD
      per_stage: true
      rebuild_when_changed: [/services/frontend]
      dependencies: ["node.22"]
      params:
        build_commands: |
          cd services/frontend
          npm install && npm run build
          zip -r ../../bundle.zip ./dist
        file_path: /bundle.zip

The ${{ steps.infra.* }} expressions reference Terraform output names. The agent verifies that every expression has a matching output block in outputs.tf — a mismatch would cause a runtime failure.

IAM policies

The generate-iam-policies tool scans the Terraform files and produces .devramps/my_app/aws_additional_iam_policies.json. It detects both direct resource blocks and well-known Terraform modules (like terraform-aws-modules/vpc/aws) and maps them to the required IAM actions. The output is grouped by AWS service — one statement for EC2, one for ECS, one for S3, and so on.

Validation and application code

The agent validates the pipeline definition (checking step types, dependency references, stage names) and generates starter application code: an Express server with a health check at /health and a simple API at /api/hello, plus a React + Vite frontend that calls it.

Review and Bootstrap

Look through the generated files. The Terraform is worth reviewing most carefully — VPC CIDR ranges, instance sizes, security group ingress rules. Everything is standard code in your repo. Change whatever you want.

When it looks right:

npx @devramps/cli bootstrap

This authenticates via the browser, then deploys CloudFormation stacks to your AWS account. It provisions IAM roles, ECR repositories, S3 buckets for build artifacts, and a Terraform state bucket. It shows you exactly what it will create and asks for confirmation first.

Push and Deploy

Connect the repo in the DevRamps dashboard, then push:

git add .
git commit -m "Initial project setup"
git push origin main

The push triggers the pipeline. In the dashboard you’ll see it move through each step:

  1. Synthesize Infrastructureterraform plan then terraform apply
  2. Build artifacts — Docker image for the backend, zipped Vite bundle for the frontend
  3. Deploy Backend — ECS service update with the new image
  4. Deploy Frontend — bundle uploaded to S3, CloudFront cache invalidated

The first run takes a few minutes since Terraform is creating all the resources. After that, deploys only touch what changed.

When the pipeline finishes, find the CloudFront domain in the dashboard or in the Terraform outputs. Open it in a browser — you’ll see the React app, fetching data from the Express API through the same CloudFront distribution.

Where to Go Next

This setup is a single staging environment. Some things to consider adding:

A production stage. Add another stage to the pipeline with a separate AWS account or region. The bake period gives you a window to verify staging before production deploys. See the stages documentation.

Ephemeral environments. An ephemeral_environments block in the pipeline gives you a fresh deployment per pull request. It spins up on PR open and tears down on merge. More on this in the ephemeral environments guide.

Slack notifications. A notifications block sends alerts on failures, required approvals, and rollbacks. Three lines of YAML.

Custom domain. Add an ACM certificate and Route 53 record to the Terraform. Update CloudFront’s viewer_certificate block and add an alias. ACM certificates are free.

Database migrations. The DEVRAMPS:DATABASE:MIGRATE step type runs migrations as part of the deploy, after infrastructure synthesis.

Auto-rollback. Set auto_rollback_alarm_name on a stage and point it at a CloudWatch alarm. If the alarm fires post-deploy, the stage rolls back automatically.

Full documentation at devramps.com/docs.