Skip to main content

Node Inputs

The three current sources of ActionFlow node inputs, Flow input keys, placeholder resolution, required fields, and runtime validation.

Node inputs

Inputs are the values passed to a node function for one execution. A node can receive values saved in its configuration, values mapped from upstream outputs, and values supplied for the current run.

Input data types are catalog and editor metadata. They help configure and select values, but the current runtime does not provide a static type guarantee for every saved edge, object field, webhook body, or API input.

The three input sources

1. Saved node values

The inspector stores values in the node's inputData.inputs. These can be literal configuration or saved expressions such as {{generateTextNodeId.data.text}}.

Examples include a selected model, a prompt string, a number, a channel name, or a named organization connection. Saved values stay with the ActionFlow until a run input or connected mapping overrides them.

2. Connected data mappings

A named data edge reads a source output and assigns it to a target input. The runtime also recognizes a named source path when a field is mapped from an upstream node.

For a target input named prompt, a saved value can be replaced by a defined value from a connected source. A null value is defined and replaces the saved value; an undefined mapping leaves the saved value in place.

An untargeted incoming edge is different: it orders the target and exposes the source result as inputs[sourceNode.id]. It does not populate a named targetHandle input. A targetHandle must be present in the saved edge for the runtime to select that input key.

3. Per-run values and the trigger envelope

The runtime applies per-run values to a copy of the saved graph. Flow input keys use:

{nodeId}_{inputName}

For example:

{
  "generateTextNodeId_prompt": "Summarize this ticket",
  "sendMessageNodeId_recipient": "[email protected]"
}

The key is split at its last underscore, so a node ID or input name can itself contain an underscore. An override is applied only when the prefix matches an existing node ID.

A webhook body is always available as trigger.body. When the parsed body is an object and not an array, the webhook also passes that object as payload.inputs; keys shaped {nodeId}_{inputName} can then override node inputs. Scalar and array bodies do not populate payload.inputs and remain available through trigger.body (as do non-JSON text bodies). The envelope also contains selected headers, query, and method. The REST POST /api/runs request keeps payload.inputs and payload.trigger separate.

Required and optional inputs

Catalog input definitions contain a required flag, a dataType, and other editor metadata. The flag describes the node's configuration contract; it is not a guarantee that a value will have the expected runtime shape.

For a reachable node, validateFlow currently considers a required input satisfied when either:

  • the saved value is present and not null, undefined, or an empty string; or
  • for a handle-backed input, an incoming edge has a targetHandle equal to the input name.

An untargeted default edge does not satisfy a named required input. An empty optional input can be omitted, but its node function decides whether a default exists or whether the value is required for that particular operation.

Some input definitions are shown or hidden based on other saved fields. validateFlow checks the required fields visible for the node's current operation or mode, while the run form collects the required fields that are not already saved on reachable nodes.

Run inputs and validation timing

extractFlowInputs builds the Actionflow Studio run form from reachable required fields that are not already saved. It does not make every field on every node a public input.

The ingress surface matters:

  • Actionflow Studio Manual Try merges the entered values into the node inputs, persists that graph, and then calls POST /api/runs. The REST route validates the persisted saved graph; it does not validate a copied graph for this Actionflow Studio path.
  • Public template Try is a different path. It applies allowlisted values to an execution copy, validates that copy, and enqueues the values as inputs; it does not persist the entered values into the template.
  • POST /api/runs from a backend validates the saved graph before it merges payload.inputs and payload.trigger.
  • A flow webhook validates the saved graph before it merges the request body and trigger envelope.

Therefore, a request value does not bypass a pre-enqueue required-input error caused by a blank saved field or a missing named data edge. Fix and save the graph when the API returns a saved-flow validation error or a webhook returns 422.

Placeholder mappings

The current stored output reference is:

{{nodeId.outputPath}}

Examples include {{startNodeId.body}} and {{generateTextNodeId.data.text}}. The resolver reads the requested dotted path first and then tries the same path under a data wrapper.

Nested values

Use dotted paths for nested objects. Array properties can be read when the path syntax and actual result support it. The editor offers a path chip for object and JSON outputs, but the runtime still reads the actual value.

{{databaseNodeId.data.customer.email}}
{{databaseNodeId.data.rows.0.id}}

The first path must exist in the referenced result. A declared output name or a visible chip is not proof that the nested path exists.

Exact and embedded references

  • A string that is exactly one placeholder preserves the raw referenced value, including an object, array, or buffer.
  • A placeholder embedded in a larger string is converted to text. Objects are JSON-stringified; null and undefined become an empty string.
  • A missing node, an unreachable node, a circular reference, or a missing path resolves to undefined in an exact mapping or an empty string in an embedded mapping.
  • Placeholder resolution is depth-capped. A deeply nested value can remain unresolved even when its node is reachable.

A placeholder is not a passive lookup. Resolving a reachable reference can execute the referenced node before the normal traversal reaches it, including its downstream side effects. Use an explicit execution edge when ordering matters.

Legacy placeholders

Older saved values can use single-brace references such as {generateText.output}. The advanced selector has compatibility logic that resolves the node name or slug and converts a recognized legacy reference to {{nodeId.output}} for storage.

The runtime placeholder resolver itself matches the double-brace form. If a legacy single-brace expression cannot be converted, it is not a supported runtime reference. Open the field in the advanced selector, let it resolve the chip, and save the normalized double-brace value.

Runtime validation

validateFlow is a graph and requirement check. It does not deeply validate every nested value, convert a Number to Text, or prove an Object shape. The node function or external provider performs the final validation for the value it receives.

A node function can:

  • return success: true with a result;
  • return success: false with an error; or
  • throw an exception.

The first two forms are stored as node output. A reported failure normally stops the run unless continueOnError is enabled; a thrown exception stops immediately. See Flow execution model for failure propagation and partial results.

For predictable inputs:

  1. Validate webhook/API payloads in your integration.
  2. Save a value or explicit mapping for every required field.
  3. Use the exact output path returned by the upstream node.
  4. Run the full graph with representative data.
  5. Inspect the target's resolved input before relying on a downstream side effect.

Troubleshooting

SymptomCheck
Required input is missingCheck the saved value and the exact named target handle. A generic execution edge is not enough.
A placeholder becomes emptyCheck node reachability, the output path, the actual result, and whether the reference is still in legacy single-brace form.
An object reaches a scalar fieldInspect the actual value; the catalog badge is not a runtime converter.
A run input is ignoredConfirm the key is {nodeId}_{inputName} and that the prefix exactly matches a saved node ID.
A node fails after a mappingInspect the node function's validation and the provider response, not only the canvas connection.

On this page