Building Workflows
This guide covers how to design, connect, save, import, and organize workflows in NORA.
Entering Edit Mode
Click the Edit Mode button in the top-right corner. The toolbar expands with editing controls, and the header shows NORA (Edit Mode).
In Edit Mode:
– Nodes can be selected, edited, connected, duplicated, and deleted
– New nodes can be added to the canvas
– The Tool Library drawer is accessible
– Edge labels can be set by clicking connections
Click Exit Edit Mode when you’re done editing to return to Run Mode.
Adding Nodes
Add Block
Click Add Block in the toolbar. A new Command Node titled “New Block” is placed on the canvas. Double-click it (or select it and click Edit Block) to configure its title, command, working directory, and other properties.
Add Note
Click Add Note to place a Notepad Node. Type directly into the note to add your text. Use notes to document setup steps, add reminders, or label sections of your workflow.
Add Condition (Template Library)
Click Add Condition to add a node from the condition template library. The dropdown to the left of the button lets you pick which template to use.
Despite the name, the condition library includes templates for all node types, not just conditions:
| Category | Available Templates |
|---|---|
| Basic Logic | IF/Else (Status), Has Result? |
| Comparisons | Compare Values, Threshold Check, Range Check |
| Time/Date | Time Window, Day Check, Wait/Delay, Wait Until Time |
| Data Quality | Validation Check |
| Display | Media Viewer |
| AI | AI Router, AI Agent, AI Autonomous Agent, Custom Script Agent |
Each template pre-configures the node’s type and default settings, so you get a ready-to-customize starting point.
Quick Add (Desktop Only)
Click 📁 Quick Add to create nodes from files and folders on your disk. A modal offers three options:
| Option | What Happens |
|---|---|
| 📁 Folder | Select a folder → creates a Command Node with the path. If the folder contains multiple scripts, a sub-modal shows them so you can pick one or create separate nodes for each. |
| 📄 File | Select a file → creates a Command Node configured to run or reference that file. |
| 📦 Multiple Folders | Select several folders → creates one node per folder, auto-arranged in a grid layout. |
From the Tool Library
Open the Tool Library drawer (click 🧰 on the right edge or press Ctrl+Shift+L). Browse your saved tools and click Insert to place a pre-configured node onto the canvas. See the Tool Library guide for more.
Drag & Drop from File Explorer (Desktop Only)
Drag files or folders directly from Windows File Explorer onto the NORA canvas to auto-create nodes. You can also drag onto existing nodes:
| Drop Target | Result |
|---|---|
| Empty canvas | Creates a Command Node for the dropped file/folder |
| Regular node | Adds the file as a link button on that node |
| AI Autonomous Agent node | Adds the file as a tool the agent can invoke |
Editing Node Properties
To edit a node:
1. Click the node to select it (highlighted border)
2. Click Edit Block in the toolbar, or double-click the node
The Edit Block modal opens with all configurable fields. The available fields change based on the node’s Type — you can even change the type from the dropdown to convert one node type to another.
Common fields for all node types:
– ID — unique identifier (kebab-case recommended)
– Type — the node type (Script, Condition, AI Agent, etc.)
– Title — display name on the canvas
– Description — optional explanation
Type-specific fields are documented in the Node Types guide.
Inline Editing
Some properties can be edited directly on the node without opening the modal:
– Command Node: The command text area is editable directly on the node in Edit Mode
– Notepad Node: Type directly into the note body
Adding Links
In the Edit Block modal, scroll to the Links section. Enter a Label and URL for each link, then click Add. Links appear as buttons on the node.
Links can be:
– URLs: https://example.com — opens in browser
– File paths: file:///C:/path/to/file.py — opens in your configured editor
– Directory paths: file:///C:/path/to/folder — opens in file explorer
Connecting Nodes
Connections (edges) define the execution order of your workflow. A workflow runs from source (right handle) to target (left handle).
Dragging to Connect
- Hover over the right edge of a node to see the source handle (small circle)
- Click and drag from the handle
- Drop on the left edge of the target node (its target handle)
- A connection line appears
Using the Connect Button
- Select a node by clicking it
- Click Connect in the toolbar
- Enter the ID of the target node
- Click Connect
Labeling Edges
Click a connection in Edit Mode — or double-click a connection in any mode — to open the Edge Label Modal:
Edge labels are critical for:
– Condition Nodes — labels determine which path to follow (success/error, in-window/out-of-window, match/no-match)
– AI Router Nodes — labels must match category names
– AI Agent Nodes — routing is via named source handles, but labels can add documentation
– Any node — labels help document what each connection means
To add or edit a label:
1. In Edit Mode, click any connection line
2. The Edge Label Modal opens
3. Type a label or click a quick-label button
4. Click Save Label
Quick-label buttons are context-aware. They change based on the source node:
– Condition (status): success, error
– Condition (time): in-window, out-of-window
– Condition (day): match, no-match
– AI Router: shows configured category names
– AI Agent: shows configured tool names
– Custom Script Agent: shows configured route labels
Loop Edges (Repeat a Section of a Workflow)
NORA supports loop-back edges that re-execute a section of your workflow multiple times. This is useful for retry patterns, polling loops, and iterative processing.
Creating a Loop Edge
- In Edit Mode, draw a connection from a downstream node back to an upstream node (creating a back-edge)
- Double-click the connection to open the Edge Label Modal
- Click the ↺ Loop Back button in the Loop section
- Set the iteration count (1–50) — this is how many times the loop will re-execute
- Click Save Label
The edge label will be set to loop:N (e.g., loop:3 for 3 iterations).
How Loops Execute
When a workflow reaches a loop edge:
- First pass: The workflow runs normally through all nodes from top to bottom
- Loop back: When the source node of the loop edge completes, the engine checks the iteration count
- Path reset: All nodes between the loop target and loop source are cleared — their statuses and outputs reset
- Re-execute: The target node and all downstream nodes in the loop path run again
- Repeat: Steps 2–4 repeat until the configured number of iterations is reached
Visual Feedback During Loops
| Visual | Meaning |
|---|---|
| Purple edge animation | The loop edge highlights purple (distinct from green/red) when the loop fires |
| Edge counter | The loop edge label updates live: loop:3 ↺ 1/3 → loop:3 ↺ 2/3 → loop:3 ✓ 3/3 |
| Purple badge | The target node shows a ↺ N/M badge (e.g., ↺ 2/3) during loop execution |
| Node reset | Intermediate nodes in the loop path reset to idle (gray) before each iteration |
Tips & Limits
- Safety cap: Loops are capped at 50 iterations maximum, even if you enter a higher number
- Default iterations:
loopwithout a number defaults to 10 iterations - Condition-gated loops: Place a Condition Node before the loop edge to loop only on certain outcomes (e.g., loop on
error, continue onsuccess) - Nested loops: You can have loops inside loops — each loop edge has its own independent counter
- Email reports: Loop iteration counts appear in the Execution Summary section of workflow email notifications
- Save/load: Loop edge labels persist when saving and loading workflow configs
Deleting Connections
In the Edge Label Modal, click Delete Edge to remove the connection.
Saving Workflows
Quick Save (Ctrl+S)
If you loaded a workflow from a file, press Ctrl+S or click 💾 Save to save back to that file.
- The save button shows
*when there are unsaved changes - A confirmation dialog appears: “You are about to save changes to: [path]. A backup of the original file will be created.”
- After saving, the button briefly shows ✓ and the last-saved timestamp updates
Save As (Ctrl+Shift+S)
Click 📄 Save As… or press Ctrl+Shift+S to save to a new file. Choose a filename and location.
Automatic Backups
Every time you save, NORA creates a backup of the previous version in a .backups/ folder adjacent to the config file. NORA maintains a 3-level backup rotation:
my-workflow.js ← current version
.backups/
my-workflow.backup.1.js ← previous version
my-workflow.backup.2.js ← two versions ago
my-workflow.backup.3.js ← three versions ago
If something goes wrong, you can restore from a backup by copying it over the current file.
Save Draft
In Edit Mode, click Save Draft to save an in-progress version. Click Load Draft to restore it. Drafts are useful for experimenting without overwriting your saved config.
Workflow Config File Format
Workflow configs are JavaScript module files. NORA supports two formats:
ESM format (recommended):
export const workflowBlocks = [
{
"id": "step-1",
"type": "script",
"title": "Run Script",
"description": "Execute the processing script",
"command": "python process.py",
"workingDir": "C:/projects/myproject",
"position": { "x": 100, "y": 300 }
}
];
export const workflowConnections = [
{
"id": "edge-1",
"source": "step-1",
"target": "step-2",
"type": "smoothstep"
}
];
CJS format (also supported):
module.exports = {
workflowBlocks: [ /* ... */ ],
workflowConnections: [ /* ... */ ]
};
Node Definition Schema
All nodes share these required fields:
| Field | Type | Description |
|---|---|---|
id |
string | Unique kebab-case identifier (e.g., "step-1", "check-status") |
type |
string | Node type — see type-specific fields below |
title |
string | Display name shown on the canvas |
description |
string | Detailed description of what this node does |
position |
{ x, y } |
Canvas coordinates for placement |
Type-Specific Fields
script — Shell command execution
| Field | Type | Required | Description |
|---|---|---|---|
command |
string | Yes | Shell command to execute |
workingDir |
string | Yes | Working directory path |
interactive |
boolean | No | If true, opens in a separate terminal window |
links |
array | No | Associated URLs or file paths shown as buttons |
retries |
number | No | Max retry attempts on failure |
retryDelay |
number | No | Initial delay between retries (seconds) |
backoffStrategy |
string | No | "fixed", "linear", or "exponential" |
condition — Decision routing
| Field | Type | Required | Description |
|---|---|---|---|
logicType |
string | Yes | "status", "time-window", or "day-check" |
startTime |
string | time-window | Start time in "HH:MM" format |
endTime |
string | time-window | End time in "HH:MM" format |
timezone |
string | time-window | "local" or a timezone identifier |
selectedDays |
number[] | day-check | Days of week (0=Sun through 6=Sat) |
wait — Timed pause
| Field | Type | Required | Description |
|---|---|---|---|
seconds |
number | Yes | Pause duration in seconds |
wait-until-time — Schedule gate
| Field | Type | Required | Description |
|---|---|---|---|
targetTime |
string | Yes | Target time in "HH:MM" (24-hour format) |
offsetDays |
number | No | Days offset from today (default: 0) |
aiRouter — AI text classification
| Field | Type | Required | Description |
|---|---|---|---|
aiProvider |
string | Yes | "gemini", "openai", or "anthropic" |
aiModel |
string | Yes | Model identifier (e.g., "gemini-2.0-flash") |
inputFolderPath |
string | Yes | Folder containing files to classify |
filePattern |
string | Yes | File filter (e.g., "*.txt;*.html") |
sortBy |
string | Yes | "modified" or "created" |
categories |
string[] | Yes | Classification category names |
customPrompt |
string | No | Override the default classification prompt |
aiCsvEnabled |
boolean | No | Enable CSV output of classifications |
aiCsvDir |
string | No | CSV output directory |
aiAgent — Single-turn AI tool calling
| Field | Type | Required | Description |
|---|---|---|---|
aiProvider |
string | Yes | "gemini", "openai", or "anthropic" |
aiModel |
string | Yes | Model identifier |
memoryFolderPath |
string | Yes | Folder of context files for the AI to read |
filePattern |
string | Yes | File filter (e.g., "*.json;*.txt") |
sortBy |
string | Yes | "modified" or "created" |
tools |
string[] | Yes | Tool names the agent can call |
customPrompt |
string | Yes | System prompt with instructions |
conversationMode |
string | No | "single-turn" (default) or "multi-turn" |
maxTurns |
number | No | Max turns for multi-turn mode (default: 5) |
aiAutonomousAgent — Multi-step autonomous agent
| Field | Type | Required | Description |
|---|---|---|---|
aiProvider |
string | Yes | "gemini", "openai", or "anthropic" |
aiModel |
string | Yes | Model identifier |
userRequest |
string | Yes | Task/objective description |
goalPrompt |
string | Yes | System prompt defining agent behavior |
memoryFolderPath |
string | No | Folder of context files |
filePattern |
string | No | File filter for context files |
maxIterations |
number | No | Max tool-call cycles (default: 10) |
timeoutMinutes |
number | No | Overall timeout (default: 30) |
budgetLimit |
number | No | Max AI cost in USD (default: 10.00) |
tools |
array | No | Tool definitions — toolRef objects or inline definitions |
customScriptAgent — User-coded agent script
| Field | Type | Required | Description |
|---|---|---|---|
scriptPath |
string | Yes | Path to the Python or Node.js script |
scriptType |
string | No | "auto-detect", "python", or "node" |
routeLabels |
string | Yes | Comma-separated custom route label names |
userRequest |
string | Yes | Task/prompt sent to the script |
workingDir |
string | No | Working directory for the script |
memoryFolderPath |
string | No | Folder of context files |
maxRuntime |
number | No | Timeout in minutes (default: 30) |
notepad — Annotations and notes
| Field | Type | Required | Description |
|---|---|---|---|
notes |
string | Yes | Text content (supports line breaks) |
media-viewer — Media display
| Field | Type | Required | Description |
|---|---|---|---|
mediaPath |
string | No | Path to a file or folder |
autoLatest |
boolean | No | Auto-display the latest matching file |
filePattern |
string | No | File filter (e.g., "*.png;*.jpg") |
sortBy |
string | No | "modified" or "created" |
pollInterval |
number | No | Refresh interval in seconds |
Connection Definition Schema
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique edge identifier |
source |
string | Yes | Source node ID |
target |
string | Yes | Target node ID |
type |
string | Yes | Always "smoothstep" |
label |
string | No | Edge label (required for condition and AI Router routing) |
sourceHandle |
string | No | Named output handle (for AI Agent, Autonomous Agent, Custom Script Agent nodes) |
Edge Label and Source Handle Rules
How edges determine routing for different node types:
| Node Type | Routing Mechanism | Values |
|---|---|---|
| Condition (status) | label |
"success", "error" |
| Condition (time-window) | label |
"in-window", "out-of-window" |
| Condition (day-check) | label |
"match", "no-match" |
| AI Router | label |
Category name (case-insensitive match) |
| AI Agent | sourceHandle |
"success", "error", "tool_<slug>" |
| AI Autonomous Agent | sourceHandle |
"complete", "partial", "needs-input", "error" |
| Custom Script Agent | sourceHandle |
"route_<label>", "success", "error" |
Positioning Guidelines
- Horizontal spacing: ~350–400px between consecutive nodes
- Vertical spacing: ~150–200px for parallel branches
- Starting point: Main flow typically starts around
{ x: 100, y: 300 } - Notes: Place Notepad nodes at the bottom or side, away from the main flow
Importing Workflow Configs
Browse Configs
In Run Mode, click 📂 Browse Configs to open the config file browser. This shows all available workflow configs organized by folder:
- Source directories are scanned for
.jsfiles containing workflow exports - Custom workflow folders added in Settings are also included
- Search to filter by name
- Sort by recent, A-Z, or Z-A
- Expandable folders for organized browsing
Click a config to see a mini preview of the workflow on a small canvas. Then choose:
– Replace — clear the current canvas and load this config
– Append — add this config’s nodes to the existing canvas
Import Config from File
In Edit Mode, click Import Config and select a .js or .json file from your file system.
Export Config
In Edit Mode, click Export Config to download the current workflow as a file.
Loading Defaults
Default Workflow
In Settings → Workflow Folders, you can set a default workflow that loads automatically when NORA starts. This is the workflow you’ll see every time you open the app.
Session Persistence
If you refresh the page (Ctrl+R), NORA reloads the last active workflow from that session. This means you won’t lose your place during development.
New Workflow
Click 📄 New in Edit Mode to start with a completely blank canvas. The workflow name changes to “Untitled Workflow”.
Config Validation
When you load a workflow config, NORA automatically validates it and checks for:
| Check | What It Catches |
|---|---|
| Required fields | Nodes missing id, type, title, or position |
| Valid connections | Edges referencing node IDs that don’t exist |
| Orphaned edges | Connections where the source or target was deleted |
| Unlabeled condition edges | Condition nodes with edges that lack the required labels |
If errors are found, an Error Modal lists all issues so you can fix them.
Organization Tips
Folder Structure
Organize your config files into folders by category or project:
my-workflows/
data-processing/
daily-etl.js
weekly-report.js
lead-generation/
cold-outreach.js
follow-up.js
devops/
deploy-staging.js
deploy-production.js
Add these folders in Settings → Workflow Folders so they appear in the config browser.
Using Notepad Nodes
Place Notepad Nodes on your canvas to:
– Document what the workflow does and why
– List setup requirements (API keys, dependencies, folders)
– Note cost estimates and ROI calculations
– Mark sections with colored notes
Layout for Readability
Use the Layout dropdown to auto-arrange nodes, then fine-tune:
– Hierarchical works well for linear workflows
– Grid is good for workflows with many parallel branches
– Keep related nodes close together
– Use consistent horizontal spacing (~350–400px between steps)
Sharing Configs
Current limitation: Workflow config files use absolute file paths (e.g.,
C:/Users/YourName/projects/data.csv). When sharing a config with someone else, they will need to update all paths to match their system’s directory structure.
To share a workflow:
1. Export or copy the .js config file
2. Send it to the recipient
3. The recipient updates all file paths, working directories, and folder paths to match their system
4. The recipient loads the config via Browse Configs or Import Config
Tip: Using relative paths in commands (e.g.,
./scripts/process.pywith a configurable working directory) reduces the number of paths that need updating.
What’s Next?
- Running Workflows — Learn about foreground, background, and scheduled execution
- AI Features — Set up AI providers and use AI-powered nodes
- Settings & Configuration — Configure workflow folders, editors, and more
- Reference — Full config schema field reference, troubleshooting, and glossary