- Documentation
- Workflows
- Build your first workflow
Build your first workflow
A guided walkthrough of building, testing, and publishing a real workflow end to end in the visual editor.
What you will build
You will build a workflow that fires when an order webhook arrives, branches on the order total, and posts a Slack message for high-value orders. Along the way you will connect an app, map data between steps with expressions, test a node against real input, and publish a live version.
This is a teaching walkthrough, not a reference. Each step explains why the editor behaves the way it does, so the next workflow you build comes naturally. By the end you will understand the four moves that every workflow needs: pick a trigger, add nodes, wire data between them, and publish.
A workflow is a graph: one trigger plus the nodes connected after it. The graph lives on a version, and only an active version receives live events. While you edit, you are always working on a draft. Publishing is the moment your draft becomes the live version.
Before you start
You need an existing workflow to open in the editor. From your workspace, go to Workflows and open one (or create one), which lands you on the editor route:
/your-workspace/workflows/<workflowId>/editorThe editor opens against a specific version. A new workflow opens on version 1 in Draft status. The header breadcrumb reads Workflows > your workflow title > Editor.
You do not need to connect Slack in advance. You will connect it from inside the builder when you add the Slack node, which is the only place connections are created.
Add the trigger
Open the Add node panel
Click the Add node button (the plus icon) in the top-left toolbar. A panel titled Add node slides in from the right.
Because your workflow has no trigger yet, the panel only offers triggers. The description reads
Start by choosing a trigger to begin your workflow.and the search box readsSearch triggers.... Every workflow has exactly one trigger, and it has to come first, so the editor will not let you add anything else until one exists.Choose the webhook trigger
Under the System tab, pick the Webhook trigger. A webhook trigger starts a run whenever an external system sends an HTTP request to your workflow.
The trigger drops onto the canvas as the first node. The panel description now changes to
Select a node to add to your workflow.and a Triggers tab appears, because the editor now knows it can offer downstream nodes.
For webhook, RSS, and polling triggers, one incoming request fires one run. If the request body is a top-level array, the platform wraps it as { items: [...] }; a single object passes through unchanged. To process array elements one at a time, you add a Loop node later. This walkthrough uses a single order object, so you read fields directly off $trigger.
Add the branch and Slack nodes
You want two more nodes after the trigger: a Branch that splits on the order total, and a Slack action on the high-value path.
Add a Branch node
Open Add node again, switch to the System tab, and choose Branch (under the
Control Flowcategory). A Branch node routes a run down different paths based on conditions you define. Connect the trigger's output to the Branch node's input by dragging an edge between their handles.The panel only lists system nodes that are fully built. Branch, Switch, Loop, Parallel, Transform, HTTP, Code, Delay, Call Workflow, and the five AI nodes are available. Other entries you may have seen elsewhere are not yet authorable, so they will not appear here.
Add a Slack action
Open Add node once more, switch to the Apps tab, and search for Slack. Pick the action you want, for example sending a channel message. Connect one of the Branch node's condition outputs to the Slack node so Slack only runs when that condition matches.
App actions are provider operations from the integrations catalog. They need a connection before they can run, which you set up next.
Connect Slack
App action nodes need a connection: a stored credential to the third-party app. You create it right here on the node, because the builder is where connections are made and selected. There is no separate connections screen to visit first.
Open the node's auth section
Open the Slack node's panel and find its authentication section. If you have no Slack connection yet, it shows a Connect New Account button.
Run the connect flow
Click Connect New Account. Slack uses OAuth, so you see a
Connect via OAuth 2.0heading and a prompt that you will be redirected to Slack to authorize access. Click Connect Account, which opens a popup window to Slack's consent screen.If nothing happens, your browser blocked the popup. You will see
Please allow popups for this site to complete OAuth authentication. Allow popups for the site and click Connect Account again.Select the connection
After you authorize in Slack, the popup closes and the connection is created. Back on the node, the connection is selected automatically. If you already had a Slack connection, you would instead pick it from a list (the dialog labels these "accounts," though the underlying object is a connection).
A connection is created once and reused everywhere. The same Slack connection can be selected on any node in any workflow in this workspace. Re-running the connect flow for the same Slack account updates the existing connection instead of creating a duplicate. For the full connect flow across OAuth, API-key, and subdomain apps, see Connect an account.
Map data into the branch and the message
Now wire the order data through your nodes. TaskJuice does not use a drag-and-drop mapping table. Instead, each configurable field accepts a JSONata expression, and you reference upstream output through aliases.
The two you need here:
$triggeris the trigger's output payload. For an order object posted to the webhook, the total is$trigger.total.$stepsis the output of every prior node, keyed by node ID, for example$steps.action1.data.id. Each entry exposes.data(the node's output) and.meta(engine metadata).
Configure the branch condition
Open the Branch node. Branch conditions are built with a structured editor, not raw JSONata: each condition has a field (a path), an operator from a fixed list, and a value.
Set the first condition's field to
total, its operator to Greater Than, and its value to100. This routes runs with an order total above 100 down that condition's output path. A Branch needs at least 2 conditions and allows at most 8, so add a second condition (for example,totalLess Than100) or set a default path for everything else.Map the Slack message
Open the Slack node and find the message field. Type
$to open the reference autocomplete dropdown, or use the reference picker popover to browse available references grouped by scope ($trigger,$steps,$input,$meta). Write an expression like:"New high-value order " & $trigger.orderId & " for $" & $trigger.totalThe
&operator concatenates strings in JSONata. An empty expression returns the field's value unchanged, so a field you leave blank is a no-op, not an error.
The reference picker shows real upstream field paths only after you have tested the upstream node,
because it reads those paths from the node's pinned test output. If $trigger's fields do not
appear yet, test the trigger first (next section). Field extraction goes 5 levels deep.
To reshape data more heavily than a single expression allows, add a Transform node, which offers operations like Set, Rename, Merge, Concatenate, and Calculate. For the full alias list and JSONata syntax, see Workflow expressions. For more on mapping fields, see Map data between nodes.
Test a node before you trust it
Each node's panel has a test button (its label is node-specific, for example "Test switch" or "Test loop"). Testing runs the node for real against pinned or typed input. It is not a simulation, so what you see is what the node will actually produce.
Test the trigger
Test the trigger first. A webhook trigger defaults its test input to a stub like
{ data: { test: true, timestamp: "2026-06-02T14:30:00.000Z" } }. Replace that with a realistic order object so downstream expressions have real fields to resolve against:{ "orderId": "ord_8421", "total": 149.99, "customerEmail": "casey@example.com" }When the test succeeds, the trigger's output is pinned. That pinned output is what populates the reference picker for every downstream node, which is why you test the trigger before mapping the Slack message.
Test the Slack node
With the trigger pinned, the test seeds
$stepsfrom upstream nodes and$metafrom accumulated metadata, so your expressions resolve against realistic context. Test the Slack node and confirm the message text reads the way you expect.The test button stays disabled until the node is valid. For example, a Switch node shows the tooltip
Configure a selector and at least one valid case before testing.until you finish configuring it. The result comes back as a success or an error, so a red result means the node would fail at runtime.
Publish the version
Publishing compiles your draft, validates it, and makes it the live version. Click Publish (the rocket icon) in the header. The button shows Publishing... while it works, and the Publish button only appears for draft versions.
When validation passes and no evaluation suites are configured, the version activates immediately and you see the toast Workflow published successfully. Your workflow's status flips to Published and this version becomes Active. Only the Active version receives live events.
Once a version is Active, editing its graph does not change the running version. The editor
forks your change into a new Draft version labelled "Draft from v1" and leaves the live version
dispatching untouched. Publishing that draft is what atomically swaps which version is live.
In-flight runs finish on the version they started on. This is why you can safely edit a workflow
that is already handling traffic.
Verify it worked
- The header shows the version status badge as
Activeand your workflow status asPublished. - The Run button (the play icon) becomes enabled. It is disabled unless the current version is
Active, so an enabled Run button confirms a live version. - Send a test request to the webhook with an order total above 100, then open the workflow's runs to confirm a run started and the Slack message posted.
What could go wrong
Publishing runs a full validation pass first. If anything is wrong, you get a failure toast titled Failed to publish workflow with the specific problem, and nothing goes live. The most common blockers on a first build:
| Symptom | Cause | Fix |
|---|---|---|
| "Workflow must include at least one trigger node" | You deleted or never added the trigger. | Add a trigger as the first node. |
| "Action node authentication not hooked up." | The Slack node has no connection selected. | Open the node's auth section and connect or select an account. |
| "Action node has an inactive connection" | The selected connection is not active (for example, it needs reauthorization). | Reconnect the account on the node. |
| "Branch node must have at least 2 conditions" | The Branch has only one condition. | Add a second condition or remove the Branch. |
| "...has no connected edge" | A Branch condition or Switch case output is not wired to a node. | Connect every condition output, or remove the unused condition. |
| "Workflow version is currently compiling. Please wait." | You clicked Publish again while a previous publish was still compiling. | Wait for the status to settle, then retry. |
If a referenced Form is still in Draft, publish is blocked with the toast Some referenced forms are not published: publish the form first, then publish the workflow.
Next steps
- Test, validate, and publish a version covers the publish gate and every validation rule in depth.
- Map data between nodes goes deeper on expressions, the reference picker, and the Transform node.
- Connections explains workspace vs account scope and how a connection is reused.