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.
# 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:
| Field | Logic | Behavior when condition triggers |
|---|---|---|
methods / routes | match | skip silently if no match |
headers / params | match | skip silently if no match |
skip | OR -- any true | skip silently |
check | AND -- all must be true | return error to caller |
Skip Conditions
Skip conditions allow you to conditionally skip resource execution based on runtime values.
Basic Usage
# 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
# 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') == nullPreflight Checks
Preflight checks validate inputs before resource execution begins. If any condition fails, execution is aborted with a custom error.
Basic Usage
# 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
# 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:
{
"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
# 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
# resources/example.yaml
validations:
methods: [GET] # only GET
methods: [GET, POST] # GET and POST
# omit to allow all methodsRoute Restrictions
# resources/example.yaml
validations:
routes: [/api/v1/users] # single route
routes: [/api/v1/users, /api/v1/profiles] # multiple routes
# omit to allow all routesCombined Example
# 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
# 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)
# 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: 1rules (array format)
# 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: 1fields (alternative map format)
# resources/example.yaml
validations:
required: [email, name]
fields:
email:
type: string
name:
type: string
minLength: 1Validation Rules Reference
| Rule | Type | Description |
|---|---|---|
required | array | List of required fields |
properties / fields / rules | object/array | Field-specific validation rules |
type | string | string, number, integer, boolean, object, array, email, url, uuid, date |
minLength | number | Minimum string length |
maxLength | number | Maximum string length |
minimum / min | number | Minimum numeric value |
maximum / max | number | Maximum numeric value |
enum | array | Allowed values |
pattern | string | Regex pattern (for strings) |
minItems | number | Minimum array items |
maxItems | number | Maximum array items |
message | string | Custom error message for this field |
Custom Expression Rules
# 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
# 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
# resources/example.yaml
validations:
params:
- q
- userId
- action
chat:
prompt: "{{ get('q') }}"Parameters not in this list are inaccessible via get().
Combined Example
# 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 ResourceSee Also
- Validation Examples - Best practices and examples
- Expressions - Expression syntax for conditions
- Resources Overview - Resource structure
- Unified API - Using
get()in validations - Workflow Configuration — Route configuration
