Skip to content

Validation and Control Flow

The validations: block controls whether a resource runs and what it accepts. It fires before the action -- before any LLM call, HTTP request, or script execution.

yaml
# resources/example.yaml
validations:
  methods: [POST]          # skip unless method matches
  routes: [/api/v1/data]  # skip unless route matches
  headers: [Authorization] # skip unless header present
  params: [q]              # skip unless param present
  skip:
    - get('mode') == 'dry-run'  # skip silently (no error)
  check:
    - get('q') != ''            # fail with error below if false
  error:
    code: 400
    message: "q is required"

Fields summary:

FieldLogicBehavior when condition triggers
methods / routesmatchskip silently if no match
headers / paramsmatchskip silently if no match
skipOR -- any trueskip silently
checkAND -- all must be truereturn error to caller

Skip Conditions

Skip conditions allow you to conditionally skip resource execution based on runtime values.

Basic Usage

yaml
# resources/conditional-resource.yaml
actionId: conditionalResource
name: Conditional Resource
validations:
  skip:
    - get('skip') == true
    - get('mode') == 'dry-run'
chat:
  prompt: "{{ get('q') }}"

How It Works

Any true condition skips the resource silently -- it produces no output but its slot in the dependency graph still exists so downstream resources can reference it. Use get() to access any data source in skip conditions.

Common Patterns

yaml
# resources/example.yaml
validations:
  skip:
    # Skip if flag is set
    - get('skip') == true
    # Skip if no query parameter
    - get('q') == '' || get('q') == null
    # Skip based on item value (in items iteration)
    - get('current') == 'skip_this'
    # Skip if previous resource failed
    - get('previousResource') == null

Preflight Checks

Preflight checks validate inputs before resource execution begins. If any condition fails, execution is aborted with a custom error.

Basic Usage

yaml
# resources/validated-resource.yaml
actionId: validatedResource
name: Validated Resource
validations:
  check:
    - get('q') != ''
    - get('userId') != null
    - len(get('q')) > 3
  error:
    code: 400
    message: Query parameter 'q' is required and must be at least 3 characters
chat:
  prompt: "{{ get('q') }}"

How It Works

All check conditions must pass (AND logic). If any one fails, execution stops immediately and the configured error is returned to the caller -- no LLM call, no HTTP request, no work done.

Check Expressions

yaml
# resources/example.yaml
validations:
  check:
    - get('q') != ''
    - get('userId') != null
    - type(get('age')) == 'int' || type(get('age')) == 'float'
    - get('age') >= 18
    - len(get('email')) > 5
    - get('email') contains '@'
    - get('status') == 'active' || get('status') == 'pending'
    - get('previousResource') != null
  error:
    code: 400
    message: "Validation failed"

Error Response

When a check validation fails:

json
{
  "success": false,
  "error": {
    "code": 400,
    "message": "Query parameter 'q' is required and must be at least 3 characters"
  }
}

Route and Method Restrictions

Limit which HTTP requests can trigger a resource.

Basic Usage

yaml
# resources/api-resource.yaml
actionId: apiResource
name: API Resource
validations:
  methods: [GET, POST]
  routes: [/api/v1/data, /api/v1/query]
chat:
  prompt: "{{ get('q') }}"

How It Works

  • Resource only executes if both conditions match
  • If restrictions don't match, resource is skipped silently
  • Empty arrays mean "allow all"

Method Restrictions

yaml
# resources/example.yaml
validations:
  methods: [GET]         # only GET
  methods: [GET, POST]   # GET and POST
  # omit to allow all methods

Route Restrictions

yaml
# resources/example.yaml
validations:
  routes: [/api/v1/users]                   # single route
  routes: [/api/v1/users, /api/v1/profiles] # multiple routes
  # omit to allow all routes

Combined Example

yaml
# resources/example.yaml
validations:
  methods: [POST]
  routes:
    - /api/v1/create
    - /api/v1/update
chat:
  prompt: "Create: {{ get('data') }}"

Input Validation

Validate the structure and content of request data using required, rules, and expr.

Basic Usage

yaml
# resources/validated-input.yaml
actionId: validatedInput
name: Validated Input
validations:
  required:
    - userId
    - action
  properties:
    userId:
      type: string
      minLength: 1
    action:
      type: string
      enum: [create, update, delete]
    age:
      type: number
      minimum: 18
      maximum: 120
chat:
  prompt: "{{ get('action') }} user {{ get('userId') }}"

Validation Syntax

KDeps supports multiple syntaxes for field validation:

properties (map format)

yaml
# resources/example.yaml
validations:
  required: [email, name]
  properties:
    email:
      type: string
      pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
    name:
      type: string
      minLength: 1

rules (array format)

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

fields (alternative map format)

yaml
# resources/example.yaml
validations:
  required: [email, name]
  fields:
    email:
      type: string
    name:
      type: string
      minLength: 1

Validation Rules Reference

RuleTypeDescription
requiredarrayList of required fields
properties / fields / rulesobject/arrayField-specific validation rules
typestringstring, number, integer, boolean, object, array, email, url, uuid, date
minLengthnumberMinimum string length
maxLengthnumberMaximum string length
minimum / minnumberMinimum numeric value
maximum / maxnumberMaximum numeric value
enumarrayAllowed values
patternstringRegex pattern (for strings)
minItemsnumberMinimum array items
maxItemsnumberMaximum array items
messagestringCustom error message for this field

Custom Expression Rules

yaml
# resources/example.yaml
validations:
  required: [email, password, confirmPassword]
  properties:
    email:
      type: string
      pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
    password:
      type: string
      minLength: 8
    confirmPassword:
      type: string
  expr:
    - "get('password') == get('confirmPassword')"
    - "get('email') contains '@'"
chat:
  prompt: "Process user: {{ get('email') }}"

Allowed Headers and Parameters

Restrict which headers and query parameters are allowed in requests.

Allowed Headers

yaml
# resources/example.yaml
validations:
  headers:
    - Authorization
    - Content-Type
    - X-API-Key
chat:
  prompt: "{{ get('q') }}"

Headers not in this list are inaccessible via get().

Allowed Parameters

yaml
# resources/example.yaml
validations:
  params:
    - q
    - userId
    - action
chat:
  prompt: "{{ get('q') }}"

Parameters not in this list are inaccessible via get().

Combined Example

yaml
# resources/example.yaml
validations:
  methods: [POST]
  routes: [/api/v1/secure]
  headers:
    - Authorization
    - Content-Type
  params:
    - action
chat:
  prompt: "Secure action: {{ get('action') }}"

Execution Order

Request
  ↓ methods / routes     → skip if no match
  ↓ headers / params     → filter inaccessible keys
  ↓ skip conditions      → skip if any true
  ↓ check + error        → abort with error if any false
  ↓ required/rules/expr  → abort with 422 if invalid
  ↓ Execute Resource

See Also

Released under the Apache 2.0 License.