Skip to main content

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:

TypePurposeExample
TriggerStart an automation from an external eventShopify order webhook, RSS feed poll
ActionPerform work when the automation runsSend a Discord message, update a spreadsheet
LogicBranch the flow based on a conditionCheck 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:

  1. The Automation Builder stores the node graph (nodes + edges) in the database
  2. When a trigger fires (webhook, poll, or manual), the Automation Engine walks the graph
  3. For each extension node, the Engine dispatches to the Automation Worker via HTTP
  4. The Worker executes your handler in a sandboxed V8 isolate
  5. 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:

  • category must be "automation_node"
  • node_type must be "trigger", "action", or "logic"
  • targets must include "editor" (the automation builder surface)
  • server must be true (nodes execute server-side)
  • Trigger nodes require node.trigger_mode ("webhook", "polling", or "both")
  • Action and logic nodes must NOT have trigger_mode or poll_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:

PropertyTypeDescription
ctx.fetch(url, options)FunctionHTTP client with egress allowlist enforcement
ctx.cache.get(key)FunctionRead from scoped Redis cache
ctx.cache.set(key, value, ttl?)FunctionWrite to scoped Redis cache
ctx.installConfigRecord<string, unknown>Extension-level config (from extension_installs.config)
ctx.nodeConfigRecord<string, unknown>Per-node-instance config (from automation_nodes.config)
ctx.inputDataRecord<string, unknown>Data from upstream node or webhook/poll payload
ctx.authObject{ accountId, extensionId, installId }

Timeouts

Node TypeTimeoutRationale
Action5000msMay call external APIs
Logic2000msShould be fast computation
Trigger (poll)5000msMay check external service
Trigger (webhook)1000msJust parsing/validation

Next steps