Back to articles

How to run agent tool calls without keeping a VM open

Put the agent's workspace on a persistent disk and run each bash or file tool as one disk.exec call in a fresh microVM, with nothing to keep alive between calls.

5 min read

To run an agent's tool calls without keeping a VM open, put the agent's working directory on a persistent disk and implement each tool as one short-lived command against that disk. With Archil, every disk.exec() call starts a Firecracker microVM with the disk mounted, runs the command, returns the output and shuts the microVM down, so there is no sandbox to start, keep alive or clean up between tool calls.

How to run agent tool calls without keeping a VM open

The pattern has three parts:

  1. A disk for the agent's state. The repository, installed dependencies, generated files and notes all live on one disk that outlives any machine.
  2. A tool wrapper that runs one command per call. The agent's bash tool (and, if you like, its file tools) calls exec with the command the model asked for and returns stdout, stderr and the exit code.
  3. Instructions that tell the model the rules. Each command starts fresh, so anything worth keeping goes on the disk.

Nothing has to run while the model is thinking. The disk holds the state, and a microVM exists only while a command runs.

Step 1: Create a disk for the agent's workspace

Create one disk per agent, per task or per user, whichever matches how you want to isolate state. The disk uses Archil-managed storage by default, so you don't need a bucket of your own.

Terminal
npm install disk
export ARCHIL_API_KEY=key-...
export ARCHIL_REGION=aws-us-east-1
npx disk create agent-workspace

Step 2: Give the agent tools that run against the disk

If you use the AI SDK, createDiskTools from @archildata/ai-sdk gives the agent tools to read, write, delete and list files, glob, grep and run bash, all against the disk and without a separate sandbox. This is the setup from the Archil quickstart:

TypeScript
import * as archil from "disk";
import { anthropic } from "@ai-sdk/anthropic";
import { ToolLoopAgent } from "ai";
import { createDiskTools } from "@archildata/ai-sdk";
 
const disk = await archil.getDisk(process.env.ARCHIL_DISK_ID!);
const workspace = archil.workspace({
  workspace: { disk, conditional: true },
});
 
const agent = new ToolLoopAgent({
  model: anthropic("claude-sonnet-5"),
  instructions: [
    "Everything happens in /mnt/archil/workspace. Use that path for bash and for the file tools.",
    "Each bash command runs in a fresh microVM, so anything you install belongs in the workspace if you want it next time.",
  ].join(" "),
  tools: createDiskTools(workspace),
});
 
await agent.generate({ prompt: "Clone https://github.com/expressjs/express and run its tests" });

With any other framework, write the tool yourself. It is one call:

TypeScript
import * as archil from "disk";
 
const disk = await archil.getDisk(process.env.ARCHIL_DISK_ID!);
 
export async function bash({ command }: { command: string }) {
  const { stdout, stderr, exitCode } = await disk.exec(command);
  return { stdout, stderr, exitCode };
}

In Python, Disk.exec is subject to the client's default 30 second request timeout, so create the client with a longer one for tools that run tests or builds:

Python
from archil import Archil
 
client = Archil(timeout=300)
disk = client.disks.get("dsk-0123456789abcdef")
 
res = disk.exec("cd express && npm test")
print(res.exit_code, res.stdout[-2000:])

Step 3: Keep state on the disk, not in the VM

Each command starts with the working directory set to where the disk is mounted, /mnt/archil. Between calls:

  • Kept: files written to the disk, including installed dependencies such as node_modules or a Python virtual environment created inside the workspace. Writes are committed before the call returns, so the next call sees them.
  • Not kept: running processes, memory, environment variables, and files written outside the disk.

Two habits make agents work well with this:

  • Install project dependencies into the workspace once, then reuse them. The first npm install pays the download; later calls only read the installed files.
  • Chain related steps in one command (cd app && npm run build && npm test) instead of relying on a previous call's cd or exported variables.

What it costs and how fast it is

Archil bills each exec call as one serverless tool call: $0.05 per 1,000 calls, with execution included and no separate CPU or memory charge. A call that runs several commands chained together is still one call. The Free plan includes 1,000 tool calls a month. See Pricing & Billing.

Every result includes timing.queueMs (scheduling, booting the microVM and mounting the disk) and timing.executeMs (the command itself), so you can measure the overhead on your own account. In our measurement from a laptop to a disk in AWS us-west-2, 50 sequential cat calls on a small file returned in 92 ms at the median and 136 ms at p90 end to end, internet round trip included.

Limits, and when to keep a VM after all

  • Each command can run for up to 5 minutes. After that the call returns 504 with Exec timed out and the command is stopped.
  • Stdout and stderr are limited to the trailing 128 KiB in the response. Write larger output to the disk and read it with the S3-compatible API.
  • Nothing keeps running between calls, so a dev server, a file watcher or a stateful interpreter needs a long-lived machine.

For those steps, start an Archil persistent sandbox with the same disk mounted, and keep using serverless calls for everything else. Persistent sandboxes run until you stop, pause or delete them and are billed per vCPU-hour and GiB-hour.

See Serverless execution for the full reference, including mounting several disks in one call and read-only mounts.

Hunter Leath

Founder & CEO