Skip to content

Workflow DSL Reference

Complete reference for the CNCF Serverless Workflow DSL 1.0 as implemented in Triggerfish's workflow engine. For usage guide and examples, see Workflows.

Document Structure

Every workflow YAML must have a top-level document field and a do block.

yaml
document:
  dsl: "1.0"
  namespace: my-namespace
  name: my-workflow
  version: "1.0.0"            # optional
  description: "What it does"  # optional
classification_ceiling: INTERNAL  # optional
input:                            # optional
  from: "${ . }"
output:                           # optional
  from:
    result: "${ .final_step }"
timeout:                          # optional
  after: PT5M
do:
  - task_name:
      # task definition

Document Metadata

FieldTypeRequiredDescription
dslstringyesDSL version. Must be "1.0"
namespacestringyesLogical grouping (e.g., ops, reports)
namestringyesUnique workflow name within the namespace
versionstringnoSemantic version string
descriptionstringnoHuman-readable description

Top-Level Fields

FieldTypeRequiredDescription
documentobjectyesDocument metadata (see above)
doarrayyesOrdered list of task entries
classification_ceilingstringnoMaximum allowed session taint during execution
inputtransformnoTransform applied to workflow input
outputtransformnoTransform applied to workflow output
timeoutobjectnoWorkflow-level timeout (after: <ISO 8601>)
metadataobjectnoArbitrary key-value metadata

Task Entry Format

Each entry in the do block is a single-key object. The key is the task name, the value is the task definition.

yaml
do:
  - my_task_name:
      call: http
      with:
        endpoint: "https://example.com"

Task names must be unique within the same do block. The task result is stored in the data context under the task name.


Common Task Fields

All task types share these optional fields:

FieldTypeDescription
ifstringExpression condition. Task is skipped when falsy.
inputtransformTransform applied before task execution
outputtransformTransform applied after task execution
timeoutobjectTask timeout: after: <ISO 8601 duration>
thenstringFlow directive: continue, end, or a task name
metadataobjectArbitrary key-value metadata. When self-healing is enabled, requires description, expects, produces.

Self-Healing Configuration

The metadata.triggerfish.self_healing block enables an autonomous healing agent for the workflow. See Self-Healing for a full guide.

yaml
metadata:
  triggerfish:
    self_healing:
      enabled: true
      retry_budget: 3
      approval_required: true
      pause_on_intervention: blocking_only
      pause_timeout_seconds: 300
      pause_timeout_policy: escalate_and_halt
      notify_on: [intervention, escalation, approval_required]
FieldTypeRequiredDefaultDescription
enabledbooleanyesEnable the healing agent
retry_budgetnumberno3Max intervention attempts
approval_requiredbooleannotrueRequire human approval for fixes
pause_on_interventionstringno"blocking_only"always | never | blocking_only
pause_timeout_secondsnumberno300Seconds before timeout policy fires
pause_timeout_policystringno"escalate_and_halt"escalate_and_halt | escalate_and_skip | escalate_and_fail
notify_onarrayno[]intervention | escalation | approval_required

Step Metadata (Required When Self-Healing Enabled)

When self_healing.enabled is true, every task must include these metadata fields. The parser rejects workflows missing any of them.

FieldTypeDescription
descriptionstringWhat the step does and why
expectsstringInput shape or preconditions needed
producesstringOutput shape generated
yaml
- fetch-invoices:
    call: http
    with:
      endpoint: "https://api.example.com/invoices"
    metadata:
      description: "Fetch open invoices from billing API"
      expects: "API available, returns JSON array"
      produces: "Array of {id, amount, status} objects"

Task Types

call

Dispatch to an HTTP endpoint or Triggerfish service.

FieldTypeRequiredDescription
callstringyesCall type (see dispatch table below)
withobjectnoArguments passed to the target tool
yaml
- fetch:
    call: http
    with:
      endpoint: "https://api.example.com/data"
      method: GET

run

Execute a shell command, inline script, or sub-workflow. The run field must contain exactly one of shell, script, or workflow.

