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.mdnpm install agental-sdk
- Node 20.16 or later, and nothing else. It uses only
fetchand 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.
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 keptcreateanswers when the machine is running. A sandbox you have already isagental.sandboxes.get(id), andagental.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 to90000, since a proxy in front of the API stops waiting after 100 seconds. One that runs out is killed and exits124. Longer work goes tosandbox.commands.start, which takes up to600000and answers at once. - File paths are relative to the work folder,
/opt/agental.files.readgives text, andfiles.readBytesaUint8Array.
Output as it arrives
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
| Option | What it does |
|---|---|
apiKey | The API key. Left out, as above. |
baseUrl | Where the API answers. Left out, as above. |
maxRetries | How many times a request that is safe to send again is sent again. 3 unless you say. |
retryDelayMs | The shortest wait before it is sent again, in milliseconds. 1000 unless you say. |
pollIntervalMs | How often something waited for, such as a machine starting, is looked at, in milliseconds. 2000 unless you say. |
fetch | What 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:
| Calls | Guide |
|---|---|
agental.sandboxes.create, get, list; sandbox.stop, start, update, delete | Sandbox lifecycle |
sandbox.exec, execStream, commands.run, commands.start | Running commands |
sandbox.files.read, readBytes, write | Files |
sandbox.browser | Browser |
sandbox.desktop | Desktop |
sandbox.snapshot, restore; agental.snapshots | Snapshots |
sandbox.fork | Forking |
agental.templates, sandbox.secrets | Templates and secrets |
template.setNetwork, sandbox.setNetwork | Outbound rules |
sandbox.expose, routes | Public URLs |
sandbox.email, agental.email | |
agental.createWebhook, listWebhooks; verifyWebhook, imported on its own | Webhooks |
sandbox.metrics, agental.metrics, runningOverTime | Metrics |
agental.usage, sandbox.usage | Usage |
agental.setTelemetry, testTelemetry | OpenTelemetry |
agental.billing, prices, checkout, burst, setBurstBudget | Billing |
agental.apiKeys | API keys |
agental.exportAccount | Your 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. PassidempotencyKeyyourself 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
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;
}
}| Error | What it means |
|---|---|
ApiError | The API's own refusal, with status, code and message. Decide from code: Errors lists them. |
ProxyError | A 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. |
ConnectionError | The API was not reached. |
TimeoutError | A 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.
The full machine-readable reference is OpenAPI 3.1. Every page as Markdown, for an agent: llms.txt. Questions: [email protected]