🚀 Announcing Agent Sandbox v1.0.6!
We're excited to announce Agent Sandbox v1.0.6! This release adds the first part of a multi-cluster warm-pool fleet planner, interactive processes via commands.start() in the TypeScript SDK, and closer parity across the Go and Python SDKs (per-request command timeouts, claim expiry, sandboxd health and metadata, claim labels and selectors). It also fixes warm-pool status updates under API throttling, stale evictions in the router cache, and dropped PTY output in sandboxd.
⚠️ Breaking Changes / Action Required
- Sandbox Name Length Validation with
spec.service(#1475): Thev1beta1Sandbox CRD now rejects names longer than 63 characters whenspec.serviceistrue. These Sandboxes never worked: the controller gives the headless Service the Sandbox's name, so Service creation failed and the Sandbox never became Ready. A new root-level CEL rule now reports that failure at admission time.- Action Required: The rule covers the whole object and doesn't exempt existing objects. A pre-existing Sandbox with a name over 63 characters and
spec.service: truewill fail every update, including status updates. To fix it, disable or unsetspec.service, or recreate the Sandbox with a name of 63 characters or fewer.
- Action Required: The rule covers the whole object and doesn't exempt existing objects. A pre-existing Sandbox with a name over 63 characters and
- Router Scoped-Token v2 Authorization &
proxy.LookupInterface (#1498): Scoped-token v2 now authorizes the Sandbox UID thatsandbox-routerresolves from its Pod cache, not the caller'sX-Sandbox-UIDheader. A v2 token minted for a deleted Sandbox can no longer reach a replacement Sandbox with the same name. Path-routed (browser) requests now authorize with v2 instead of failing with403. Under v2, cache misses andX-Sandbox-Pod-IPoverrides are rejected. In every mode, if a request'sX-Sandbox-UIDandX-Sandbox-IDdisagree, it now routes to the Sandbox named byX-Sandbox-ID.- Action Required: Out-of-tree implementations of
proxy.Lookupmust implementResolveinstead ofGet/GetByName, pass the dialedcache.EntrytoInvalidate, and dropInvalidateByName.
- Action Required: Out-of-tree implementations of
Key Highlights
Core Controller & Router Stability
- Warm Pool Status Updates Under Throttling (#1852): Fixed
SandboxWarmPoolstatus.replicasandstatus.readyReplicasfreezing when a reconcile hit partial batch errors, such as APF429 Too Many Requeststhrottling during batch creation. - Configurable Warm-Candidate Grace Period (#1758): The new
--sandbox-claim-warm-candidate-grace-periodflag (default2s) sets how long aSandboxClaimwaits for a warm candidate to report a Pod IP before falling back to cold creation. Raise it on clusters with slow IPAM or CNI. - Ready Event Gating (#1826): Sandbox Ready-transition events are now gated on both the Ready condition's status and its reason. New tests confirm the transition reconciles without panicking when events are disabled with
--disable-sandbox-events. - UID-Fenced Router Cache Invalidation (#1498):
sandbox-routernow fences dial-failure and owner-change evictions by Pod UID. A slow dial failure to a terminated Pod no longer evicts the cache entry for its replacement.
Interactive Processes & sandboxd Runtime
- Interactive Processes in the TypeScript SDK (#1802): The new
commands.start()launches long-running processes, shells, and REPLs. It supports streaming stdin/stdout/stderr, backpressure, PTY sizing and resizing, signals (signal(),kill()), and process lifecycle management. - sandboxd PTY Output and Initial Size (#1804): Fixed races in the
sandboxdProcessService where short-lived PTY processes lost buffered output before the stream ended, or started with a0x0window.
SDK Parity & Developer Experience
- Python SDK Improvements:
- Injected
ApiClient(#1509):SandboxClient,AsyncSandboxClient,K8sHelper, andAsyncK8sHelperaccept a pre-configuredapi_clientfor multi-cluster and multi-context setups. - kubectl Tunnels Follow the Injected Client (#1830): kubectl port-forward tunnels now use the cluster and credentials of an injected
api_clientinstead of the ambient kubeconfig. Basic auth is not carried over. - Per-Request Command Timeouts (#1842):
commands.run()acceptscommand_timeout, andExecutionResultexposestimed_out, in both the legacy runtime andsandboxdmodes. - mTLS and Custom Headers for Direct Connections (#1782):
SandboxDirectConnectionConfigaddsextra_headers,client_cert, andca_cert. - In-Cluster Mode Names Aligned with Go and TypeScript (#1854): The
SandboxdInClusterConnectionConfigmodesservice-dnsandpod-ipare renamed toin-cluster-serviceandin-cluster-pod-ip, andSandboxServiceUnavailableErroris renamed toSandboxNoServiceError. The old names still work but are deprecated. - Kubernetes Client 37 Compatibility (#1869): Updated custom-object response parsing and Pod metadata handling for the typed signatures in
kubernetes>=37.0.0.
- Injected
- Go SDK Improvements:
- Claim Expiry with
ShutdownAfter(#1865):Options.ShutdownAftersetsspec.lifecycle.shutdownTime, with theDeletepolicy, on claims the client creates. A crashed client no longer leaks sandboxes. This matches the Python and TypeScript SDKs. - Command Environment & Working Directory (#1849):
RunacceptsWithEnvandWithWorkingDir. - Health & Metadata APIs (#1839): New
Sandbox.HealthandSandbox.Metadatahelpers forsandboxd. - Claim Labels & Selectors (#1836):
Options.Labelslabels claims at creation, andWithLabelSelectorfiltersListAllSandboxes. - Fail Fast on Terminal Claim Conditions (#1834): When a claim can't become ready,
OpenandGetSandboxnow return a sentinel error right away (ErrWarmPoolNotFound,ErrTemplateNotFound, orErrClaimFailed). - Clear Error for Unsupported Runtime (#1835):
RunwithRuntimeSandboxdover a direct RESTAPIURLnow returnsErrUnsupportedByRuntimeinstead of hanging until it fails withErrNotReady.
- Claim Expiry with
- TypeScript SDK Improvements:
- Readiness & Pod IP Helpers (#1821, #1867): New
Sandbox.status()andSandbox.getPodIP(). Pod IPs are canonicalized, including IPv4-mapped IPv6 and dual-stack addresses. - Volume Claim Templates (#1814):
createSandboxacceptsvolumeClaimTemplates. - Fail Fast on Clean Stream Close (#1792):
commands.run()now fails immediately with a connection error whensandboxdcloses the HTTP/2 stream without a response.
- Readiness & Pod IP Helpers (#1821, #1867): New
Multi-Cluster Fleet & Reinforcement Learning
- Multi-Cluster Warm-Pool Fleet Planner (#1435, #1394): Adds the multi-cluster fleet KEP and the first part of a reference planner under
examples/multi-cluster-fleet/. It covers capacity-aware replica placement (Hamilton apportionment), warm-pool sizing, and a per-cluster member daemon that reconciles pools. - Shared Run IDs in
agent-sandbox-rl(#1813): The newFleetConfig.run_idlets a job's orchestrator and workers share one run ID, along with its warm pools and templates. Only the process that warmed a pool resizes or deletes it.
Examples & Documentation
- Docker Sandboxes Example (#1831):
examples/docker-sbxruns Docker Sandboxes (sbx) inside Agent Sandbox microVMs on KVM-enabled Kubernetes nodes. - Python Runtime Sandbox Timeouts (#1841): The
examples/python-runtime-sandboxexecution server accepts a per-requesttimeout_secondsand reportstimed_out. - Scale & Performance Tuning Guide (#1793): Expanded coverage of burst adoption vs. sustained throughput, warm-pool sharding, APF isolation, and controller worker tuning.
- Sandbox Status Conditions Reference (#1825): New reference for Sandbox status conditions and their transition reasons.
Installation
Standard Install (Core + Extensions)
Recommended for most users and for GitOps tools (Argo CD, Config Sync, kustomize):
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v1.0.6/sandbox-with-extensions.yamlSelective Install
Install components separately:
# Core only:
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v1.0.6/sandbox.yaml
# Extensions (opt-in):
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v1.0.6/extensions.yamlPython SDK
pip install k8s-agent-sandbox==1.0.6Contributors
Thanks to everyone who contributed to this release:
@Aasif-Simpplr, @Beverly621, @YoungJinJung, @abhayjoshi201, @aditya-shantanu, @briankhoi, @dependabot, @ekam-walia, @ericcurtin, @hyperb1iss, @igooch, @ilaigold, @janetkuo, @khirotaka, @lunarwhite, @mtkumar123, @vicentefb
New Contributors
- @Beverly621 made their first contribution in #1475
- @Aasif-Simpplr made their first contribution in #1841
- @mtkumar123 made their first contribution in #1827
- @ilaigold made their first contribution in #1862
- @ekam-walia made their first contribution in #1863
Full Changelog: v1.0.5...v1.0.6