> For the complete documentation index, see [llms.txt](https://docs.appfarm.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.appfarm.io/library/action-nodes/run-flow.md).

# Run flow

The Run Flow action node calls a [flow](/reference/flows.md) from within an [app](/reference/apps.md) action or from another [flow](/reference/flows.md).

## Usage

This action node is useful in the following cases:

* When integration logic or business logic should be shared across apps in a solution. The logic can be maintained in a flow and called from any app using Run Flow.
* When a flow needs to call another flow, for example, to chain an authentication step before a data retrieval step.
* When structured data needs to be passed to server-side logic without first persisting it. Because action params support [schemas](/reference/platform-concepts/schemas.md), the caller can pass complex data directly.

{% hint style="info" %}
**Good to know**

If the called Flow action has **No concurrency** enabled and is already running, the call fails instead of starting a new run. See [Concurrency](/reference/flows.md#concurrency).
{% endhint %}

{% hint style="info" %}
**Good to know**

Run Flow in an app or in another flow can't run a Flow action that has **Private Action** selected. The call fails with `AuthorizationError` (status `403`). To run a private action, use [Run Action](/library/action-nodes/run-action.md) inside the same flow. See [Actions](/reference/actions.md#properties).
{% endhint %}

## Input mapping

When a flow and flow action are selected, the flow action's [action params](/reference/actions/action-params.md) are displayed on the action node. Each param is bound to a value from the calling context, e.g., a data source, an app variable, an action variable, or a function result. Params marked as required must have a value bound; optional params can be left unbound, in which case the action uses the param's default value.

If an action param has a schema as its data type, click the three-dot menu on the param to open the data binding popover and select **Add schema**. This lets you bind data from the calling context directly to the individual properties of the action param's schema.

## Return data mapping

When the flow action completes, any [action variables](/reference/actions/action-variables.md) and [action data sources](/reference/actions/action-data-sources.md) that are marked as returned from the action are available for mapping back into the calling context. The return mapping determines where the output data lands and how it is applied.

Each returned item is mapped to a target in the calling context — either an app data source, an action data source, an app variable, or an action variable. The target must match the returned data: a returned data source must be mapped to a data source backed by the same object class, a returned action variable must be mapped to a variable of the same data type, and if the data type is a schema, the schemas must have a matching structure.

The mapping mode controls how the returned data is applied to the target:

* **Replace** replaces the contents of the target data source with the returned data.
* **Add to Data Source (merge duplicates)** appends the returned data to the existing contents of the target data source and merges any duplicates. This mode is only available when the target is a data source with cardinality many.

If the returned data contains runtime properties that do not exist on the target, those properties are silently dropped.

### Streaming returned outputs

When a returned action variable or action data source on the called action is marked **Streamable**, writes to it during the action's run are delivered to the caller's mapping as they occur, instead of only when the action completes. This is useful for long-running actions that produce results incrementally and a caller that wants to display partial results — for example, populating a list in an app as the called action appends to it.

Streaming only applies when Run Flow runs directly in an app action. When Run Flow is used inside another flow, streamable outputs are mapped once, when the called flow finishes, and Create shows a warning on the node.

Streamed updates use the same return mapping that applies at end-of-run: the target, mapping mode, and matching rules from Return mapping all apply unchanged. Only outputs marked **Streamable** stream; non-streamable returned outputs are delivered once, when the called action completes.

End-of-run is authoritative. When the called action completes, the final state of each returned output is applied through the same mapping. Any writes that arrive after the action has completed are ignored.

Streamed updates are batched, so the caller's UI sees coherent snapshots rather than a flicker from each individual write.

If the called action fails partway through, any partial writes that streamed to the caller are reverted. A failed Run Flow writes nothing, the same as when no outputs are streamable.

## Passing file objects

A flow action can accept [file objects](/reference/data-model/object-classes.md#file-object-class) as input and return them as output, the same way it handles other objects. A flow can receive an uploaded document, generate a file on the server and return it, or move files between apps in a solution.

When Run Flow is used in an app action, a file object passed into the flow or returned to the app must be persisted first. The call from an app to a flow is a network request, which carries a reference to a stored file but not a file's unsaved contents. A file object that has not been persisted, one still held in a runtime-only data source, cannot cross this boundary and produces an error that tells you to persist the file first. Add a [Persist objects](/library/action-nodes/persist-objects.md) action node before the file crosses the boundary.

{% hint style="info" %}
**Good to know**

A persisted file object passes at any size, because it crosses as a URL reference to the stored file rather than as the file itself.

When a flow calls another flow, this requirement does not apply. Both flows run on the server, and file objects are passed by reference whether or not they have been persisted.
{% endhint %}

## Asynchronous execution

When **Run async** is set, the calling action does not wait for the flow to finish before continuing. The flow runs to completion server-side, detached from the caller, bounded by **Timeout**.

**Return Data Mapping** and action variable mapping are hidden when **Run async** is set, because no result is sent back to the caller. Errors in the asynchronous flow do not propagate to the caller, so check the flow's run logs for the outcome.

**Timeout** sets how long the asynchronous run may take, in seconds. It is only available when **Run async** is set. It must be a whole number from 1 to 14,400 (4 hours). The default is 300 seconds (5 minutes). When the timeout is reached, the action node that is running in the called flow is stopped with a Flow timeout exception (Appfarm error code `17035`). A [Catch Exception](/library/action-nodes/catch-exception.md) node in the called flow can handle it, for example to record that the run did not finish. The Catch Exception gets 60 seconds to finish before the run is stopped. The caller is not notified. Create shows a warning if an Agent node in the called flow has a longer timeout than the run.

Asynchronous Run Flow calls can be nested at most 10 levels deep, for example when a flow starts itself asynchronously. A call beyond that fails with error `17019`. If too many asynchronous flow runs are already in progress, the call fails with error `17023` and the flow is not started.

{% hint style="info" %}
**Good to know**

Data persisted by the called flow is not automatically synced back to database-connected data sources in the caller. The caller continues without waiting, so any changes the flow makes to the database are not reflected in the caller's data sources until those data sources are refetched.
{% endhint %}

## Stop a running Flow

In an app action, Run Flow can store an ID for the run in **Run ID**. Bind it to a String property, for example an app variable. The ID is stored before the Flow starts, so another action can use it while the Flow is still running.

To stop the run, add a [Manage Flow](/library/action-nodes/manage-flow.md) action node to another action, set **Operation** to `Stop`, and bind its **Run ID** to the stored ID. **Result** stores the outcome:

* `stopped`: the stop reached the run.
* `not_running`: the run had already ended.

Only the user who started the run can stop it. Stopping a run also stops the Flows it started with **Run async**.

A stopped run fails with error `17036`. To handle it in the calling action, add a [Catch Exception](/library/action-nodes/catch-exception.md) node with **Defined Errors** and `17036` in **Appfarm Error Codes**. A Run ID can only be used by one run at a time; reusing it while the run is active fails with error `17037`.

**Run ID** is only shown when Run Flow is used in an app.

## Run as a service account

By default, a flow called by Run Flow runs as the calling user. Setting **Run as** runs the flow under the selected service account instead.

Two conditions must be met:

* The calling user must have permission to act as the selected service account. This is configured under [Accounts and roles](/reference/security/permissions.md#accounts-roles) in Permissions.
* The selected service account must have sufficient permissions to run the flow and to access and manipulate the data the flow touches.

## Properties

| Property                | Description                                                                                                                                                                                                                                                                                                |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Flow**                | Select the flow to call.                                                                                                                                                                                                                                                                                   |
| **Flow Action**         | Select the action from the selected flow to run. MCP tools and API Endpoint actions can't be selected.                                                                                                                                                                                                     |
| **Action Params Input** | *Displayed if the selected flow action has action params.* Bind values from the calling context to each of the flow action's input params.                                                                                                                                                                 |
| **Return Data Mapping** | *Displayed if the selected flow action returns action variables or action data sources.* *Hidden if **Run async** is set.* Map each returned item to a target in the calling context and select the mapping mode.                                                                                          |
| **Run as**              | Optionally select a service account to run the flow on behalf of the calling user.                                                                                                                                                                                                                         |
| **Run async**           | Run the flow without waiting for it to finish. The calling action continues immediately. When set, **Return Data Mapping** is hidden.                                                                                                                                                                      |
| **Timeout**             | *Displayed if **Run async** is set.* How long the asynchronous run may take, in seconds: a whole number from 1 to 14,400 (4 hours). Default is 300. Can be data-bound. When it is reached, the running node is stopped with a Flow timeout exception that a Catch Exception in the called flow can handle. |
| **Run ID**              | *Apps only.* Bind a String property to store an ID for the run before the Flow starts. Pass it to **Manage Flow** to stop the run. See [Stop a running Flow](#stop-a-running-flow).                                                                                                                        |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.appfarm.io/library/action-nodes/run-flow.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
