Skip to main content

Custom Code Nodes

Custom Code Nodes allow you to execute JavaScript code within your conversation pathways. Use them to call external APIs, perform calculations, transform data, and implement complex business logic.

Overview

Custom Code Nodes let you:
  • Call external APIs and services
  • Perform complex calculations
  • Transform and validate data
  • Implement custom business logic
  • Integrate with internal systems

Creating a Code Node

In the Pathway Editor

1

Add Code Node

Drag a Code Node onto the pathway canvas
2

Write Code

Enter your JavaScript code in the editor
3

Configure Inputs/Outputs

Define what data flows in and out
4

Connect

Wire the node into your pathway

Via API

curl -X POST https://api.usecrew.ai/v1/pathways/{pathway_id}/nodes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "type": "code",
    "name": "Check Inventory",
    "code": "const available = await checkInventory(inputs.product_id); return { available };",
    "inputs": ["product_id"],
    "outputs": ["available"]
  }'

Code Environment

Available Objects

ObjectDescription
inputsData passed to the node
contextConversation context
callerCaller information
memoryPersistent memory
secretsEncrypted secrets

inputs

Data from previous nodes or collected during conversation:
// Access inputs
const productId = inputs.product_id;
const quantity = inputs.quantity;
const customerEmail = inputs.email;

context

Current conversation state:
// Access context
const callId = context.call_id;
const agentId = context.agent_id;
const intent = context.detected_intent;
const turnCount = context.turn_count;

caller

Information about the caller:
// Access caller info
const phone = caller.phone_number;
const name = caller.name; // If known
const isKnown = caller.is_known;

memory

Read and write persistent memory:
// Read memory
const previousOrders = memory.get('order_history');

// Write memory
memory.set('last_product_viewed', inputs.product_id);

secrets

Access encrypted secrets (API keys, etc.):
// Access secrets (set in dashboard)
const apiKey = secrets.INVENTORY_API_KEY;

Making HTTP Requests

Use the built-in fetch function:
// GET request
const response = await fetch('https://api.example.com/products', {
  headers: {
    'Authorization': `Bearer ${secrets.API_KEY}`
  }
});
const products = await response.json();

// POST request
const result = await fetch('https://api.example.com/orders', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${secrets.API_KEY}`
  },
  body: JSON.stringify({
    product_id: inputs.product_id,
    quantity: inputs.quantity
  })
});

Return Values

Return an object with output values:
// Single output
return { available: true };

// Multiple outputs
return {
  available: true,
  quantity: 50,
  price: 29.99
};

// Conditional routing
return {
  result: inventory > 0 ? 'in_stock' : 'out_of_stock',
  quantity: inventory
};

Error Handling

Handle errors gracefully:
try {
  const response = await fetch('https://api.example.com/check');
  
  if (!response.ok) {
    throw new Error(`API returned ${response.status}`);
  }
  
  const data = await response.json();
  return { success: true, data };
  
} catch (error) {
  // Log error (visible in dashboard)
  console.error('API call failed:', error.message);
  
  // Return error state for pathway to handle
  return { 
    success: false, 
    error: error.message 
  };
}

Common Patterns

API Integration

// Check appointment availability
const response = await fetch(
  `https://api.calendar.com/slots?date=${inputs.requested_date}`,
  {
    headers: { 'Authorization': `Bearer ${secrets.CALENDAR_API_KEY}` }
  }
);

const slots = await response.json();
const available = slots.filter(s => s.available);

return {
  has_availability: available.length > 0,
  slots: available.slice(0, 3) // Return top 3 options
};

Data Transformation

// Format phone number
const cleaned = inputs.phone.replace(/\D/g, '');
const formatted = `+1${cleaned}`;

return { formatted_phone: formatted };

Business Logic

// Calculate pricing
const basePrice = inputs.service_price;
const quantity = inputs.quantity;
const discount = inputs.promo_code ? 0.1 : 0;

const subtotal = basePrice * quantity;
const discountAmount = subtotal * discount;
const total = subtotal - discountAmount;

return {
  subtotal,
  discount: discountAmount,
  total,
  formatted_total: `$${total.toFixed(2)}`
};

CRM Lookup

// Look up customer in CRM
const response = await fetch(
  `https://crm.example.com/customers?phone=${caller.phone_number}`,
  {
    headers: { 'Authorization': `Bearer ${secrets.CRM_API_KEY}` }
  }
);

if (response.status === 404) {
  return { customer_found: false };
}

const customer = await response.json();

// Store in memory for later use
memory.set('customer_id', customer.id);
memory.set('customer_tier', customer.tier);

return {
  customer_found: true,
  customer_name: customer.name,
  is_vip: customer.tier === 'vip'
};

Limitations

LimitValue
Execution timeout10 seconds
Memory (RAM)128 MB
Outbound requests5 concurrent
Code size50 KB

Restricted Features

The following are not available for security:
  • eval() and Function()
  • File system access
  • Process/OS access
  • require/import (use built-in modules)

Debugging

Console Logging

console.log('Processing request for:', inputs.product_id);
console.error('API returned error:', error.message);
Logs are visible in the call details and pathway debugger.

Test Mode

Test your code in the pathway editor:
  1. Click Test on the code node
  2. Provide sample inputs
  3. View output and logs

Sandbox Execution

Code runs in a secure sandbox:
  • Isolated from other customers
  • No access to system resources
  • Network requests logged and monitored

Secrets Management

Store sensitive values securely:
1

Navigate to Secrets

Go to SettingsSecrets
2

Add Secret

Click Add Secret and enter name and value
3

Use in Code

Access via secrets.SECRET_NAME
Secrets are:
  • Encrypted at rest
  • Never exposed in logs
  • Scoped to workspace

Best Practices

Always have a fallback for when external APIs fail.
One node should do one thing well.
Set reasonable timeouts for external calls.
Log enough to debug, but don’t log sensitive data.
Test with various inputs including edge cases.

Next Steps