lambda-microvm-hook-server 0.1.0

Hook server for supervising commands in AWS Lambda MicroVMs
Documentation

Run Aether in an AWS Lambda MicroVM

This crate provides the lifecycle hook server needed to run Aether as a one-shot coding agent in a Lambda MicroVM.

Build a MicroVM image

1. Create a Dockerfile containing Aether, the hook server, Git, and the GitHub CLI:

FROM rust:1.97-bookworm AS build
RUN cargo install --locked aether-agent-cli
RUN cargo install --locked lambda-microvm-hook-server

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates git gh \
    && rm -rf /var/lib/apt/lists/*
COPY --from=build /usr/local/cargo/bin/aether /usr/local/bin/
COPY --from=build /usr/local/cargo/bin/lambda-microvm-hook-server /usr/local/bin/
CMD ["lambda-microvm-hook-server"]

2. Upload it to S3:

zip aether-microvm.zip Dockerfile
aws s3 cp aether-microvm.zip s3://YOUR_BUCKET/aether-microvm.zip

3. Create the microVM image

Replace the bucket, Region, account ID, and role name:

aws lambda-microvms create-microvm-image \
  --name aether \
  --code-artifact uri=s3://YOUR_BUCKET/aether-microvm.zip \
  --base-image-arn arn:aws:lambda:YOUR_REGION:aws:microvm-image:al2023-1 \
  --build-role-arn arn:aws:iam::YOUR_ACCOUNT_ID:role/YOUR_BUILD_ROLE \
  --egress-network-connectors arn:aws:lambda:YOUR_REGION:aws:network-connector:aws-network-connector:INTERNET_EGRESS \
  --hooks '{
    "port": 9000,
    "microvmImageHooks": {
      "ready": "/aws/lambda-microvms/runtime/v1/ready",
      "readyTimeoutInSeconds": 300
    },
    "microvmHooks": {
      "run": "/aws/lambda-microvms/runtime/v1/run",
      "runTimeoutInSeconds": 60,
      "terminate": "/aws/lambda-microvms/runtime/v1/terminate",
      "terminateTimeoutInSeconds": 30
    }
  }'

4. Wait for AWS to build your microVM image

aws lambda-microvms get-microvm-image --image-identifier aether

Wait until state is CREATED:

Run your agent

Create a short-lived fine-grained GitHub token with Contents: read/write and Pull requests: read/write, then export it with your model provider's key:

export GH_TOKEN=...
export ZAI_API_KEY=...

The setup script is supplied dynamically for each run. This example clones the requested repository and passes the user's prompt directly to Aether:

cat > setup.sh <<'EOF'
set -eu

repository=$1
prompt=$2
workspace=/workspace/repository

gh auth setup-git
gh repo clone "$repository" "$workspace"
cd "$workspace"
exec aether headless --output text "$prompt"
EOF

Build the run payload. OWNER/REPOSITORY may be public or private as long as the token can access it.

jq -n \
  --rawfile setup setup.sh \
  --arg repository "OWNER/REPOSITORY" \
  --arg prompt "Fix the failing login test, add a regression test, and open a pull request" \
  --arg github_token "$GH_TOKEN" \
  --arg zai_key "$ZAI_API_KEY" \
  '{
    command: "/bin/sh",
    args: ["-c", $setup, "setup.sh", $repository, $prompt],
    environment: {
      GH_TOKEN: $github_token,
      ZAI_API_KEY: $zai_key
    }
  }' > payload.json

Run the agent:

aws lambda-microvms run-microvm \
  --image-identifier aether \
  --egress-network-connectors arn:aws:lambda:YOUR_REGION:aws:network-connector:aws-network-connector:INTERNET_EGRESS \
  --run-hook-payload file://payload.json \
  --maximum-duration-in-seconds 3600

Aether clones the repository, completes the task, and opens the PR. Watch the image's CloudWatch logs or run gh pr list --repo OWNER/REPOSITORY to see when it appears.

When Aether finishes, the hook server exits and Lambda terminates the MicroVM. The maximum duration is only a guardrail for a stuck agent. The run payload contains credentials, so use narrowly scoped, short-lived tokens.