Skip to main content

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>/editor

The 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

  1. 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 reads Search 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.

  2. 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.

One webhook POST becomes one run

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.

  1. Add a Branch node

    Open Add node again, switch to the System tab, and choose Branch (under the Control Flow category). 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.

  2. 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.

  1. 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.

  2. Run the connect flow

    Click Connect New Account. Slack uses OAuth, so you see a Connect via OAuth 2.0 heading 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.

  3. 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:

  • $trigger is the trigger's output payload. For an order object posted to the webhook, the total is $trigger.total.
  • $steps is 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).
  1. 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 to 100. 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, total Less Than 100) or set a default path for everything else.

  2. 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.total

    The & 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 needs a test run first

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.

  1. 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.

  2. Test the Slack node

    With the trigger pinned, the test seeds $steps from upstream nodes and $meta from 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.

Editing a live version creates a new draft

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 Active and your workflow status as Published.
  • 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:

SymptomCauseFix
"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

Was this helpful?