Skip to main content
This page is the exact contract a node script runs under. For how to attach a script and route from one, start with Script a step.

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 default works too, and an ESM file with top-level await is loaded as a module.
  • A node with an input schema must destructure args. The async (page) => { ... } form does not receive args and 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 becomes script_output, and a throw is a failure. See Route to the next node yourself.

Timeouts

The whole script has a hard limit of 5 minutes. When it is reached the run is killed and treated as a failure, so the node’s failure action decides what happens next. Design a script to finish well inside that.
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, and context, so you do not launch a browser yourself.
  • python3 is present, with python3-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.
Do not use shared/ to carry state from one run to the next. A running script’s writes to shared/ are not saved back to the workflow. Durable shared/ content comes from how the workflow is built, not from a running script. Keep per-run state in workspace/, and treat shared/ as read-only reference.

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 is handoff(...). See Route to the next node yourself.
  • Node built-ins resolve normally.
  • Helper modules must be required by their absolute path under shared/, for example require('/home/agent/shared/file_claim/lib/dates.js'). A relative require('./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.

Credential tokens

A script fills a secret with a ##NAME## token, replaced from the profile just before the script runs, so the value never reaches the model. The token name is the credential key in upper case. The usage is in Credentials in a script, and the full model is in Credentials.

Script a step

Attach a script, route from it, and pin its inputs

Workflow filesystem

Directories, quotas, and file transfer

Credentials

How a ##TOKEN## gets its value

Nodes

Where a script file lives on a node