Concept

Execution model

How the engine owns a run end to end, how single activities can be routed to remote workers, and how feedback reaches Studio.

Flow Current 3 min read Updated

The engine owns the workflow#

The whole workflow definition is handed to one Kiwi Flow engine instance, which executes it in-process, end to end. There is no "host worker" that a run itself is dispatched to. Loading the workflow, running activities, resolving inputs, mapping outputs, error handling, branching and emitting feedback are all the engine's job, and the engine works standalone, without any other Kiwify Labs product.

What can be distributed#

Individual activities can be. An activity that needs a particular machine (a Windows desktop with a thick-client application, a host with browsers, a specific network zone) calls Kiwi Distro for that single step:

  1. The activity resolves its own inputs and calls the Kiwi Distro middleware through its client SDK, authenticating with OAuth2 client credentials.
  2. The middleware routes the call to any capable worker. Kiwi Flow never learns which node ran it; a dedicated server, a container or a laptop all look the same.
  3. The worker executes and returns its output. Only the activity's resolved inputs are sent, never the whole workflow.
  4. The engine resumes with the next activity.

Adding capacity for specialist work means adding workers to Kiwi Distro; nothing changes in Kiwi Flow. See Run scripts and remote work with Kiwi Distro.

Activities are plugins#

Each activity type is a self-registering class that declares its inputs, outputs and valid operations. The same definitions drive the engine, the Studio property panel and the AI generator's catalogue, so they cannot drift apart. Activity libraries (cloud, databases, messaging, caches, email providers, Kiwi Fabric and Kiwi Distro connectors) are loaded as external plugins.

Scripts#

js_script runs a sandboxed JavaScript snippet. Inputs are injected as variables and results are written to an output object. Each script has a timeout and memory limit. Conditions on if_else and expressions in input mappings use the same sandboxed engine.

Execution feedback#

The engine emits an event for every activity, including remote ones:

json
{
  "runId": "run_abc123",
  "activityId": "a3",
  "activityName": "Enter Order in SAP",
  "status": "success",
  "output": { },
  "error": null,
  "branchTaken": null,
  "durationMs": 1240,
  "timestamp": "2026-04-28T10:05:00Z"
}

For flow-control activities, branchTaken carries the branch id so Studio can highlight the path that was followed. Events reach Studio in real time through a SignalR hub, and the full per-activity detail is kept in run history.

State and resilience#

Execution state is persisted. Network interruptions do not lose a run, and waits (delay, approval, external_task) can last hours or days.

Guards#

Run-level guards bound a run's resources: a run timeout, a maximum output size per activity, a maximum number of concurrent runs and a REST rate limit. Loops are bounded by maxLoopIterations. See Administration and access control.