> ## Documentation Index
> Fetch the complete documentation index at: https://microstrate-1133-notifications-prefs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Functions

> Access platform services and data transformation utilities

# Functions Step

The Functions step provides access to QuivaWorks platform services (streams, storage) and data transformation utilities (encoding, merging, templating). Use Functions to interact with real-time streams, persist data, and transform formats.

<Info>
  **Platform Integration**: Functions connect your flows to QuivaWorks' infrastructure for real-time streaming, persistent storage, and data transformation.
</Info>

***

## How Functions Work

Functions take input, execute an operation (platform service or transformation), and return the result:

<CodeGroup>
  ```text Stream Publishing theme={null}
  Agent: Generates event data
  ↓
  Functions: Publish to stream
    Function: publish-message-to-stream
    Stream: "user-events"
    Message: ${agent.output}
  ↓
  Event published to real-time stream
  ```

  ```text Data Storage theme={null}
  Form: User preferences
  ↓
  Functions: Store in KV bucket
    Function: put-kv-item
    Bucket: "user-prefs"
    Key: ${user.id}
    Value: ${form.data}
  ↓
  Data persisted
  ```

  ```text Data Transformation theme={null}
  HTTP Request: Returns base64 data
  ↓
  Functions: Decode
    Function: base64-decode
    Input: ${http.body.encoded}
  ↓
  Decoded data
  ```
</CodeGroup>

***

## When to Use Functions

| Use Functions When                       | Use Alternative When                 |
| ---------------------------------------- | ------------------------------------ |
| Need real-time streaming                 | Batch processing (use HTTP/database) |
| Persist configuration/state              | Temporary data in flow               |
| Store files/media                        | External storage service preferred   |
| Transform data formats (JSON/XML/Base64) | Complex custom logic (use Eval)      |
| Merge complex data structures            | Simple field extraction (use Map)    |

**Examples**:

**Use Functions**: Publish events to stream for real-time analytics\
**Use HTTP instead**: Send to external webhook (when external service required)

**Use Functions**: Store user preferences in KV storage\
**Pass in flow**: Temporary data that doesn't need persistence

**Use Functions**: Decode Base64 encoded data\
**Use Eval instead**: Complex custom encoding algorithm (when custom logic needed)

***

## Function Categories

QuivaWorks provides functions across multiple categories:

<CardGroup cols={2}>
  <Card title="Stream Functions" icon="stream" href="/flows/functions/streams">
    Real-time data streaming
  </Card>

  <Card title="Key-Value Storage" icon="database" href="/flows/functions/key-value">
    Fast KV storage operations
  </Card>

  <Card title="Object Storage" icon="box" href="/flows/functions/object-storage">
    Large file/object storage
  </Card>

  <Card title="Data Transformation Utilities" icon="shuffle" href="/flows/functions/utility">
    Transform, encode, and manipulate data
  </Card>
</CardGroup>

***

## Configuration

### Function Selection

<ParamField path="function" type="string" required>
  Which function to execute

  **Examples**:

  ```
  publish-message-to-stream
  put-kv-item
  base64-encode
  deep-merge-objects
  ```
</ParamField>

### Function Inputs

<ParamField path="inputs" type="object" required>
  Input parameters for the function

  Can reference previous steps:

  ```json theme={null}
  {
    "text": "${trigger.body.message}",
    "maxLength": 100
  }
  ```

  Each function has specific input requirements (see function documentation)
</ParamField>

***

## Quick Examples by Category

### Stream Functions

<CodeGroup>
  ```json Publish Event theme={null}
  {
    "function": "publish-message-to-stream",
    "inputs": {
      "stream": "user-events",
      "message": {
        "event": "purchase",
        "user_id": "${customer.id}",
        "amount": "${order.total}",
        "timestamp": "${now}"
      }
    }
  }
  ```

  ```json Get Stream Item theme={null}
  {
    "function": "get-item-from-stream",
    "inputs": {
      "stream": "user-events",
      "key": "${event.id}"
    }
  }
  ```

  ```json Search Stream theme={null}
  {
    "function": "search-stream-items",
    "inputs": {
      "stream": "user-events",
      "key": "user_${customer.id}",
      "timestamp": "${start_time}"
    }
  }
  ```
