ai newsDi., 20. Okt.
EilmeldungGetting Hands‑On with Timestral: Mistral’s Open‑Source Time‑Series Foundation Models

CDK Pipelines for AI Agents: Deploying a Claude‑Powered Coding Assistant with Zero Manual Steps

Deploying AI coding assistants usually means juggling Docker builds, secret management, and ad‑hoc scripts. With CDK Pipelines you can treat the entire Claude‑based agent as infrastructure code and let AWS handle the build, test, and deploy phases automatically. This post walks you through a fully

dev.toDienstag 09:56 · 20.10.10 Min. Lesezeit
Bild: dev.to

Deploying AI coding assistants usually means juggling Docker builds, secret management, and ad‑hoc scripts. With CDK Pipelines you can treat the entire Claude‑based agent as infrastructure code and let AWS handle the build, test, and deploy phases automatically. This post walks you through a fully automated, reproducible workflow that any team can adopt.

When you ship a traditional web service, you already know the value of Infrastructure as Code (IaC) – a practice where you describe cloud resources in a programming language instead of clicking around the console.

CDK Pipelines is an IaC pattern built on top of the AWS Cloud Development Kit (CDK). It gives you a ready‑made CodePipeline (a series of automated steps) that knows how to:

Why does this matter for AI agents? An AI coding assistant is more than a piece of Python or Node code. It usually consists of:

If you manage each of those pieces by hand, you end up with:

Treating the whole assistant as a single pipeline eliminates these problems. The pipeline becomes the single source of truth, and every run is repeatable, version‑controlled, and auditable.

Key takeaway: CDK Pipelines turn the “run‑once” steps of building and deploying an AI agent into a reliable, version‑controlled process that anyone can trigger.

Think of a pipeline like a bakery assembly line. The source stage is the delivery truck bringing flour, the build stage is the mixer turning flour into dough, the test stage is the quality inspector, and the deploy stage is the oven that bakes the bread and puts it on the shelf. If you skip any station or let a worker improvise, the loaf may be undercooked or miss a crucial ingredient. CDK Pipelines make sure every loaf follows the same recipe, every time.

Before we write any CDK code, we need a local project that represents the assistant. The goal is to keep it tiny so the example stays approachable.

mkdir claude-coding-assistant cd claude-coding-assistant Enter fullscreen mode Exit fullscreen mode 2. Initialize a TypeScript CDK app npm init -y # creates package.json npm install aws-cdk-lib constructs # CDK core libraries npm install -D typescript ts-node # development tools npx cdk init app --language = typescript Enter fullscreen mode Exit fullscreen mode The cdk init command scaffolds a CDK app – a Node project where each file is a construct (a reusable piece of cloud infrastructure).

Create a folder cli/ and a tiny Node script that calls Claude:

The Docker image will contain Node, the Claude SDK, and our script.

# Dockerfile FROM node:20-alpine AS builder WORKDIR /app COPY package*.json./ RUN npm ci COPY.. RUN npm run build # compile TypeScript FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist./dist COPY --from=builder /app/node_modules./node_modules ENTRYPOINT ["node", "dist/cli/index.js"] Enter fullscreen mode Exit fullscreen mode In plain English: We first compile the TypeScript code ( npm run build ) in a temporary image, then copy the compiled output into a small runtime image. This two‑stage build keeps the final image lightweight.

git init git add. git commit -m "Initial Claude assistant skeleton" Enter fullscreen mode Exit fullscreen mode Now the repository is ready to be connected to a GitHub source stage.

With the project source ready, we can describe the whole pipeline in CDK. The stack will contain:

npm install @aws-cdk/aws-codepipeline @aws-cdk/aws-codepipeline-actions \ @aws-cdk/aws-codebuild @aws-cdk/aws-ecs @aws-cdk/aws-ecs-patterns \ @aws-cdk/aws-secretsmanager Enter fullscreen mode Exit fullscreen mode 2. Create pipeline-stack.ts // lib/pipeline-stack.ts import * as cdk from ' aws-cdk-lib '; import { Construct } from ' constructs '; import * as codepipeline from ' aws-cdk-lib/aws-codepipeline '; import * as cpactions from ' aws-cdk-lib/aws-codepipeline-actions '; import * as codebuild from ' aws-cdk-lib/aws-codebuild '; import * as ecs from ' aws-cdk-lib/aws-ecs '; import * as ecs_patterns from ' aws-cdk-lib/aws-ecs-patterns '; import * as secretsmanager from ' aws-cdk-lib/aws-secretsmanager '; // A PipelineStack defines the CI/CD flow for our Claude assistant. export class PipelineStack extends cdk. Stack { constructor ( scope: Construct, id: string, props?: cdk.

