GitHub App tokens, push limits and API budgets for secrets
A secret can now hold a GitHub App's private key (githubApp): our servers make its installation tokens and add them to your sandboxes' GitHub requests and git pushes, and the key itself goes into no request. git.push names the branches a push may update, such as refs/heads/task/{label.task}: each label's branch belongs to the first sandbox made with it, even once it is deleted, and that label can't change after the sandbox is made. Any other push is refused with git's own [remote rejected], as is any API call that would move, merge or write to another branch. api caps each sandbox's calls and writes an hour, lists the GraphQL mutations allowed, and lets sandboxes share cached reads. A rule's path segment that is * alone now names any one segment. See GitHub: an App's tokens, branch limits and API budgets.
SDKs take a secret's GitHub App, push limits and API budgets
withruntime 0.25.0 for JavaScript and 0.23.0 for Python, the Go SDK 0.12.0, and the Java and Ruby SDKs 0.11.0 set and return githubApp, git and api. See GitHub: an App's tokens, branch limits and API budgets.
Clear refusals instead of 500 errors on sandbox create
A create that asks for ports beyond 80 and 443 (network.connect) from an account without a kept top-up is refused with 403 connect_not_allowed, saying what lifts it, and a maxTotalCostMicros below the first minutes a paid sandbox holds is refused with 400 invalid_request naming that field; both answered 500 before. A pause sent while a sandbox is still starting, a wake sent while it is pausing, and a restart sent while it is stopping now wait for it instead of being refused, and a file call right after a wake waits for the sandbox to listen instead of answering guest_busy. A persistent sandbox stopped before it ever started now reads diskKept: false, since it has no disk to restart from; it read true, and its restart was refused. See networking, limits and the API guide.
API key limited to chosen sandboxes, approved in the browser
An agent with no key can now ask for a key that reaches only the sandboxes it names, whichever key or connector made them: runtime keys create --sandbox <id> --actions get,exec. An owner or admin approves it from a link, seeing each sandbox and what the key may do. Without create it cannot start, wake or restart them; a running one is billed as usual until its own time limit. See asked for in the browser.
Snapshot starts no longer stop for CPU on one server
A sandbox started from a snapshot whose server was short of CPU for your other sandboxes used to stop with account_busy_here. Now it starts on another server that holds a checked copy of the snapshot, and stops only when none of them has room (or after it has moved 3 times). See A sandbox stopped on its own.
Apps console with traffic and live releases
Console → Apps shows each App as a card with its last day of requests, error rate, copies running, last release and this month's cost. An App's page draws its copies by version, a release step by step as requests move to the new version, its requests, errors and latency over an hour, a day or a week, its busiest routes, and log search by request id or any words. A failed release keeps its output, and the previous version rolls back in one click. See custom domains on an App.
Move from Cloudflare Sandbox to Runtime
A Worker written for Cloudflare's Sandbox SDK (0.x) now runs on Runtime sandboxes once you change its import to withruntime/cloudflare, delete the containers block from wrangler.jsonc and add a RUNTIME_API_KEY secret. Commands, streaming, files, background processes, the code interpreter, preview URLs, sessions and gitCheckout work as before. See change the import.
A sandbox can name the secrets it gets
Create a sandbox with secrets: ["ANTHROPIC_API_KEY"] (runtime sandboxes create --secret ANTHROPIC_API_KEY) and it gets only that egress secret: no placeholder for any other, and our proxy puts no other value into its requests. An agent given untrusted input can no longer send a key meant for other work. [] is none; the list narrows each secret's own only, is fixed for the sandbox's life, and a fork or copy of a snapshot may only narrow it. In the API, the MCP tool and every SDK. See secrets sandboxes never see.
One deletion email a day, not one per pause
A sandbox with :retention days of its own is a day or so from deletion after each idle pause, and its owners were emailed a warning on every pause, though using it again cancels the deletion. Warnings for dates you set this way are now emailed at most once a day for the account, listing every sandbox due, and never once a sandbox has woken or paused again since; the email says its own retention chose the date, and null keeps it while you have credit. See pricing.
A secret that could not be added is no longer silent
When a request to a secret's host leaves your sandbox without the secret because our server could not add it at that moment, the sandbox now gets a sandbox.secret_not_applied event with reason withheld, saying the fault is ours and what to do. See events.
A worker's key runs its own Apps
A key made by another key, or a key in a compartment, can now create, list, deploy, roll back and delete the Apps and Functions its own agent made, as it does sandboxes, over the API and MCP. Another agent's App still answers 404. Such a key deploys from an image only: a deploy naming a build answers 403 (forbidden, or outside_compartment in a compartment); deploy builds with an account's key. Such a key asks an App for at most 2 minCopies, 2 spares and 20 maxCopies; a larger App is made with a key made on the website. It cannot give an App or Function a name one of the account's own Apps holds: create or rename answers 409 name_taken. See Run a swarm.
MCP: runtime_apps action deploy takes its id
It refused its own id, and listed no image or build, for every key; it now takes them. The runtime_apps tool also answers a worker's or compartment's key in the Apps beta, which it refused before.
Snapshots and forks in bursts no longer wait running
A snapshot or a fork of a running sandbox now stops it at once, so the snapshot, or the fork's copies, hold the memory of the moment you asked, and then waits for its turn at the server's disk with the sandbox stopped. Before, it waited for that turn with the sandbox still running, and a burst on one server could take tens of seconds each, the sandbox changing all the while. A sandbox whose time limit or funded time ends soon, on a busy server, still waits running and stops at its turn, as before. See products.
Secret scopes in the Python, Go, Ruby and Java SDKs
The SDKs can now give a secret to some sandboxes instead of all of them, as the JavaScript SDK can: only on secrets.set (only= in Python and Ruby, Only in Go, a sixth argument in Java) and secrets.scope(name, only) (Scope in Go), which changes who gets an existing secret without its value. Python is 0.17.0, Go 0.6.0, Ruby 0.5.0 and Java 0.5.0. See
Give a secret to one App's copies
runtime secrets scope NAME --only-app <app id> gives a secret to every copy of an App, including copies later deploys, restarts and scaling make; a deploy names the secrets its copies see with secrets: ["NAME"], and a copy holds only the placeholder. An App copy's identity token now says which App it is (app_id). See secrets sandboxes never see.
A sandbox out of memory still answers
When a sandbox's programs fill its memory, Linux now ends one of them for memory, as the guide says, instead of the whole sandbox slowing until commands, reads and kills time out. Your programs share its memory less a small reserve for the sandbox's own services. See when a program runs out of memory.
Upload stalled: a clear answer in 30 seconds, not a 503 after two minutes
A request whose body stops arriving for 30 seconds, such as a chunk of a large upload, is now answered at once with the bytes received, where before it waited about two minutes and answered 503 api_unavailable. A body that keeps arriving, however slowly, is never cut. The SDKs and the CLI get 503 body_stalled and send it again by themselves with the same key; other clients get 408 request_timeout. See errors.
Fetch a web page in under a second with a paused browser
The guides show how to keep spare browsers paused, charged only for storage, and wake one per page: wake to page done measured 0.56 to 0.81 seconds. Python's guide gains its browser section. See Spare browsers, paused.
Connection limit per site: 429 Too Many Requests from the egress proxy
A sandbox opens up to 20 new connections a second to one site, and an account's sandboxes on one server up to 100 together, after a burst. Past it the connection is refused with 429 and a sentence naming the site. Downloads over open connections, installs, clones, storage, CDNs and AI APIs are never counted. See connections to one site.
Identity tokens from any running sandbox
A program with no RUNTIME_ID_TOKEN_REQUEST_* variables, such as one started before they were set or a sandbox kept from older guest software, now gets a token too: Sandbox.identityToken() (TypeScript 0.17.3), Python's Sandbox.identity_token() (0.16.2) and runtime sandboxes identity-token ask the sandbox's host for them, and the docs show the same with curl alone. See identity tokens.
No 429 for a busy key right after an update of Runtime
A key whose account runs many sandboxes may send up to 8 times the ordinary rate. Just after Runtime updated its servers, its first requests met the ordinary rate instead, for the moment it took to recognise the key, so a burst sent then was answered 429 rate_limited. Those requests now wait that moment, at most two seconds, and are served at the key's own rate.
Daytona's GPU and sort enums import from the drop-ins
The Daytona drop-ins follow Daytona 0.225.0 and the Prime Sandboxes one follows 0.4.6. GpuType, SandboxClass and the list sort enums now import from withruntime/daytona and withruntime.daytona, and the sort enums sort list. A Python create that asks for a GPU type now gets a plain error, as TypeScript already did, instead of a CPU sandbox. Prime's new lan_network_id on create is refused before a sandbox is made, naming Runtime's private network. See Migrate.
Idle sandboxes now pause after 5 minutes
A new sandbox, browser or sleeping container pauses after 5 minutes with nothing happening in it by default, where it was 1 minute before. Rates are unchanged, but an idle sandbox that sets no idle time now runs, and is billed for its memory, up to 4 more minutes before it pauses; set idlePauseSeconds to 60 to keep the old default. The shortest idle pause is now 60 seconds, not 10: a time of 10 to 59 seconds you set on a new sandbox, or change to, is raised to 60, so that sandbox runs, and is billed, until 60 seconds idle. The answer shows the 60 it got; 0 still turns pausing off. Sandboxes made before today keep the setting they have, under 60 too. See pause when idle.