Sign inStart your trial

Custom Code

Run JavaScript or Python in a sandbox with workflow context and structured output

Custom code nodes run JavaScript (Node.js 24) or Python (3.13) in an isolated sandbox. Use them when no built-in node fits, bespoke transformations, calls to obscure APIs, or one-off data work.

#Runtimes

  • JavaScript: Node.js 24
  • Python: 3.13

Standard library only. Third-party packages are not installed in the sandbox, if you need a library, use an HTTP Request node against a service that does the work.

#Workflow context

The sandbox writes a context.json file you can read at runtime. It contains:

  • variables, current workflow variable values
  • trigger, the data that started the workflow (webhook payload, schedule metadata, etc.)
  • secrets, credentials you’ve referenced on this node, keyed by alias

JavaScript

const fs = require("fs");
const ctx = JSON.parse(fs.readFileSync("./context.json", "utf8"));

const customer = ctx.variables.customerName;
const apiKey = ctx.secrets.STRIPE_KEY;
const payload = ctx.trigger;

Python

import json

with open("context.json") as f:
    ctx = json.load(f)

customer = ctx["variables"]["customerName"]
api_key = ctx["secrets"]["STRIPE_KEY"]
payload = ctx["trigger"]

#Returning data

Print JSON to stdout. Downstream nodes get the parsed object.

console.log(JSON.stringify({ total: 42, status: "processed" }));
import json
print(json.dumps({"total": 42, "status": "processed"}))

Non-JSON stdout becomes { rawOutput: string }. Empty stdout produces null. stderr is captured for debugging but not passed downstream.

#Output declarations

You can declare typed output fields in the node config so downstream nodes get tag suggestions in the variable picker. Each declaration is a { field, type, description? } where type is one of String, Number, Boolean, Object, or Array.

This is purely for UX, your code can output whatever JSON it wants; declarations just teach the variable picker in the builder what to suggest.

#Secrets

Reference workspace secrets by adding them to the node’s credentials list. Each entry is a credential ID plus an alias (must be a valid identifier). The alias becomes the key in context.secrets. Don’t paste keys into the code body, secrets are encrypted at rest and never logged.

#Limits

LimitValue
Max code size50 KB
Default timeout120 seconds
Max timeout300 seconds (5 minutes)
Min timeout1 second

Each execution spins up a fresh sandbox. No state persists between runs.

#When something goes wrong

Common failures:

  • Out of memory: your code allocated more than the sandbox allows. Process data in chunks or filter before loading.
  • Timeout: execution went past the configured timeout. Increase it (up to 300s) or break the work into multiple steps.
  • Crash: your code threw an unhandled exception. Check the run detail view, stderr is captured there.
  • Sandbox failure: rare infrastructure issue. Retry; contact support if it persists.

#Cost

Each execution is 5 Workflow Credits regardless of runtime, duration, or success. See billing .

#Security

Code runs in an isolated Vercel Sandbox :

  • No host environment access
  • No internal network access
  • A fresh sandbox per run, destroyed afterwards
  • Secrets only available via the credentials list you configured

#Example: classify and route

const fs = require("fs");
const ctx = JSON.parse(fs.readFileSync("./context.json", "utf8"));

const order = ctx.trigger;
const total = order.items.reduce((sum, i) => sum + i.price * i.qty, 0);
const tier = total > 500 ? "priority" : "standard";

console.log(JSON.stringify({ total, tier, itemCount: order.items.length }));

A downstream Condition node can branch on tier to route priority orders through extra approval and standard orders straight to fulfillment.