Docs
Developer Documentation

Automation Flow Nodes

Create visual trigger, condition, and action nodes for Medusa's automation engine.

Medusa features a visual node-based automation flow editor where administrators create reactive event pipelines. Modules can supply custom action and condition nodes that appear in the canvas palette and execute seamlessly within automation workflows.

Automation nodes reside in resources/nodes/ and load from every *.js file located directly in that directory.

Base Class Definition

modules/example/resources/nodes/sendAlert.js
import { Nodes } from "#medusa/modules";

export class SendAlertNode extends Nodes {
    constructor(medusa) {
        super(medusa, {
            name: "send_alert",
            title: "Send Item Alert",
            category: "Example",
            description: "Dispatches an alert notification to a specified channel.",
            icon: "TbBell",
            accent: "indigo",
            hasTarget: true,
            hasSource: true,
            fields: [
                {
                    key: "channel",
                    type: "channel",
                    label: "Destination Channel",
                    default: ""
                },
                {
                    key: "message",
                    type: "text",
                    label: "Alert Message",
                    placeholder: "Item %item_name% was updated.",
                    default: ""
                }
            ],
            branches: []
        });
    }

    async run(context) {
        const channelId = context.text("channel", "");
        const template = context.text("message", "Item updated.");
        if (!channelId) return { success: false };

        const formatted = context.fill(template);
        await this.medusa.discord.post(channelId, { content: formatted });

        return { success: true };
    }
}

Conditional Branching Nodes

Nodes that evaluate conditions define branches and return the targeted branch identifier in run():

modules/example/resources/nodes/checkStock.js
import { Nodes } from "#medusa/modules";

export class CheckStockNode extends Nodes {
    constructor(medusa) {
        super(medusa, {
            name: "check_stock",
            title: "Check Item Stock",
            category: "Example",
            description: "Evaluates whether an item has available inventory.",
            icon: "TbCheck",
            accent: "emerald",
            fields: [
                { key: "identifier", type: "text", label: "Item Identifier", default: "%item_id%" },
                { key: "minStock", type: "number", label: "Minimum Quantity", default: 1 }
            ],
            branches: [
                { id: "available", label: "In Stock" },
                { id: "empty", label: "Out of Stock" }
            ]
        });
    }

    async run(context) {
        const identifier = context.text("identifier", "");
        const minStock = context.number("minStock", 1);
        const handler = this.medusa.modules.handlers.get(this.module, "items");
        if (!handler) return { success: true, branch: "empty" };

        const item = await handler.getByIdentifier(identifier).catch(() => null);
        if (item && item.quantity >= minStock) {
            return { success: true, branch: "available" };
        }

        return { success: true, branch: "empty" };
    }
}

Constructor Options

The configuration object passed to super(medusa, meta) accepts the following properties:

PropertyTypeDefaultDescription
namestringRequiredUnique node identifier. Full type key becomes <module>:<name>.
titlestringnameDisplay title shown on the node card in the flow builder.
categorystring"General"Palette category where this node appears in the node selector.
descriptionstring""Subtitle describing what the node does.
iconstring"TbSparkles"Tabler icon component name (e.g. "TbBell", "TbCoins", "TbShield").
accentstring"indigo"Mantine theme color accent applied to the node header and handles.
hasTargetbooleantrueWhen true, renders an incoming execution handle on the left.
hasSourcebooleantrueWhen true, renders an outgoing execution handle on the right.
fieldsArray<object>[]List of field configuration inputs rendered inside the node body.
branchesArray<object>[]List of labeled output branches for conditional flows.
ordernumber0Sort weight within the palette category.

Node Field Types

Fields declared inside fields define controls displayed on the canvas:

Field TypeControl RenderedContext Method
"text"Single-line text inputcontext.text(key, fallback)
"number"Numeric inputcontext.number(key, fallback)
"select"Dropdown menu with options arraycontext.text(key, fallback)
"duration"Numeric input paired with unit dropdowncontext.number(key, fallback)
"boolean"Toggle switchcontext.boolean(key, fallback)
"channel"Discord channel pickercontext.text(key, fallback)
"role"Discord role pickercontext.text(key, fallback)

Execution Context

The context object provided to run(context) supplies runtime data, trigger parameters, and helper methods:

Property / MethodReturn TypeDescription
context.guildIdstringDiscord snowflake ID of the active server.
context.dataobjectRaw field configuration values configured on this node instance.
context.text(key, fallback)stringEvaluates a text field with variable interpolation.
context.number(key, fallback)numberResolves a numeric field value.
context.boolean(key, fallback)booleanResolves a boolean field value.
context.resolveMember()Promise<GuildMember>Resolves the Discord member triggering the flow.
context.fill(template)stringReplaces variable placeholders in arbitrary text.

On this page