Skip to main content

Overview

Every Flow has Input and Output nodes that define its interface—what data it accepts and what it returns. These nodes are the contract between your Flow and the outside world.

Input Nodes

The Input node is the entry point for data into your Flow.

Structure

Green node on the left side of the Canvas with:
  • Name: Usually “Input” (can be customized)
  • Schema: Defines expected data structure
  • Output ports: Send data to downstream nodes

Defining the input schema

  1. Select the Input node
  2. Go to Properties → Input/Output
  3. Define fields:
    • Field name
    • Data type
    • Required vs. optional
    • Default value
    • Description
Example schema:
{
  "user_id": {
    "type": "string",
    "required": true,
    "description": "Unique identifier for the user"
  },
  "action_type": {
    "type": "enum",
    "options": ["create", "update", "delete"],
    "required": true,
    "description": "Type of action to perform"
  },
  "data": {
    "type": "object",
    "required": false,
    "description": "Additional data for the action"
  },
  "priority": {
    "type": "enum",
    "options": ["low", "medium", "high"],
    "required": false,
    "default": "medium",
    "description": "Processing priority"
  }
}

Data types

Supported types:
TypeDescriptionExample
stringText"Hello"
numberInteger or float42, 3.14
booleanTrue or falsetrue, false
arrayList of items[1, 2, 3]
objectNested structure{"key": "value"}
enumLimited options"small" from ["small", "medium", "large"]
anyAny typeFlexible but less safe

Required vs. optional fields

Required fields:
  • Must be present in input
  • Execution fails if missing
  • Use for essential data
Optional fields:
  • Can be omitted
  • Can have default values
  • Use for configuration or preferences

Default values

Set defaults for optional fields:
{
  "timeout": {
    "type": "number",
    "required": false,
    "default": 30,
    "description": "Timeout in seconds"
  },
  "retry": {
    "type": "boolean",
    "required": false,
    "default": true,
    "description": "Whether to retry on failure"
  }
}
Benefits:
  • Simpler API for consumers
  • Backward compatibility when adding new fields
  • Clear default behavior

Validation rules

Add validation beyond just types: String validation:
  • Min/max length
  • Regex pattern
  • Format (email, URL, UUID, etc.)
Number validation:
  • Min/max value
  • Integer only
  • Positive only
Array validation:
  • Min/max items
  • Unique items only
  • Item type
Example:
{
  "email": {
    "type": "string",
    "required": true,
    "format": "email",
    "description": "User's email address"
  },
  "age": {
    "type": "number",
    "required": true,
    "min": 0,
    "max": 150,
    "description": "User's age"
  },
  "tags": {
    "type": "array",
    "items": "string",
    "unique": true,
    "max_items": 10,
    "description": "User tags"
  }
}

Multiple Input nodes

Most Flows have one Input node, but you can have multiple for different entry points: Use cases:
  • Different trigger types (webhook, schedule, manual)
  • Different input formats (JSON, form data, file upload)
  • Different access levels (admin vs. user)
Example:
Webhook Input → Validate → Process → Output
Schedule Input ↗              ↓
                         Store → Output

Output Nodes

The Output node is the exit point for data from your Flow.

Structure

Orange node on the right side of the Canvas with:
  • Name: Usually “Output” (can be customized)
  • Schema: Defines returned data structure
  • Input ports: Receive data from upstream nodes

Defining the output schema

  1. Select the Output node
  2. Go to Properties → Input/Output
  3. Define fields (same process as Input)
Example schema:
{
  "status": {
    "type": "enum",
    "options": ["success", "partial", "failed"],
    "required": true,
    "description": "Execution status"
  },
  "result": {
    "type": "object",
    "required": false,
    "description": "Result data if successful"
  },
  "error": {
    "type": "object",
    "required": false,
    "description": "Error details if failed"
  },
  "execution_time_ms": {
    "type": "number",
    "required": true,
    "description": "Time taken in milliseconds"
  }
}

Output mapping

Map internal data to output schema: Scenario:
  • Processing returns { "processed_data": [...], "count": 10 }
  • Output expects { "result": object, "item_count": number }
Mapping:
  1. Click connection to Output node
  2. Properties → Field Mapping
  3. Map:
    • processed_dataresult
    • countitem_count