StackProps ) { super ( scope, id, props ); // -------------------------------------------------------------------- // 1️⃣ Source stage – pull code from GitHub // -------------------------------------------------------------------- const sourceOutput = new codepipeline. Artifact (); const sourceAction = new cpactions. GitHubSourceAction ({ actionName: ' GitHub_Source ', owner: ' my-github-org ', // replace with your org/user repo: ' claude-coding-assistant ', // repo name branch: ' main ', oauthToken: cdk.

SecretValue. secretsManager ( ' github-token ' ), // stored secret output: sourceOutput, }); // -------------------------------------------------------------------- // 2️⃣ Build stage – Docker image + Claude sanity test // -------------------------------------------------------------------- // Secret that holds Claude API key (must be created in Secrets Manager) const claudeSecret = secretsmanager. Secret. fromSecretNameV2 ( this, ' ClaudeApiKey ', ' claude/api-key ' ); const buildProject = new codebuild. PipelineProject ( this, ' BuildProject ', { environment: { buildImage: codebuild.

LinuxBuildImage. STANDARD_7_0, privileged: true, // required for Docker-in-Docker // Pass the secret as an environment variable that CodeBuild will mask in logs environmentVariables: { CLAUDE_API_KEY: { type: codebuild. BuildEnvironmentVariableType.

SECRETS_MANAGER, value: claudeSecret. secretArn, }, }, }, // Grant the build role permission to read the secret role: new iam. Role ( this, ' BuildRole ', { assumedBy: new iam. ServicePrincipal ( ' codebuild.amazonaws.com ' ), managedPolicies: [ iam.

ManagedPolicy. fromAwsManagedPolicyName ( ' AmazonEC2ContainerRegistryPowerUser ' ), ], }). addToPolicy ( new iam. PolicyStatement ({ actions: [ ' secretsmanager:GetSecretValue ' ], resources: [ claudeSecret. secretArn ], }) ), // The buildspec tells CodeBuild exactly what to do. // Note the explicit export of the secret – otherwise it never reaches the Docker build. buildSpec: codebuild. BuildSpec. fromObject ({ version: ' 0.2 ', phases: { pre_build: { commands: [ ' echo Logging in to Amazon ECR... ', ' aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com ', ], }, build: { commands: [ // Export secret into the Docker build context (gotcha #1) ' export CLAUDE_API_KEY=$CLAUDE_API_KEY ', ' docker build -t claude-assistant. ', // Tag with the commit SHA from the source artifact ' docker tag claude-assistant:latest $ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/claude-assistant:$CODEBUILD_RESOLVED_SOURCE_VERSION ', // Push the image for later deployment ' docker push $ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/claude-assistant:$CODEBUILD_RESOLVED_SOURCE_VERSION ', // Run a quick sanity test – invoke the CLI with a sample prompt ' docker run --rm -e CLAUDE_API_KEY=$CLAUDE_API_KEY $ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/claude-assistant:$CODEBUILD_RESOLVED_SOURCE_VERSION node -e "require( \'./dist/cli/index \' )" <<< "write a function that adds two numbers" ', ], }, }, artifacts: { files: [ ' **/* ' ], }, }), }); const buildAction = new cpactions.

