The ticket queue looked harmless on Monday morning: a flaky test, a dependency bump, a typo in the README. The coding agent took them together in the same checkout, and by noon the dependency bump had broken the test fix sitting next to it. Nobody could say which change had installed what.
That mess is what a sandbox per task prevents: every ticket gets its own isolated machine, a clean checkout goes in, the agent's packages stay inside, and a patch comes out. Solari gives each task an AI Sandbox, created by API, that clones the repository, runs the tests, pauses while the agent waits and hands back the result. This guide follows that loop from create to the finished patch.
Why Each Task Gets Its Own Machine
The case for a machine per task starts with what a coding agent does to the machine it runs on. It installs packages, rewrites files and leaves processes behind, and a sandbox keeps all of that away from the next ticket.
On Solari the default is a dedicated microVM for each sandbox, and no organization ever shares a VM with another. Size is set per task at create time, from 1 to 8 CPUs and up to 16 GB of memory; a request above either ceiling is rejected with a 400, not quietly reduced. A cheaper shared tier exists too, but it refuses file operations, so a coding agent stays on dedicated.
A clean machine is only useful once the code is inside it.
Getting the Repository and Files In
Work enters the sandbox through Git for the code and through the files surface for everything else. The sketch below creates a sandbox for a ticket, clones a shallow copy of the repository and writes the ticket text beside it:
The git namespace returns typed results for status, commits and logs, and runs its commands without a shell, so there is nothing to escape. Larger inputs, such as a fixture database, go in through the files surface's upload and download.
With the code in place, the agent can start running it.
Running Tests the Way a Developer Would
Running the test suite is where a coding agent spends most of its time, so command handling comes next. commands.run waits for a command to finish and returns the exit code with stdout and stderr; its default deadline is 10 minutes, and a command that hits it returns timedOut: true instead of throwing. commands.start streams output from long-running processes such as a dev server.
Named shells keep the working directory and exported variables from call to call, the way a developer's terminal does. Like a continuous integration job, the per-task sandbox makes the result depend on the change, not on what the last run left behind.
Tests rarely end the task, because the agent usually has to wait for something.
Pausing While the Agent Waits
Coding agents wait on model responses, CI runs and human reviewers, and the lifecycle decides what the sandbox does meanwhile. The figure sets out the states a machine moves through.

Pause works like hibernation on a laptop: memory and running processes are saved, and resume() brings the sandbox back exactly as it was. An idle sandbox pauses by default, and because sandboxes share the VM lifecycle, a paused machine does not count against the plan's limit on running machines. On that lifecycle, a same-host resume took about 1.3 seconds on staging, five trials, once the pause had finished saving.
Parking covers shorter gaps: the CPUs freeze while the slot stays held, so the next call wakes the machine with nothing to restore. Because a parked machine still counts toward the limit, it fits a wait on a model, not an overnight review.
Pause keeps a single moment, though, and setup that every task repeats needs a different tool.
Snapshot Once, Fork for Every Task
Most repositories need the same slow setup before any ticket starts, and snapshots stop each task from paying for it again. A snapshot is a full disk and memory image taken while the machine keeps running, and fromSnapshot starts an independent sandbox from it:
Two snapshot rules matter here: a fork passes the same memory size as its source, and snapshot() on a paused machine returns 409 NotRunning until it is resumed. Stored snapshots bill at $0.05 per GB-month after the first 10 GB, so superseded ones are worth deleting.
With setup handled, the last step is getting the work back out.
Getting the Patch Out
The finished work leaves the way the code came in. git.push publishes the agent's branch, and a personal access token passed to it travels as environment variables of that one command, never in the URL, in .git/config or in the process arguments. Logs and build artifacts come out through the files surface.
When a reviewer wants to see the change running, previewUrl(port) returns a signed URL for a dev server, valid for an hour; like the sandbox id, it is a credential to keep out of logs. After the merge the sandbox is killed, or paused if the review might come back.
Choosing the Right Setup
Every ticket runs the same loop on Solari: create a sandbox, bring the code in, run the tests, pause through the waits and push the patch out. The habits that keep it clean are a dedicated sandbox per ticket, forked from a snapshot of installed dependencies, paused when idle, and a Git token scoped to a single command. The lifecycle guide covers each state in depth, and the Solari introduction shows how the same account adds a browser when the agent checks its work in a real page.
Get Started With Solari
The first step is to snapshot a sandbox with the repository's dependencies installed, then fork a fresh copy for the next ticket. Solari sandboxes are ready in 90 ms, and over a sandbox's full lifecycle Solari is about 1.3x faster than E2B and almost 3x cheaper per sandbox hour. Create a free Solari account and the Free plan's credits cover the first sandbox.
