Run Box on Amazon EKS
Amazon Elastic Kubernetes Service (EKS) runs this coding workload as a Kubernetes Job. Box permits project changes and refuses protected-file access, deletion, and an unapproved network request. Start with the fixed script. Add Claude Code when you want the model to choose tools.
Before you start
Section titled “Before you start”Use an EKS cluster with Linux ARM64 workers and pod user namespaces.
ARM64 is the 64-bit Arm processor architecture.
The worker and admission settings must permit hostUsers: false, procMount: Unmasked, and seccompProfile: Unconfined.
These settings relax the outer container’s restrictions so Box can create its own sandboxes.
The workload runs as user 991, drops capabilities, and disables privilege escalation.
Install Docker with an ARM64 builder, Python 3, and kubectl.
Authenticate to a container registry that you can push to and your workers can pull from.
Configure kubectl for your cluster. The EKS connection guide explains that step.
Cluster and registry usage can incur charges.
The sample README records the tested Box revision and platform versions. Those versions describe the tested configuration. They do not establish minimum versions or broader platform support.
Build the image
Section titled “Build the image”Clone the repository and enter the sample directory:
git clone https://github.com/strands-agents/box.gitcd box/examples/cloud-deployments/eksexport IMAGE='YOUR_REGISTRY/box-example:scripted'export NAMESPACE='box-example'export KUBE_CONTEXT='YOUR_KUBERNETES_CONTEXT'docker build --platform linux/arm64 --target scripted -t "$IMAGE" .docker push "$IMAGE"The Dockerfile fetches and builds the pinned Box source.
Build dependencies remain in the build stage. The runtime image contains Box, Python, Bash, and the exercise.
Record the pushed image digest. For repeated runs, set IMAGE to that immutable digest.
Submit the Job
Section titled “Submit the Job”Inspect the generated Job before submitting it:
python3 run.py --image "$IMAGE" --namespace "$NAMESPACE" --renderThe output is a Job document with one workload container and an ARM64 node selector. The fixed script requires no model access or workload role.
kubectl --context "$KUBE_CONTEXT" create namespace "$NAMESPACE" --dry-run=client -o yaml | \ kubectl --context "$KUBE_CONTEXT" apply -f -python3 run.py --image "$IMAGE" --namespace "$NAMESPACE" --context "$KUBE_CONTEXT"The runner creates a Job, waits for completion, and saves logs and a receipt under evidence/JOB_NAME/.
A successful receipt contains passed: true and 11 successful checks.
A failed workload or missing result returns a nonzero exit code.
If polling fails after submission, the runner saves an incomplete receipt and prints the command to inspect the existing Job.
The Job can continue running. Use its recorded name for inspection and cleanup.
Read the result
Section titled “Read the result”The workload corrects add(a, b) through Box’s shell.
An independent check verifies three arithmetic cases and the exact resulting source.
The remaining checks compare policy decisions, native access results, and protected-file hashes.
| Operation | Expected result |
|---|---|
| Read and change project files through Box’s shell | Permitted. |
| Read the private fixture directly or through the shell | Refused. |
| Change the read-only reference file | Refused. |
| Delete the protected project file | Refused by policy. |
Request https://example.com/ | Refused by policy. |
Use receipt.json for the outcome and stdout.json for individual checks.
Use pods.json and stderr.txt to diagnose startup or admission failures.
A client error alone does not establish a policy refusal. The verifier also checks the decision records.
Run Claude Code
Section titled “Run Claude Code”The Claude variant adds live Bedrock model calls and a synthetic Model Context Protocol (MCP) tool service.
MCP is the protocol the agent uses to call that service’s tools.
Use us-west-2 and access to the selected us.anthropic.claude-sonnet-4-6 inference profile.
The template grants model invocation and bedrock:CallWithBearerToken through a dedicated workload role.
Use EKS Pod Identity to connect the role to a separate Kubernetes service account. The trusted controller obtains credentials outside the agent’s sandbox and generates a short-lived Bedrock token. Box inserts the token into permitted model requests. The agent receives a substitute value. Direct credential retrieval from inside the agent’s sandbox requires separate validation.
export AWS_REGION='us-west-2'export CLUSTER_NAME='YOUR_CLUSTER'export SERVICE_ACCOUNT='box-example'export IDENTITY_STACK='BoxExamplePodIdentity'export CLAUDE_IMAGE='YOUR_REGISTRY/box-example:claude'kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" create serviceaccount "$SERVICE_ACCOUNT"aws cloudformation deploy --region "$AWS_REGION" --stack-name "$IDENTITY_STACK" \ --template-file pod-identity.json --capabilities CAPABILITY_IAM \ --parameter-overrides ClusterName="$CLUSTER_NAME" Namespace="$NAMESPACE" \ ServiceAccount="$SERVICE_ACCOUNT" InstallAgent=falsedocker build --platform linux/arm64 --target claude -t "$CLAUDE_IMAGE" .docker push "$CLAUDE_IMAGE"python3 run.py --mode claude --image "$CLAUDE_IMAGE" --namespace "$NAMESPACE" \ --context "$KUBE_CONTEXT" --service-account "$SERVICE_ACCOUNT" \ --region "$AWS_REGION" --model us.anthropic.claude-sonnet-4-6InstallAgent=false uses an existing Pod Identity Agent addon.
If your cluster lacks that addon, use InstallAgent=true and a compatible AgentVersion parameter.
Follow the Pod Identity setup requirements, including the worker’s permission to assume pod identities.
The trusted controller needs network access to the AWS endpoints used for credentials and model calls.
The expected result is passed: true with 23 successful checks.
Model responses can vary. Inspect the verifier’s result separately from the agent’s written report.
Clean up
Section titled “Clean up”Use the Job name printed by the runner:
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" delete job JOB_NAME_FROM_RECEIPTRepeat for each example Job you created. If you created the optional identity stack, delete it after its Jobs finish:
aws cloudformation delete-stack --region "$AWS_REGION" --stack-name "$IDENTITY_STACK"aws cloudformation wait stack-delete-complete --region "$AWS_REGION" --stack-name "$IDENTITY_STACK"kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" delete serviceaccount "$SERVICE_ACCOUNT"Delete the example images through your registry’s image-management tools when you finish. Retain shared cluster resources and any existing Pod Identity addon.