Skip to main content
Flows

Flows

A Flow is a directed graph of typed nodes you connect together to orchestrate a task: call an LLM, hit an external API, branch on a condition, loop over a list, or invoke a project Action. Flows are defined declaratively — the same document your Flow Builder canvas edits is what gets executed — so every run is reproducible and versionable.

Overview

A Flow consists of:
  1. Nodes - Typed steps (start, if, llm_call, rest_call, action_call, python, for_each, output, response) that read inputs and produce outputs
  2. Connections - Directed edges wiring one node’s output port to another node’s input port
  3. Parameters - Values passed in at run time (manual trigger or schedule), available to every node

Flow Structure

Flows use a YAML-based document format — the same envelope the Flow Builder posts when you edit on the canvas or switch to the YAML view:

Key Concepts

Nodes

Every node has an id (unique within the flow), a type (which node class runs it), an optional label, and a config bag whose shape is validated against that node type’s schema. See the Node Reference for every type.

Connections and ports

A connection wires one node’s output port to another node’s input port:
Most nodes have a single input (in) and a single output, so from_port/to_port can usually be omitted. Two node types are the exception:
  • if is a branching node — its outputs are the mutually-exclusive ports true/false, and every outgoing connection from it must set from_port.
  • for_each is a container node — it owns a nested body sub-flow (its own nodes/connections) instead of branching, executed once per item.

Data flow between nodes

A node receives its upstream nodes’ outputs as inputs, keyed by input port name, plus the run’s parameters. Most nodes read inputs.get("in") and save_as a named key in their own output — see Templating & Expressions for exactly how each node type consumes them.

Runs

A flow is executed as a run, triggered either manually or on a schedule. Each node execution is tracked as a step with its own status (PENDING -> RUNNING -> SUCCESS/ERROR/SKIPPED). See Triggers & Runs.

Best Practices

  1. One response node per flow - a flow may contain at most one top-level response node; it’s what gets returned to the caller
  2. Name your save_as keys clearly - downstream nodes reference upstream output by the key you chose (e.g. weather, result)
  3. Set from_port on every branch - connections leaving an if node must declare true or false explicitly
  4. Keep loops bounded - for_each enforces a max_iterations cap (default 1000) to guard against runaway iteration
  5. Avoid cycles - a flow must be a DAG; the validator rejects any cycle before a run starts

Next Steps