Skip to content

Input object

The input object is a property-style shorthand for request body fields. Instead of get('field'), you write input.field. It is automatically available in all expressions and expr blocks. This is a workflow mode concept - it reads the incoming request.

Basic usage

Property access

Access request body fields as properties:

yaml
# resources/example.yaml
after:
  - set('query', input.q)
  - set('userId', input.userId)
  - set('items', input.items)

chat:
  prompt: "User {{ get('userId') }} asked: {{ get('query') }}"

In string interpolation

Use input directly in interpolated strings:

yaml
# resources/example.yaml
chat:
  prompt: "Hello {{ input.name }}, you asked about {{ input.topic }}"

Nested properties

Access nested object properties:

yaml
# resources/example.yaml
after:
  - set('city', input.user.address.city)
  - set('email', input.user.email)

Comparison with unified API

The input object is a convenience wrapper around request body data. Both approaches work:

Input ObjectUnified APIDescription
input.fieldget('field')Request body field
input.user.nameget('user').nameNested property
input.items[0]get('items')[0]Array element

Example:

yaml
# resources/example.yaml -- using input object
after:
  - set('name', input.name)
  - set('email', input.user.email)

# Equivalent using Unified API
after:
  - set('name', get('name'))
  - set('email', get('user').email)

When to use

Use input when:

  • Accessing request body fields frequently
  • Working with nested object structures
  • Writing concise property access code

Use get() when:

  • Need to access query parameters, headers, or other sources
  • Need type hints for disambiguation
  • Want consistency across all data access

Examples

Simple form data

yaml
# resources/create-user.yaml
actionId: createUser
validations:
  required:
    - name
    - email
  rules:
    - field: name
      type: string
    - field: email
      type: string
      pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"

after:
  - set('userName', input.name)
  - set('userEmail', input.email)

sql:
  connectionName: main
  query: |
    INSERT INTO users (name, email) 
    VALUES ($1, $2)
  params:
    - get('userName')
    - get('userEmail')

Nested object access

yaml
# resources/example.yaml
after:
  # Access nested properties
  - set('shippingCity', input.order.shippingAddress.city)
  - set('billingEmail', input.order.billing.email)
  - set('itemCount', len(input.order.items))

chat:
  prompt: |
    Process order with {{ get('itemCount') }} items.
    Shipping to: {{ get('shippingCity') }}

Array processing

yaml
# resources/example.yaml
after:
  - set('items', input.items)
  - set('totalItems', len(get('items')))
  - set('firstItem', get('items')[0])

chat:
  prompt: |
    Process {{ get('totalItems') }} items.
    First item: {{ get('firstItem') }}

Conditional based on input

yaml
# resources/example.yaml
after:
  - set('hasItems', input.items != nil && len(input.items) > 0)
  - set('isPremium', input.user.tier == 'premium')

validations:

  skip:
  - "!get('hasItems')"

chat:
  prompt: |
    {{ get('isPremium') ? 'Premium user' : 'Standard user' }}:
    Process {{ len(input.items) }} items.

Input object vs request body

The input object is the same as request.body:

yaml
# resources/example.yaml
after:
  # These are equivalent:
  - set('name1', input.name)
  - set('name2', request.body.name)
  - set('name3', get('name'))

Limitations

  1. Body data only - input only contains request body data, not query parameters or headers
  2. No type hints - Cannot specify data source like get('key', 'param')
  3. No fallback - Returns nil if property doesn't exist (use default() for fallbacks)

Best practices

  1. Use for body data - Perfect for POST/PUT request bodies
  2. Combine with validation - Validate input structure before using
  3. Use default() for safety - default(input.field, 'fallback')
  4. Prefer get() for flexibility - When you need query params, headers, or type hints

See also

Released under the Apache 2.0 License.