CodeBuildAction ({ actionName: ' Build_and_Test ', project: buildProject, input: sourceOutput, outputs: [ new codepipeline. Artifact ()], // dummy artifact for downstream }); // -------------------------------------------------------------------- // 3️⃣ Deploy stage – ECS Fargate service // -------------------------------------------------------------------- const cluster = new ecs. Cluster ( this, ' AssistantCluster ', { vpc: new ec2.

Vpc ( this, ' VPC ' ), // creates a new VPC (simplified) }); const fargateService = new ecs_patterns. ApplicationLoadBalancedFargateService ( this, ' AssistantService ', { cluster, taskImageOptions: { image: ecs. ContainerImage. fromRegistry ( ` ${ cdk.

Aws. ACCOUNT_ID }.dkr.ecr. ${ cdk. Aws.

REGION }.amazonaws.com/claude-assistant: ${ cdk. Fn. getArtifactMetadata ( sourceOutput, ' CommitId ' )} ` ), // Pass the API key at runtime (environment variable) environment: { CLAUDE_API_KEY: claudeSecret. secretValue. toString (), }, secrets: { CLAUDE_API_KEY: ecs. Secret. fromSecretsManager ( claudeSecret ), }, }, desiredCount: 1, publicLoadBalancer: true, } ); // -------------------------------------------------------------------- // Assemble the pipeline // -------------------------------------------------------------------- new codepipeline.

Pipeline ( this, ' ClaudeAssistantPipeline ', { pipelineName: ' ClaudeAssistantPipeline ', stages: [ { stageName: ' Source ', actions: [ sourceAction ], }, { stageName: ' Build ', actions: [ buildAction ], }, { stageName: ' Deploy ', actions: [ new cpactions. EcsDeployAction ({ actionName: ' DeployToFargate ', service: fargateService. service, input: buildAction. actionProperties. outputs! [ 0 ], }), ], }, ], }); } } Enter fullscreen mode Exit fullscreen mode What the code does, step by step Step Explanation Source Pulls the latest commit from GitHub using a personal‑access token stored in Secrets Manager. Build Spins up a CodeBuild container, logs in to Amazon ECR (Elastic Container Registry), builds the Docker image, pushes it, and runs a tiny Claude request to confirm the key works.

The line export CLAUDE_API_KEY=$CLAUDE_API_KEY is the crucial fix that forwards the secret into the Docker build context. Deploy Creates an ECS Fargate service (serverless containers) behind an Application Load Balancer. The container receives the Claude API key at runtime via the secrets field, which keeps the value encrypted in transit and out of logs.

Pipeline Chains the three stages together so that a new commit automatically triggers the whole flow. Helpful tip: After you write the stack, run cdk bootstrap once per account/region before any cdk deploy. This creates the CDK‑specific S3 bucket and IAM roles needed for the pipeline.

Forgetting this step is a common source of “bootstrap missing” errors.

npx cdk bootstrap aws://123456789012/us-east-1 Enter fullscreen mode Exit fullscreen mode Replace the account ID and region with yours. The command creates a bucket named cdk-bootstrap-<account>-<region> and a few roles that the pipeline later assumes.

The most fragile part of an AI‑driven pipeline is secret propagation. CodeBuild can read a secret, but Docker builds run in a separate process that does not inherit environment variables automatically. If you try to docker build without explicitly exporting the secret, the container’s build‑time script will see an empty CLAUDE_API_KEY and any API call will fail.

Below is a minimal Dockerfile snippet that accepts the secret as a build‑time argument:

# Inside Dockerfile (add near the top) ARG CLAUDE_API_KEY ENV CLAUDE_API_KEY=${CLAUDE_API_KEY} Enter fullscreen mode Exit fullscreen mode Now, when the build command runs, the secret is baked into the image’s environment (still encrypted at rest because the image is stored in ECR). For extra safety you can avoid persisting the key by only passing it at runtime (as we do for the ECS task).

In plain English: Think of the secret as a password you need to write on a sticky note for the baker (Docker) to see. If you forget to put the note on the counter, the baker can’t add the secret ingredient, and the cake (your image) will be flavorless.

The buildspec includes a one‑line sanity test:

docker run --rm -e CLAUDE_API_KEY = $CLAUDE_API_KEY \ $ACCOUNT_ID.dkr.ecr. $AWS_DEFAULT_REGION.amazonaws.com/claude-assistant: $CODEBUILD_RESOLVED_SOURCE_VERSION \ node -e "require('./dist/cli/index')" <<< "write a function that adds two numbers" Enter fullscreen mode Exit fullscreen mode What happens?

If the key is missing, the CLI will exit with an authentication error, and the entire pipeline will fail—exactly what you want for early detection.

Automation is only as good as the feedback you get when something goes wrong. With CDK Pipelines you have three built‑in places to observe the health of your AI assistant:

// Inside PipelineStack constructor, after the Deploy stage definition const testProject = new codebuild. PipelineProject ( this, ' PostDeployTest ', { environment: { buildImage: codebuild. LinuxBuildImage.

STANDARD_7_0, }, buildSpec: codebuild. BuildSpec. fromObject ({ version: ' 0.2 ', phases: { build: { commands: [ // Grab the load balancer DNS name from CloudFormation output `LB_DNS=$(aws cloudformation describe-stacks --stack-name ${ cdk. Stack. of ( this ). stackName } --query "Stacks.Outputs[?OutputKey==\'LoadBalancerDNS\'].OutputValue" --output text)`, ' echo Testing endpoint $LB_DNS ', // Send a sample request `RESPONSE=$(curl -s -X POST -H "Content-Type: application/json" -d \'{"prompt":"write a function that multiplies two numbers"}\' http://$LB_DNS)`, // Very naive validation ' if echo $RESPONSE | grep -q "function"; then echo "✅ Test passed"; else echo "❌ Test failed"; exit 1; fi ', ], }, }, }), }); const testAction = new cpactions.

CodeBuildAction ({ actionName: ' PostDeployTest ', project: testProject, input: buildAction. actionProperties. outputs! [ 0 ], }); pipeline. addStage ({ stageName: ' Test ', actions: [ testAction ], }); Enter fullscreen mode Exit fullscreen mode The snippet does three things:

Key tip: CloudWatch Logs automatically capture curl output and any echo statements. If your test fails, the pipeline will stop and you’ll see the exact HTTP payload that caused the problem.

In plain English: By describing your Claude‑powered coding assistant as code, you let AWS do the heavy lifting of building, testing, and deploying. No manual Docker commands, no hidden credentials, and no “it works on my machine” surprises.

With these pieces in place, any team can spin up a reproducible, auditable, and secure Claude‑based coding assistant in minutes—no manual Docker pushes, no secret leaks, and no hidden steps. Happy building!

This article was written with the help of an AI system — Groq (GPT OSS 120B).

Published: 2026-10-20 · Primary focus: CDK

All code blocks are intended to be correct and runnable, but please verify them against the official docs for the tools mentioned before using in production.

Find an error? Drop a comment — corrections are always welcome.

Quelle: dev.to (dev.to). Original öffnen