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
└─ methodThere 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 ticket2. 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 textThis 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_criteriaType: What data type
Text, Number, Boolean, Array, Object, Enum, Date, FileRequired Status: Must be provided?
prompt (required) → Must be connected or hardcoded
thread_id (optional) → Can be omittedExample:
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:
| Situation | Use | Example |
|---|---|---|
| Data changes per execution | Trigger or Previous Node | Email body, form input, API data |
| Fixed configuration | Hardcoded | Model name, channel name |
| User customization | Trigger Parameter | Topic, tone, length |
| Processing previous output | Previous Node Output | AI 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 promptPros: 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 outputPros: 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 runOptional 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 errorInput 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 nodeMissing Required Input
Slack requires: message (Text)
Current state: Not connected, not hardcoded
Error: Required input "message" not provided
Solution: Connect to output OR hardcode valueObject Structure Mismatch
Node expects: {name: Text, age: Number}
You provide: {name: Text} (missing age)
Error: Required field "age" missing
Solution: Provide complete object structureValue 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 2Input Best Practices
1. Minimize Required Inputs
✓ Good: Only truly necessary fields required
✗ Bad: 10 required inputs (hard to use)
Too many required = friction2. Use Semantic Names
✓ Good: customer_email, generated_title, approval_status
✗ Bad: data1, param, x, output3. Provide Sensible Defaults
✓ Good:
├─ model defaults to "claude-3.5-sonnet"
├─ temperature defaults to 0.7
✗ Bad:
├─ model required every time
├─ temperature required every time4. 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 confidentInput 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 outputsPattern 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.003Every 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 syntaxInput 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 executionsCache When Possible
If same input used multiple places:
├─ Store in Database
├─ Pass ID to downstream nodes
└─ Avoid passing large data repeatedlyInput vs Output vs Handle
| Concept | Meaning | Example |
|---|---|---|
| Input | Data entering the node | Prompt, message, ID |
| Output | Data leaving the node | Generated text, result |
| Handle | Connection 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.