Build a flow once and call it from other flows, like a function: Flow input takes the arguments, Return gives back the result, and Run flow calls it. Run flow can also call one of this flow's own canvases (Canvas · in its list).
The three nodes
| Node | Type | Role |
|---|---|---|
| Flow input | flow/input | Starts a callable flow. Its output is what the caller sent, or its sample when you run the flow directly. |
| Return | flow/return | Ends the callable flow and hands output back to the caller. A flow can have several (e.g. "Return product" and "Nothing found"). |
| Run flow | flow/run | Calls a flow and waits for its Return. Leaves through next with the returned value, or through error with { "error": "<message>" } when the called flow fails. |
Make a flow callable
- Start it with a Flow input node and give it a
sample, e.g.{ "keyword": "tumbler stainless 1 liter" }. The sample's keys become the inputs callers fill in. - End each path with a Return node, e.g.
{ "link": "{{ nodes.affiliate.output.link }}" }. - In Settings, turn on Other flows can call it (
caller: "self"; only your own flows can call it).
Call it
Add Run flow, pick the flow, fill one value per input key (the input field lists the called flow's sample keys; it falls back to a JSON box when there is no sample):
{
"id": "finder",
"type": "flow/run",
"name": "Find on Shopee",
"field": {
"flowId": "6ae08f2f…",
"input": { "keyword": "{{ nodes.loop.output.item.keyword }}" },
"cache": 360
}
}
Read the result as {{ nodes.finder.output.link }}.
Reuse results (cache)
cache is in minutes (0 = off). Before calling (and before waiting in the called flow's browser queue), the node asks mooflair for a result of the same flow, the same input and the same campaign within that time (POST /api/run/cache); on a hit it uses it and logs Used the cached result of <flow>. Real runs store successful results (PUT /api/run/cache); test runs only read, because their Return may hold simulated values.
Which version is called
A called flow runs its published version when it has one, otherwise its draft. Publish the called flow after changing it. Calls nest up to 5 levels; a loop (A calls B calls A) is refused: flows can't call each other in a loop (or deeper than 5).
Where a called flow runs
A called flow is walked inside the caller's run, in the caller's browsers: its nodes act in the browser named by their browser setting (𝕏 nodes x, Shopee nodes shopee), exactly like the caller's own. So Shopee Product Finder, called from an 𝕏 flow, signs in and searches in the campaign's shopee browser, and the 𝕏 nodes keep using x. Browser names belong to the campaign (or the flow in tests), so a called flow using x uses the caller's x.
- Its logs belong to the run, nested under the Run flow node by flow name (
Shopee Product Finder › …); its waits for a human show in the run too. - The run's cursor follows the node into whichever browser it acts in, so the follows it.
- A called flow needs its own Sign in node for the browser it uses, as the caller needs one for its own.
- AI usage counts in the run.
Error flows
In a flow's Settings › Error flow, pick a callable flow. When a run fails, the error flow runs inline with:
{
"flow": { "id": "6ae1933938a65c8f9374bfe0", "name": "𝕏 Auto Reply" },
"run": { "id": "6ae19596c810b38d560717b2", "dry": false },
"error": "Collect posts failed: Timed out after 600000ms"
}
Use it to notify you, clean up or record the failure. Its own outcome doesn't change the failed run's status.
Convert to flow
Turn a piece of a flow into its own callable flow: select the nodes (or right-click one) › Convert to flow, name it, Convert.
- The nodes move into a new flow that starts with Flow input and ends with Return; a Run flow node takes their place.
- Values the nodes read from earlier nodes become Flow input keys, and the Run flow node passes them in.
- Values later nodes read from the moved nodes come back through Return, and their expressions are rewritten to
{{ nodes.<run flow id>.output.<key> }}.
Rules: no triggers in the selection, one way in (every connection from outside lands on the same node) and at most one way out.
FAQ
Can a called flow call another flow?
Yes. Each level follows the same inline-or-own-browser rule.
Why does my Run flow node only show a JSON box for input?
The called flow's Flow input has no sample. Add one with the keys you expect.
Does an error flow need Other flows can call it?
It needs a Flow input to receive the failure; turn on Other flows can call it so it can be picked.