Sandboxed JavaScript execution with isolated-vm for custom transformations, data processing, and business logic within workflows.
You need custom business logic that doesn't fit into a simple database query. Maybe you're calculating customer lifetime value with a complex formula. Or scoring leads based on 15 different signals. Or transforming API responses into exactly the format you need.
The built-in tools get you 90% of the way there. But that last 10%? That's YOUR specific logic.
"I need to calculate customer health scores. It's based on their usage frequency, support ticket count, payment history, and feature adoption. Each factor has different weights depending on their plan tier."
"I'll write a Python function that takes all those inputs and calculates the score. Should I use a weighted average or something more sophisticated?"
"Weighted average is fine. Enterprise customers should have 2x weight on feature adoption. And if they've had more than 3 support tickets in the last month, deduct 20 points."
*Writes Python function with your exact logic, adds it to workflow*
"Done. Here's the function. I tested it on your top 10 customers—scores range from 42 to 94. Want me to run it on everyone and add the scores to the database?"
"Yes. And recalculate it daily so the scores stay fresh."
"Perfect. Created a daily workflow that recalculates health scores for all customers and updates the database. Your dashboard will show the latest scores automatically."
This isn't magic. This is collaboration.
When you need custom logic that's specific to your business, just describe it. Your Awareness writes the code and makes it work.
isolated-vm with memory and CPU limits
Direct execution without sandboxing
Basic timeout wrapper when isolated-vm unavailable
Currently JavaScript only
Add a Code node to your workflow to transform data, apply business logic, or perform calculations:
{
"id": "transform_data",
"type": "code",
"name": "Calculate Totals",
"language": "javascript",
"sandbox": true, // Always use sandboxed execution
"code": `
// Input: { orders: [...] }
// Context: { variables: {...}, userId: "..." }
const total = input.orders.reduce((sum, order) => {
return sum + (order.quantity * order.price);
}, 0);
const itemCount = input.orders.length;
const avgPrice = total / itemCount;
console.log(`Processed ${itemCount} orders, total: $${total}`);
return {
total,
itemCount,
avgPrice,
timestamp: new Date().toISOString()
};
`
}
// Node output available to subsequent nodes:
// {{transform_data.output.total}}
// {{transform_data.output.avgPrice}}input - Node input datactx - Workflow context (variables, userId)console - Logging (log, info, warn, error)JSON - JSON.parse, JSON.stringifyMath - Math operationsDate - Date/time handlingArray - Array methodsObject - Object methodsString - String methodsRegExp - Regular expressionsrequire() - No module importsimport - No ES6 importsfs - No file system accessfetch - No network requestsXMLHttpRequest - No HTTPWebSocket - No websocketsprocess - No process accesssetTimeout - No timerseval - No dynamic code executionFunction() - No function constructor// Input: { users: [{firstName: "John", lastName: "Doe"}, ...] }
return input.users.map(user => ({
fullName: `${user.firstName} ${user.lastName}`,
email: `${user.firstName.toLowerCase()}.${user.lastName.toLowerCase()}@example.com`
}));
// Output: [{ fullName: "John Doe", email: "john.doe@example.com" }, ...]// Input: { transactions: [{amount: 100, category: "food"}, ...] }
const filtered = input.transactions.filter(t => t.amount > 50);
const byCategory = filtered.reduce((acc, t) => {
acc[t.category] = (acc[t.category] || 0) + t.amount;
return acc;
}, {});
return {
totalTransactions: filtered.length,
totalAmount: filtered.reduce((sum, t) => sum + t.amount, 0),
byCategory
};
// Output: { totalTransactions: 42, totalAmount: 5230, byCategory: {...} }// Input: { score: 85, attendance: 0.92 }
const grade = input.score >= 90 ? 'A' :
input.score >= 80 ? 'B' :
input.score >= 70 ? 'C' :
input.score >= 60 ? 'D' : 'F';
const status = input.attendance >= 0.9 && input.score >= 70
? 'passing'
: 'needs_improvement';
console.log(`Student grade: ${grade}, status: ${status}`);
return { grade, status, passesThreshold: status === 'passing' };// Input: { events: [{date: "2024-01-15", ...}, ...] }
const now = new Date();
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
const recentEvents = input.events.filter(e => {
const eventDate = new Date(e.date);
return eventDate >= weekAgo && eventDate <= now;
});
return {
recentCount: recentEvents.length,
oldestRecent: recentEvents[0]?.date,
newestRecent: recentEvents[recentEvents.length - 1]?.date
};// Context: { variables: { apiKey: "...", threshold: 100 }, userId: "user_123" }
const userApiKey = ctx.variables.apiKey;
const threshold = ctx.variables.threshold;
const currentUser = ctx.userId;
console.log(`Processing for user: ${currentUser}`);
return input.items.filter(item => {
return item.value > threshold && item.userId === currentUser;
}).map(item => ({
...item,
processedBy: currentUser,
processedAt: new Date().toISOString()
}));Code execution errors are captured and returned with context:
// Error response structure
{
"success": false,
"error": "ReferenceError: undefinedVariable is not defined",
"logs": [
"Starting processing...",
"[ERROR] Unexpected error occurred"
]
}
// Timeout error
{
"success": false,
"error": "Code execution timed out (10s limit)",
"logs": []
}
// Memory limit error (isolated-vm)
{
"success": false,
"error": "Isolate was disposed during execution",
"logs": []
}Configure node-level error handling with onError: "fail" (stop workflow), "continue" (skip node), or "retry" (retry with backoff).
Use console.log to debug code execution. Logs are captured and returned with results:
console.log('Starting transformation');
console.log('Input data:', JSON.stringify(input, null, 2));
console.log('User ID:', ctx.userId);
const result = input.items.map((item, idx) => {
console.log(`Processing item ${idx}: ${item.name}`);
return { ...item, processed: true };
});
console.log('Transformation complete, count:', result.length);
return result;
// Execution result includes logs:
{
"success": true,
"result": [...],
"logs": [
"Starting transformation",
"Input data: {...}",
"User ID: user_123",
"Processing item 0: Widget",
"Processing item 1: Gadget",
"Transformation complete, count: 2"
]
}