> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gorules.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Function nodes

> Write typed TypeScript for complex logic, API calls, and advanced data processing.

Function nodes let you write TypeScript for logic that expressions and decision tables can't handle. Use them for complex algorithms, external API calls, or custom data transformations.

## Creating a function node

1. Add a **Function** node to your decision graph
2. Connect it between other nodes
3. Open the node to edit its code

## Basic structure

Every function node exports a typed handler that receives input and returns output:

```typescript theme={null}
export const handler = async (input: FunctionInput) => {
  return input;
};
```

`FunctionInput` is generated for you from the graph's resolved schema at this point in the flow - the same types you see in the [Interface tab](/brms/build/graphs#interface). You don't declare it; it's already in scope.

## Type checking

The editor type-checks your code in strict mode as you type. Reference a field that doesn't exist on the input, or use a number where a string is expected, and you get a diagnostic in place - before anything runs. When you change the graph's input schema, `FunctionInput` updates and any code that no longer matches is flagged.

Type annotations are optional: a plain JavaScript handler is valid and runs the same. The types are there to catch mistakes, not to gate you.

## Accessing previous nodes

Use `input.$nodes` to access outputs from any upstream node in your graph:

```typescript theme={null}
export const handler = async (input: FunctionInput) => {
  // Access output from specific nodes by name
  const creditScore = input.$nodes.CreditCheck.score;
  const riskLevel = input.$nodes.RiskAssessment.level;

  return {
    approved: creditScore > 700 && riskLevel === "low"
  };
};
```

Use `input.$nodes.NodeName.field` to reference any field from an upstream node's output. Node names are case-sensitive and must match exactly.

## Example: Calculate loyalty points

```typescript theme={null}
export const handler = async (input: FunctionInput) => {
  const { orderTotal, customerTier } = input;

  // Base points: $1 = 1 point
  let points = Math.floor(orderTotal);

  // Tier multipliers
  const multipliers: Record<string, number> = {
    platinum: 3,
    gold: 2,
    silver: 1.5,
    bronze: 1
  };

  const multiplier = multipliers[customerTier] ?? 1;
  points = Math.floor(points * multiplier);

  return {
    loyaltyPoints: points,
    tier: customerTier,
    multiplier
  };
};
```

## Supported libraries

Function nodes include several built-in libraries:

| Library | Purpose | Example |
| - | - | - |
| `dayjs` | Date and time manipulation | `dayjs().add(7, 'days')` |
| `big.js` | Arbitrary-precision decimals | `new Big('0.1').plus('0.2')` |
| `zod` | Input validation and parsing | `z.string().email().parse(input)` |
| `http` | HTTP requests (axios-like API) | `await http.get(url)` |
| `zen` | Evaluate other decisions | `await zen.evaluate(decisionId, input)` |

### Using dayjs

```typescript theme={null}
import dayjs from 'dayjs';

export const handler = async (input: FunctionInput) => {
  const today = dayjs();
  const birthDate = dayjs(input.birthDate);
  const age = today.diff(birthDate, 'year');

  return {
    age,
    isAdult: age >= 18,
    nextBirthday: birthDate.add(age + 1, 'year').format('YYYY-MM-DD')
  };
};
```

### Using big.js for precision

```typescript theme={null}
import Big from 'big.js';

export const handler = async (input: FunctionInput) => {
  const price = new Big(input.price);
  const taxRate = new Big(input.taxRate);

  const tax = price.times(taxRate);
  const total = price.plus(tax);

  return {
    subtotal: price.toNumber(),
    tax: tax.toNumber(),
    total: total.toNumber()
  };
};
```

### Making HTTP requests

```typescript theme={null}
import http from 'http';

export const handler = async (input: FunctionInput) => {
  const response = await http.get('https://api.example.com/rates', {
    params: { currency: input.currency }
  });

  return {
    exchangeRate: response.data.rate,
    updatedAt: response.data.timestamp
  };
};
```

## Async/await

Function nodes support async operations. Use `async/await` for any asynchronous logic:

```typescript theme={null}
export const handler = async (input: FunctionInput) => {
  // Parallel API calls
  const [userData, orderHistory] = await Promise.all([
    fetchUser(input.userId),
    fetchOrders(input.userId)
  ]);

  return {
    user: userData,
    totalOrders: orderHistory.length,
    lifetimeValue: orderHistory.reduce((sum, o) => sum + o.total, 0)
  };
};
```

## Debugging

Use `console.log` to debug your functions. Output appears in the function editor's console and in simulation traces:

```typescript theme={null}
export const handler = async (input: FunctionInput) => {
  console.log('Input received:', input);

  const result = calculateSomething(input);
  console.log('Calculation result:', result);

  return result;
};
```

## Execution limits

Function nodes have these constraints:

| Limit | Value |
| - | - |
| Execution timeout | 5000ms (by default) |
| Memory | Shared with engine |

If your function exceeds the timeout, evaluation fails with an error.

## Best practices

**Keep functions focused** - Each function should do one thing well. Use multiple function nodes for complex workflows.

**Handle errors gracefully** - Wrap risky operations in try/catch blocks.

**Avoid side effects** - Functions should be deterministic when possible. Same input should produce same output.

**Use expressions first** - If the ZEN expression language can handle your logic, prefer it over function nodes for better performance.

```typescript theme={null}
// Handle potential errors
export const handler = async (input: FunctionInput) => {
  try {
    const result = await riskyOperation(input);
    return { success: true, data: result };
  } catch (error) {
    console.error('Operation failed:', error.message);
    return { success: false, error: error.message };
  }
};
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.