Skip to content

Blocks

A block is the unit you build a flow out of. Each one has one clear job - call an API, ask a yes-or-no question, loop over a list, transform a value. You assemble a flow by placing blocks and wiring them together, and the wiring is rarely a straight line: a flow usually follows a real business process - an approval, an onboarding, an order moving through its steps - and those branch on a decision, loop over a batch, and rejoin. This page is about the pieces themselves - what a block is, what every block has in common, and how one block's result becomes the next block's input.

One block, one job

The discipline that keeps flows readable is that a block does one thing. An HTTP Request makes one web request. A Condition asks one yes-or-no question and forks the flow two ways. A Transform Data reshapes one value into another. As a rule you do not pack fetch, transform, and route into a single block; you place three and connect them, so the flow reads as the sequence of things it does. Two blocks bend this rule by design: a Custom Cloud Code block runs whatever code you write, and an AI Agent runs a model with its own tools - each does many things inside one block, but all toward the single goal you give it. Reach for them when a routine is genuinely one unit, not to collapse a flow that should read as separate steps.

Most blocks are actions - a step that does work, like calling a service. Some are triggers - how a flow reacts to an outside event; most start a run, but a trigger can also sit in the middle of a flow and wait for something to happen - a person approving a step, a reply arriving - before the flow goes on (covered in Triggers). Some are block containers that hold other blocks and run them, like a List Iterator looping a set of steps over every item in a list, or an Actions Group running several actions at once. And some are utilities that shape the flow itself rather than touch your data - a Condition branching the path, a Handle Error catching a failure. Whatever the kind, the rule holds: each block has its one job, and the flow is the arrangement of those jobs.

The block palette and its categories

You add a block from the palette in the Flow Editor and drop it onto the canvas. The palette groups blocks by the kind of work they do, so you find the one you want by what it is for. The blocks built into FlowRunner™ fall into a handful of groups:

Those are only the start. A large library of Extensions - blocks for outside services like Backendless, Airtable, Stripe, Slack, and many more - is there out of the box, with nothing to install. A connected MCP server adds its tools as blocks the same way, under MCP Extensions. And two groups fill in from your own workspace: your flows each appear under Flows as Actions, ready to call as a step from another flow, and assistants you create show up under AI Assistants. So the palette is wide from the start and grows further with everything you build and connect.

The block palette: a search box above the categories - AI, AI Assistants, Subflows, Triggers (showing the External Callback block), Actions, Flows as Actions, and Utils (Condition, Handle Error, List Iterator, Repeat, Return Result, Set Variables) - each block grouped under the kind of work it does.

Every built-in block has a page in the Block Reference, with its full configuration and a worked example. The categories are only a way to find a block; once it is on the canvas, you configure it the same way whichever group it came from.

What every block has in common

Whatever a block does, you select the block and configure it in its panel. Most of that panel is specific to the block - a Condition asks for a value and a comparison, an HTTP Request asks for a URL and a method. But a couple of things recur almost everywhere. You give the block a Name: naming it for what it does ("Look up customer", not the default "HTTP Request") makes the flow readable at a glance. You can leave Notes on it for whoever reads the flow later, which never affect how it runs. And most blocks publish their result under an alias for later blocks to read - the idea the next section is about.

A block selected on the canvas with its configuration panel open: a Transform Data block named "Create Inquiry Object", its block-specific settings above, and the result alias set under Reference Result Data As, with an option to assign the result to a variable as well.

Other shared controls appear where they apply - skipping a block at run time and using a stand-in result in its place, storing its result in a variable, tuning what it writes to the log - and each block's reference page lists exactly which ones it carries.

A block produces a result that later blocks read

This is the idea that makes a flow more than a list of disconnected steps. When a block runs, it produces a result - the data it generated. An HTTP Request produces the response the service sent back, a Transform Data produces the reshaped value, a Condition produces true or false. That result does not vanish when the block finishes. It joins the run's Flow Context - the pool of values any later step can read: every block result so far, the Initial Data the run began with, and the Shared Memory the flow carries across runs. You reach into all of it the same way, through the Expression Editor.

When a later block needs what an earlier one produced, it reads that result by its alias - a short name for the result. By default the alias is the block's name with "Result" on the end - HTTP Request Result, Condition Result - and you can rename it to something clearer. In the Expression Editor you pick the alias, choose the field you want, and it drops in as a reference like HTTP Request Result → title. The full syntax - reaching deeper into objects, indexing lists, combining values - is the subject of Expressions.

So a flow is wired for order, not for data: the wires say what runs after what, while a result stays readable - by its alias - for any later block that needs it, not only the one wired right after. If you would rather hold a value under a name of your own, or keep it past the block that made it, you store it in a variable with Set Variables and read it from there. Either way a later block gets what it needs by name - which is why naming matters: a result read as Look Up Customer Result → email tells you what it is; a default alias does not.

When a block fails

A block can fail - a service is down, a write is rejected, input does not make sense. By default, the first failure ends the run: no later block gets to react. When you want a flow to recover instead of stop, you reach for a Handle Error block. You connect the block that might fail to a Handle Error, and from then on that block has two exits - its normal path when it succeeds, and the Handle Error when it fails. On a failure the flow diverts into the recovery steps you built after the handler rather than stopping.

A flow on the canvas: a "Submit To Internal System" block with two exits - a green success path on to "Inform Stakeholders", and a red error path into a Handle Error and then a "Log Error" step, which rejoins the main path afterward.

The Handle Error catches the error and produces it as its result, the same way any block produces a result, so a recovery step reads what went wrong through the handler's alias - Handle Error Result → message for the reason, Handle Error Result → source for the block that failed. The block itself is covered on its reference page; the patterns you build around it - retry, fall back, notify - are the subject of the Error Handling guide.

Where to go next

  • Expressions - how a block reads another block's result, and the full reference syntax
  • Variables and Data Buckets - storing a result by name with Assign to a Variable, so it outlives the block
  • Triggers - how a flow reacts to outside events, to start or resume a run
  • Flows and Instances - how the blocks you wire become a running instance
  • Block Reference - every block, one page each, with full configuration and a worked example