JavaScript in agent functions
Agent functions run modern JavaScript in a secure sandbox, not in Node.js or a browser. This page lists what the language gives you, the built-ins added for you, and what's blocked.
Language version
Everything up to ES2024 works, including:
async/await, async generators andfor await- optional chaining
?.,??and??=,||=,&&= - classes with private
#fieldsand static blocks Array.prototype.at,findLast,toSorted,Object.groupBy,Object.hasOwn,String.prototype.replaceAllMap,Set,WeakMap,WeakSet,Reflect,BigInt,JSON,Math,Date,RegExp(including thedflag),PromiseUint8Array,ArrayBuffer,DataView
Code runs as a module, in strict mode.
export default async function* ({ orders = [] }) {
const byStatus = Object.groupBy(orders, (order) => order.status ?? "unknown");
const newest = orders.toSorted((a, b) => b.createdAt.localeCompare(a.createdAt)).at(0);
return { counts: Object.fromEntries(Object.entries(byStatus).map(([k, v]) => [k, v.length])), newest };
}
Built-ins you get without an import
| Name | Use it for |
|---|---|
console | Logs you see in the run panel and in Analysis. See Test and debug. |
Buffer | Bytes and encodings: base64, hex, latin1 |
URL, URLSearchParams | Building and reading links and query strings |
Intl | Formatting numbers, money and dates |
Buffer
Buffer covers the common parts of Node's: Buffer.from, alloc, concat, byteLength, compare, isBuffer, and on a buffer toString, slice, subarray, equals, write, copy, fill and toJSON. The encodings are utf8, hex, base64, ascii and latin1 (binary). base64url, utf16le and Node's readUInt8-style methods aren't available. A buffer can be up to 1 MB.
// base64 encode and decode, instead of btoa / atob
const encoded = Buffer.from("user:secret").toString("base64"); // "dXNlcjpzZWNyZXQ="
const decoded = Buffer.from(encoded, "base64").toString("utf8"); // "user:secret"
// base64url, by hand
const base64url = encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
// bytes to hex
const hex = Buffer.from("hello").toString("hex"); // "68656c6c6f"
URL and URLSearchParams
const link = new URL("https://shop.example.com/track");
link.searchParams.set("order", orderId);
link.searchParams.set("lang", "en");
link.toString(); // "https://shop.example.com/track?order=A-1001&lang=en"
const params = new URLSearchParams("utm_source=whatsapp&utm_campaign=diwali");
params.get("utm_campaign"); // "diwali"
Intl
Intl.NumberFormat and Intl.DateTimeFormat format with a locale. They support a smaller set of options than a browser:
| Formatter | Options |
|---|---|
Intl.NumberFormat(locale, options) | style: "decimal", "currency" or "percent"; currency: a 3-letter code such as "INR"; minimumFractionDigits, maximumFractionDigits |
Intl.DateTimeFormat(locale, options) | dateStyle: "short", "medium" or "long" |
Any other option, such as timeZone or timeStyle, stops the function with an error that lists the allowed ones. Dates are formatted as a date only, in UTC. The locale defaults to "en".
const price = new Intl.NumberFormat("en-IN", { style: "currency", currency: "INR" }).format(149999.5);
// "₹1,49,999.50"
const share = new Intl.NumberFormat("en", { style: "percent", maximumFractionDigits: 1 }).format(0.256);
// "25.6%"
const day = new Intl.DateTimeFormat("en-GB", { dateStyle: "long" }).format(new Date("2026-10-29T10:00:00Z"));
// "29 October 2026"
Dates and time zones
The function's clock is in UTC. new Date() is the current time, and methods such as getHours() return UTC values. To show a local time, add the offset yourself:
const now = new Date();
const ist = new Date(now.getTime() + 5.5 * 60 * 60 * 1000); // India, UTC+5:30
const time = `${String(ist.getUTCHours()).padStart(2, "0")}:${String(ist.getUTCMinutes()).padStart(2, "0")}`;
const isBusinessHours = ist.getUTCHours() >= 9 && ist.getUTCHours() < 18;
Math.random() works. For IDs and anything secret, use crypto.randomUUID() and crypto.randomBytes().
What's blocked
These names don't exist, or throw when used. Using one is usually caught when you save.
| Blocked | Use instead |
|---|---|
fetch, XMLHttpRequest, WebSocket, Worker | apis.execute |
setTimeout, setInterval, setImmediate, clearTimeout, queueMicrotask | await your calls. A function can't wait or schedule work for later. |
require, process, module, exports, __dirname, fs, http, child_process and other Node.js modules; npm packages | The modules listed in Structure of an agent function |
eval, new Function(…) | Write the logic in the function body |
atob, btoa | Buffer.from(text).toString("base64") and Buffer.from(b64, "base64").toString() |
TextEncoder, TextDecoder | Buffer.from(text) and buffer.toString("utf8") |
Proxy, WeakRef, FinalizationRegistry, performance, WebAssembly, SharedArrayBuffer, Atomics | Not needed in functions |
Int8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, BigInt64Array, BigUint64Array | Uint8Array, DataView or Buffer |
Symbol.for, Symbol.keyFor, RegExp.$1 … RegExp.input | Symbol(), and the match array a regex returns |
Global names from classic functions, such as data, ymLib, app and resolve, don't exist either. What a classic function read from data.profile, data.user, data.sender and data.source is on the context argument.
Built-ins can't be changed
Built-in objects and their prototypes are frozen, so code can call them but not change them. Array.prototype.last = …, Object.assign = … or adding a name to globalThis throws. Your own objects and classes work as usual.
// Fails: changes a built-in
Array.prototype.last = function () { return this[this.length - 1]; };
// Works: a helper of your own
const last = (list) => list[list.length - 1];
Related
- Limits: time, memory and calls per run
- Crypto helpers: hashing, signing, encryption and random values