Repository navigation
Anthropic self hosted sandboxes #706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5640858
f466c64
1bf34bd
4f2d598
71556d2
d07e91b
1ce711b
d041576
8278d05
32a2c52
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,227 @@ | ||
| export const metadata = { | ||
| title: "Anthropic Self-Hosted Sandboxes with kagent", | ||
| publishDate: "2026-11-07T00:00:00Z", | ||
| description: | ||
| "kagent lets you run Anthropic self-hosted sandboxes on your own infrastructure.", | ||
| author: "Steven Jin", | ||
| authorIds: ["stevenjin8"], | ||
| }; | ||
|
|
||
| # Anthropic Self-Hosted Sandboxes with kagent | ||
|
|
||
| <Aside type="warning"> | ||
| This post uses a pre-release version with commit `4de694355985` of kagent and an experimental feature. | ||
| The API will likely change in the future. | ||
| </Aside> | ||
|
|
||
| In May 2026, Anthropic released [self-hosted sandboxes](https://claude.com/resources/articles/claude-managed-agents-updates), allowing your Claude agents to provision sandboxes and execute code on your infrastructure. | ||
| Anthropic hosts the agent loop, while kagent connects to Anthropic and runs the agent's code execution sandbox on your Kubernetes cluster. | ||
|
|
||
| As a new contributor, I was surprised that kagent aims to be a complete agentic solution regardless of your provider or harness. | ||
| This integration is an example of doing things beyond running harnesses. | ||
| In this post, we will create an agent on Anthropic, watch kagent provision a sandbox for it, and see how kagent suspends idle sandboxes while persisting their state. | ||
| Although this post focuses on Anthropic, we plan on providing similar integrations for other managed agent platforms. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| You will need Kind, the kagent CLI, and the Anthropic `ant` CLI to follow these instructions. | ||
|
|
||
| Install the kagent CLI. | ||
|
|
||
| ``` | ||
| curl https://raw.githubusercontent.com/kagent-dev/kagent/refs/heads/main/scripts/get-kagent | bash -s -- --version v1.0.0 | ||
| kagent version | ||
| ``` | ||
|
|
||
| See the [Anthropic docs](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/quickstart) to install the Anthropic CLI. Then, log in to the CLI. | ||
|
|
||
| ``` | ||
| ant auth login # Or export ANTHROPIC_API_KEY | ||
| ``` | ||
|
|
||
| Next, create a [self-hosted environment](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#run-your-first-session) on [Claude Platform](https://platform.claude.com/environments), and generate its environment key. | ||
|
|
||
| ``` | ||
|
Nadine2016 marked this conversation as resolved.
Resolved
|
||
| ANTHROPIC_ENVIRONMENT_ID=env_xxx | ||
| ANTHROPIC_ENVIRONMENT_KEY=sk-ant-oatxxx | ||
| ``` | ||
|
|
||
| ## Setup and Installation | ||
|
|
||
| Start by provisioning a [Kind](https://kind.sigs.k8s.io/) cluster. | ||
|
|
||
| ```bash | ||
| curl -fsSL https://raw.githubusercontent.com/kagent-dev/kagent/4de694355985e9d06dc92ad1adfa64d96d32f19e/scripts/kind/kind-config.yaml | | ||
| kind create cluster --name kagent \ | ||
| --image kindest/node:v1.35.0 --config - | ||
| ``` | ||
|
|
||
| Store the environment key in a Kubernetes Secret so it isn't exposed in the controller's configuration. | ||
|
|
||
| ```bash | ||
| kubectl create namespace kagent | ||
| kubectl create secret generic anthropic-environment-key -n kagent \ | ||
| --from-literal=key="${ANTHROPIC_ENVIRONMENT_KEY}" | ||
| ``` | ||
|
|
||
| Next, create the configuration files for our kagent install. | ||
|
|
||
| ```bash | ||
| VALUES_DIR=$(mktemp -d) | ||
|
|
||
| cat > ${VALUES_DIR}/kagent-values.yaml <<EOF | ||
| registry: ghcr.io | ||
| tag: 0.0.0-alpha.g4de694355985 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we install the CLI with 1.0.0-rc3 but then install a pre-release here. should these two match?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally, yes, but I couldn't find a great way of installing the prerelease CLI |
||
| config: | ||
| sandboxes: | ||
| guestImage: ghcr.io/kagent-dev/kagent/sandbox-guest@sha256:94b1f9e216eee8778797d54b9d6e2b17b74089157d708097577b1479e4d92bd0 | ||
|
|
||
| controller: | ||
| image: | ||
| pullPolicy: Always | ||
| env: | ||
| - name: EXPERIMENTAL_ANTHROPIC_SELF_HOSTED_SANDBOXES_ENABLED | ||
| value: "true" | ||
| - name: EXPERIMENTAL_ANTHROPIC_SELF_HOSTED_SANDBOXES_ENVIRONMENT_ID | ||
| value: ${ANTHROPIC_ENVIRONMENT_ID} | ||
| - name: EXPERIMENTAL_ANTHROPIC_SELF_HOSTED_SANDBOXES_ENVIRONMENT_KEY | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this key be stored in a secret instead so that it is not visible inside the controller?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that's a fair point, and we need to think about the UX better, but secrets will always be visible inside the controller, otherwise it wouldn't be able to use it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let me make it a secret/secretref |
||
| valueFrom: | ||
| secretKeyRef: | ||
| name: anthropic-environment-key | ||
| key: key | ||
| - name: EXPERIMENTAL_ANTHROPIC_SELF_HOSTED_SANDBOXES_TEMPLATE_NAMESPACE | ||
| value: kagent | ||
| - name: EXPERIMENTAL_ANTHROPIC_SELF_HOSTED_SANDBOXES_TEMPLATE_NAME | ||
| value: anthropic-self-hosted-sandbox | ||
| EOF | ||
|
|
||
| cat > ${VALUES_DIR}/config.yaml <<EOF | ||
| install: | ||
| kagent: | ||
| repository: oci://ghcr.io/kagent-dev/kagent/helm/ | ||
| version: 0.0.0-alpha.g4de694355985 | ||
| valuesFiles: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add inline values blocks to make this easier |
||
| - kagent-values.yaml | ||
| EOF | ||
| ``` | ||
|
|
||
| Install kagent in your cluster. | ||
|
|
||
| ```bash | ||
| # This can take a while | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably try and fix that 😆 |
||
| # OPENAI_API_KEY is only read if we want to create an agent using an OpenAI model, which we do not do. | ||
| OPENAI_API_KEY=unset kagent --config "${VALUES_DIR}/config.yaml" install | ||
|
Stevenjin8 marked this conversation as resolved.
Resolved
|
||
| ``` | ||
|
|
||
| Next, create the [`SandboxTemplate`](/docs/kagent/1.x/reference/api-ref#sandboxtemplate) referenced above and its [`EgressPolicy`](/docs/kagent/1.x/reference/api-ref#egresspolicy). | ||
|
Stevenjin8 marked this conversation as resolved.
Resolved
|
||
| These configure the sandboxes kagent will create for our Anthropic agents. | ||
|
|
||
| ```bash | ||
| kubectl apply -f - <<EOF | ||
| apiVersion: api.kagent.dev/v1alpha3 | ||
| kind: EgressPolicy | ||
| metadata: | ||
| name: anthropic-managed-agents | ||
| namespace: kagent | ||
| spec: | ||
| destinations: | ||
| - origin: https://*.anthropic.com | ||
| --- | ||
| apiVersion: api.kagent.dev/v1alpha3 | ||
| kind: SandboxTemplate | ||
| metadata: | ||
| name: anthropic-self-hosted-sandbox | ||
| namespace: kagent | ||
| spec: | ||
| workload: | ||
| # Nightly sandbox-guest image containing ant v2.5.0. | ||
| image: ghcr.io/kagent-dev/kagent/sandbox-guest@sha256:94b1f9e216eee8778797d54b9d6e2b17b74089157d708097577b1479e4d92bd0 | ||
|
Comment on lines
+136
to
+138
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this automatically used if nothing is set? If not we should probably do that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. Especially since we are using nightly images and there isn't a great way to install the nightly CLI. You need to authenticate to gh to download nightly release images |
||
| substrate: | ||
| workerPoolRef: | ||
| name: kagent-default | ||
| snapshotPolicy: | ||
| location: gs://ate-snapshots/anthropic-managed-agents/ | ||
| egressPolicyRefs: | ||
| - name: anthropic-managed-agents | ||
| EOF | ||
| kubectl wait -n kagent --for=condition=Ready \ | ||
| sandboxtemplate/anthropic-self-hosted-sandbox --timeout=15m | ||
| ``` | ||
|
|
||
| In a separate terminal, port-forward the kagent controller on your local machine so the `kagent` CLI can connect to the control plane. | ||
|
|
||
| ``` | ||
| kubectl port-forward -n kagent service/kagent-controller 8083:8083 | ||
| ``` | ||
|
|
||
| ## kagent in action | ||
|
|
||
| Create an [Anthropic agent](https://platform.claude.com/docs/en/managed-agents/agent-setup). | ||
|
|
||
| ```bash | ||
| AGENT_ID=$(ant --format json beta:agents create \ | ||
| --name "kagent-sandbox-agent" \ | ||
| --model claude-haiku-5-5 \ | ||
| --system "You are a helpful coding agent that is testing a sandbox implementation. Your working directory is /data/workspace. Be concise." \ | ||
| --tool '{type: agent_toolset_20260401}' | \ | ||
| jq -r .id) | ||
| ``` | ||
|
|
||
| Then, create a [session](https://platform.claude.com/docs/en/managed-agents/sessions) for the agent in your environment. | ||
|
|
||
| ```bash | ||
| SESSION_ID=$(ant --format json beta:sessions create \ | ||
| --agent "$AGENT_ID" \ | ||
| --environment-id "$ANTHROPIC_ENVIRONMENT_ID" | \ | ||
| jq -r .id) | ||
| ``` | ||
|
|
||
| Open an interactive chat with the agent and ask it to create the `/data/workspace/helloworld.txt` file containing the `Hello world!` string. | ||
|
|
||
| ```bash | ||
| ant beta:sessions connect "$SESSION_ID" | ||
| ``` | ||
|
|
||
|  | ||
|
|
||
| We can see that kagent provisioned a sandbox in our cluster by listing sandboxes in another terminal. | ||
| Note that you will have to set the `ANTHROPIC_ENVIRONMENT_ID` environment variable again. | ||
|
|
||
| ```bash | ||
| USER_ID=$(printf '%s' 'kagent:anthropic-self-hosted-sandboxes' | base64 | tr '+/' '-_' | tr -d '=\n') | ||
| USER_ID="${USER_ID}.$(printf '%s' "$ANTHROPIC_ENVIRONMENT_ID" | base64 | tr '+/' '-_' | tr -d '=\n')" | ||
| kagent sandbox list --user-id "$USER_ID" | ||
| ``` | ||
|
|
||
| ```console | ||
| ID TEMPLATE STATE OPERATION EXPIRES FAILURE | ||
| 01a1b853-xxx kagent/anthropic-self-hosted-sandbox RUNTIME_STATE_READY RUNTIME_OPERATION_NONE 2026-11-08T11:24:07Z | ||
| ``` | ||
|
|
||
| After about five minutes without work, the sandbox automatically suspends and stops consuming CPU and memory. | ||
|
|
||
| ```console | ||
| $ kagent sandbox list --user-id "$USER_ID" | ||
| ID TEMPLATE STATE OPERATION EXPIRES FAILURE | ||
| 01a1b853-xxx kagent/anthropic-self-hosted-sandbox RUNTIME_STATE_SUSPENDED RUNTIME_OPERATION_NONE 2026-11-08T11:24:07Z | ||
| ``` | ||
|
|
||
| In the same session, we can ask the agent to check the contents of the file we just created. | ||
| This will automatically resume the sandbox with the filesystem intact! | ||
|
|
||
|  | ||
|
|
||
| By default, all outbound network access is denied. | ||
| In the same session, if we ask the agent to access `kagent.dev`, we see that network access is denied. | ||
|
|
||
|  | ||
|
|
||
|
Stevenjin8 marked this conversation as resolved.
Resolved
|
||
| You can dynamically control which websites your agent can access using [Egress Policies](/docs/kagent/1.x/reference/api-ref#egresspolicy). | ||
| These policies also let you inject credentials into your agent's outbound requests without placing those credentials in the sandbox. | ||
|
|
||
| ## What's next | ||
|
|
||
| We are excited to expand the Sandbox API and deepen its integration with Anthropic self-hosted sandboxes. | ||
| We plan to make the API more expressive so operators can control which agents get which `SandboxTemplate`. | ||
| We also plan to improve suspension and resumption so you can run more sandboxes on your cluster. | ||
| Finally, we hope to release integrations for other managed agent platforms! | ||
Uh oh!
There was an error while loading. Please reload this page.