Agent Sandbox#
Sandboxed agents run in isolated pods managed by the upstream agent-sandbox project. Each sandbox enforces process isolation, denies all outbound network access by default, and restricts filesystem writes to the working directory and /tmp.
About#
When the kagent controller reconciles a SandboxAgent, it does the following.
- Generates an
srt-settings.jsonfile with the sandbox runtime configuration and mounts it into the pod. - Creates an upstream
agents.x-k8s.io/v1alpha1Sandbox resource instead of a Deployment. - Delegates pod lifecycle to the agent-sandbox controller, which manages process-level isolation.
The default runtime settings are:
| Category | Default |
|---|---|
| Network | All outbound denied unless listed in allowedDomains |
| Filesystem writes | Allowed in . (working directory) and /tmp |
| Filesystem reads | Unrestricted |
Before you begin#
-
Install kagent v0.9.1 or later by following the quick start guide.
-
Install the agent-sandbox controller and CRDs. The example uses version 0.3.10.
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v{VERSIONS.agentSandbox}/manifest.yamlkubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v{VERSIONS.agentSandbox}/extensions.yaml -
If you installed agent-sandbox after kagent was already running, restart the kagent controller so it registers the new Sandbox API.
kubectl -n kagent rollout restart deploy/kagent-controller
Create a sandboxed agent#
A SandboxAgent has the same spec as a regular Agent. The only difference is kind: SandboxAgent. Instead of creating a Deployment, the kagent controller creates an upstream agents.x-k8s.io Sandbox CR.
-
Apply the following SandboxAgent resource.
kubectl apply -f - <<EOFapiVersion: kagent.dev/v1alpha2kind: SandboxAgentmetadata:name: sandbox-agentnamespace: kagentspec:type: Declarativedeclarative:modelConfig: default-model-configsystemMessage: "You are a helpful assistant running in a sandboxed environment."EOF -
Verify that the agent is accepted and ready.
kubectl -n kagent get sandboxagentsExample output:
NAME READY ACCEPTEDsandbox-agent True True -
Confirm that the upstream Sandbox resource was created.
kubectl -n kagent get sandboxes.agents.x-k8s.ioExample output:
NAME AGEsandbox-agent 30s
Because no sandbox.network is set, this agent has no outbound network access.
Configure network access#
By default, sandboxed agents cannot make outbound network requests. To allow access to specific domains, set spec.sandbox.network.allowedDomains.
- Wildcards such as
*.example.comare supported. - When empty or unset, all outbound access is denied.
Re-apply sandbox-agent with api.github.com in the allowlist.
kubectl apply -f - <<EOFapiVersion: kagent.dev/v1alpha2kind: SandboxAgentmetadata:name: sandbox-agentnamespace: kagentspec:type: Declarativesandbox:network:allowedDomains:- api.github.comdeclarative:modelConfig: default-model-configsystemMessage: "You are a helpful assistant running in a sandboxed environment."EOF
Test the sandboxed agent#
To verify the network allowlist enforces correctly, give the agent a way to make outbound HTTP requests. The simplest path is a container-based skill that runs curl, because skills give the agent a bash tool that runs through the srt sandbox runtime, and srt is what reads srt-settings.json and applies the allowlist.
To invoke a sandboxed agent, you can use A2A requests or the kagent UI.
Step 1: Build a curl skill#
-
Create a skill directory with a
SKILL.mdfile that tells the agent how to use the skill.mkdir fetch-url-skillcd fetch-url-skillcat > SKILL.md <<'EOF'---name: fetch-url-skilldescription: Fetch a URL using curl and return the HTTP status code. Use this when the user asks to fetch, get, or download a URL.---# Fetch URL skillUse this skill when the user asks you to fetch, GET, or test a URL.## Instructions- Run the `bash` tool with the command `curl -sS -o /dev/null -w "HTTP %{http_code}\n" --max-time 10 <URL>` where `<URL>` is the URL the user wants to fetch.- Report the exact HTTP status line back to the user, including any error message that curl prints.EOF -
Build the skill image and push it to a local registry. For full prerequisites and registry setup, see Add skills to agents.
cat > Dockerfile <<'EOF'FROM scratchCOPY . /EOFdocker build -t localhost:5000/fetch-url-skill:latest .docker push localhost:5000/fetch-url-skill:latest
Step 2: Add the skill to the SandboxAgent#
Re-apply sandbox-agent with the skill reference and an updated system message that points the agent at the skill.
kubectl apply -f - <<EOFapiVersion: kagent.dev/v1alpha2kind: SandboxAgentmetadata:name: sandbox-agentnamespace: kagentspec:type: Declarativeskills:insecureSkipVerify: truerefs:# For Kind clusters, use kind-registry:5000 instead of localhost:5000- kind-registry:5000/fetch-url-skill:latestsandbox:network:allowedDomains:- api.github.comdeclarative:modelConfig: default-model-configsystemMessage: "You are a helpful assistant. When the user asks you to fetch a URL, use the fetch-url-skill. Always report back exactly what curl returned."EOF
Wait for the agent to become ready.
kubectl -n kagent get sandboxagents sandbox-agent
Example output:
NAME READY ACCEPTEDsandbox-agent True True
Step 3: Send requests to the sandbox A2A endpoint#
Send A2A JSON-RPC requests directly to the controller's /api/a2a-sandboxes/<namespace>/<name>/ endpoint. Sandboxed agents support exactly one chat session, so the second request must reuse the contextId returned by the first.
Alternatively, you can open the agent in the kagent UI and then send requests through the UI's chat interface to try to access allowed or denied domains.
-
Port-forward the kagent controller.
kubectl -n kagent port-forward svc/kagent-controller 8083:8083 -
Send a request that hits an allowed domain. Capture the
contextIdfrom the response.UUID=$(uuidgen)curl -sS -X POST 'http://localhost:8083/api/a2a-sandboxes/kagent/sandbox-agent/' \-H 'Content-Type: application/json' \-d "{\"jsonrpc\":\"2.0\",\"id\":\"$UUID\",\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"user\",\"parts\":[{\"kind\":\"text\",\"text\":\"Fetch https://api.github.com/zen and tell me exactly what curl returned\"}],\"messageId\":\"$UUID\",\"kind\":\"message\"}}}"The agent runs
curl https://api.github.com/zenthroughsrt, which lets the request through. Example response (truncated):{"result": {"status": { "state": "completed" },"contextId": "707433f6-6d11-4a4d-9756-b4e0b1d9203a","artifacts": [{"parts": [{"kind": "text","text": "The exact response from curl when fetching https://api.github.com/zen is: ..."}]}]}} -
Send a second request with a denied domain, reusing the
contextIdfrom the first response.CTX="707433f6-6d11-4a4d-9756-b4e0b1d9203a" # from previous responseUUID=$(uuidgen)curl -sS -X POST 'http://localhost:8083/api/a2a-sandboxes/kagent/sandbox-agent/' \-H 'Content-Type: application/json' \-d "{\"jsonrpc\":\"2.0\",\"id\":\"$UUID\",\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"user\",\"parts\":[{\"kind\":\"text\",\"text\":\"Fetch https://example.com and tell me exactly what curl returned, including any error messages\"}],\"messageId\":\"$UUID\",\"contextId\":\"$CTX\",\"kind\":\"message\"}}}"The sandbox blocks the request because
example.comis not in the allowlist. The agent reports the curl error verbatim:The exact response from curl when fetching https://example.com is:curl: (56) CONNECT tunnel failed, response 403The
403comes fromsrt's outbound HTTPS proxy, which rejects connections to hosts outsideallowedDomains. Addexample.comtospec.sandbox.network.allowedDomainsand reapply if you want to permit it.
Cleanup#
When you are done, remove the resources that you created.
-
Delete the SandboxAgent. The kagent controller deletes the upstream Sandbox resource and pod with it.
kubectl delete sandboxagent sandbox-agent -n kagent -
Remove the skill image from your local registry and delete the skill directory.
docker rmi localhost:5000/fetch-url-skill:latestcd ..rm -rf fetch-url-skill -
Optionally, uninstall the agent-sandbox controller and CRDs if you no longer need sandboxed agents in this cluster.
kubectl delete -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v{VERSIONS.agentSandbox}/extensions.yamlkubectl delete -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v{VERSIONS.agentSandbox}/manifest.yaml
Next steps#
Continue configuring your sandboxed agent, such as with skills, tools, or human-in-the-loop safeguards.