Nodes are the fundamental building blocks of AutoMFlows workflows. Each node represents a discrete operation, from browser interactions to API calls to data manipulation.
Node Categories
AutoMFlows provides 70+ built-in node types organized into categories:
Browser Start, Open Browser, Navigation, Context Manipulation
Interaction Action (click, hover, drag), Type, Keyboard, Scroll
Data Element Query, Data Extractor, Smart Extractor, Screenshot
Form Form Input (select, check, upload), Storage, Dialog, Download, Iframe
Verification Verify (browser, API, database)
Logic JavaScript Code, Loop, Wait
Value Int Value, String Value, Boolean Value, Input Value
Config Load Config File, Select Config File
Database Connect, Disconnect, Query, Transactions
Notification Email, Slack, Webhook
Node Structure
Every node follows the same base structure:
// shared/src/types.ts:79
export interface BaseNode {
id : string ; // Unique identifier (auto-generated)
type : NodeType | string ; // Node type (enum or plugin type)
position : { x : number ; y : number }; // Canvas coordinates
data : NodeData | Record < string , any >; // Type-specific configuration
}
Node Handler Interface
Each node type has a handler that implements the execution logic:
// backend/src/nodes/base.ts:4
export interface NodeHandler {
execute ( node : BaseNode , context : ContextManager ) : Promise < void >;
}
Handlers receive:
node : The node configuration with all properties
context : The execution context containing page, browser, data, and variables
Browser Nodes
Start Node
Every workflow begins with a Start node. It configures global execution settings:
export interface StartNodeData {
label ?: string ;
recordSession ?: boolean ; // Record video of browser session
screenshotAllNodes ?: boolean ; // Take screenshots on all nodes
screenshotTiming ?: 'pre' | 'post' | 'both' ;
snapshotAllNodes ?: boolean ; // Capture accessibility snapshots
snapshotTiming ?: 'pre' | 'post' | 'both' ;
slowMo ?: number ; // Delay between nodes (ms)
scrollThenAction ?: boolean ; // Smooth scroll before UI interactions
}
The Start node is special—it doesn’t execute any action but configures the execution environment for all subsequent nodes.
Open Browser Node
Launches a browser instance using Playwright:
export interface OpenBrowserNodeData {
headless ?: boolean ; // Run without UI (default: false)
viewportWidth ?: number ; // Viewport width in pixels
viewportHeight ?: number ; // Viewport height in pixels
maxWindow ?: boolean ; // Maximize window (default: true)
browser ?: 'chromium' | 'firefox' | 'webkit' ;
capabilities ?: Record < string , any >; // Playwright context options
launchOptions ?: Record < string , any >; // Playwright launch options
stealthMode ?: boolean ; // Enable stealth mode to avoid detection
jsScript ?: string ; // JavaScript to inject on all pages
}
Implementation: backend/src/nodes/browser.ts:13
Example: Open Browser with Custom Options
{
"type" : "openBrowser" ,
"data" : {
"headless" : false ,
"viewportWidth" : 1920 ,
"viewportHeight" : 1080 ,
"browser" : "chromium" ,
"stealthMode" : true ,
"capabilities" : {
"locale" : "en-US" ,
"timezoneId" : "America/New_York" ,
"geolocation" : { "latitude" : 40.7128 , "longitude" : -74.0060 },
"permissions" : [ "geolocation" ]
},
"jsScript" : "Object.defineProperty(navigator, 'webdriver', {get: () => false});"
}
}
Navigation Node
Handles page navigation and tab management:
export interface NavigationNodeData {
action : 'navigate' | 'goBack' | 'goForward' | 'reload' | 'newTab' | 'switchTab' | 'closeTab' ;
url ?: string ; // For navigate/newTab
waitUntil ?: 'load' | 'domcontentloaded' | 'networkidle' | 'commit' ;
referer ?: string ; // Custom referer header
tabIndex ?: number ; // For switchTab/closeTab
urlPattern ?: string ; // For switchTab by URL
contextKey ?: string ; // Store page reference
timeout ?: number ;
failSilently ?: boolean ;
// Wait conditions and retry config...
}
Implementation: backend/src/nodes/browser.ts:63
Interaction Nodes
Action Node
Unified handler for mouse interactions:
export interface ActionNodeData {
action : 'click' | 'doubleClick' | 'rightClick' | 'hover' | 'dragAndDrop' ;
selector : string ;
selectorType ?: SelectorType ;
selectorModifiers ?: SelectorModifiers ;
// Action-specific
button ?: 'left' | 'right' | 'middle' ;
delay ?: number ; // For hover/doubleClick
targetSelector ?: string ; // For dragAndDrop
targetX ?: number ; // For dragAndDrop coordinates
targetY ?: number ;
timeout ?: number ;
failSilently ?: boolean ;
// Wait conditions and retry config...
}
Implementation: backend/src/nodes/handlers/action.ts:9
Click
Clicks on an element. Supports left, right, middle mouse buttons.
Double Click
Performs double-click. Optional delay between clicks.
Right Click
Opens context menu on element.
Hover
Moves mouse over element. Useful for dropdown menus.
Drag and Drop
Drags element to target selector or coordinates.
Type Node
Enters text into input fields:
export interface TypeNodeData {
selector : string ;
selectorType ?: SelectorType ;
text : string ; // Supports ${data.key} interpolation
inputMethod ?: 'fill' | 'type' | 'pressSequentially' | 'append' | 'prepend' | 'direct' ;
delay ?: number ; // Keystroke delay for type method
clearFirst ?: boolean ; // Clear field before typing
timeout ?: number ;
// Wait conditions and retry config...
}
Implementation: backend/src/nodes/handlers/type.ts
Handles form-specific interactions:
export interface FormInputNodeData {
action : 'select' | 'check' | 'uncheck' | 'upload' ;
selector : string ;
// Select-specific
values ?: string | string []; // Options to select
selectBy ?: 'value' | 'label' | 'index' ;
multiple ?: boolean ; // Multiple selection
// Upload-specific
filePaths ?: string | string []; // Files to upload
// Check/uncheck-specific
force ?: boolean ; // Force action even if disabled
timeout ?: number ;
// Wait conditions and retry config...
}
Implementation: backend/src/nodes/handlers/formInput.ts
Element Query Node
Queries element properties:
export interface ElementQueryNodeData {
action : 'getText' | 'getAttribute' | 'getCount' | 'isVisible' | 'isEnabled' | 'isChecked' | 'getBoundingBox' | 'getAllText' ;
selector : string ;
selectorType ?: SelectorType ;
attributeName ?: string ; // For getAttribute
outputVariable ?: string ; // Store result (default varies by action)
timeout ?: number ;
// Wait conditions and retry config...
}
Implementation: backend/src/nodes/handlers/elementQuery.ts
Output variables:
getText: Stores in data.elementText
getAttribute: Stores in data.attributeValue
getCount: Stores in data.elementCount
isVisible: Stores in data.isVisible
getAllText: Stores array in data.allElementText
Extracts structured data from multiple elements:
export interface DataExtractorNodeData {
containerSelector : string ; // Parent container
containerSelectorType ?: SelectorType ;
fields : DataExtractorFieldDefinition [];
outputVariable ?: string ; // Store results (default: 'extractedData')
limit ?: number ; // Max items to extract
timeout ?: number ;
saveToCSV ?: boolean ; // Save to CSV file
csvFilePath ?: string ;
csvDelimiter ?: string ;
}
export interface DataExtractorFieldDefinition {
name : string ; // Field name in output
selector : string ; // Relative to container
selectorType ?: SelectorType ;
extract : 'text' | 'attribute' | 'innerHTML' ;
attribute ?: string ; // If extract='attribute'
}
Implementation: backend/src/nodes/handlers/dataExtractor.ts
Example: Extract Product Data
Automatic extraction patterns:
export interface SmartExtractorNodeData {
mode : 'allLinks' | 'allImages' | 'tables' | 'repeatedItems' ;
tableIndex ?: number ; // For 'tables' mode
outputVariable ?: string ; // Store results
includeMetadata ?: boolean ; // Include element metadata
limit ?: number ;
timeout ?: number ;
}
Implementation: backend/src/nodes/handlers/smartExtractor.ts
Logic Nodes
JavaScript Code Node
Executes arbitrary JavaScript in the browser or Node.js context:
export interface JavaScriptCodeNodeData {
code : string ; // JavaScript code to execute
failSilently ?: boolean ;
}
Implementation: backend/src/nodes/logic.ts
JavaScript Code nodes execute server-side with full access to the execution context. Only use in trusted environments.
// Available in code execution scope:
// - context: ContextManager instance
// - page: Playwright Page instance
// - browser: Playwright Browser instance
// - data: context.getAllData()
// - variables: context.getAllVariables()
// Example: Custom data manipulation
const products = data . extractedData ;
const totalPrice = products . reduce (( sum , p ) => {
const price = parseFloat ( p . price . replace ( '$' , '' ));
return sum + price ;
}, 0 );
context . setData ( 'totalPrice' , totalPrice );
Loop Node
Iterates over arrays or conditions:
export interface LoopNodeData {
mode : 'forEach' | 'doWhile' ;
failSilently ?: boolean ;
// forEach mode
arrayVariable ?: string ; // e.g., "products" for data.products
// doWhile mode
condition ?: SwitchCondition ;
updateStep ?: string ; // JavaScript code to run each iteration
maxIterations ?: number ; // Safety limit (default: 1000)
}
Implementation: backend/src/nodes/logic.ts
During loop execution, these variables are available: // forEach mode
data . loopIteration // Current iteration index (0-based)
data . loopItem // Current array item
data . loopArray // Full array being iterated
// doWhile mode
data . loopIteration // Current iteration count
Wait Node
Pauses execution based on conditions:
export interface WaitNodeData {
waitType : 'timeout' | 'selector' | 'url' | 'condition' | 'api-response' ;
value : number | string ; // Timeout ms, selector, URL, JS condition
selectorType ?: SelectorType ;
timeout ?: number ;
pause ?: boolean ; // Pause execution (for debugging)
// API response wait config
apiWaitConfig ?: {
contextKey : string ; // Which API response to check
checkType : 'status' | 'header' | 'body-path' | 'body-value' ;
path ?: string ;
expectedValue ?: any ;
matchType ?: MatchType ;
};
// Retry config...
}
Implementation: backend/src/nodes/handlers/wait.ts
API Nodes
API Request Node
Makes HTTP requests:
export interface ApiRequestNodeData {
method : 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' ;
url : string ; // Supports ${data.key} interpolation
headers ?: Record < string , string >;
body ?: string ;
bodyType ?: 'json' | 'form-data' | 'raw' | 'url-encoded' ;
formFields ?: Array <{ key : string ; value : string ; type : 'text' }>;
formFiles ?: Array <{ key : string ; filePath : string }>;
timeout ?: number ;
contextKey ?: string ; // Store response (default: 'apiResponse')
failSilently ?: boolean ;
// Retry config with API-specific conditions...
}
Implementation: backend/src/nodes/api.ts
Response structure:
data . apiResponse = {
status: 200 ,
statusText: 'OK' ,
headers: { 'content-type' : 'application/json' },
body: { /* parsed JSON or raw text */ }
}
Verification Node
Asserts conditions across multiple domains:
export interface VerifyNodeData {
domain : 'browser' | 'api' | 'database' ;
verificationType : string ; // Domain-specific types
// Browser verification
urlPattern ?: string ;
expectedText ?: string ;
selector ?: string ;
elementCheck ?: 'visible' | 'hidden' | 'exists' | 'notExists' | 'count' | 'enabled' | 'disabled' ;
// API verification
statusCode ?: number ;
jsonPath ?: string ;
headerName ?: string ;
apiContextKey ?: string ;
// Database verification
dbContextKey ?: string ;
dbVerificationType ?: 'rowCount' | 'columnValue' | 'rowExists' | 'queryResult' ;
columnName ?: string ;
rowIndex ?: number ;
// Common
matchType ?: 'contains' | 'equals' | 'regex' | 'startsWith' | 'endsWith' ;
comparisonOperator ?: 'equals' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual' ;
expectedValue ?: any ;
caseSensitive ?: boolean ;
timeout ?: number ;
failSilently ?: boolean ;
}
Implementation: backend/src/nodes/handlers/verify.ts
Value Nodes
Provide static or dynamic values:
Int Value
String Value
Boolean Value
Input Value
export interface IntValueNodeData {
value : number | string ; // Number or ${data.key}
variableName ?: string ; // Store in data[variableName]
}
export interface StringValueNodeData {
value : string ; // String or ${data.key}
variableName ?: string ;
}
export interface BooleanValueNodeData {
value : boolean | string ; // Boolean or ${data.key}
variableName ?: string ;
}
export interface InputValueNodeData {
dataType : 'int' | 'float' | 'double' | 'string' | 'boolean' ;
value : string | number | boolean ;
variableName ?: string ;
}
Value nodes are typically used with property input connections to provide dynamic values to other nodes.
Node Handler Registry
Node handlers are registered in a central map:
// backend/src/nodes/index.ts:20
const handlers : NodeHandlerMap = {
[NodeType. START ]: new StartHandler (),
[NodeType. OPEN_BROWSER ]: new OpenBrowserHandler (),
[NodeType. TYPE ]: new TypeHandler (),
[NodeType. ACTION ]: new ActionHandler (),
// ... 60+ more handlers
};
export function getNodeHandler ( nodeType : NodeType | string ) : NodeHandler | undefined {
// Check built-in handlers first
if ( Object . values ( NodeType ). includes ( nodeType as NodeType )) {
return handlers [ nodeType as NodeType ];
}
// Check plugin registry for custom types
return pluginRegistry . getHandler ( nodeType );
}
Before node execution, property inputs are resolved:
// backend/src/engine/executor/resolvePropertyInputs.ts
export async function resolvePropertyInputs (
node : BaseNode ,
context : ContextManager
) : Promise < BaseNode > {
const data = node . data as any ;
if ( ! data . _inputConnections ) return node ;
// Resolve each connected property
for ( const [ propertyName , connection ] of Object . entries ( data . _inputConnections )) {
const sourceValue = context . getData ( ` ${ connection . sourceNodeId } _output` );
if ( sourceValue !== undefined ) {
data [ propertyName ] = sourceValue ;
}
}
return { ... node , data };
}
This allows nodes to receive dynamic values from upstream nodes’ outputs.