Action Nodes
Action nodes process data when an automation runs. They receive input data from the upstream node and produce output data for downstream nodes. Their ctx.fetch() cannot reach external hosts.
Create a project
lumio init my-action-node
When prompted:
- Category:
automation_node - Node type: Action
Handler
Define your action handler in server/handler.ts:
import { defineAutomationAction } from "@zaflun/lumio-sdk/server";
defineAutomationAction(async (ctx) => {
const amount = Number(ctx.inputData.amount ?? 0);
const taxRate = Number(ctx.nodeConfig.taxRate ?? 0);
return {
output: { total: amount * (1 + taxRate) },
status: "success",
};
});
Return value
The handler must return an ActionResult:
| Field | Type | Required | Description |
|---|---|---|---|
output | Record<string, unknown> | Yes | Data for downstream nodes. Must match the output_schema from the manifest. |
status | "success" | "error" | Yes | Whether the action completed successfully |
error_message | string | No | Human-readable error message (only when status: "error") |
When status is "error", the automation engine stops the current execution branch and records the error in the execution history.
Input/output schemas
The manifest declares what data the node accepts and produces:
{
"node": {
"input_schema": {
"type": "object",
"properties": {
"message": { "type": "string", "title": "Message to send" },
"channel": { "type": "string", "title": "Channel name" }
},
"required": ["message"]
},
"output_schema": {
"type": "object",
"properties": {
"message_id": { "type": "string" },
"sent_at": { "type": "string" }
}
}
}
}
The input_schema describes the fields your node expects in its config; the Automation Builder does not render a form from it (see Config Panel). The output_schema defines which fields downstream nodes can reference via template syntax (\{\{ext_abc12.message_id\}\}).
Output template references
Downstream nodes reference your action output using template syntax:
{{ext_abc12.message_id}}
{{ext_abc12.sent_at}}
Format: ext_{short_id}.{output_field}. Fields are derived from the output_schema properties.
Example: Format an incoming message
import { defineAutomationAction } from "@zaflun/lumio-sdk/server";
defineAutomationAction(async (ctx) => {
const message = String(ctx.inputData.message ?? ctx.nodeConfig.default_message ?? "");
return {
output: { message: message.trim(), length: message.trim().length },
status: "success",
};
});
Next steps
- Config Panel -- where a node's config comes from
- Testing -- test your action node locally