Automation Nodes
Automation nodes are extensions that add custom functionality to the visual Automation Builder. Users drag your node onto the canvas, configure it, and connect it to other nodes to build automated workflows.
Three node types are supported:
| Type | Purpose | Example |
|---|---|---|
| Trigger | Start an automation from an external event | Shopify order webhook, RSS feed poll |
| Action | Perform work when the automation runs | Send a Discord message, update a spreadsheet |
| Logic | Branch the flow based on a condition | Check if order total exceeds a threshold |
Each automation node extension declares exactly one node. Multiple nodes require multiple extensions.
Architecture
Automation nodes run server-side in a V8 isolate inside the Automation Worker service. The execution flow:
- The Automation Builder stores the node graph (nodes + edges) in the database
- When a trigger fires (webhook, poll, or manual), the Automation Engine walks the graph
- For each extension node, the Engine dispatches to the Automation Worker via HTTP
- The Worker executes your handler in a sandboxed V8 isolate
- The handler result flows back: action output feeds downstream nodes, logic branches route the flow
The node config UI in the Automation Builder is rendered as a Custom React Component via the SDK iframe sandbox (same mechanism as widget config panels).
Manifest
Automation node extensions use category: "automation_node" and require a node_type field plus a node configuration object:
{
"$schema": "https://lumio.vision/schemas/lumio.config.schema.json",
"extension_id": "your-uuid-here",
"name": "My Custom Action",
"category": "automation_node",
"version": "1.0.0",
"node_type": "action",
"node": {
"input_schema": {
"type": "object",
"properties": {
"message": { "type": "string", "title": "Message" }
},
"required": ["message"]
},
"output_schema": {
"type": "object",
"properties": {
"success": { "type": "boolean" }
}
},
"icon": "send",
"color": "#3b82f6"
},
"targets": ["editor"],
"server": true,
"egress": {
"allow_hosts": ["api.example.com"]
}
}
Key manifest rules:
categorymust be"automation_node"node_typemust be"trigger","action", or"logic"targetsmust include"editor"(the automation builder surface)servermust betrue(nodes execute server-side)- Trigger nodes require
node.trigger_mode("webhook","polling", or"both") - Action and logic nodes must NOT have
trigger_modeorpoll_interval_seconds
Handler file
Your server handler lives in server/handler.ts. Each node type uses a different SDK wrapper:
- Action:
defineAutomationAction - Trigger:
defineAutomationTrigger - Logic:
defineAutomationLogic
See the dedicated guide for each node type:
Context API
Every handler receives a ctx object:
| Property | Type | Description |
|---|---|---|
ctx.fetch(url, options) | Function | HTTP client with egress allowlist enforcement |
ctx.cache.get(key) | Function | Read from scoped Redis cache |
ctx.cache.set(key, value, ttl?) | Function | Write to scoped Redis cache |
ctx.installConfig | Record<string, unknown> | Extension-level config (from extension_installs.config) |
ctx.nodeConfig | Record<string, unknown> | Per-node-instance config (from automation_nodes.config) |
ctx.inputData | Record<string, unknown> | Data from upstream node or webhook/poll payload |
ctx.auth | Object | { accountId, extensionId, installId } |
Timeouts
| Node Type | Timeout | Rationale |
|---|---|---|
| Action | 5000ms | May call external APIs |
| Logic | 2000ms | Should be fast computation |
| Trigger (poll) | 5000ms | May check external service |
| Trigger (webhook) | 1000ms | Just parsing/validation |
Next steps
- Action Nodes -- build an action node
- Trigger Nodes -- build a trigger node
- Logic Nodes -- build a logic node
- Config Panel -- custom config UI in the Automation Builder
- Testing -- local development and testing