</CodeGroup>

### Key-Value Storage

<CodeGroup>
  ```json Store Configuration theme={null}
  {
    "function": "put-kv-item",
    "inputs": {
      "bucket": "app-config",
      "key": "feature-flags",
      "value": {
        "new_ui": true,
        "beta_features": false
      }
    }
  }
  ```

  ```json Retrieve Setting theme={null}
  {
    "function": "get-kv-bucket-item",
    "inputs": {
      "bucket": "app-config",
      "key": "feature-flags"
    }
  }
  ```

  ```json List Buckets theme={null}
  {
    "function": "list-key-value-buckets"
  }
  ```
</CodeGroup>

### Object Storage

<CodeGroup>
  ```json Store File theme={null}
  {
    "function": "put-object-by-key",
    "inputs": {
      "bucket": "user-uploads",
      "key": "documents/${user.id}/${filename}",
      "object": "${file_data}"
    }
  }
  ```

  ```json Retrieve File theme={null}
  {
    "function": "get-object-from-bucket",
    "inputs": {
      "bucket": "user-uploads",
      "key": "documents/${user.id}/${filename}"
    }
  }
  ```

  ```json List Files theme={null}
  {
    "function": "list-object-keys",
    "inputs": {
      "bucket": "user-uploads",
      "prefix": "documents/${user.id}/"
    }
  }
  ```
</CodeGroup>

### Data Transformation Utilities

<CodeGroup>
  ```json Base64 Encode theme={null}
  {
    "function": "base64-encode",
    "inputs": "${data}"
  }
  ```

  ```json Base64 Decode theme={null}
  {
    "function": "base64-decode",
    "inputs": "${http.body.data}"
  }
  ```

  ```json JSON to XML theme={null}
  {
    "function": "json-xml",
    "inputs": {
      "json": "${data}",
      "options": {
        "compact": true,
        "spaces": 2
      }
    }
  }
  ```

  ```json XML to JSON theme={null}
  {
    "function": "xml-json",
    "inputs": {
      "xml": "${http.response}",
      "options": {
        "compact": true,
        "trim": true
      }
    }
  }
  ```

  ```json Handlebars Template theme={null}
  {
    "function": "handlebars",
    "inputs": {
      "template": "Hello {{name}}, your order #{{order_id}} total is ${{total}}",
      "variables": {
        "name": "${customer.name}",
        "order_id": "${order.id}",
        "total": "${order.total}"
      }
    }
  }
  ```

  ```json Deep Merge Objects theme={null}
  {
    "function": "deep-merge-objects",
    "inputs": {
      "objects": [
        "${user_profile}",
        "${preferences}",
        "${settings}"
      ]
    }
  }
  ```

  ```json Group By theme={null}
  {
    "function": "group-by",
    "inputs": {
      "array": "${orders}",
      "property": "status"
    }
  }
  ```

  ```json JSON Path Mapping theme={null}
  {
    "function": "mapping",
    "inputs": {
      "data": "${complex_object}",
      "path": {
        "userName": "$.user.name",
        "userEmail": "$.user.email"
      }
    }
  }
  ```

  ```json Set Operations theme={null}
  {
    "function": "set-operations",
    "inputs": {
      "a": "${list1}",
      "b": "${list2}",
      "operation": "union"
    }
  }
  ```

  ```json Get Secret theme={null}
  {
    "function": "secret-key-get-node",
    "inputs": {
      "key": "stripe_api_key"
    }
  }
  ```

  ```json Invoke Function theme={null}
  {
    "function": "function-invoke",
    "inputs": {
      "invocation_type": "RequestResponse",
      "payload": {
        "data": "${data_to_process}"
      },
      "subject": "data-processor-function"
    }
  }
  ```

  ```json Upload via SFTP theme={null}
  {
    "function": "sftp",
    "inputs": {
      "host": "sftp.example.com",
      "port": 22,
      "username": "user",
      "password": "${secret.sftp_password}",
      "fileContents": "${report_data}",
      "filePath": "/reports/daily-report.pdf"
    }
  }
  ```
