Skip to content
This documentation covers the kagent 1.0 alpha. For the latest 0.x release, see the 0.x docs.

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Standalone sandboxes

Page as Markdown

Run commands and transfer files in a scratch environment that no agent conversation owns.

A Sandbox is a scratch environment for running commands and working with files. It is scoped to the caller who created it, it expires on a timer, and no agent conversation owns it. You create one from a SandboxTemplate, run processes and move files in it, then delete it or let it expire.

A Sandbox and a SessionSessionA running conversation with one Agent. Unlike the resources it is built from, a Session is not a Kubernetes resource: kagent's gRPC API creates it and its PostgreSQL database tracks it.Learn more are separate runtimes with separate configuration and separate lifetimes. Neither resource references the other.

What you configureWhat runsWhat you call it with
An AgentAgentA Kubernetes custom resource that pairs one AgentTemplate with one Harness. Each side takes either an inline spec or a reference to an existing resource, and the controller compiles the pair into a revision.Learn more that pairs an AgentTemplate with a HarnessA SessionA2A interactions and tasks
A SandboxTemplate that defines a tools environmentA SandboxGuest process and file operations

An agent can create a Sandbox of its own through the kagent MCPMCPModel Context Protocol, an open protocol for exposing tools and resources to a model. kagent reaches an MCP server through a RemoteMCPServer resource, and an AgentTemplate binds individual tools from it.Learn more server, using the same service that a person calls. The agent’s conversation and the Sandbox’s lifetime stay independent of each other.

Before you begin

  1. Install kagent and set the following controller.sandbox values on the installation. Sandbox preparation needs a guest image digest, and the chart ships no default, so a SandboxTemplate never becomes ready until you set one. The remaining values allocate the compute that each Sandbox runs on and bound how long it lives.

    controller:
      sandbox:
        guestImage:
          digest: sha256:1821780ef01958f63cb9a1a1d9a175f7e386e7c72859dd29ab86d8644a47d2d4
        cpu: 1
        memory: 1Gi
        defaultTTL: 1h
        maxTTL: 24h

    A SandboxTemplate cannot override these values, so they are the installation’s policy rather than a per-template choice.

    ValueDefaultDescription
    controller.sandbox.guestImage.digest""The digest-pinned guest image. Required: preparation fails without it. The controller passes the digest to Agent Substrate unchanged and resolves no tags, so supply a digest rather than a tag.
    controller.sandbox.cpu1CPU allocated to each Sandbox.
    controller.sandbox.memory1GiMemory allocated to each Sandbox.
    controller.sandbox.defaultTTL1hLifetime applied when kagent sandbox create omits --ttl.
    controller.sandbox.maxTTL24hUpper bound on any requested lifetime. Note that activity does not extend a Sandbox’s lifetime. A Sandbox expires the configured interval after it is created, however recently a command ran in it.
  2. Download the kagent CLI. The --version flag matches the CLI to the release that these docs cover.

    curl https://raw.githubusercontent.com/kagent-dev/kagent/refs/heads/main/scripts/get-kagent | bash -s -- --version v1.0.0-alpha7
  3. Install jq to read the Sandbox ID out of the CLI’s JSON output.

Create a SandboxTemplate

A SandboxTemplate is a namespaced api.kagent.dev/v1alpha3 resource that prepares a reusable runtime. Applying one does not allocate a Sandbox.

  1. Apply a SandboxTemplate.

    kubectl apply -f - <<EOF
    apiVersion: api.kagent.dev/v1alpha3
    kind: SandboxTemplate
    metadata:
      name: scratch
      namespace: kagent
    spec:
      workload:
        # Replace with your own tools image and its digest.
        image: registry.example.com/tools@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
      env:
        - name: LANG
          value: C.UTF-8
      substrate:
        workerPoolRef:
          name: kagent-default
        snapshotPolicy:
          location: s3://ate-snapshots/kagent/
    EOF

    Review the following table to understand this configuration. For the complete schema, see the API reference.

    FieldRequiredDescription
    workload.imageYesThe tools image, pinned by sha256 digest. A tag alone is rejected, because a prepared revision must be reproducible.
    envNoEnvironment defaults for the guest, up to 100. Each entry sets a literal value, which is required and may be an empty string. The schema defines no secret-backed source, so the API server rejects a credentialRef entry as an unknown field.
    substrate.workerPoolRef.nameYesThe WorkerPool that this template’s Actors are scheduled onto.
    substrate.snapshotPolicy.locationYesThe object storage location for Actor snapshotsSnapshotThe stored state that an Actor suspends to, held in object storage. Resuming restores the Actor from its most recent snapshot, which is what makes suspending idle agents cheap.Learn more.

    A SandboxTemplate takes no startup command and no guest toggle. kagent supplies the guest entrypoint from the image that controller.sandbox.guestImage.digest names. That image replaces the tools image’s own entrypoint. Your tools image contributes the installed programs and nothing else.

  2. Confirm that the template prepared a revision before you create a Sandbox from it.

    kubectl get sandboxtemplate scratch -n kagent \
      -o jsonpath='{range .status.conditions[?(@.type=="Ready")]}{.status} {.reason} {.message}{end}'

