Daytona

Run an agent's commands and files in a Daytona sandbox, with snapshots for forking.

Daytona runs each sandbox as a container. It is the provider to pick if you want to fork threads at a sandbox state: threads takes Daytona snapshots.

import { daytona } from "@threads/daytona";

const daytonaSandbox = daytona({
  apiKey: process.env["DAYTONA_API_KEY"] ?? "",
  ttlMinutes: 60,
});

In TypeScript, apiKey is required. Python falls back to the DAYTONA_API_KEY environment variable.

Options

TypeScriptPythonDefaultWhat it does
apiKeyapi_keyrequired (TS), DAYTONA_API_KEY (Python)Authenticates threads' calls to Daytona. Never enters the sandbox.
apiUrlapi_urlhttps://app.daytona.io/apiDaytona API endpoint.
imagesnapshotDaytona's defaultThe Daytona snapshot new sandboxes start from.
ttlMinuteslifetime_ms60 minutes (TS), none (Python)How long a sandbox lives before Daytona deletes it.
autoStopMinutesauto_stop_minutes60Idle minutes before Daytona stops a leaked sandbox. A safety net, not the normal cleanup.
network: "open"allow_internet=TrueblockedOpens the network. Also set egress: "unenforced" on the agent.
targetDaytona'sPython only: the Daytona region to place sandboxes in.
const open = agent({
  model,
  sandbox: daytona({ apiKey: process.env["DAYTONA_API_KEY"] ?? "", network: "open" }),
  egress: "unenforced",
});

Good to know

  • Snapshots stop the sandbox. Daytona can only snapshot a stopped container. threads stops it, captures it and starts it again, so background processes (a dev server, for example) end at each snapshot. Snapshots are taken at the end of turns that changed something.
  • Crashes park. If the host crashes mid-command, threads can't prove the command's child processes are gone, so the run parks for you instead of re-running it.

See Sandboxes for the tools an agent gets and how internet access works.

Edit on GitHub

On this page