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

# Function node

> Execute custom JavaScript functions in your workflow

Execute custom JavaScript functions deployed on Cloudflare Workers. Functions can process data, integrate with external APIs, and update workflow variables.

## Configuration

* `id`: Unique node identifier
* `function_id`: ID of deployed function to execute
* `save_response_to`: Variable name to store function response (optional)

## Workflow library example

Use function slugs in local workflow source. `kapso push` resolves the slug to the Platform API `function_id`.

```javascript theme={null}
workflow.addNode("normalize_phone", {
  type: "function",
  functionSlug: "normalize-phone",
  saveResponseTo: "normalized_phone"
});
```

## Function context

Kapso sends this JSON body to your function. Read it with `await request.json()`:

```javascript theme={null}
{
  execution_context: {
    vars: {},      // Workflow variables
    system: {},    // System info (flow_id, started_at, etc)
    context: {}    // Channel info (phone_number, etc)
  },
  flow_events: [], // Recent workflow events (last 10)
  flow_info: {
    id: "flow_123",
    name: "Customer Support",
    step_id: "current_step_456"
  },
  whatsapp_context: { // Only if WhatsApp workflow
    conversation: {},
    messages: []
  }
}
```

Your function still uses the standard runtime signature:

```javascript theme={null}
async function handler(request, env) {
  const body = await request.json();
  const executionContext = body.execution_context || {};
  const vars = executionContext.vars || {};

  return new Response(JSON.stringify({
    vars: {
      normalized_email: (vars.email || "").trim().toLowerCase()
    }
  }), {
    headers: { "Content-Type": "application/json" }
  });
}
```

## Function response

Functions can return JSON to update the workflow:

```javascript theme={null}
return new Response(JSON.stringify({
  vars: {
    user_score: 85,
    validated: true
  },
  next_edge: "success" // Optional: suggest next workflow path
}))
```

Functions can also emit project events:

```javascript theme={null}
return new Response(JSON.stringify({
  vars: {
    lead_score: 92
  },
  project_events: [
    {
      name: "lead.qualified",
      properties: {
        score: 92,
        source: "workflow"
      }
    }
  ]
}))
```

Project events follow the same validation rules as the Events API. A Function node response can emit at most 5 project events. See [Events](/docs/platform/events) for limits and caveats.

## How it works

1. **Invokes function**: Calls your deployed function with workflow context
2. **Processes response**: Updates workflow variables from function response
3. **Continues workflow**: Advances to next step via `next` edge
4. **Saves data**: Optionally stores full response in specified variable

## Usage patterns

**Data validation**

```mermaid theme={null}
graph LR
    A[Wait for response] --> B[Function<br/>Validate input]
    B --> C[Send text<br/>Confirmation]
    B --> D[Send text<br/>Error message]
```

**API integration**

```mermaid theme={null}
graph LR
    A[Function<br/>Get user data] --> B[Function<br/>Process order]
    B --> C[Send template<br/>Order confirmation]
```

**Conditional processing**

```mermaid theme={null}
graph LR
    A[Function<br/>Calculate score] --> B[Decide<br/>Score check]
    B --> C[Send text<br/>Approved]
    B --> D[Send text<br/>Rejected]
```