Multiple Output nodes

Flows can have multiple outputs for different outcomes: Common pattern:
Process → [success] → Success Output
        → [error] → Error Output
Success Output schema:
{
  "status": "success",
  "data": "object",
  "message": "string"
}
Error Output schema:
{
  "status": "error",
  "error_code": "string",
  "error_message": "string",
  "details": "object"
}
Benefits:
  • Type-safe error handling
  • Clear success vs. failure contracts
  • Easier debugging

Partial outputs

Some Flows stream or emit data progressively: Use case: Processing a large list
Input (100 items)

Process (batches of 10)
  ↓ (after each batch)
Partial Output (progress update)
  ↓ (after all batches)
Final Output (complete results)
Configuration:
  • Enable “Allow partial outputs” in Output node settings
  • Define partial output schema
  • Connect processing node to Output with “partial” flag

I/O best practices

Be explicit — Clear schemas prevent integration errors
Validate early — Check input immediately after Input node
Document fields — Descriptions help users understand the API
Version schemas — When changing, maintain backward compatibility
Use specific types — Avoid any unless truly necessary
Provide examples — Sample input/output helps users

Common I/O patterns

Pattern 1: Simple transformation

Input:
{ "text": "string" }
Output:
{ "result": "string" }
Clean, focused interface.

Pattern 2: Batch processing

Input:
{ "items": ["array of objects"] }
Output:
{
  "processed": "number",
  "failed": "number",
  "results": ["array of objects"]
}
Clear accounting of what happened.

Pattern 3: Configuration with data

Input:
{
  "data": "object",
  "config": {
    "format": "enum",
    "validate": "boolean",
    "timeout": "number"
  }
}
Output:
{
  "data": "object",
  "metadata": {
    "processing_time": "number",
    "validation_passed": "boolean"
  }
}
Flexible configuration with results and metadata.

Pattern 4: Status + details

Output:
{
  "status": "enum: ['success', 'failed']",
  "message": "string (human-readable)",
  "data": "object (if success)",
  "error": "object (if failed)"
}
Consistent structure for both outcomes.

Testing I/O

Test Input

  1. Select the Flow (or Input node)
  2. Go to Properties → Execute
  3. Provide test payload matching input schema
  4. Click Execute
  5. View output
Example test payload:
{
  "user_id": "test_123",
  "action_type": "create",
  "data": {
    "name": "Test User",
    "email": "test@example.com"
  },
  "priority": "high"
}

Validate schema

Triform validates input against schema automatically: Valid input: Execution proceeds
Invalid input: Execution fails with validation error
Common validation errors:
  • Missing required field
  • Wrong type (string instead of number)
  • Value out of range
  • Invalid enum value
  • Malformed email/URL

Edge case testing

Test with:
  • Empty input: {} or []
  • Minimal input: Only required fields
  • Maximum input: All optional fields, large values
  • Invalid input: Wrong types, missing fields
  • Boundary values: Min/max numbers, empty strings

Documenting I/O

In Triform

  • Add descriptions to each field
  • Provide examples in the Input/Output panel
  • Use clear, consistent naming

For external users

When exposing as API:
  1. Generate docs from schema (Triform can do this)
  2. Include:
    • Field descriptions
    • Example request/response
    • Error codes and meanings
    • Rate limits and quotas
Example doc:
## POST /v1/process-user

Process user action.

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| user_id | string | Yes | User identifier |
| action_type | enum | Yes | One of: create, update, delete |
| data | object | No | Additional data |
| priority | enum | No | One of: low, medium, high (default: medium) |

### Example Request

\```json
{
  "user_id": "user_123",
  "action_type": "create",
  "data": {"name": "Alice"},
  "priority": "high"
}
\```

### Response

| Field | Type | Description |
|-------|------|-------------|
| status | enum | success, partial, or failed |
| result | object | Result data (if successful) |
| error | object | Error details (if failed) |

### Example Response (Success)

\```json
{
  "status": "success",
  "result": {"id": "new_123"},
  "execution_time_ms": 250
}
\```

Next steps

Continue exploring the documentation to learn about creating and connecting nodes, node interactions, understanding Flows, and building with Triton.
I