Script
The Script node runs a snippet of custom code as a workflow step. It supports two languages with two very different execution models: Python runs on an external Python Runner service over HTTP, while JavaScript runs in-process in a sandboxed GraalVM engine. Both receive input variables from the workflow and return a structured result, so you can drop custom logic into a job without building a separate service.
Common uses include:
- Transforming or reshaping data that the built-in data nodes cannot express.
- Running a small calculation or business rule inline.
- Reading and writing spreadsheet, CSV, or JSON files as job artifacts (JavaScript).
- Calling Python libraries for tasks the platform does not expose natively.
Before You Start​
| What you may need | Where to set it up | Why it matters |
|---|---|---|
| Python Runner service | Platform configuration | Python scripts require a reachable Python Runner and a token. JavaScript needs neither. |
| Input values for the script | Global Variables | Pass reusable values into inputVariables instead of hard-coding them. |
| Files to read or produce | Files | JavaScript file reads and writes flow through artifact storage (S3 / MinIO). |
Actions​
| Action | Description |
|---|---|
script:execute | Execute a Python or JavaScript snippet and return its result |
script:execute​
Runs the configured script in the selected language. Expressions in the source ({{ ... }}) are resolved before the code runs, so workflow values can be templated directly into the script. The script body lives under the scriptConfig root; timeouts live under executionSettings.
Parameters
| Parameter | Location | Type | Required | Default | Description |
|---|---|---|---|---|---|
language | scriptConfig | string | No | javascript | python or javascript |
script | scriptConfig | string | Yes | -- | Source code. {{expr}} placeholders are resolved before execution |
inputVariables (alias input) | scriptConfig | object | No | {} | Variables injected into the script scope |
timeoutMinutes | executionSettings | number | No | 10s (300s when FileIO is used) | JavaScript path only. Maximum run time |
timeoutSeconds | executionSettings | number | No | 10 | Python path only. Clamped to 1-30 seconds |
Python mode​
When language is python, the node sends the script and its input variables to the external Python Runner service over HTTP and returns the runner's response. The runner is a separate service (default :8080, path /api/v1/python/execute).
The Python path requires the runner to be configured:
python-runner.base-url— required. Base URL of the runner service.python-runner.execute-path— required. Execution endpoint path.python-runner.token— optional (empty by default). When present, the node sends it asAuthorization: Bearer <token>.
If python-runner.token is absent, JavaScript steps still run normally, but a Python step throws an IllegalStateException at runtime and the step ends in FAILED.
JavaScript mode​
When language is javascript (the default), the node runs the code in-process on a sandboxed GraalVM engine. No external service or token is needed.
JavaScript scripts can read and write files through a global FileIO helper, available when the artifact client is configured (backed by S3 / MinIO). File writes are uploaded to artifact storage and returned as job-execution artifacts.
| FileIO method | Purpose |
|---|---|
readFile / writeFile | Read or write raw file content |
readExcel / readExcelSheet / getExcelSheetNames / createWorkbook | Read Excel workbooks and sheets, or build a new workbook |
readCsv / readCsvWithDelimiter / writeCsv | Read CSV (optionally with a custom delimiter) and write CSV |
readJson / writeJson | Read and write JSON files |
Each write helper returns metadata for the produced artifact: { storagePath, fileName, mimeType, size }.
JavaScript runs in a GraalVM sandbox with allowAllAccess disabled. Scripts have no arbitrary host access — no filesystem, network, or process APIs beyond what the platform exposes. The only file capability available is the FileIO API described above.
Example: Transform input rows in JavaScript
| Field | Value |
|---|---|
| language | javascript |
| inputVariables | { "rows": [{"amount": 10}, {"amount": 20}] } |
| script | const total = rows.reduce((s, r) => s + r.amount, 0); ({ total }); |
What happens:
- The node resolves any
{{ ... }}expressions in the script. - It injects
rowsinto the script scope frominputVariables. - GraalVM runs the code in the sandbox and captures its return value.
- The result (
{ total: 30 }) is returned in theresultfield for later steps.
Output​
JavaScript returns a structured result object:
| Field | Type | Description |
|---|---|---|
result | any | The script's return value |
stdout | string | Captured standard output |
stderr | string | Captured standard error |
success | boolean | true when the script completed without error |
executionTimeMs | integer | Wall-clock run time in milliseconds |
exitCode | integer | Exit code of the run |
error | string | Error message when the script failed |
artifacts | array | Files written by FileIO, each { storagePath, fileName, mimeType, size } |
Python returns the runner's raw JSON response, which uses the same field shape.
Example output (JavaScript):
{
"result": {"total": 30},
"stdout": "",
"stderr": "",
"success": true,
"executionTimeMs": 42,
"exitCode": 0,
"error": null,
"artifacts": []
}
Common Error Scenarios​
| Error | Likely Cause | What to Check |
|---|---|---|
IllegalStateException on a Python step | python-runner.token is not configured | Configure the runner token, or switch the step to JavaScript |
| Python step fails to connect | python-runner.base-url / execute-path wrong or runner down | Confirm the Python Runner service is reachable at the configured URL |
| Script timed out | Run exceeded timeoutMinutes (JS) or timeoutSeconds (Python) | Increase the timeout, or reduce the work the script does |
ReferenceError in JavaScript | Script used a host API blocked by the sandbox | Use only standard JS and the FileIO API — no filesystem, network, or process access |
| FileIO write fails | Artifact client not configured | Confirm artifact storage (S3 / MinIO) is available for the environment |
Non-zero exitCode / success: false | The script threw an error | Read error and stderr for the failure detail |
Best Practices​
- Prefer JavaScript for file work. The
FileIOhelpers keep reads and writes inside artifact storage without an external service. - Return a value, do not print it. Downstream steps read
result; usestdoutonly for logging. - Set explicit timeouts. Give long-running scripts a realistic
timeoutMinutes(JS) ortimeoutSeconds(Python, max 30) so they are not cut off early. - Keep secrets out of source. Pass credentials through
inputVariablesfrom Global Variables rather than embedding them in the script. - Confirm the Python Runner before shipping. A Python step fails at runtime if the runner or its token is missing, so verify the configuration in each environment.
- Keep scripts small. Move heavy or reusable logic into a dedicated connector or service; use Script for glue and light transforms.