Skip to main content

Node Inputs

Learn how node inputs work in ActionFlows (static values, expressions, and data mapped from upstream nodes) to pass data through your flows.

Inputs

Data Flowing Into Nodes

Inputs are the parameters and data that nodes accept. Every node declares what it needs, when it's required, and what type it expects.


What Are Inputs

An input is a data entry point on a node (left side). Data enters through inputs via three channels.


Three Sources of Input Data

1. Trigger Data

Initial data that starts the run.

Start node + Flow inputs:
└─ {nodeId}_{inputName} keys for empty required fields

Flow webhook / API trigger payload on the start node:
├─ body
├─ headers
├─ query
└─ method

There is no Email Trigger node. Inbound mail must POST a flow webhook or you paste text into Flow inputs.

Trigger data flows to downstream nodes as connected inputs.

Example:

Helpdesk POSTs a flow webhook

Start node exposes body

Generate Text prompt mapped from body.text

AI classifies the ticket

2. Previous Node Output

Output from one node becomes input to the next.

Generate Text outputs: text (Text)

Slack input: message (connected to Generate Text.text)

Slack sends the generated text

This is data flow through the workflow.

Rules:

  • Types must match (Text to Text, Number to Number, and so on)
  • Incompatible connections disabled
  • One output can feed multiple inputs
  • Explicit mapping (you choose what connects where)

3. User Configuration

Static values you hardcode on the node.

Generate Text node:
├─ model: "claude-3.5-sonnet" (hardcoded, never changes)
├─ temperature: 0.7 (hardcoded)
└─ max_tokens: 1000 (hardcoded)

These stay constant across all executions.

When to use:

  • Settings that don't change
  • Model selection
  • API configuration
  • Default values

Input Declaration

Every input is declared with:

Name: What it represents

prompt, channel, message, customer_id, filter_criteria

Type: What data type

Text, Number, Boolean, Array, Object, Enum, Date, File

Required Status: Must be provided?

prompt (required) → Must be connected or hardcoded
thread_id (optional) → Can be omitted

Example:

Generate Text declares:
├─ prompt (required, Text)
├─ model (optional, Enum, default: "claude-3.5-sonnet")
├─ temperature (optional, Number, default: 0.7)
└─ max_tokens (optional, Number, default: 1000)

Input Sources: Decision Matrix

When to use which source:

SituationUseExample
Data changes per executionTrigger or Previous NodeEmail body, form input, API data
Fixed configurationHardcodedModel name, channel name
User customizationTrigger ParameterTopic, tone, length
Processing previous outputPrevious Node OutputAI result to Slack, DB query to filter

Three Ways to Provide Input

Approach 1: Connect to Node Output

Most dynamic. Data flows automatically.

Start (webhook body or Flow inputs)
  ↓ (connection or mapping)
Generate Text (input: prompt)

The ticket text becomes the prompt

Pros: Dynamic, automatic, responsive

Cons: Requires source node to exist

Approach 2: Hardcode Value

Enter static value directly.

Slack node:
├─ channel: "#announcements" (typed directly)
├─ message: Connected to AI output

Pros: Simple, clear, stable

Cons: Same value every time, hard to maintain

Approach 3: Mix Both

Connected for dynamic data, hardcoded for config.

Generate Text:
├─ prompt: mapped from start / webhook body (dynamic)
├─ model: Hardcoded "claude-3.5-sonnet" (stable)
└─ temperature: Hardcoded 0.7 (stable)

Pros: Best of both, flexible, controlled

Cons: More complexity


Input Types and Validation

Primitive Types

Text: "hello", "[email protected]"
Number: 42, 3.14, -100
Boolean: true, false
Date: 2025-10-28, 2025-10-28T15:30:00Z
Array: [1, 2, 3], ["a", "b", "c"]
Enum: "pending" | "approved" | "rejected"
File: {name: "doc.pdf", content: [...], type: "application/pdf"}

Complex Types

Object: {name: "John", age: 30, email: "john@..."}
Array<Object>: [{id: 1, name: "Item1"}, {id: 2, name: "Item2"}]
Array<Text>: ["email1@...", "email2@..."]

Type Safety

Generate Text expects: prompt (Text)
You provide: 42 (Number)

Error: Type mismatch
Cannot connect Number to Text

Platform prevents incorrect connections at design time.

// IMG: Type matching validation on canvas


Required vs Optional Inputs

Required Input

Must be provided. Missing = error.

Slack node:
├─ channel (required) → Must connect or hardcode
├─ message (required) → Must connect or hardcode

If either missing → Linting error → Can't run

Optional Input

Can be omitted. Has default behavior.

Generate Text:
├─ model (optional) → Defaults to "claude-3.5-sonnet"
├─ temperature (optional) → Defaults to 0.7
└─ max_tokens (optional) → Defaults to 2000

If omitted → Uses defaults → No error

Input Variables and References

Reference inputs from other nodes by dropping an output chip. Stored form: {{nodeId.outputName}}.