Shell:

FieldTypeRequiredDescription
run.shell.commandstringyesShell command to execute
run.shell.argumentsobjectnoNamed arguments
run.shell.environmentobjectnoEnvironment variables

Script:

FieldTypeRequiredDescription
run.script.languagestringyesScript language
run.script.codestringyesInline script code
run.script.argumentsobjectnoNamed arguments

Sub-workflow:

FieldTypeRequiredDescription
run.workflow.namestringyesName of the saved workflow
run.workflow.versionstringnoVersion constraint
run.workflow.inputobjectnoInput data for sub-workflow

set

Assign values to the data context.

FieldTypeRequiredDescription
setobjectyesKey-value pairs to assign. Values can be expressions.
yaml
- prepare:
    set:
      full_name: "${ .first_name } ${ .last_name }"
      count: 0

switch

Conditional branching. The switch field is an array of case entries. Each case is a single-key object where the key is the case name.

Case fieldTypeRequiredDescription
whenstringnoExpression condition. Omit for default case.
thenstringyesFlow directive: continue, end, or task name

Cases are evaluated in order. The first case with a truthy when (or no when) is taken.

yaml
- route:
    switch:
      - high:
          when: "${ .priority > 7 }"
          then: alert_team
      - low:
          then: log_only

for

Iterate over a collection.

FieldTypeRequiredDescription
for.eachstringyesVariable name for the current item
for.instringyesExpression referencing the collection
for.atstringnoVariable name for the current index
doarrayyesNested task list executed for each iteration
yaml
- process_all:
    for:
      each: item
      in: "${ .items }"
      at: idx
    do:
      - handle:
          call: triggerfish:llm
          with:
            task: "Process item ${ .idx }: ${ .item.name }"

raise

Halt the workflow with a structured error.

FieldTypeRequiredDescription
raise.error.statusnumberyesHTTP-style status code
raise.error.typestringyesError type URI/string
raise.error.titlestringyesHuman-readable title
raise.error.detailstringnoDetailed error message
yaml
- abort:
    raise:
      error:
        status: 422
        type: "validation-error"
        title: "Invalid input"
        detail: "Field 'email' is required"

emit

Record a workflow event. Events are stored in the run result.

FieldTypeRequiredDescription
emit.event.typestringyesEvent type identifier
emit.event.sourcestringnoEvent source URI
emit.event.dataobjectnoEvent payload
yaml
- record:
    emit:
      event:
        type: "step.completed"
        source: "workflow/pipeline"
        data:
          step: "transform"
          duration_ms: 1200

wait

Pause execution for a duration.

FieldTypeRequiredDescription
waitstringyesISO 8601 duration (e.g., PT5S)

Common durations: PT1S (1 second), PT30S (30 seconds), PT1M (1 minute), PT5M (5 minutes).


Call Dispatch Table

Maps the call field value to the Triggerfish tool that is actually invoked.

call valueTool invokedRequired with: fields
httpweb_fetchendpoint or url; optional method, headers, body
triggerfish:llmllm_taskprompt or task; optional tools, max_iterations
triggerfish:agentsubagentprompt or task; optional tools, agent
triggerfish:memorymemory_*operation (save/search/get/list/delete) + operation fields
triggerfish:web_searchweb_searchquery; optional max_results
triggerfish:web_fetchweb_fetchurl; optional method, headers, body
triggerfish:mcpmcp__<server>__<tool>server, tool; optional arguments
triggerfish:messagesend_messagechannel, text; optional recipient

Unsupported CNCF call types (grpc, openapi, asyncapi) return an error.


Expression Syntax

Expressions are delimited by ${ } and resolve against the workflow data context.

Dot-Path Resolution

SyntaxDescriptionExample result
${ . }Entire data context{...}
${ .key }Top-level key"value"
${ .a.b.c }Nested key"deep value"
${ .items[0] }Array index{...first item...}
${ .items[0].name }Array index then key"first"