</CodeGroup>

***

## Complete Function Documentation

For detailed documentation of all available functions with syntax, parameters, and examples:

<CardGroup cols={2}>
  <Card title="Functions Overview" icon="book" href="/flows/functions/overview">
    Complete list of all available functions
  </Card>

  <Card title="Stream Functions" icon="stream" href="/flows/functions/streams">
    Real-time streaming operations
  </Card>

  <Card title="Key-Value Storage" icon="database" href="/flows/functions/key-value">
    KV bucket storage operations
  </Card>

  <Card title="Object Storage" icon="box" href="/flows/functions/object-storage">
    Object storage operations
  </Card>

  <Card title="Data Transformation Utilities" icon="shuffle" href="/flows/functions/utility">
    Encoding, merging, templating, and utilities
  </Card>
</CardGroup>

***

## Common Flow Patterns

<AccordionGroup>
  <Accordion title="Event Tracking Pipeline" icon="stream">
    Track user events in real-time stream

    ```text theme={null}
    Trigger: User action
    ↓
    Agent: Enrich event data
    ↓
    Functions: Publish to stream
      Function: publish-message-to-stream
      Stream: "user-events"
      Message: ${agent.output}
    ↓
    Functions: Store in KV for quick access
      Function: put-kv-item
      Bucket: "recent-events"
      Key: ${user.id}
      Value: ${agent.output}
    ```

    **Use when**: Need real-time event processing and analytics
  </Accordion>

  <Accordion title="Configuration Management" icon="gear">
    Store and retrieve app configuration

    ```text theme={null}
    Trigger: Config update request
    ↓
    Functions: Save configuration
      Function: put-kv-item
      Bucket: "app-config"
      Key: ${config.key}
      Value: ${config.value}
    ↓
    (Later) Flow needs config
    ↓
    Functions: Retrieve configuration
      Function: get-kv-bucket-item
      Bucket: "app-config"
      Key: "feature-flags"
    ↓
    Agent: Use configuration
    ```

    **Use when**: Need persistent configuration across flows
  </Accordion>

  <Accordion title="File Upload & Storage" icon="upload">
    Handle file uploads with object storage

    ```text theme={null}
    Form: File upload
    ↓
    Functions: Encode file
      Function: base64-encode
      Input: ${form.file}
    ↓
    Functions: Store file
      Function: put-object-by-key
      Bucket: "uploads"
      Key: "files/${user.id}/${filename}"
      Object: ${encoded_file}
    ↓
    Agent: Send confirmation with file URL
    ```

    **Use when**: Need to store files/media
  </Accordion>

  <Accordion title="Data Format Conversion" icon="arrows-rotate">
    Convert between data formats

    ```text theme={null}
    HTTP Request: Receives JSON data
    ↓
    Functions: Convert to XML
      Function: json-xml
      JSON: ${http.body}
      Options: {compact: true}
    ↓
    Functions: Encode for transmission
      Function: base64-encode
      Input: ${xml_data}
    ↓
    HTTP Request: Send to legacy system
    ```

    **Use when**: Integrating systems with different formats
  </Accordion>

  <Accordion title="Complex Data Merging" icon="code-merge">
    Merge data from multiple sources

    ```text theme={null}
    HTTP Request 1: Get user profile
    ↓
    HTTP Request 2: Get preferences  
    ↓
    Functions: Get cached data
      Function: get-kv-bucket-item
      Bucket: "user-cache"
      Key: ${user.id}
    ↓
    Functions: Deep merge all data
      Function: deep-merge-objects
      Objects: [${profile}, ${preferences}, ${cached}]
    ↓
    Agent: Use complete user data
    ```

    **Use when**: Need to combine nested data structures
  </Accordion>

  <Accordion title="Dynamic Template Rendering" icon="wand-magic-sparkles">
    Generate dynamic content from templates

    ```text theme={null}
    Agent: Prepare email data
    ↓
    Functions: Render template
      Function: handlebars
      Template: "Hello {{name}}, your order {{order_id}}..."
      Variables: ${agent.output}
    ↓
    HTTP Request: Send email via SendGrid
    ```

    **Use when**: Need dynamic content generation
  </Accordion>

  <Accordion title="Data Organization & Grouping" icon="table">
    Organize data for analysis

    ```text theme={null}
    Database: Get all orders
    ↓
    Functions: Group by customer
      Function: group-by
      Array: ${orders}
      Property: "customer_id"
    ↓
    Map: Calculate per-customer totals
    ↓
    Functions: Store aggregated data
      Function: put-kv-item
      Bucket: "analytics"
      Key: "customer-totals"
    ```

    **Use when**: Need to organize data by property
  </Accordion>

  <Accordion title="Stream Analytics" icon="chart-line">
    Aggregate and analyze stream data

    ```text theme={null}
    Trigger: Schedule (hourly)
    ↓
    Functions: Aggregate stream items
      Function: aggregate-stream-items
      Stream: "user-events"
      Key: "event_type"
      TimeWindow: "1h"
    ↓
    Agent: Generate insights report
    ↓
    Functions: Store insights
      Function: put-kv-item
      Bucket: "analytics"
      Key: "hourly-summary-${timestamp}"
    ```

    **Use when**: Need to analyze streaming data
  </Accordion>

  <Accordion title="SFTP File Delivery" icon="server">
    Upload files to partner SFTP servers

    ```text theme={null}
    Agent: Generate report
    ↓
    Functions: Get SFTP credentials
      Function: secret-key-get-node
      Key: "partner_sftp_password"
    ↓
    Functions: Upload via SFTP
      Function: sftp
      Host: "partner.sftp.com"
      FileContents: ${report_data}
      FilePath: "/incoming/daily-report.pdf"
      Password: ${secret.value}
    ↓
    HTTP Request: Notify partner of upload
    ```

    **Use when**: Need to deliver files to partners/systems via SFTP
  </Accordion>

  <Accordion title="Function Orchestration" icon="diagram-project">
    Chain multiple functions together

    ```text theme={null}
    Trigger: Receive webhook
    ↓
    Functions: Invoke validation function
      Function: function-invoke
      Type: RequestResponse
      Subject: "webhook-validator"
      Payload: ${webhook.data}
    ↓
    Functions: Invoke processor if valid
      Function: function-invoke
      Type: Async
      Subject: "data-processor"
      Payload: ${validated_data}
    ↓
    Response: Return success
    ```

    **Use when**: Need modular function composition
  </Accordion>

  <Accordion title="SOAP API Integration" icon="cloud">
    Work with XML-based SOAP APIs

    ```text theme={null}
    Agent: Build request data (JSON)
    ↓
    Functions: Convert to XML
      Function: json-xml
      JSON: ${agent.output}
      Options: {compact: true}
    ↓
    HTTP Request: Call SOAP API
      Body: ${xml_request}
    ↓
    Functions: Parse XML response
      Function: xml-json
      XML: ${http.response}
      Options: {compact: true, trim: true}
    ↓
    Agent: Process JSON data
    ```

    **Use when**: Integrating with SOAP/XML services
  </Accordion>
