The entry function
A script exports one async function. The runtime calls it with a single object.
Notes on the shape:
- CommonJS is the norm:
module.exports = async (...) => { ... }.export defaultworks too, and an ESM file with top-levelawaitis loaded as a module. - A node with an input schema must destructure
args. Theasync (page) => { ... }form does not receiveargsand fails validation when the node declares inputs. - The return value decides output and routing. The golden path is to return
asteroid.handoff(...), which chooses the next node and carries its data. An object instead becomes output variables, a string becomesscript_output, and a throw is a failure. See Route to the next node yourself.
Timeouts
Inside that budget, Playwright actions carry their own defaults, kept short so a wrong selector fails fast instead of stalling.
Raise a limit for a genuinely slow step:
The sandbox
A script runs in the execution’s sandbox, next to the browser.- Node.js 22. Node built-in modules (
node:fs,node:path,node:crypto, and the rest) are available. - Playwright drives a headless Chromium over the live session. You get it through
page,browser, andcontext, so you do not launch a browser yourself. python3is present, withpython3-yaml, reachable from the workflow’s Bash tool.- No PDF or OCR libraries. To read a PDF or a print-only page, parse it in the browser page with
pdf.js, not with a Node module. See the PDF pattern.
The filesystem
The working directory is/home/agent. A script reads and writes files with node:fs, using absolute paths.
A script’s own file lives under
/home/agent/shared/<node-slug>/, where the runtime derives <node-slug> from the node’s display name. Because it re-derives the slug, a rename never breaks how the runtime finds the entry script. It does not, however, rewrite absolute paths you wrote by hand. A hardcoded /home/agent/shared/<node-slug>/... path (a required helper, a reference file) breaks when you rename the node, so update those yourself.
Workflow filesystem
The full directory layout, the quotas, and how files get in and out
Requiring modules
require('asteroid')is provided by the runtime. Its whole surface ishandoff(...)andgenerateTotp(...). See Route to the next node yourself and Two-factor codes.- Node built-ins resolve normally.
- Helper modules must be required by their absolute path under
shared/, for examplerequire('/home/agent/shared/file_claim/lib/dates.js'). A relativerequire('./dates.js')does not resolve, because the runtime runs your script from a private copy that holds no sibling files. - Use absolute
/home/agent/...paths. They work exactly as written from the entry script. Pass a required helper the paths it needs as arguments, rather than letting it compute its own, so it never depends on where the runtime placed your script.
Secret tokens
A script fills a secret with a##ITEM_KEY.FIELD## token. The runtime replaces it from the
secret attached to the profile, just before the script runs, so the value never reaches the model.
The usage is in Secrets in a script, and the full
model is in Secrets & 2FA.
Two-factor codes
asteroid.generateTotp(secret, options?) returns the current authenticator code as a string. Pass
the token of a TOTP seed field. The runtime fills the token before the script runs, so the seed
stays inside the script run. Only the generated code reaches the page.
The secret may be a bare base32 seed or an
otpauth://totp/ URI. A URI’s own digits, period
and algorithm apply unless an option overrides them.
- A token the run does not fill throws, and the error names the token.
- An unusable seed throws a fixed message that never quotes the seed.
- Generate the code immediately before you submit it. If the site rejects it, generate a fresh code and retry once.
Related
Script a step
Attach a script, route from it, and pin its inputs
Workflow filesystem
Directories, quotas, and file transfer
Secrets & 2FA
How a
##ITEM_KEY.FIELD## token gets its valueNodes
Where a script file lives on a node

