Docs

TypeScript SDK

The whole API from TypeScript and JavaScript. It waits for a machine to be running, sends a request again where that is safe, and throws every refusal as an error with the API's code.

For your agent

agental.io/docs/typescript.md
shell
npm install agental-sdk
  • Node 20.16 or later, and nothing else. It uses only fetch and Web Crypto, so Bun, Deno and Cloudflare Workers should run it too, but it is tested on Node alone.
  • An ES module, with its types.
  • The agental command is the package agental, beside it.

Make a client

Make an API key in the console, under API keys, and put it in AGENTAL_API_KEY. A client made with nothing reads it from there.

typescript
import { Agental } from "agental-sdk";

const agental = new Agental(); // reads AGENTAL_API_KEY

const sandbox = await agental.sandboxes.create({ size: "small" });
const { exitCode, stdout } = await sandbox.exec("uname -a");
console.log(exitCode, stdout);

await sandbox.files.write("app/main.py", "print('hello')\n");
console.log((await sandbox.exec(["python3", "/opt/agental/app/main.py"])).stdout);

await sandbox.stop(); // the disk is kept
  • create answers when the machine is running. A sandbox you have already is agental.sandboxes.get(id), and agental.sandboxes.list() gives all of them.
  • A command given as a string is a line of shell, run by sh -c. Given as an array, its arguments are passed exactly, with no shell.
  • A command gets 60 seconds unless you pass timeoutMs, up to 90000, since a proxy in front of the API stops waiting after 100 seconds. One that runs out is killed and exits 124. Longer work goes to sandbox.commands.start, which takes up to 600000 and answers at once.
  • File paths are relative to the work folder, /opt/agental. files.read gives text, and files.readBytes a Uint8Array.

Output as it arrives

typescript
for await (const event of sandbox.execStream("npm test")) {
  if (event.type === "exit") console.log("exited", event.exitCode);
  else process.stdout.write(event.data);
}

For a command that takes more than a minute, sandbox.commands.run runs it without holding a request open, and commands.start starts it to be looked at later. See Running commands.

Where the key comes from

  • apiKey, when you pass one.
  • Otherwise AGENTAL_API_KEY.
  • Otherwise the key the agental command keeps on this computer, in ~/.config/agental/credentials.json, for the API it signed in to and no other.

The API is baseUrl, otherwise AGENTAL_API_URL, otherwise the API the command signed in to, otherwise https://agental.io.

Options

OptionWhat it does
apiKeyThe API key. Left out, as above.
baseUrlWhere the API answers. Left out, as above.
maxRetriesHow many times a request that is safe to send again is sent again. 3 unless you say.
retryDelayMsThe shortest wait before it is sent again, in milliseconds. 1000 unless you say.
pollIntervalMsHow often something waited for, such as a machine starting, is looked at, in milliseconds. 2000 unless you say.
fetchWhat requests are sent with. Left out, the runtime's own fetch.

What is in it

Each guide shows its calls in TypeScript. Where to find them:

CallsGuide
agental.sandboxes.create, get, list; sandbox.stop, start, update, deleteSandbox lifecycle
sandbox.exec, execStream, commands.run, commands.startRunning commands
sandbox.files.read, readBytes, writeFiles
sandbox.browserBrowser
sandbox.desktopDesktop
sandbox.snapshot, restore; agental.snapshotsSnapshots
sandbox.forkForking
agental.templates, sandbox.secretsTemplates and secrets
template.setNetwork, sandbox.setNetworkOutbound rules
sandbox.expose, routesPublic URLs
sandbox.email, agental.emailEmail
agental.createWebhook, listWebhooks; verifyWebhook, imported on its ownWebhooks
sandbox.metrics, agental.metrics, runningOverTimeMetrics
agental.usage, sandbox.usageUsage
agental.setTelemetry, testTelemetryOpenTelemetry
agental.billing, prices, checkout, burst, setBurstBudgetBilling
agental.apiKeysAPI keys
agental.exportAccountYour account and data

What it does for you

  • A create or a fork is sent with an Idempotency-Key. If its answer is lost, or the machine is not confirmed yet, the same request is sent again with the same key, which gives the same sandbox back and never a second one. Pass idempotencyKey yourself to be able to ask again after your process has died.
  • Reads, file writes, starts and stops are sent again when a proxy answers in the API's place, when the connection drops, and when the sandbox was moved to another server during the request.
  • A command is never sent twice. One that was cut off may have done part of its work, so whether to run it again is yours to decide.
  • A delete carries the confirm header the API asks for.

Errors

typescript
import { ApiError } from "agental-sdk";

try {
  await sandbox.exec("make");
} catch (error) {
  if (error instanceof ApiError && error.code === "sandbox_not_running") {
    await sandbox.start();
  } else {
    throw error;
  }
}
ErrorWhat it means
ApiErrorThe API's own refusal, with status, code and message. Decide from code: Errors lists them.
ProxyErrorA 502, a 504 or any answer with no code in it: something in front of the API answered, and the request may still be running.
ConnectionErrorThe API was not reached.
TimeoutErrorA wait ran out, such as for a machine to start.

All of them are AgentalError. A command that exits non-zero is not an error: read exitCode.

NextThe Python SDK is the same API in Python. For another language, the whole API is OpenAPI 3.1.

The full machine-readable reference is OpenAPI 3.1. Every page as Markdown, for an agent: llms.txt. Questions: [email protected]