Simple reference

Prompt: Analyze: {{startNodeId.body}}

Nested Object Reference

Database returns: {
  customer: {
    name: "John",
    email: "[email protected]"
  }
}

Email prompt: "Send to {databaseRead.customer.email}"

Array Item Reference

Loop outputs: item (current iteration)

Action: "Process {loopNode.item.id}"

Platform auto-completes. Type-safe.

// IMG: Auto-complete suggestions for variable references


Input Validation and Errors

Type Mismatch

Generate Text expects: prompt (Text)
You connect: Array output

Error: Cannot connect Array to Text input
Solution: Extract single Text value or use different node

Missing Required Input

Slack requires: message (Text)
Current state: Not connected, not hardcoded

Error: Required input "message" not provided
Solution: Connect to output OR hardcode value

Object Structure Mismatch

Node expects: {name: Text, age: Number}
You provide: {name: Text} (missing age)

Error: Required field "age" missing
Solution: Provide complete object structure

Value Out of Range

Node expects: temperature (Number, 0-2)
You set: 5

Error: Value 5 exceeds maximum of 2
Solution: Use value between 0 and 2

Input Best Practices

1. Minimize Required Inputs

✓ Good: Only truly necessary fields required
✗ Bad: 10 required inputs (hard to use)

Too many required = friction

2. Use Semantic Names

✓ Good: customer_email, generated_title, approval_status
✗ Bad: data1, param, x, output

3. Provide Sensible Defaults

✓ Good:
├─ model defaults to "claude-3.5-sonnet"
├─ temperature defaults to 0.7

✗ Bad:
├─ model required every time
├─ temperature required every time

4. Use Enums for Fixed Choices

✓ Good:
status: "pending" | "approved" | "rejected"
(dropdown selection)

✗ Bad:
status: Text (user types, typos possible)

5. Document Complex Inputs

Generate Report requires:
├─ filters (Object)
   {
     "date_range": {"start": "YYYY-MM-DD", "end": "YYYY-MM-DD"},
     "categories": ["sales", "marketing", "support"],
     "min_amount": 1000
   }

6. Test inputs in Actionflow Studio

Before deploying, verify inputs work with realistic data:

1. Hardcode sample values
2. Run in Actionflow Studio
3. Check output
4. Deploy confident

Input Patterns

Pattern 1: Parameterized Flow

Users customize execution.

Flow inputs / mapped prompt fields define:
├─ topic (Text)
├─ tone (text)
└─ length (Number)

Generate Text uses:
"Write {tone} {length}-word article on {topic}"

User runs:
├─ Run 1: AI="AI", tone="formal", length=500
├─ Run 2: AI="Marketing", tone="casual", length=1000

Different inputs → Different outputs

Pattern 2: Configuration Input

Static settings define behavior.

Database Write:
├─ table: "users" (hardcoded)
├─ operation: "create" (hardcoded)

Config once, process many.

Pattern 3: Conditional Input

Input determines flow path.

If node evaluates: {generateText.classification} == "urgent"
├─ true → escalate
└─ false → standard

Same input data, different routing.

Debugging Inputs

Inspect in Run History

Click node in execution history

Inputs received:
├─ prompt: "Summarize this..."
├─ model: "claude-3.5-sonnet"
├─ temperature: 0.7
└─ max_tokens: 1000

Duration: 1,240ms
Cost: $0.003

Every execution logged. Full visibility.

Common Issues

"Required input not provided"

Solution: Connect to output OR hardcode value

"Type mismatch"

Solution: Ensure output type matches input type
Use Transform node if needed to convert

"Variable reference not found"

Solution: Check node name and output name
Use auto-complete to verify syntax

Input Performance

Minimize Data Size

✓ Efficient: Pass ID → Look up details downstream
✗ Inefficient: Pass entire 100-field object (need 5 fields)

Batch Processing

✓ For 100 items: 1 execution (Array input with 100 items)
✗ For 100 items: 100 separate executions

One execution >> 100 executions

Cache When Possible

If same input used multiple places:
├─ Store in Database
├─ Pass ID to downstream nodes
└─ Avoid passing large data repeatedly

Input vs Output vs Handle

ConceptMeaningExample
InputData entering the nodePrompt, message, ID
OutputData leaving the nodeGenerated text, result
HandleConnection point (input or output)The dot/circle on canvas

Input = specific instance of a handle carrying data.


Comparison: Input Handling

n8n

  • Loose typing, minimal validation
  • Errors at runtime
  • More flexible, less safe

Gumloop

  • Text-focused (LLM chains)
  • Limited input types
  • Simple, narrow scope

ActionFlows

  • Strict typing, design-time validation
  • Errors caught before execution
  • Type-safe and flexible

Next Steps

Handles: Connection mechanics and outputs

Node Anatomy: How a node is structured

Actionflow Studio: Wire inputs on the canvas and run the flow

Node Catalog: See all node inputs

Use typed inputs to keep data flow valid.

On this page