CSL Syntax Reference
Complete reference for CDL (Cascade Definition Language) syntax
Every CDL file must conform to this specification. This page documents every keyword, option, and allowed value.
CDL File Structure
Minimal Application
apiVersion: cascade.io/v1
kind: Application
metadata:
name: my-app
namespace: default
spec:
workflows:
- name: MyWorkflow
start: StartState
states:
- name: StartState
type: Task
end: trueTop-Level Sections
| Section | Type | Required | Purpose |
|---|---|---|---|
apiVersion | string | ✓ | Always cascade.io/v1 |
kind | string | ✓ | Always Application |
metadata | object | ✓ | Name, namespace, labels |
spec | object | ✓ | App configuration |
Metadata Section
metadata:
name: my-app # App name (required)
namespace: default # Namespace (default: default)
labels:
team: engineering
version: "1.0"
annotations:
description: "My application"| Field | Type | Required | Notes |
|---|---|---|---|
name | string | ✓ | Alphanumeric, dash, underscore |
namespace | string | Default: default | |
labels | map | Arbitrary key-value pairs | |
annotations | map | Arbitrary key-value pairs |
Workflows Section
spec:
workflows:
- name: ProcessOrder # Workflow name (required)
description: "Handle order" # Optional description
start: ValidateOrder # First state (required)
timeout: 24h # Max workflow duration
states:
- ...| Field | Type | Required | Notes |
|---|---|---|---|
name | string | ✓ | Workflow identifier |
description | string | Documentation | |
start | string | ✓ | Name of first state |
timeout | duration | Format: 30s, 5m, 24h |
State Types Reference
Task State (Activity Execution)
- name: ValidateOrder
type: Task
description: "Validate order details"
resource: urn:cascade:activity:validate_order
parameters:
order_id: "{{ workflow.input.order_id }}"
strict: true
result: $.validation
resultPath: $.validation_result # Alternative to result
timeout: 30s
retries:
max_attempts: 3
backoff:
initial_interval: 1s
max_interval: 60s
multiplier: 2.0
next: ProcessPayment
end: false| Field | Type | Required | Notes |
|---|---|---|---|
resource | string | ✓ | URN pointing to activity |
parameters | map | Input to activity | |
result | string | JSONPath to store result (e.g., $.order) | |
resultPath | string | Alternative to result | |
timeout | duration | Activity must complete within time | |
retries | object | Retry configuration | |
next | string | Next state name | |
end | boolean | If true, workflow ends here |
Task Execution Flow:
- Deserialize parameters from context
- Call activity
- Handle result/error
- Store result in context
- Proceed to next state
Choice State (Branching)
- name: RouteLoan
type: Choice
choices:
- condition: "{{ $.credit_score >= 750 }}"
next: FastTrack
description: "Excellent credit"
- condition: "{{ $.amount <= 5000 }}"
next: AutoApprove
description: "Small amount"
default: ManagerReview| Field | Type | Required | Notes |
|---|---|---|---|
choices | array | ✓ | List of conditions & paths |
choices[].condition | string | ✓ | Boolean expression |
choices[].next | string | ✓ | Target state |
choices[].description | string | Documentation | |
default | string | ✓ | Fallback state |
Evaluation:
- Conditions evaluated top-to-bottom
- First match wins
- If no matches, use
default
HumanTask State (Manual Approval)
- name: ManagerApproval
type: HumanTask
description: "Loan requires manager approval"
ui:
schema: urn:cascade:schema:approval_form
target: appsmith # appsmith, rjsf, echarts, tanstack
pre_populate:
application_id: "{{ $.app_id }}"
assignee:
role: loan_manager # Role or user_id
tags:
department: "{{ $.dept }}"
timeout: 24h
timeoutAction: ESCALATE_TO_DIRECTOR
next: ProcessDecision| Field | Type | Required | Notes |
|---|---|---|---|
ui | object | ✓ | UI rendering config |
ui.schema | string | ✓ | URN to JSON schema |
ui.target | string | ✓ | UI framework |
ui.pre_populate | map | Context variables to inject | |
assignee | object | Who performs task | |
assignee.role | string | Role name | |
assignee.user_id | string | Specific user | |
assignee.tags | map | Filter users | |
timeout | duration | ✓ | How long to wait |
timeoutAction | string | ESCALATE_*, CANCEL, AUTO_APPROVE |
Parallel State (Multi-Branch)
- name: VerifyApplicant
type: Parallel
branches:
- name: VerifyIdentity
type: Task
resource: urn:cascade:activity:verify_identity
parameters:
document_id: "{{ $.doc_id }}"
result: $.identity
- name: CheckCredit
type: Task
resource: urn:cascade:activity:check_credit
parameters:
ssn: "{{ $.ssn }}"
result: $.credit
completion_strategy: ALL
next: CombineResults| Field | Type | Required | Notes |
|---|---|---|---|
branches | array | ✓ | List of states to run in parallel |
completion_strategy | string | ALL (default), ANY, N_OF_M | |
n | integer | If strategy is N_OF_M |
Wait State (Delay)
- name: CooldownPeriod
type: Wait
duration: 1h # Wait 1 hour
next: RetryPayment
# Or wait until specific time
- name: WaitUntilNextDay
type: Wait
until: "{{ now | addDate 1 day | startOfDay }}"
next: ResumeProcess| Field | Type | Required | Notes |
|---|---|---|---|
duration | duration | Wait X seconds/minutes/hours | |
until | string | Wait until this time | |
Use either duration or until |
Receive State (Event Waiting)
- name: AwaitPayment
type: Receive
event_name: payment_confirmed
timeout: 5m
timeoutAction: RETRY
next: ProcessConfirmation| Field | Type | Required | Notes |
|---|---|---|---|
event_name | string | ✓ | Event to wait for |
timeout | duration | Max wait time | |
timeoutAction | string | On timeout: retry, skip, escalate |
EvaluatePolicy State (Business Rules)
- name: CheckPolicy
type: EvaluatePolicy
resource: urn:cascade:policy:loan_approval
parameters:
credit_score: "{{ $.credit_score }}"
amount: "{{ $.amount }}"
result: $.policy_result
next: ApplyDecision| Field | Type | Required | Notes |
|---|---|---|---|
resource | string | ✓ | URN to policy |
parameters | map | Policy inputs | |
result | string | Store result at path |
Retry Configuration
retries:
max_attempts: 3
backoff:
initial_interval: 1s
max_interval: 60s
multiplier: 2.0| Field | Type | Notes |
|---|---|---|
max_attempts | integer | How many times to try |
initial_interval | duration | Starting delay |
max_interval | duration | Max delay cap |
multiplier | float | Exponential backoff factor |
Retry Timeline (example above):
- Attempt 1: 0s
- Attempt 2: after 1s
- Attempt 3: after 2s
- Attempt 4: after 4s
Parameters & Templating
Parameter Resolution
Parameters support template expressions:
parameters:
# Direct context reference
order_id: "{{ $.order_id }}"
# Nested path
customer_email: "{{ $.customer.email }}"
# Array index
first_item: "{{ $.items[0].sku }}"
# Default value
department: "{{ $.dept | default: 'sales' }}"
# Function
tomorrow: "{{ now | addDate 1 day }}"
# Literal values
amount: 100
enabled: true
items:
- id: 1
name: "item1"Available Functions
| Function | Usage | Notes |
|---|---|---|
default | {{ value | default: 'fallback' }} | Use fallback if null |
addDate | {{ now | addDate 1 day }} | Add duration to date |
startOfDay | {{ now | startOfDay }} | Get start of day |
format | {{ date | format 'YYYY-MM-DD' }} | Format date |
upper | {{ text | upper }} | Uppercase string |
lower | {{ text | lower }} | Lowercase string |
Result Path Syntax
Results stored using JSONPath expressions:
result: $.field_name # Top level
result: $.nested.path.value # Nested
result: $.array[0].item # Array element
result: $.array.item # All array itemsExamples:
# Store at top level
- result: $.payment
# Accessible as: $.payment
# Store nested
- result: $.verification.identity
# Accessible as: $.verification.identity
# Array storage
- result: $.items[0].sku
# Accessible as: $.items[0].skuTimeout Formats
Valid duration strings:
timeout: 1000ms # Milliseconds
timeout: 30s # Seconds
timeout: 5m # Minutes
timeout: 1h # Hours
timeout: 2h30m # CombinedComparison Operators in Conditions
conditions:
- "{{ $.age >= 18 }}"
- "{{ $.amount > 1000 }}"
- "{{ $.status == 'active' }}"
- "{{ $.name != 'admin' }}"
- "{{ $.score <= 100 }}"
- "{{ $.items.length > 0 }}"
- "{{ $.name contains 'test' }}"| Operator | Usage | Example |
|---|---|---|
== | Equality | status == 'active' |
!= | Inequality | status != 'inactive' |
> | Greater than | amount > 1000 |
< | Less than | amount < 100 |
>= | Greater or equal | age >= 18 |
<= | Less or equal | score <= 100 |
&& | AND | age >= 18 && status == 'active' |
|| | OR | tier == 'gold' || amount > 5000 |
URN Format
Uniform Resource Name uniquely identifies resources:
urn:cascade:activity:validate_order
urn:cascade:policy:loan_approval
urn:cascade:schema:application_form
urn:cascade:service:notification
Parts:
├── urn - Scheme (always "urn")
├── cascade - Authority
├── resource_type - activity, policy, schema, service
└── resource_name - Specific resourceResource Types
| Type | Usage |
|---|---|
activity | Go functions executed by workflows |
policy | Business rules (OPA, DMN) |
schema | JSON schemas for validation/UI |
service | Internal services |
Common Patterns
Sequential Workflow
states:
- name: Step1
type: Task
next: Step2
- name: Step2
type: Task
next: Step3
- name: Step3
type: Task
end: trueBranching Workflow
states:
- name: CheckAmount
type: Choice
choices:
- condition: "{{ $.amount <= 1000 }}"
next: FastApprove
- condition: "{{ $.amount <= 10000 }}"
next: ManagerApprove
default: ExecutiveApprove
- name: FastApprove
type: Task
end: true
- name: ManagerApprove
type: Task
end: true
- name: ExecutiveApprove
type: Task
end: trueError Handling
- name: RiskyOperation
type: Task
resource: urn:cascade:activity:risky_call
retries:
max_attempts: 3
backoff:
initial_interval: 5s
max_interval: 30s
timeout: 30s
next: OnSuccess
- name: OnSuccess
type: Task
end: trueValidation Rules
Application-level:
- Must have exactly one workflow per app (for now)
- Workflow name must be unique within app
- Start state must exist
State-level:
- State names must be unique within workflow
nextmust reference existing stateresourcein Task must be valid URNschemain HumanTask must be valid URN
Parameter-level:
- Template syntax must be valid
- All context references must be defined before use
Best Practices
✅ DO:
- Use meaningful state names
- Set timeouts on all activities
- Document complex conditions
- Use retries for external APIs
- Validate early (before expensive operations)
- Store results in context for later use
❌ DON’T:
- Create cycles (infinite loops)
- Use vague names like “state_1”
- Forget timeouts (activity hangs)
- Hard-code values (use parameters)
- Chain too many states (>15 per workflow)
Quick Reference
# Minimal state
- name: StateName
type: Task|Choice|HumanTask|Parallel|Wait|Receive|EvaluatePolicy
[required fields for type]
next: NextStateName | end: trueUpdated: October 29, 2025
Version: 1.0
CDL Version: cascade.io/v1
Last updated on