Docs · Automating
Workflow nodes
Every node a workflow can use, grouped as the node picker groups them, with what each one asks for.
The node picker opens on Tab, or on the + at the end of a node or on a wire. It groups the nodes as this page does, and has a search box. For what a workflow is and how items move through one, read Workflows first.
Nodes marked host reach the machine Mosaic is installed on, and are off on Mosaic Cloud and, until the operator says otherwise, on a server. See Commands, scripts, code and files.
Most nodes run once for each item that reaches them. Those that would do something once for the lot, such as a mail or a command, start on Once, for all items and say so in a Run field you can change.
#Triggers
The six ways a workflow starts are described under What starts a workflow. A workflow can have more than one trigger.
#Mosaic
| Node | What it does |
|---|---|
| Run a query | Runs one of the check's or the library's data sources through its read-only connection. Query values fills the query's {{tokens}} from the item, usually {{ $json.field }}. Only at these places takes a place's code, or several with commas, for a source that reads one server per place: only those servers are opened, and a code no server answers to stops the node. Up to 1,000 rows to start with, 50,000 at most; when rows are left out, the node's console says so |
| Run a check | Runs a check now, with Check parameters filled from the item, and hands on the run, or its rows. The run is recorded in the check's history like any other |
| Ask an agent | Hands each item to an agent, which reads its systems and says what it found. Agent inputs fills the agent's inputs; an input not named takes the item's field of the same name. Ten items a run to start with, since each is a model reading systems for a minute |
| Places from Business Locations | One item for each open place a place query chooses, with its server's address as host |
| Show on a monitor | What reaches it becomes a monitor's answer. Passes the items on, so a mail about what went down can follow |
| Show as a table | Keeps every item that reaches it as a table to search, sort and download as Excel or CSV. It asks for nothing: the table is called what the node is called. Passes the items on |
#Messages and requests
#HTTP request
Calls any address: an API, a service desk, a webhook.
| Field | Notes |
|---|---|
| Method | GET, POST, PUT, PATCH, DELETE, HEAD |
| URL | Keep a secret in an environment variable and write {{ NAME }} |
| Query parameters, Headers | Names and values. Header names are suggested as you type |
| Authorization | None · Bearer token · Basic: a user and a password · API key, in a header or the query · OAuth 2.0: client credentials |
| Body | none · form-data · x-www-form-urlencoded · raw (Text, JavaScript, JSON, HTML, XML) · binary · GraphQL |
| Response | Work it out · JSON · Text |
| Fail when the answer is an error | On to start with |
| Keep the item's fields | Add the answer's fields to the item that came in, so what earlier nodes made goes on beside it. Off, only the answer goes on |
The body and Authorization work as Postman's do, in Postman's words, so a request that works there can be copied across. Every method but HEAD can carry a body, GET included. Each body mode keeps its own content when you switch between them, and the two forms share their rows. binary sends a file from the machine Mosaic runs on, so it is a host field. A header typed by hand wins over the same header from Authorization.
For OAuth 2.0, the token is asked for once and kept until it runs out, so a workflow sending a hundred requests asks for one token.
On Mosaic Cloud, a request to an address inside a private network is refused.
#Send an email
To, Cc, Subject and Message, every field taking expressions. One message for all the items to start with, or one for each. It needs a mail server: set MOSAIC_SMTP_HOST, with its user and password, where Mosaic runs. Until then the node says it cannot send yet.
#Post to chat
Microsoft Teams, Slack, Discord or any webhook. Webhook URL is the channel's incoming webhook:
It is a password in the shape of an address: keep it in an environment variable and write
{{ NAME }}.
#Search Microsoft 365
Finds the passages in your organisation's SharePoint, OneDrive or Copilot connectors that answer a question. No model answers: it is the text a person would have gone looking for.
| Field | Notes |
|---|---|
| Search for | One sentence, as you would ask a person. 1,500 characters at most. Takes expressions: {{ $json.store }} |
| Look in | SharePoint, OneDrive, or Copilot connectors |
| Only where | Optional, in Microsoft's Keyword Query Language: path:"https://contoso.sharepoint.com/sites/IT/", FileType:"pdf". A filter Microsoft cannot read is ignored without a word |
| At most this many documents | 10 to start with, 25 at most |
One item comes out for each document found: title, author, url, text (the passages, most relevant first), relevance from 0 to 1, sensitivity (its label, where it has one) and the query that found it. Nothing found is no items, and a line in the node's console.
It reads as the account the Microsoft 365 Copilot integration is signed in as, and finds only what that account may read.
#Ask Copilot
Asks Microsoft 365 Copilot a question and hands on what it answered.
| Field | Notes |
|---|---|
| Ask | The question. Takes expressions |
| What it should know | Optional. Facts for it to reason over, such as what a check found |
| Files to read | Optional. Addresses of SharePoint or OneDrive files, separated by commas |
| Let it search the web | Off to start with. Off, it answers from your organisation's content and what you gave it |
| At most this many questions | 10 to start with, 50 at most. Each question is a conversation of its own and takes tens of seconds |
Each item comes out with answer, in plain words, and sources: what Copilot cited, each with a name and a url.
What you write in Ask and What it should know is sent to Microsoft. The node needs the Microsoft 365 Copilot integration signed in with the permissions the chat asks for, a Copilot licence on that account, the workspace's AI switch on, and Pro or above.
#Check a port
Whether each item's host answers on a TCP port, as nc -z says it: a connection opened and closed, with no shell, so it works on Windows too. Host is {{ $json.host }} to start with, Port 22, Wait 3 seconds. Each item comes out with status: online, offline, or nohost when it had no host. 32 hosts are tried at once, so four hundred stores take seconds.
#Data
| Node | What it does |
|---|---|
| Edit fields | Adds or changes fields, as text, a number, true or false, JSON, or as it comes. A name with dots, customer.name, sets a field inside another. Other fields: keep them or drop them |
| Filter | Keeps the items that meet the conditions |
| Sort | Orders the items by one or more fields, ascending or descending |
| Limit | Keeps the first or the last few items |
| Remove duplicates | Keeps one item of each that repeats, comparing every field or the ones you name |
| Split out | One item for each entry of a list held in a field, with the other fields dropped or copied onto each |
| Summarize | Count, Count different, Sum, Average, Smallest, Largest, Join as text, First, Last, overall or grouped by fields |
#Conditions
Filter, If and Switch test items with conditions, all of them or any of them, with Ignore upper and lower case as a switch. A condition compares a value, usually an expression, by its type:
| Type | Tests |
|---|---|
| Text | is equal to, is not equal to, is in, is not in, contains, does not contain, starts with, ends with, matches the pattern, does not match the pattern, is empty, is not empty |
| Number | is equal to, is not equal to, is in, is not in, is greater than, is at least, is less than, is at most, is empty, is not empty |
| Date | is equal to, is after, is before, is empty, is not empty |
| True or false | is true, is false, is equal to |
| List | contains, does not contain, has this many entries, has more entries than, has fewer entries than, is empty, is not empty |
| Anything | exists, does not exist, is empty, is not empty, is equal to, is not equal to, is in, is not in |
is in and is not in take a list of values separated by commas: Store type is in Outlet, Concession.
#Flow
| Node | What it does |
|---|---|
| If | Sends each item down true or false |
| Switch | Sends each item down the output its routing rules choose, each rule an output with a name. Items no rule matches go to an Otherwise output or are dropped. Each item goes to the first rule that matches, or, if you ask, to every one that does |
| Merge | Joins two inputs: one after the other, matched on a field, side by side by position, or waiting for both and handing on one. See Joining on a field |
| Loop over items | Hands items on a batch at a time. Wire the last node of the loop back into it, and done carries on once every item has gone round |
| Wait | Pauses, up to an hour |
| Stop and error | Ends the run as failed, with a message |
| No operation | Does nothing: a place to join wires or mark a point |
#Joining on a field
Merge set to Matched on a field is a join. Wire the items to keep into input 1, and the ones to look things up in into input 2.
| Field | Notes |
|---|---|
| Field of input 1, Field of input 2 | The field the two inputs share, as each one names it: a code, a barcode, a document number. Leave the second empty when both call it the same |
| Keep | Only items that match · Every item of input 1 · Everything from either |
| Fields to add from input 2 | Names separated by commas. Empty adds every field input 2 has, its own copy of the matched field among them. Named, they are on every item of input 1, empty where nothing matched |
Every item of input 1 is a left join, and it is how a column is added to a list. To put each article's price beside the lines of a stock count:
- Start with When run by hand.
- From it, Read a file, read as Excel: one item for each line of the count.
- From the trigger again, on a second wire, Run a query: a data source that returns the article code and its price. It runs once, because the trigger hands it one item.
- Merge the two: the file into input 1, the query into input 2, matched on the article code, keeping every item of input 1, adding the price.
- End with Show as a table.
Values are matched as a Check matches keys: as text, without the spaces around them. 40112 and 40112 are one value; ab-1 and AB-1 are two. An empty value matches nothing, not even another empty one. An item that finds two matches comes out twice, once for each.
The node's console says how the join went — 1,370 of the 1,500 items of input 1 found a match in input 2, and 130 did not. A field name that no item has stops the run and lists the names there are, since a join on a field typed wrong would otherwise match nothing and say nothing.
#Files and server
All of these are host nodes. Paths are on the machine Mosaic runs on, read and written with the account Mosaic runs as. A path field has a Browse button over that machine's folders.
| Node | What it does |
|---|---|
| Execute a command | Runs a command line. Shell: the default (cmd on Windows, sh elsewhere), PowerShell, Bash or Command Prompt. A time limit of 60 seconds to start with, and it fails when the exit code is not 0 |
| Run a script | Runs a PowerShell, Bash, Python, JavaScript (Node) or batch script, with arguments and a working folder. A time limit of 120 seconds to start with |
| Code | JavaScript over the items: return a list of objects. Once for all items, or once for each. It sees the items, not Mosaic |
| Write a file | Creates a file, replaces one, adds to the end of one, leaves it as it is, or fails. As text or Base64 |
| Read a file | Reads a file as text, JSON, one item per line, one item per CSV row, or one item per row of an Excel sheet. See Reading an Excel sheet |
| Copy a file, Move or rename a file | To another folder or name, replacing a file already there only if you say so |
| Delete a file | A file, or a folder and everything in it. Fine if it is not there, to start with |
| List a folder | One item for each file, folder or both, by a name pattern like *.csv, in sub-folders too if you ask, older than so many days if you ask |
| Run on another machine | See below |
#Reading an Excel sheet
Read a file with Read it as set to Excel, one item per row reads an .xlsx workbook.
| Field | Notes |
|---|---|
| Sheet | The name on its tab, or its position: 2 is the second sheet. Empty reads the first |
| The first row names the columns | On to start with. Off, the columns are called column1, column2, and the first row is an item like the rest |
Each cell arrives as what it holds. A number is a number, so it can be summed and goes back out to Excel as one. Text is text, so a code Excel kept as text keeps its leading zeros. A date is 2026-11-09, a date and time 2026-11-09T14:30:00. An empty cell is empty, and a row with nothing in it is skipped. A formula gives the value Excel last calculated for it.
The node's console says what it read: Read 1,500 rows of 12 columns from the sheet "Count". A workbook read as text or JSON by mistake is refused, with the setting to change. The older .xls format is not read: save the file as .xlsx first.
Where the file nodes are off, as on Mosaic Cloud, read a spreadsheet through a file data source and Run a query instead.
#Run on another machine
Runs a script on a store's server or a till, copies a folder there, or starts a long job there and follows it, through PowerShell remoting.
| Do | What happens |
|---|---|
| Run a script, and wait | PowerShell, run there as written. The item is $item: $item.host, $item.register. What it returns is result; what it prints is output. An error stops it |
| Copy a folder or a file there | From the machine Mosaic runs on into a folder there. A folder goes in whole; the next time, only what changed is sent. C:\Packs\Store copied into C:\ lands as C:\Store |
| Start a job that carries on by itself | Starts the script there as a task of its own, so a restart of Mosaic or a closed browser does not end it. It runs in the session of whoever is signed in there, or as the machine's own account (SYSTEM) |
| Look in on a job | Reads how a started job is doing. Job is {{ $json.run }}, or latest for the last one started on that machine |
Wait for it to end takes up to 60 minutes. Starting a job with a wait makes the node wait for it and fail if the job fails or stops, with what the job printed. Looking in with a wait carries on until the job has finished, failed or stopped, through a restart of the machine.
What it needs:
- Mosaic running on Windows.
- PowerShell remoting switched on at the other end (
Enable-PSRemoting). Connect over HTTPS uses port 5986. - User: an administrator of that machine. Left empty, Mosaic connects as the account it runs as, and in a domain nothing more is needed.
- Password: only from a secret variable,
{{ NAME }}. A typed password is refused, because it would be saved with the workflow. It is sent to PowerShell on standard input, never on a command line.