</AccordionGroup>

***

## Best Practices

<CardGroup cols={2}>
  <Card title="Use Platform Functions" icon="thumbs-up">
    Use QuivaWorks' platform functions for streams and storage rather than external services when possible.
  </Card>

  <Card title="Persist Important Data" icon="database">
    Use KV or Object storage for data that needs to persist across flow executions.
  </Card>

  <Card title="Stream Real-Time Events" icon="stream">
    Use streams for event tracking, analytics, and real-time processing.
  </Card>

  <Card title="Transform Before Agent" icon="arrows-rotate">
    Clean and transform data with Functions before passing to agents.
  </Card>

  <Card title="Name Steps Clearly" icon="tag">
    Use descriptive names: "Store User Preferences" not "Function 1"
  </Card>

  <Card title="Handle Errors" icon="shield-check">
    Check function results and handle errors appropriately.
  </Card>

  <Card title="Use Secrets for Credentials" icon="key">
    Always use secret-key-get-node for passwords, API keys, and sensitive data.
  </Card>

  <Card title="Modular Architecture" icon="boxes-stacked">
    Use function-invoke to break complex logic into reusable functions.
  </Card>
</CardGroup>

***

## Functions vs. Alternatives

**Use Functions when**:

* Need QuivaWorks platform services (streams, storage)
* Need data transformation (encoding, merging, templates)
* Want built-in, tested operations
* Need to persist data across flows
* Need to orchestrate multiple functions
* Need to upload files via SFTP