Editing a template prepares a new revision. A Sandbox that already exists keeps the revision it was created from, and deleting the template retires preparation without removing the Sandboxes that pinned it.

Run a command

Warning

The gateway denies every outbound connection from a Sandbox. kagent compiles an empty egress policy as it creates a Sandbox, and the gateway rejects any destination that the policy does not name, so a command that fetches a package, clones a repository, or calls an API fails. The SandboxTemplate schema defines no destination field, so no configuration opens one. Move what a command needs into the Sandbox with kagent sandbox upload.

Each kagent sandbox command makes one lifecycle attempt rather than retrying for you, so create takes a stable --request-id that you reuse to retry the same creation.

  1. List the templates that your installation prepared.

    kagent sandbox templates

    Example output:

    NAMESPACE  NAME     IMAGE
    kagent     scratch  registry.example.com/tools@sha256:aaaa...
    
  2. Create a Sandbox, and save its ID.

    export SANDBOX_ID=$(kagent sandbox create scratch --request-id my-first-sandbox -o json | jq -r '.id')
    echo $SANDBOX_ID

    Run the command without -o json to see the table instead. STATE and OPERATION both matter, because lifecycle work can still be pending when a call returns.

    ID                                    TEMPLATE        STATE                OPERATION               EXPIRES               FAILURE
    0198c3f1-2a44-7c90-b5e1-9d8f3a7b2c04  kagent/scratch  RUNTIME_STATE_READY  RUNTIME_OPERATION_NONE  2026-10-01T16:30:00Z
    
  3. Run a command in the Sandbox. The default working directory is /data/workspace, which the guest creates before it reports ready.

    kagent sandbox exec $SANDBOX_ID -- python --version

    A timeout stops the command from waiting rather than stopping the remote process. To reconnect to a process that outlived its exec, pass its process ID to kagent sandbox wait.

  4. Move a file in, run against it, and read the result back out.

    kagent sandbox upload $SANDBOX_ID ./script.py /data/workspace/script.py
    kagent sandbox exec $SANDBOX_ID -- python /data/workspace/script.py
    kagent sandbox download $SANDBOX_ID /data/workspace/out.txt ./out.txt
  5. Delete the Sandbox when you are finished. Deleting is not required, because the Sandbox expires on its own. Deleting it releases the compute immediately.

    kagent sandbox delete $SANDBOX_ID

Important

Suspending a Sandbox interrupts whatever it is doing. kagent sandbox suspend waits for no process, output stream, or file transfer, so a command can be cut off mid-run and a file can be left partly written. Resuming restores the durable files under /data, but a process handle does not survive, because the guest holds it in memory. Suspend a Sandbox only when you can repeat whatever it was running.

Reach a sandbox from an agent

kagent’s Helm chart installs a RemoteMCPServer named kagent-api in the controller’s namespace, pointing at the controller’s own /mcp endpoint. This server exposes the Session and checkpoint tools alongside the sandbox tools, so an AgentTemplate reaches sandboxes through an ordinary tool binding.

tools:
  - mcp:
      server:
        kind: RemoteMCPServer
        name: kagent-api
      tools:
        - list_sandbox_templates
        - create_sandbox
        - list_sandboxes

An agent that creates a Sandbox owns it under whatever identity the MCP connection authenticated, not under the identity of the person it is talking to. A Session share token grants no access to a Sandbox. To have an agent act for the person who invoked it, configure credential propagation. The Go kagent runtime reads KAGENT_PROPAGATE_TOKEN=true to pass the caller’s credentials and identity to the MCP servers that you trust.

The MCP transfer limits are tighter than the command line’s. A gRPC file transfer is bounded at 64 MiB. An MCP transfer or output read is bounded at 1 MiB, encodes bytes as base64, and returns a continuation offset for reading more.

Next steps