Function Node

Write custom JavaScript or Python to process data, calculate values, and return results.

The Function node runs your own code in a secure sandbox. Use it when transforms aren't enough and you need full programmatic control.

Choosing a language

When you add a Function node, pick JavaScript or Python before writing code. This choice is locked for that node — you cannot switch languages later.

Existing workflows created before multi-language support default to JavaScript when they already contain function code.

LanguageRuntimeBest for
JavaScriptIn-process VM sandboxFamiliar syntax, async-friendly patterns
PythonIsolated python3 subprocessData processing, list/dict logic, teams that prefer Python

Writing function code

Open the Function node and write code in the built-in editor. Click Variables to insert data references at your cursor.

JavaScript template

// Access workflow data
const inputs = {{inputs}};
const lastOutput = {{lastOutput}};
const variables = {{variables}};
const context = {{context}};

// Your custom logic here
const result = {
  processed: true,
  data: lastOutput,
};

return result;

Python template

# inputs, lastOutput, variables, and context are available in scope

return {
    "processed": True,
    "data": lastOutput,
}

Rules (both languages)

  1. Must return a value — the returned object becomes the node's output for downstream steps.
  2. Read-only scopeinputs, lastOutput, variables, and context are provided for reading; mutating them won't affect other nodes.
  3. Size limit — code must be under 10 KB.
  4. No network or filesystem — HTTP calls, file access, subprocesses, and environment access are blocked for security.
  5. 10 second timeout — long-running code is stopped automatically.

JavaScript-specific limits

  • require, import, fetch, process, and filesystem APIs are blocked.
  • Template placeholders like {{inputs}} are replaced with actual values before your code runs.

Python-specific limits

  • Runs in an isolated subprocess with restricted builtins.
  • Allowed standard-library imports: json, math, datetime, re, decimal, fractions.
  • Blocked: os, sys, subprocess, socket, open(), eval(), exec(), and similar escape hatches.
  • Use Python dict/list syntax; returned values must be JSON-serializable.

Examples

Calculate a total (JavaScript)

const items = lastOutput.items || [];
const total = items.reduce((sum, item) => sum + (item.price || 0), 0);

return {
  items,
  total,
  currency: variables.currency || 'USD',
};

Calculate a total (Python)

items = (lastOutput or {}).get("items") or []
total = sum((item.get("price") or 0) for item in items)

return {
    "items": items,
    "total": total,
    "currency": (variables or {}).get("currency") or "USD",
}

Format data for an API

return {
  recipient: inputs.email,
  subject: `Order #${lastOutput.orderId} confirmed`,
  body: `Hi ${lastOutput.customerName},\n\nYour order of $${lastOutput.amount} has been confirmed.`,
};

Parse and validate (JavaScript)

const raw = lastOutput.content || '';
let parsed;

try {
  parsed = JSON.parse(raw);
} catch {
  return { error: 'Invalid JSON from AI node', raw };
}

if (!parsed.email) {
  return { error: 'Missing email field', parsed };
}

return { valid: true, ...parsed };

Filter and transform a list (Python)

records = (lastOutput or {}).get("data") or []

return {
    "active": [r for r in records if r.get("status") == "active"],
    "inactive": [r for r in records if r.get("status") != "active"],
    "count": len(records),
}

Available scope

VariableContents
inputsTrigger data (webhook body, manual inputs)
lastOutputPrevious node's output
variablesWorkflow variables
contextOutputs from completed nodes: context['node-id'].output

Inside a Loop node, you also have access to loopItem and loopIndex.

Editor features

  • Language picker — choose JavaScript or Python once when creating the node
  • Syntax highlighting and line numbers for the selected language
  • Expand to full-screen editor for longer scripts
  • Variable inserter — click Variables to browse and insert {{paths}} (JavaScript templates)

Error handling

If your code throws an error or has a syntax issue, the node fails and the error appears in the Execution Data tab. Common mistakes:

ErrorFix
SyntaxErrorCheck for missing brackets, indentation (Python), or typos
undefined / None accessGuard with optional chaining (?.) or defaults (or {})
Nothing returnedEnsure your code has a return statement
Code too largeKeep functions focused; split into multiple Function nodes
Blocked import / APIUse only allowed sandbox APIs for your language

Function vs Transform Code

Both support JavaScript, but they serve different purposes:

Function NodeTransform → Code
PurposeGeneral-purpose logicData transformation
LanguagesJavaScript or PythonJavaScript only
OutputAny shape you returnTransformed input data
EditorFull code editor with expandInline expression in transform panel
Best forComplex logic, validation, multi-step computationQuick expressions on data shape
ReferenceThis pageTransform Catalog

Tips

  • Pick your language first — you can't change it after you start coding.
  • Start with the default template and modify incrementally.
  • Test with a Manual trigger and check Execution Data after each change.
  • Keep functions small and focused — chain multiple Function nodes for complex pipelines.
  • Use Transform → Edit Fields for simple renaming; reserve Function for real logic.