**Use Map when**:

* Need to transform data structure
* Extracting/restructuring objects
* Functions don't fit your use case

**Use Eval when**:

* Need custom algorithms
* Complex logic not available
* Combining multiple operations uniquely

**Use External Services when**:

* Specialized service required (e.g., Twilio for SMS)
* Already using external provider
* Need features not in QuivaWorks

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Function not found" icon="magnifying-glass">
    **Causes**:

    * Wrong function name
    * Typo in function name

    **Solutions**:

    * Check function documentation for exact name
    * Verify function exists: `publish-message-to-stream` not `publish-to-stream`
    * Note: Some functions renamed (e.g., `JSON-XML` → `json-xml`)
  </Accordion>

  <Accordion title="Invalid parameters" icon="circle-exclamation">
    **Causes**:

    * Missing required parameter
    * Wrong parameter format
    * Wrong parameter name

    **Solutions**:

    * Review function documentation for exact parameter names
    * Note parameter changes: `data` → `variables` (handlebars), `key_name` → `key` (secrets)
    * Check that base64 functions take direct input, not wrapped in object
    * Verify variable references
  </Accordion>

  <Accordion title="Stream/bucket not found" icon="database">
    **Causes**:

    * Stream or bucket doesn't exist
    * Wrong name

    **Solutions**:

    * Create stream/bucket first
    * Verify exact name
    * Check account has access
  </Accordion>

  <Accordion title="Can't access output" icon="link-slash">
    **Causes**:

    * Wrong variable path
    * Function didn't execute

    **Solutions**:

    * Use `${step_name.result}`
    * For base64-decode with JSON, result is auto-parsed
    * For secret-key-get-node, check `${step_name.value}` or `${step_name.error}`
    * Check execution logs
    * Verify step name matches
  </Accordion>

  <Accordion title="SFTP connection timeout" icon="clock">
    **Causes**:

    * Wrong host or port
    * Network issues
    * Server not responding

    **Solutions**:

    * Verify host and port are correct
    * Check network connectivity
    * Increase connectionTimeout if server is slow
    * Verify credentials are correct
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Explore All Functions" icon="book" href="/flows/functions/overview">
    Browse complete function library
  </Card>

  <Card title="Map Step" icon="arrow-right-arrow-left" href="/flows/steps/map">
    Custom data transformations
  </Card>

  <Card title="Eval Step" icon="code" href="/flows/steps/eval">
    Custom JavaScript for complex logic
  </Card>

  <Card title="HTTP Request" icon="globe" href="/flows/steps/http-request">
    Call external APIs
  </Card>
</CardGroup>
