github kubernetes-sigs/agent-sandbox v1.0.7

4 hours ago

🚀 Announcing Agent Sandbox v1.0.7!

We're excited to announce Agent Sandbox v1.0.7! This release adds optional bearer-token authentication to sandboxd, streaming command execution in the Go SDK, and closer parity across the Python and TypeScript SDKs (env and cwd, named claims, custom kubeconfig, fail-fast on terminated Pods). Warm pools no longer churn members that are waiting on scheduling gates, and they now report missing templates. sandbox-router adds traffic metrics. The multi-cluster fleet example is now complete, and there are new examples for KubeRay RLlib, agent memory that outlives the sandbox, and namespace-wide network policies for RL fleets.


⚠️ Behavior Changes / Action Required

  • Python SDK No Longer Configures the Root Logger (#1900): Importing the SDK used to call logging.basicConfig, which made the application's own basicConfig call do nothing. The SDK now uses module loggers and leaves logging setup to the application.
    • Action Required: To keep seeing the SDK's INFO logs, call logging.basicConfig(level=logging.INFO) in your application.
  • sandboxd Signal Exit Codes (#1897): A process killed by signal n now reports exit code 128+n (for example, 137 for SIGKILL) instead of -1, in both Start and Execute. This matches what a shell reports, and it separates killed or OOM-killed commands from daemon-side failures.
    • Action Required: Callers that treated -1 as "killed by a signal" should check for 128+n instead.
  • WarmPoolNotProgressing Event Action (#1817): The event's action is now the hold cause (HoldingUnschedulable, HoldingSchedulingGated, or HoldingUnschedulableAndSchedulingGated), not Reconciling.
    • Action Required: Update any alerts or event filters that match on Reconciling.

Key Highlights

Core Controller & Warm Pools

  • Warm Pools Hold Members Waiting on Scheduling Gates (#1817): A warm pool member whose Pod waits on scheduling gates (SchedulingGated, for example Kueue admission) is now held the same way as an Unschedulable member, instead of being deleted as stuck when the readiness grace period expires. The grace period now starts when the Pod is scheduled, not when the Sandbox is created, so a member that has just been scheduled isn't deleted while it pulls images. In a Kueue test with too little quota, a 4-replica pool went from 11 sandboxes deleted as stuck to none.
  • Missing Template Warning (#1572): When a SandboxWarmPool needs replicas but its SandboxTemplate is missing, it now emits one SandboxTemplateError warning event and retries every minute until the template exists.
  • SandboxClaim Finished Condition Generation (#1898): A claim's Finished condition now reports the claim's own observedGeneration instead of copying the Sandbox's. kubectl wait --for=condition=Finished no longer times out after a claim-only spec change such as spec.lifecycle.shutdownTime.
  • --enable-rest-client-metrics Flag (#1571): A new controller flag, also exposed as a Helm value, turns off the client-go REST client histograms (request latency and size, DNS, rate limiting, retries). It defaults to true. rest_client_requests_total is always reported.

sandboxd

  • Optional Bearer-Token Authentication (#1895): Set --auth-token-sha256=<hex> or --auth-token-file=<path> (for example, a mounted Secret) to require Authorization: Bearer <token> on every REST request and gRPC call. With the digest flag, only the token's SHA-256 digest goes in the Pod spec. GET /v1/health stays open for kubelet probes. If neither flag is set, behavior is unchanged. NetworkPolicy is still the primary boundary.
  • --root-dir=/ Now Works (#1896): With --root-dir=/, every path except / (for example, /tmp) was rejected as escaping the root. These paths now resolve. A DELETE of / itself is refused with 403.

SDKs

  • Go SDK:
    • Streaming Command Execution (#1901): Commands.Start returns a ProcessHandle that streams stdout and stderr as output arrives, reports the exit code, and sends SIGINT, SIGTERM, or SIGKILL. Cancelling one session doesn't close the shared connection or delete the claim. Requires the sandboxd runtime.
  • Python SDK:
    • env and cwd for commands.run (#1893): Available in both the sync and async clients with the sandboxd runtime. The legacy runtime raises NotImplementedError.
    • SandboxClient as a Context Manager (#1894): On exit, with SandboxClient() as client: runs the same cleanup as the atexit hook, matching AsyncSandboxClient.
    • Short Readiness Waits (#1915): Fixed one-second readiness waits that failed immediately with TimeoutError. Watches also no longer drop the last fraction of a second of the timeout after a reconnect.
  • TypeScript SDK:
    • New createSandbox Options (#1904, #1914): env sets environment variables on the claim (spec.env). claimName and adoptExisting create or adopt a named claim that the caller owns. Both match the Python SDK.
    • Custom KubeConfig (#1909): SandboxClient accepts a kubeConfig to target a specific cluster or user, matching Python's api_client and Go's Options.RestConfig.
    • Faster getSandbox Reattach (#1877): resolveTimeout limits how long to wait for the claim's Sandbox name. waitForReady: false returns a handle without waiting for the Sandbox to become Ready. Previously, reattaching could wait the full sandboxReadyTimeout (180s by default).
    • Packaging Fixes (#1922, #1888): The package now builds in prepack instead of prepare, so installing it no longer runs an install script that needs tsc. PodTunnel no longer deep-imports @kubernetes/client-node internals, which would have broken if a later 2.x release adds an exports map.
    • Empty Pod-Name Annotation (#1903): An empty agents.x-k8s.io/pod-name annotation now falls back to the Sandbox name, matching the controller and the Go and Python SDKs.
  • Python & TypeScript SDKs:
    • Fail Fast on Terminated Pods (#1917): create_sandbox and createSandbox raise SandboxClaimFailedError as soon as the claim reports Ready=False with reason PodFailed or PodSucceeded, instead of waiting for the timeout. This matches the Go SDK.

sandbox-router

  • Traffic Metrics (#1502): New byte counters for client traffic (sandbox_router_client_rx_bytes_total, sandbox_router_client_tx_bytes_total, labeled by sandbox_namespace) and upstream traffic (sandbox_router_upstream_rx_bytes_total, sandbox_router_upstream_tx_bytes_total, labeled by sandbox_namespace and sandbox_id). Two new histograms, sandbox_router_request_size_bytes and sandbox_router_response_size_bytes, use buckets from 100 B to 1 GB. Streamed (SSE) responses are counted as they're read.

Multi-Cluster Fleet & Reinforcement Learning

  • Multi-Cluster Fleet Example Completed (#1541, #1542, #1544, #1545, #1908): Completes examples/multi-cluster-fleet/, which started in v1.0.6. It adds deployment manifests, a hub bootstrap script (setup-hub.sh), and the fleet-member image. It also adds an operator README with a ClusterProfile inventory walkthrough, e2e test tooling with a testing guide, and tools for diagnosing a ClusterProfile hub integration.
  • One NetworkPolicy per Namespace for RL Fleets (#1861): The agent-sandbox-rl SDK's new TemplateSpec.network_policy_management sets spec.networkPolicyManagement on the templates a fleet creates. With Unmanaged templates, a fleet can run under one namespace-wide NetworkPolicy instead of one per template, which avoids hundreds of policies that churn as pools come and go. preflight() warns if no policy covers the fleet's Pods. The new examples/agent-sandbox-rl-network-policy provides the policy, verification scripts, and guidance for GKE Dataplane V2 (Cilium identities).
  • KubeRay RayJob for RLlib (#1868): A CPU-only KubeRay RayJob example for RLlib SandboxEnv. It connects directly to sandboxd through in-cluster Service DNS, without the router or port-forwarding, and keeps checkpoints on a PVC.

Examples & Documentation

  • Agent Memory That Outlives the Sandbox (#1913): examples/recall-memory gives each claim persistent memory without putting a long-lived secret in the sandbox. The sandbox presents a projected service account token. The memory server validates it with TokenReview, follows the owner references from Pod to Sandbox to SandboxClaim, and issues a short-lived key scoped to that claim. Warm-pool sandboxes get no key until they are claimed.
  • One Service Across Claimed Sandboxes (#1887): Manifests and a walkthrough for putting several claimed Sandboxes behind one Kubernetes Service. Labels come from the claims' additionalPodMetadata, so unclaimed warm-pool Pods stay out of the Service.
  • Reaching In-Cluster Services by DNS (#1911): A new Example 4 in examples/policy/network-policy-management/ shows a SandboxTemplate whose sandboxes call an in-cluster Service by its DNS name (egress to kube-dns, dnsPolicy: ClusterFirst).
  • Port-Forward with Kata and gVisor (#1864): The SDK docs now say that kubectl port-forward, the default sandboxd connectivity mode, doesn't work with Kata or gVisor Pods. Use the in-cluster modes instead.

Integrations

  • SDK 1.x Support (#1871): The mcp-server, nemo-gym, and openai integrations now accept k8s-agent-sandbox>=1.0.0,<2.0. Fixed mcp-server's list_files on SDK 1.x.
  • OpenAI Agents Claim Leak (#1932): K8sSandboxClient.delete() no longer reports success while leaving the claim, Pod, and PVC running when the claim lookup fails.

Installation

Standard Install (Core + Extensions)

Recommended for most users and GitOps engines (Argo CD, Config Sync, kustomize):

kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v1.0.7/sandbox-with-extensions.yaml

Selective Install

Install components separately:

# Core only:
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v1.0.7/sandbox.yaml

# Extensions (opt-in):
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v1.0.7/extensions.yaml

Python SDK

pip install k8s-agent-sandbox==1.0.7

Contributors

We extend our sincere thanks to all contributors to this release:
@HasonoCell, @Sean-790761, @YoungJinJung, @aditya-shantanu, @anuptalwalkar, @dependabot, @briankhoi, @chandwaniac, @dongjiang1989, @ericcurtin, @esposem, @git-jxj, @ilaigold, @khirotaka, @lunarwhite, @pranavthakur0-0, @tomergee, @toruiwasa, @vicentefb

New Contributors

Full Changelog: v1.0.6...v1.0.7

Don't miss a new agent-sandbox release

NewReleases is sending notifications on new releases.