The leading dot (or $.) anchors the path at the context root. Paths that resolve to undefined produce an empty string when interpolated, or undefined when used as a standalone value.

Operators

TypeOperatorsExample
Comparison==, !=, >, <, >=, <=${ .count > 0 }
Arithmetic+, -, *, /, %${ .price * .quantity }

Comparison expressions return true or false. Arithmetic expressions return a number (undefined if either operand is not numeric or division by zero).

Literals

TypeExamples
String"hello", 'hello'
Number42, 3.14, -1
Booleantrue, false
Nullnull

Interpolation Modes

Single expression (raw value): When the entire string is one ${ } expression, the raw typed value is returned (number, boolean, object, array).

yaml
count: "${ .items.length }"  # returns a number, not a string

Mixed / multiple expressions (string): When ${ } expressions are mixed with text or there are multiple expressions, the result is always a string.

yaml
message: "Found ${ .count } items in ${ .category }"  # returns a string

Truthiness

For if: conditions and switch when: expressions, values are evaluated using JavaScript-style truthiness:

ValueTruthy?
trueyes
Non-zero numberyes
Non-empty stringyes
Non-empty arrayyes
Objectyes
false, 0, "", null, undefined, empty arrayno

Input/Output Transforms

Transforms reshape data flowing into and out of tasks.

input

Applied before task execution. Replaces the task's view of the data context.

yaml
- step:
    call: http
    input:
      from: "${ .config }"       # task sees only the config object
    with:
      endpoint: "${ .api_url }"  # resolved against the config object

from as string: Expression that replaces the entire input context.

from as object: Maps new keys to expressions:

yaml
input:
  from:
    url: "${ .config.api_url }"
    token: "${ .secrets.api_token }"

output

Applied after task execution. Reshapes the result before storing it in the context under the task name.

yaml
- fetch:
    call: http
    output:
      from:
        items: "${ .fetch.data.results }"
        count: "${ .fetch.data.total }"

Flow Directives

The then field on any task controls execution flow after the task completes.

ValueBehaviour
continueProceed to the next task in sequence (default)
endStop the workflow. Status: completed.
<task name>Jump to the named task. The task must exist in the same do block.

Switch cases also use flow directives in their then field.


Classification Ceiling

Optional field restricting the maximum session taint during execution.

yaml
classification_ceiling: INTERNAL
ValueMeaning
PUBLICWorkflow halts if any classified data is accessed
INTERNALAllows PUBLIC and INTERNAL data
CONFIDENTIALAllows up to CONFIDENTIAL data
RESTRICTEDAllows all classification levels
(omitted)No ceiling enforced

The ceiling is checked before every task. If the session taint has escalated past the ceiling (e.g., because a prior task accessed classified data), the workflow halts with status failed and error Workflow classification ceiling breached.


Storage

Workflow Definitions

Stored with key prefix workflows:{name}. Each stored record contains:

FieldTypeDescription
namestringWorkflow name
yamlstringRaw YAML definition
classificationstringClassification level at time of save
savedAtstringISO 8601 timestamp
descriptionstringOptional description

Run History

Stored with key prefix workflow-runs:{runId}. Each run record contains:

FieldTypeDescription
runIdstringUUID for this execution
workflowNamestringName of the workflow that was executed
statusstringcompleted, failed, or cancelled
outputobjectFinal data context (internal keys filtered)
eventsarrayEvents emitted during execution
errorstringError message (if status is failed)
startedAtstringISO 8601 timestamp
completedAtstringISO 8601 timestamp
taskCountnumberNumber of tasks in the workflow
classificationstringSession taint at completion

Limits

LimitValueDescription
Sub-workflow max depth5Maximum nesting of run.workflow calls
Run history default limit10Default limit for workflow_history

Execution Statuses

StatusDescription
pendingWorkflow has been created but not started
runningWorkflow is currently executing
completedAll tasks finished successfully (or then: end)
failedA task failed, a raise was hit, or ceiling breached
cancelledExecution was cancelled externally